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/jss.h>
27 #include <ripple/protocol/UintTypes.h>
28 #include <ripple/rpc/Context.h>
29 #include <ripple/rpc/GRPCHandlers.h>
30 #include <ripple/rpc/impl/RPCHelpers.h>
31 #include <ripple/rpc/impl/GRPCHelpers.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"?
53 {
54  auto& params = context.params;
55 
56  std::string strIdent;
57  if (params.isMember(jss::account))
58  strIdent = params[jss::account].asString();
59  else if (params.isMember(jss::ident))
60  strIdent = params[jss::ident].asString();
61  else
62  return RPC::missing_field_error (jss::account);
63 
65  auto result = RPC::lookupLedger (ledger, context);
66 
67  if (!ledger)
68  return result;
69 
70  bool bStrict = params.isMember (jss::strict) && params[jss::strict].asBool ();
71  AccountID accountID;
72 
73  // Get info on account.
74 
75  auto jvAccepted = RPC::accountFromString (accountID, strIdent, bStrict);
76 
77  if (jvAccepted)
78  return jvAccepted;
79 
80  auto const sleAccepted = ledger->read(keylet::account(accountID));
81  if (sleAccepted)
82  {
83  auto const queue = params.isMember(jss::queue) &&
84  params[jss::queue].asBool();
85 
86  if (queue && !ledger->open())
87  {
88  // It doesn't make sense to request the queue
89  // with any closed or validated ledger.
91  return result;
92  }
93 
94  RPC::injectSLE(jvAccepted, *sleAccepted);
95  result[jss::account_data] = jvAccepted;
96 
97  // Return SignerList(s) if that is requested.
98  if (params.isMember (jss::signer_lists) &&
99  params[jss::signer_lists].asBool ())
100  {
101  // We put the SignerList in an array because of an anticipated
102  // future when we support multiple signer lists on one account.
103  Json::Value jvSignerList = Json::arrayValue;
104 
105  // This code will need to be revisited if in the future we support
106  // multiple SignerLists on one account.
107  auto const sleSigners = ledger->read (keylet::signers (accountID));
108  if (sleSigners)
109  jvSignerList.append (sleSigners->getJson (JsonOptions::none));
110 
111  result[jss::account_data][jss::signer_lists] =
112  std::move(jvSignerList);
113  }
114  // Return queue info if that is requested
115  if (queue)
116  {
117  Json::Value jvQueueData = Json::objectValue;
118 
119  auto const txs = context.app.getTxQ().getAccountTxs(
120  accountID, *ledger);
121  if (!txs.empty())
122  {
123  jvQueueData[jss::txn_count] = static_cast<Json::UInt>(txs.size());
124  jvQueueData[jss::lowest_sequence] = txs.begin()->first;
125  jvQueueData[jss::highest_sequence] = txs.rbegin()->first;
126 
127  auto& jvQueueTx = jvQueueData[jss::transactions];
128  jvQueueTx = Json::arrayValue;
129 
130  boost::optional<bool> anyAuthChanged(false);
131  boost::optional<XRPAmount> totalSpend(0);
132 
133  for (auto const& [txSeq, txDetails] : txs)
134  {
136 
137  jvTx[jss::seq] = txSeq;
138  jvTx[jss::fee_level] = to_string(txDetails.feeLevel);
139  if (txDetails.lastValid)
140  jvTx[jss::LastLedgerSequence] = *txDetails.lastValid;
141  if (txDetails.consequences)
142  {
143  jvTx[jss::fee] = to_string(
144  txDetails.consequences->fee);
145  auto spend = txDetails.consequences->potentialSpend +
146  txDetails.consequences->fee;
147  jvTx[jss::max_spend_drops] = to_string(spend);
148  if (totalSpend)
149  *totalSpend += spend;
150  auto authChanged = txDetails.consequences->category ==
152  if (authChanged)
153  anyAuthChanged.emplace(authChanged);
154  jvTx[jss::auth_change] = authChanged;
155  }
156  else
157  {
158  if (anyAuthChanged && !*anyAuthChanged)
159  anyAuthChanged.reset();
160  totalSpend.reset();
161  }
162 
163  jvQueueTx.append(std::move(jvTx));
164  }
165 
166  if (anyAuthChanged)
167  jvQueueData[jss::auth_change_queued] =
168  *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 
190 {
191  // Return values
192  org::xrpl::rpc::v1::GetAccountInfoResponse result;
193  grpc::Status status = grpc::Status::OK;
194 
195  // input
196  org::xrpl::rpc::v1::GetAccountInfoRequest& params = context.params;
197 
198  // get ledger
200  auto lgrStatus = RPC::ledgerFromRequest(ledger, context);
201  if (lgrStatus || !ledger)
202  {
203  grpc::Status errorStatus;
204  if (lgrStatus.toErrorCode() == rpcINVALID_PARAMS)
205  {
206  errorStatus = grpc::Status(
207  grpc::StatusCode::INVALID_ARGUMENT, lgrStatus.message());
208  }
209  else
210  {
211  errorStatus =
212  grpc::Status(grpc::StatusCode::NOT_FOUND, lgrStatus.message());
213  }
214  return {result, errorStatus};
215  }
216 
217  result.set_ledger_index(ledger->info().seq);
218  result.set_validated(
219  RPC::isValidated(context.ledgerMaster, *ledger, context.app));
220 
221  // decode account
222  AccountID accountID;
223  std::string strIdent = params.account().address();
224  error_code_i code =
225  RPC::accountFromStringWithCode(accountID, strIdent, params.strict());
226  if (code != rpcSUCCESS)
227  {
228  grpc::Status errorStatus{grpc::StatusCode::INVALID_ARGUMENT,
229  "invalid account"};
230  return {result, errorStatus};
231  }
232 
233  // get account data
234  auto const sleAccepted = ledger->read(keylet::account(accountID));
235  if (sleAccepted)
236  {
237  RPC::convert(*result.mutable_account_data(), *sleAccepted);
238 
239  // signer lists
240  if (params.signer_lists())
241  {
242  auto const sleSigners = ledger->read(keylet::signers(accountID));
243  if (sleSigners)
244  {
245  org::xrpl::rpc::v1::SignerList& signerListProto =
246  *result.mutable_signer_list();
247  RPC::convert(signerListProto, *sleSigners);
248  }
249  }
250 
251  // queued transactions
252  if (params.queue())
253  {
254  if (!ledger->open())
255  {
256  grpc::Status errorStatus{
257  grpc::StatusCode::INVALID_ARGUMENT,
258  "requested queue but ledger is not open"};
259  return {result, errorStatus};
260  }
261  auto const txs =
262  context.app.getTxQ().getAccountTxs(accountID, *ledger);
263  org::xrpl::rpc::v1::QueueData& queueData = *result.mutable_queue_data();
264  RPC::convert(queueData, txs);
265  }
266  }
267  else
268  {
269  grpc::Status errorStatus{grpc::StatusCode::NOT_FOUND,
270  "account not found"};
271  return {result, errorStatus};
272  }
273 
274  return {result, status};
275 }
276 
277 } // 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.
ripple::keylet::signers
static const signers_t signers
Definition: Indexes.h:239
std::shared_ptr
STL class.
ripple::rpcINVALID_PARAMS
@ rpcINVALID_PARAMS
Definition: ErrorCodes.h:85
ripple::doAccountInfo
Json::Value doAccountInfo(RPC::JsonContext &context)
Definition: AccountInfo.cpp:52
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:44
ripple::RPC::injectSLE
void injectSLE(Json::Value &jv, SLE const &sle)
Inject JSON describing ledger entry.
Definition: RPCHelpers.cpp:534
std::pair
Json::UInt
unsigned int UInt
Definition: json_forwards.h:28
ripple::RPC::Context::ledgerMaster
LedgerMaster & ledgerMaster
Definition: Context.h:45
ripple::LedgerInfo::seq
LedgerIndex seq
Definition: ReadView.h:87
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:484
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:229
ripple::base_uint
Definition: base_uint.h:65
ripple::RPC::convert
void convert(org::xrpl::rpc::v1::TransactionResult &to, TER from)
Definition: GRPCHelpers.cpp:897
ripple::rpcSUCCESS
@ rpcSUCCESS
Definition: ErrorCodes.h:45
Json::Value::append
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:907
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:45
ripple::RPC::accountFromStringWithCode
error_code_i accountFromStringWithCode(AccountID &result, std::string const &strIdent, bool bStrict)
Decode account ID from string.
Definition: RPCHelpers.cpp:55
ripple::keylet::account
static const account_t account
Definition: Indexes.h:116
ripple::JsonOptions::none
@ none
ripple::RPC::GRPCContext
Definition: Context.h:70
ripple::rpcACT_NOT_FOUND
@ rpcACT_NOT_FOUND
Definition: ErrorCodes.h:71
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:1417
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:418
ripple::TxConsequences::blocker
@ blocker
Affects the ability of subsequent transactions to claim a fee.
Definition: applySteps.h:137
Json::Value::begin
const_iterator begin() const
Definition: json_value.cpp:1089
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:185
ripple::RPC::accountFromString
Json::Value accountFromString(AccountID &result, std::string const &strIdent, bool bStrict)
Definition: RPCHelpers.cpp:86
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:141
ripple::AccountIDCache::toBase58
std::string toBase58(AccountID const &) const
Return ripple::toBase58 for the AccountID.
Definition: AccountID.cpp:199
ripple::RPC::ledgerFromRequest
Status ledgerFromRequest(T &ledger, GRPCContext< org::xrpl::rpc::v1::GetAccountInfoRequest > &context)
Definition: RPCHelpers.cpp:263