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/RPCHelpers.h>
31 #include <grpc/status.h>
32 
33 namespace ripple {
34 
35 // {
36 // account: <ident>,
37 // strict: <bool> // optional (default false)
38 // // if true only allow public keys and addresses.
39 // ledger_hash : <ledger>
40 // ledger_index : <ledger_index>
41 // signer_lists : <bool> // optional (default false)
42 // // if true return SignerList(s).
43 // queue : <bool> // optional (default false)
44 // // if true return information about transactions
45 // // in the current TxQ, only if the requested
46 // // ledger is open. Otherwise if true, returns an
47 // // error.
48 // }
49 
50 // 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 =
84  params.isMember(jss::queue) && 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  // Documentation states this is returned as part of the account_info
112  // response, but previously the code put it under account_data. We
113  // can move this to the documentated location from apiVersion 2
114  // onwards.
115  if (context.apiVersion == 1)
116  {
117  result[jss::account_data][jss::signer_lists] =
118  std::move(jvSignerList);
119  }
120  else
121  {
122  result[jss::signer_lists] = std::move(jvSignerList);
123  }
124  }
125  // Return queue info if that is requested
126  if (queue)
127  {
128  Json::Value jvQueueData = Json::objectValue;
129 
130  auto const txs = context.app.getTxQ().getAccountTxs(accountID);
131  if (!txs.empty())
132  {
133  jvQueueData[jss::txn_count] =
134  static_cast<Json::UInt>(txs.size());
135 
136  auto& jvQueueTx = jvQueueData[jss::transactions];
137  jvQueueTx = Json::arrayValue;
138 
139  std::uint32_t seqCount = 0;
140  std::uint32_t ticketCount = 0;
142  std::optional<std::uint32_t> highestSeq;
143  std::optional<std::uint32_t> lowestTicket;
144  std::optional<std::uint32_t> highestTicket;
145  bool anyAuthChanged = false;
146  XRPAmount totalSpend(0);
147 
148  // We expect txs to be returned sorted by SeqProxy. Verify
149  // that with a couple of asserts.
150  SeqProxy prevSeqProxy = SeqProxy::sequence(0);
151  for (auto const& tx : txs)
152  {
154 
155  if (tx.seqProxy.isSeq())
156  {
157  assert(prevSeqProxy < tx.seqProxy);
158  prevSeqProxy = tx.seqProxy;
159  jvTx[jss::seq] = tx.seqProxy.value();
160  ++seqCount;
161  if (!lowestSeq)
162  lowestSeq = tx.seqProxy.value();
163  highestSeq = tx.seqProxy.value();
164  }
165  else
166  {
167  assert(prevSeqProxy < tx.seqProxy);
168  prevSeqProxy = tx.seqProxy;
169  jvTx[jss::ticket] = tx.seqProxy.value();
170  ++ticketCount;
171  if (!lowestTicket)
172  lowestTicket = tx.seqProxy.value();
173  highestTicket = tx.seqProxy.value();
174  }
175 
176  jvTx[jss::fee_level] = to_string(tx.feeLevel);
177  if (tx.lastValid)
178  jvTx[jss::LastLedgerSequence] = *tx.lastValid;
179 
180  jvTx[jss::fee] = to_string(tx.consequences.fee());
181  auto const spend = tx.consequences.potentialSpend() +
182  tx.consequences.fee();
183  jvTx[jss::max_spend_drops] = to_string(spend);
184  totalSpend += spend;
185  bool const authChanged = tx.consequences.isBlocker();
186  if (authChanged)
187  anyAuthChanged = authChanged;
188  jvTx[jss::auth_change] = authChanged;
189 
190  jvQueueTx.append(std::move(jvTx));
191  }
192 
193  if (seqCount)
194  jvQueueData[jss::sequence_count] = seqCount;
195  if (ticketCount)
196  jvQueueData[jss::ticket_count] = ticketCount;
197  if (lowestSeq)
198  jvQueueData[jss::lowest_sequence] = *lowestSeq;
199  if (highestSeq)
200  jvQueueData[jss::highest_sequence] = *highestSeq;
201  if (lowestTicket)
202  jvQueueData[jss::lowest_ticket] = *lowestTicket;
203  if (highestTicket)
204  jvQueueData[jss::highest_ticket] = *highestTicket;
205 
206  jvQueueData[jss::auth_change_queued] = anyAuthChanged;
207  jvQueueData[jss::max_spend_drops_total] = to_string(totalSpend);
208  }
209  else
210  jvQueueData[jss::txn_count] = 0u;
211 
212  result[jss::queue_data] = std::move(jvQueueData);
213  }
214  }
215  else
216  {
217  result[jss::account] = toBase58(accountID);
219  }
220 
221  return result;
222 }
223 
224 } // namespace ripple
ripple::RPC::JsonContext
Definition: Context.h:53
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:52
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:629
Json::UInt
unsigned int UInt
Definition: json_forwards.h:27
ripple::toBase58
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:104
ripple::SeqProxy::sequence
static constexpr SeqProxy sequence(std::uint32_t v)
Factory function to return a sequence-based SeqProxy.
Definition: SeqProxy.h:76
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:577
ripple::RPC::missing_field_error
Json::Value missing_field_error(std::string const &name)
Definition: ErrorCodes.h:262
ripple::base_uint
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:81
Json::Value::append
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:882
ripple::TxQ::getAccountTxs
std::vector< TxDetails > getAccountTxs(AccountID const &account) const
Returns information about the transactions currently in the queue for the account.
Definition: TxQ.cpp:1773
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:133
ripple::JsonOptions::none
@ none
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
std::uint32_t
ripple::ReadView::read
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
std::optional::value
T value(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::RPC::Context::apiVersion
unsigned int apiVersion
Definition: Context.h:50
ripple::SeqProxy
A type that represents either a sequence value or a ticket value.
Definition: SeqProxy.h:55
std::optional< std::uint32_t >
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::keylet::signers
static Keylet signers(AccountID const &account, std::uint32_t page) noexcept
Definition: Indexes.cpp:268
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:64
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:212
ripple::RPC::accountFromString
Json::Value accountFromString(AccountID &result, std::string const &strIdent, bool bStrict)
Definition: RPCHelpers.cpp:85
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::XRPAmount
Definition: XRPAmount.h:46