rippled
AccountInfo.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/misc/TxQ.h>
22 #include <ripple/json/json_value.h>
23 #include <ripple/ledger/ReadView.h>
24 #include <ripple/protocol/ErrorCodes.h>
25 #include <ripple/protocol/Indexes.h>
26 #include <ripple/protocol/UintTypes.h>
27 #include <ripple/protocol/jss.h>
28 #include <ripple/rpc/Context.h>
29 #include <ripple/rpc/GRPCHandlers.h>
30 #include <ripple/rpc/impl/GRPCHelpers.h>
31 #include <ripple/rpc/impl/RPCHelpers.h>
32 #include <grpc/status.h>
33 
34 namespace ripple {
35 
36 // {
37 // account: <ident>,
38 // strict: <bool> // optional (default false)
39 // // if true only allow public keys and addresses.
40 // ledger_hash : <ledger>
41 // ledger_index : <ledger_index>
42 // signer_lists : <bool> // optional (default false)
43 // // if true return SignerList(s).
44 // queue : <bool> // optional (default false)
45 // // if true return information about transactions
46 // // in the current TxQ, only if the requested
47 // // ledger is open. Otherwise if true, returns an
48 // // error.
49 // }
50 
51 // TODO(tom): what is that "default"?
54 {
55  auto& params = context.params;
56 
57  std::string strIdent;
58  if (params.isMember(jss::account))
59  strIdent = params[jss::account].asString();
60  else if (params.isMember(jss::ident))
61  strIdent = params[jss::ident].asString();
62  else
63  return RPC::missing_field_error(jss::account);
64 
66  auto result = RPC::lookupLedger(ledger, context);
67 
68  if (!ledger)
69  return result;
70 
71  bool bStrict = params.isMember(jss::strict) && params[jss::strict].asBool();
72  AccountID accountID;
73 
74  // Get info on account.
75 
76  auto jvAccepted = RPC::accountFromString(accountID, strIdent, bStrict);
77 
78  if (jvAccepted)
79  return jvAccepted;
80 
81  auto const sleAccepted = ledger->read(keylet::account(accountID));
82  if (sleAccepted)
83  {
84  auto const queue =
85  params.isMember(jss::queue) && params[jss::queue].asBool();
86 
87  if (queue && !ledger->open())
88  {
89  // It doesn't make sense to request the queue
90  // with any closed or validated ledger.
92  return result;
93  }
94 
95  RPC::injectSLE(jvAccepted, *sleAccepted);
96  result[jss::account_data] = jvAccepted;
97 
98  // Return SignerList(s) if that is requested.
99  if (params.isMember(jss::signer_lists) &&
100  params[jss::signer_lists].asBool())
101  {
102  // We put the SignerList in an array because of an anticipated
103  // future when we support multiple signer lists on one account.
104  Json::Value jvSignerList = Json::arrayValue;
105 
106  // This code will need to be revisited if in the future we support
107  // multiple SignerLists on one account.
108  auto const sleSigners = ledger->read(keylet::signers(accountID));
109  if (sleSigners)
110  jvSignerList.append(sleSigners->getJson(JsonOptions::none));
111 
112  result[jss::account_data][jss::signer_lists] =
113  std::move(jvSignerList);
114  }
115  // Return queue info if that is requested
116  if (queue)
117  {
118  Json::Value jvQueueData = Json::objectValue;
119 
120  auto const txs =
121  context.app.getTxQ().getAccountTxs(accountID, *ledger);
122  if (!txs.empty())
123  {
124  jvQueueData[jss::txn_count] =
125  static_cast<Json::UInt>(txs.size());
126  jvQueueData[jss::lowest_sequence] = txs.begin()->first;
127  jvQueueData[jss::highest_sequence] = txs.rbegin()->first;
128 
129  auto& jvQueueTx = jvQueueData[jss::transactions];
130  jvQueueTx = Json::arrayValue;
131 
132  boost::optional<bool> anyAuthChanged(false);
133  boost::optional<XRPAmount> totalSpend(0);
134 
135  for (auto const& [txSeq, txDetails] : txs)
136  {
138 
139  jvTx[jss::seq] = txSeq;
140  jvTx[jss::fee_level] = to_string(txDetails.feeLevel);
141  if (txDetails.lastValid)
142  jvTx[jss::LastLedgerSequence] = *txDetails.lastValid;
143  if (txDetails.consequences)
144  {
145  jvTx[jss::fee] = to_string(txDetails.consequences->fee);
146  auto spend = txDetails.consequences->potentialSpend +
147  txDetails.consequences->fee;
148  jvTx[jss::max_spend_drops] = to_string(spend);
149  if (totalSpend)
150  *totalSpend += spend;
151  auto authChanged = txDetails.consequences->category ==
153  if (authChanged)
154  anyAuthChanged.emplace(authChanged);
155  jvTx[jss::auth_change] = authChanged;
156  }
157  else
158  {
159  if (anyAuthChanged && !*anyAuthChanged)
160  anyAuthChanged.reset();
161  totalSpend.reset();
162  }
163 
164  jvQueueTx.append(std::move(jvTx));
165  }
166 
167  if (anyAuthChanged)
168  jvQueueData[jss::auth_change_queued] = *anyAuthChanged;
169  if (totalSpend)
170  jvQueueData[jss::max_spend_drops_total] =
171  to_string(*totalSpend);
172  }
173  else
174  jvQueueData[jss::txn_count] = 0u;
175 
176  result[jss::queue_data] = std::move(jvQueueData);
177  }
178  }
179  else
180  {
181  result[jss::account] = context.app.accountIDCache().toBase58(accountID);
183  }
184 
185  return result;
186 }
187 
191 {
192  // Return values
193  org::xrpl::rpc::v1::GetAccountInfoResponse result;
194  grpc::Status status = grpc::Status::OK;
195 
196  // input
197  org::xrpl::rpc::v1::GetAccountInfoRequest& params = context.params;
198 
199  // get ledger
201  auto lgrStatus = RPC::ledgerFromRequest(ledger, context);
202  if (lgrStatus || !ledger)
203  {
204  grpc::Status errorStatus;
205  if (lgrStatus.toErrorCode() == rpcINVALID_PARAMS)
206  {
207  errorStatus = grpc::Status(
208  grpc::StatusCode::INVALID_ARGUMENT, lgrStatus.message());
209  }
210  else
211  {
212  errorStatus =
213  grpc::Status(grpc::StatusCode::NOT_FOUND, lgrStatus.message());
214  }
215  return {result, errorStatus};
216  }
217 
218  result.set_ledger_index(ledger->info().seq);
219  result.set_validated(
220  RPC::isValidated(context.ledgerMaster, *ledger, context.app));
221 
222  // decode account
223  AccountID accountID;
224  std::string strIdent = params.account().address();
225  error_code_i code =
226  RPC::accountFromStringWithCode(accountID, strIdent, params.strict());
227  if (code != rpcSUCCESS)
228  {
229  grpc::Status errorStatus{
230  grpc::StatusCode::INVALID_ARGUMENT, "invalid account"};
231  return {result, errorStatus};
232  }
233 
234  // get account data
235  auto const sleAccepted = ledger->read(keylet::account(accountID));
236  if (sleAccepted)
237  {
238  RPC::convert(*result.mutable_account_data(), *sleAccepted);
239 
240  // signer lists
241  if (params.signer_lists())
242  {
243  auto const sleSigners = ledger->read(keylet::signers(accountID));
244  if (sleSigners)
245  {
246  org::xrpl::rpc::v1::SignerList& signerListProto =
247  *result.mutable_signer_list();
248  RPC::convert(signerListProto, *sleSigners);
249  }
250  }
251 
252  // queued transactions
253  if (params.queue())
254  {
255  if (!ledger->open())
256  {
257  grpc::Status errorStatus{
258  grpc::StatusCode::INVALID_ARGUMENT,
259  "requested queue but ledger is not open"};
260  return {result, errorStatus};
261  }
262  auto const txs =
263  context.app.getTxQ().getAccountTxs(accountID, *ledger);
264  org::xrpl::rpc::v1::QueueData& queueData =
265  *result.mutable_queue_data();
266  RPC::convert(queueData, txs);
267  }
268  }
269  else
270  {
271  grpc::Status errorStatus{
272  grpc::StatusCode::NOT_FOUND, "account not found"};
273  return {result, errorStatus};
274  }
275 
276  return {result, status};
277 }
278 
279 } // namespace ripple
ripple::ReadView::info
virtual LedgerInfo const & info() const =0
Returns information about the ledger.
ripple::RPC::JsonContext
Definition: Context.h:52
std::string
STL class.
std::shared_ptr
STL class.
ripple::rpcINVALID_PARAMS
@ rpcINVALID_PARAMS
Definition: ErrorCodes.h:84
ripple::doAccountInfo
Json::Value doAccountInfo(RPC::JsonContext &context)
Definition: AccountInfo.cpp:53
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:42
ripple::RPC::injectSLE
void injectSLE(Json::Value &jv, SLE const &sle)
Inject JSON describing ledger entry.
Definition: RPCHelpers.cpp:533
std::pair
Json::UInt
unsigned int UInt
Definition: json_forwards.h:27
ripple::RPC::Context::ledgerMaster
LedgerMaster & ledgerMaster
Definition: Context.h:45
ripple::LedgerInfo::seq
LedgerIndex seq
Definition: ReadView.h:88
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:41
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:481
ripple::error_code_i
error_code_i
Definition: ErrorCodes.h:40
ripple::Application::accountIDCache
virtual AccountIDCache const & accountIDCache() const =0
ripple::RPC::missing_field_error
Json::Value missing_field_error(std::string const &name)
Definition: ErrorCodes.h:236
ripple::base_uint
Definition: base_uint.h:63
ripple::RPC::convert
void convert(org::xrpl::rpc::v1::TransactionResult &to, TER from)
Definition: GRPCHelpers.cpp:897
ripple::rpcSUCCESS
@ rpcSUCCESS
Definition: ErrorCodes.h:44
Json::Value::append
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:882
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
ripple::RPC::accountFromStringWithCode
error_code_i accountFromStringWithCode(AccountID &result, std::string const &strIdent, bool bStrict)
Decode account ID from string.
Definition: RPCHelpers.cpp:54
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:120
ripple::JsonOptions::none
@ none
ripple::RPC::GRPCContext
Definition: Context.h:70
ripple::rpcACT_NOT_FOUND
@ rpcACT_NOT_FOUND
Definition: ErrorCodes.h:70
ripple::Application::getTxQ
virtual TxQ & getTxQ()=0
ripple::RPC::Context::app
Application & app
Definition: Context.h:42
ripple::TxQ::getAccountTxs
std::map< TxSeq, AccountTxDetails const > getAccountTxs(AccountID const &account, ReadView const &view) const
Returns information about the transactions currently in the queue for the account.
Definition: TxQ.cpp:1373
ripple::ReadView::read
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
ripple::RPC::GRPCContext::params
RequestType params
Definition: Context.h:72
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::RPC::isValidated
bool isValidated(LedgerMaster &ledgerMaster, ReadView const &ledger, Application &app)
Definition: RPCHelpers.cpp:414
ripple::keylet::signers
static Keylet signers(AccountID const &account, std::uint32_t page) noexcept
Definition: Indexes.cpp:241
ripple::TxConsequences::blocker
@ blocker
Affects the ability of subsequent transactions to claim a fee.
Definition: applySteps.h:135
Json::Value::begin
const_iterator begin() const
Definition: json_value.cpp:1046
ripple::ReadView::open
virtual bool open() const =0
Returns true if this reflects an open ledger.
ripple::RPC::JsonContext::params
Json::Value params
Definition: Context.h:63
ripple::RPC::inject_error
void inject_error(error_code_i code, JsonValue &json)
Add or update the json update to reflect the error code.
Definition: ErrorCodes.h:186
ripple::RPC::accountFromString
Json::Value accountFromString(AccountID &result, std::string const &strIdent, bool bStrict)
Definition: RPCHelpers.cpp:85
ripple::doAccountInfoGrpc
std::pair< org::xrpl::rpc::v1::GetAccountInfoResponse, grpc::Status > doAccountInfoGrpc(RPC::GRPCContext< org::xrpl::rpc::v1::GetAccountInfoRequest > &context)
Definition: AccountInfo.cpp:189
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::AccountIDCache::toBase58
std::string toBase58(AccountID const &) const
Return ripple::toBase58 for the AccountID.
Definition: AccountID.cpp:190
ripple::RPC::ledgerFromRequest
Status ledgerFromRequest(T &ledger, GRPCContext< org::xrpl::rpc::v1::GetAccountInfoRequest > &context)
Definition: RPCHelpers.cpp:261