rippled
AccountObjects.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012-2014 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/app/main/Application.h>
21 #include <ripple/app/tx/impl/details/NFTokenUtils.h>
22 #include <ripple/json/json_writer.h>
23 #include <ripple/ledger/ReadView.h>
24 #include <ripple/net/RPCErr.h>
25 #include <ripple/protocol/ErrorCodes.h>
26 #include <ripple/protocol/Indexes.h>
27 #include <ripple/protocol/LedgerFormats.h>
28 #include <ripple/protocol/jss.h>
29 #include <ripple/resource/Fees.h>
30 #include <ripple/rpc/Context.h>
31 #include <ripple/rpc/impl/RPCHelpers.h>
32 #include <ripple/rpc/impl/Tuning.h>
33 
34 #include <sstream>
35 #include <string>
36 
37 namespace ripple {
38 
52 {
53  auto const& params = context.params;
54  if (!params.isMember(jss::account))
55  return RPC::missing_field_error(jss::account);
56 
58  auto result = RPC::lookupLedger(ledger, context);
59  if (ledger == nullptr)
60  return result;
61 
62  AccountID accountID;
63  {
64  auto const strIdent = params[jss::account].asString();
65  if (auto jv = RPC::accountFromString(accountID, strIdent))
66  {
67  for (auto it = jv.begin(); it != jv.end(); ++it)
68  result[it.memberName()] = *it;
69 
70  return result;
71  }
72  }
73 
74  if (!ledger->exists(keylet::account(accountID)))
75  return rpcError(rpcACT_NOT_FOUND);
76 
77  unsigned int limit;
78  if (auto err = readLimitField(limit, RPC::Tuning::accountNFTokens, context))
79  return *err;
80 
81  uint256 marker;
82 
83  if (params.isMember(jss::marker))
84  {
85  auto const& m = params[jss::marker];
86  if (!m.isString())
87  return RPC::expected_field_error(jss::marker, "string");
88 
89  if (!marker.parseHex(m.asString()))
90  return RPC::invalid_field_error(jss::marker);
91  }
92 
93  auto const first = keylet::nftpage(keylet::nftpage_min(accountID), marker);
94  auto const last = keylet::nftpage_max(accountID);
95 
96  auto cp = ledger->read(Keylet(
98  ledger->succ(first.key, last.key.next()).value_or(last.key)));
99 
100  std::uint32_t cnt = 0;
101  auto& nfts = (result[jss::account_nfts] = Json::arrayValue);
102 
103  // Continue iteration from the current page:
104 
105  while (cp)
106  {
107  auto arr = cp->getFieldArray(sfNFTokens);
108 
109  for (auto const& o : arr)
110  {
111  if (o.getFieldH256(sfNFTokenID) <= marker)
112  continue;
113 
114  {
115  Json::Value& obj = nfts.append(o.getJson(JsonOptions::none));
116 
117  // Pull out the components of the nft ID.
118  uint256 const nftokenID = o[sfNFTokenID];
119  obj[sfFlags.jsonName] = nft::getFlags(nftokenID);
120  obj[sfIssuer.jsonName] = to_string(nft::getIssuer(nftokenID));
121  obj[sfNFTokenTaxon.jsonName] =
122  nft::toUInt32(nft::getTaxon(nftokenID));
123  obj[jss::nft_serial] = nft::getSerial(nftokenID);
124  if (std::uint16_t xferFee = {nft::getTransferFee(nftokenID)})
125  obj[sfTransferFee.jsonName] = xferFee;
126  }
127 
128  if (++cnt == limit)
129  {
130  result[jss::limit] = limit;
131  result[jss::marker] = to_string(o.getFieldH256(sfNFTokenID));
132  return result;
133  }
134  }
135 
136  if (auto npm = (*cp)[~sfNextPageMin])
137  cp = ledger->read(Keylet(ltNFTOKEN_PAGE, *npm));
138  else
139  cp = nullptr;
140  }
141 
142  result[jss::account] = context.app.accountIDCache().toBase58(accountID);
144  return result;
145 }
146 
149 {
150  auto const& params = context.params;
151  if (!params.isMember(jss::account))
152  return RPC::missing_field_error(jss::account);
153 
155  auto result = RPC::lookupLedger(ledger, context);
156  if (ledger == nullptr)
157  return result;
158 
159  AccountID accountID;
160  {
161  auto const strIdent = params[jss::account].asString();
162  if (auto jv = RPC::accountFromString(accountID, strIdent))
163  {
164  for (auto it = jv.begin(); it != jv.end(); ++it)
165  result[it.memberName()] = *it;
166 
167  return result;
168  }
169  }
170 
171  if (!ledger->exists(keylet::account(accountID)))
172  return rpcError(rpcACT_NOT_FOUND);
173 
175 
176  if (params.isMember(jss::deletion_blockers_only) &&
177  params[jss::deletion_blockers_only].asBool())
178  {
179  struct
180  {
181  Json::StaticString name;
182  LedgerEntryType type;
183  } static constexpr deletionBlockers[] = {
184  {jss::check, ltCHECK},
185  {jss::escrow, ltESCROW},
186  {jss::payment_channel, ltPAYCHAN},
187  {jss::state, ltRIPPLE_STATE}};
188 
189  typeFilter.emplace();
190  typeFilter->reserve(std::size(deletionBlockers));
191 
192  for (auto [name, type] : deletionBlockers)
193  {
194  if (params.isMember(jss::type) && name != params[jss::type])
195  {
196  continue;
197  }
198 
199  typeFilter->push_back(type);
200  }
201  }
202  else
203  {
204  auto [rpcStatus, type] = RPC::chooseLedgerEntryType(params);
205 
206  if (rpcStatus)
207  {
208  result.clear();
209  rpcStatus.inject(result);
210  return result;
211  }
212  else if (type != ltANY)
213  {
214  typeFilter = std::vector<LedgerEntryType>({type});
215  }
216  }
217 
218  unsigned int limit;
219  if (auto err = readLimitField(limit, RPC::Tuning::accountObjects, context))
220  return *err;
221 
222  uint256 dirIndex;
223  uint256 entryIndex;
224  if (params.isMember(jss::marker))
225  {
226  auto const& marker = params[jss::marker];
227  if (!marker.isString())
228  return RPC::expected_field_error(jss::marker, "string");
229 
230  std::stringstream ss(marker.asString());
231  std::string s;
232  if (!std::getline(ss, s, ','))
233  return RPC::invalid_field_error(jss::marker);
234 
235  if (!dirIndex.parseHex(s))
236  return RPC::invalid_field_error(jss::marker);
237 
238  if (!std::getline(ss, s, ','))
239  return RPC::invalid_field_error(jss::marker);
240 
241  if (!entryIndex.parseHex(s))
242  return RPC::invalid_field_error(jss::marker);
243  }
244 
246  *ledger,
247  accountID,
248  typeFilter,
249  dirIndex,
250  entryIndex,
251  limit,
252  result))
253  {
254  result[jss::account_objects] = Json::arrayValue;
255  }
256 
257  result[jss::account] = context.app.accountIDCache().toBase58(accountID);
259  return result;
260 }
261 
262 } // namespace ripple
ripple::doAccountNFTs
Json::Value doAccountNFTs(RPC::JsonContext &context)
General RPC command that can retrieve objects in the account root.
Definition: AccountObjects.cpp:51
sstream
ripple::RPC::JsonContext
Definition: Context.h:53
ripple::Keylet
A pair of SHAMap key and LedgerEntryType.
Definition: Keylet.h:38
ripple::nft::getFlags
std::uint16_t getFlags(uint256 const &id)
Definition: NFTokenUtils.h:117
std::string
STL class.
std::shared_ptr
STL class.
ripple::rpcError
Json::Value rpcError(int iError)
Definition: RPCErr.cpp:29
ripple::ltANY
@ ltANY
A special type, matching any ledger entry type.
Definition: LedgerFormats.h:176
ripple::Resource::feeMediumBurdenRPC
const Charge feeMediumBurdenRPC
ripple::sfNFTokenID
const SF_UINT256 sfNFTokenID
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:42
ripple::doAccountObjects
Json::Value doAccountObjects(RPC::JsonContext &context)
Definition: AccountObjects.cpp:148
ripple::RPC::Tuning::accountNFTokens
static constexpr LimitRange accountNFTokens
Limits for the account_nftokens command, in pages.
Definition: rpc/impl/Tuning.h:55
ripple::RPC::Context::loadType
Resource::Charge & loadType
Definition: Context.h:43
std::vector
STL class.
std::size
T size(T... args)
std::optional::emplace
T emplace(T... args)
std::stringstream
STL class.
ripple::ltCHECK
@ ltCHECK
A ledger object which describes a check.
Definition: LedgerFormats.h:136
ripple::SField::jsonName
const Json::StaticString jsonName
Definition: SField.h:136
ripple::RPC::lookupLedger
Status lookupLedger(std::shared_ptr< ReadView const > &ledger, JsonContext &context, Json::Value &result)
Look up a ledger from a request and fill a Json::Result with the data representing a ledger.
Definition: RPCHelpers.cpp:582
ripple::Application::accountIDCache
virtual AccountIDCache const & accountIDCache() const =0
ripple::RPC::expected_field_error
Json::Value expected_field_error(std::string const &name, std::string const &type)
Definition: ErrorCodes.h:312
ripple::sfTransferFee
const SF_UINT16 sfTransferFee
ripple::RPC::missing_field_error
Json::Value missing_field_error(std::string const &name)
Definition: ErrorCodes.h:246
ripple::nft::getIssuer
AccountID getIssuer(uint256 const &id)
Definition: NFTokenUtils.h:177
ripple::base_uint
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:75
ripple::keylet::nftpage_min
Keylet nftpage_min(AccountID const &owner)
NFT page keylets.
Definition: Indexes.cpp:332
ripple::keylet::nftpage
Keylet nftpage(Keylet const &k, uint256 const &token)
Definition: Indexes.cpp:348
Json::Value::append
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:882
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:133
ripple::nft::toUInt32
std::uint32_t toUInt32(Taxon t)
Definition: NFTokenUtils.h:46
ripple::ltESCROW
@ ltESCROW
A ledger object describing a single escrow.
Definition: LedgerFormats.h:124
ripple::JsonOptions::none
@ none
ripple::rpcACT_NOT_FOUND
@ rpcACT_NOT_FOUND
Definition: ErrorCodes.h:70
ripple::RPC::Context::app
Application & app
Definition: Context.h:42
ripple::keylet::nftpage_max
Keylet nftpage_max(AccountID const &owner)
A keylet for the owner's last possible NFT page.
Definition: Indexes.cpp:340
ripple::ReadView::exists
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
ripple::nft::getSerial
std::uint32_t getSerial(uint256 const &id)
Definition: NFTokenUtils.h:133
std::uint32_t
ripple::ReadView::succ
virtual std::optional< key_type > succ(key_type const &key, std::optional< key_type > const &last=std::nullopt) const =0
Return the key of the next state item.
ripple::RPC::Tuning::accountObjects
static constexpr LimitRange accountObjects
Limits for the account_objects command.
Definition: rpc/impl/Tuning.h:43
ripple::ReadView::read
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
ripple::sfNFTokens
const SField sfNFTokens
ripple::ltNFTOKEN_PAGE
@ ltNFTOKEN_PAGE
A ledger object which contains a list of NFTs.
Definition: LedgerFormats.h:156
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::LedgerEntryType
LedgerEntryType
Identifiers for on-ledger objects.
Definition: LedgerFormats.h:53
ripple::sfIssuer
const SF_ACCOUNT sfIssuer
ripple::RPC::chooseLedgerEntryType
std::pair< RPC::Status, LedgerEntryType > chooseLedgerEntryType(Json::Value const &params)
Definition: RPCHelpers.cpp:882
std::getline
T getline(T... args)
Json::StaticString
Lightweight wrapper to tag static string.
Definition: json_value.h:60
ripple::sfFlags
const SF_UINT32 sfFlags
ripple::sfNextPageMin
const SF_UINT256 sfNextPageMin
std::optional
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::sfNFTokenTaxon
const SF_UINT32 sfNFTokenTaxon
ripple::ltRIPPLE_STATE
@ ltRIPPLE_STATE
A ledger object which describes a bidirectional trust line.
Definition: LedgerFormats.h:74
ripple::nft::getTransferFee
std::uint16_t getTransferFee(uint256 const &id)
Definition: NFTokenUtils.h:125
ripple::base_uint::parseHex
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:489
ripple::nft::getTaxon
Taxon getTaxon(uint256 const &id)
Definition: NFTokenUtils.h:165
ripple::RPC::JsonContext::params
Json::Value params
Definition: Context.h:64
ripple::RPC::invalid_field_error
Json::Value invalid_field_error(std::string const &name)
Definition: ErrorCodes.h:288
ripple::RPC::accountFromString
Json::Value accountFromString(AccountID &result, std::string const &strIdent, bool bStrict)
Definition: RPCHelpers.cpp:84
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::ltPAYCHAN
@ ltPAYCHAN
A ledger object describing a single unidirectional XRP payment channel.
Definition: LedgerFormats.h:130
ripple::RPC::getAccountObjects
bool getAccountObjects(ReadView const &ledger, AccountID const &account, std::optional< std::vector< LedgerEntryType >> const &typeFilter, uint256 dirIndex, uint256 const &entryIndex, std::uint32_t const limit, Json::Value &jvResult)
Gathers all objects for an account in a ledger.
Definition: RPCHelpers.cpp:135
ripple::AccountIDCache::toBase58
std::string toBase58(AccountID const &) const
Return ripple::toBase58 for the AccountID.
Definition: AccountID.cpp:134
string