rippled
Loading...
Searching...
No Matches
LedgerData.cpp
1#include <xrpld/app/ledger/LedgerToJson.h>
2#include <xrpld/rpc/Context.h>
3#include <xrpld/rpc/GRPCHandlers.h>
4#include <xrpld/rpc/Role.h>
5#include <xrpld/rpc/detail/RPCHelpers.h>
6#include <xrpld/rpc/detail/RPCLedgerHelpers.h>
7#include <xrpld/rpc/detail/Tuning.h>
8
9#include <xrpl/ledger/ReadView.h>
10#include <xrpl/protocol/ErrorCodes.h>
11#include <xrpl/protocol/LedgerFormats.h>
12#include <xrpl/protocol/jss.h>
13
14namespace xrpl {
15
16// Get state nodes from a ledger
17// Inputs:
18// limit: integer, maximum number of entries
19// marker: opaque, resume point
20// binary: boolean, format
21// type: string // optional, defaults to all ledger node types
22// Outputs:
23// ledger_hash: chosen ledger's hash
24// ledger_index: chosen ledger's index
25// state: array of state nodes
26// marker: resume point, if any
29{
31 auto const& params = context.params;
32
33 auto jvResult = RPC::lookupLedger(lpLedger, context);
34 if (!lpLedger)
35 return jvResult;
36
37 bool const isMarker = params.isMember(jss::marker);
39 if (isMarker)
40 {
41 Json::Value const& jMarker = params[jss::marker];
42 if (!(jMarker.isString() && key.parseHex(jMarker.asString())))
43 return RPC::expected_field_error(jss::marker, "valid");
44 }
45
46 bool const isBinary = params[jss::binary].asBool();
47
48 int limit = -1;
49 if (params.isMember(jss::limit))
50 {
51 Json::Value const& jLimit = params[jss::limit];
52 if (!jLimit.isIntegral())
53 return RPC::expected_field_error(jss::limit, "integer");
54
55 limit = jLimit.asInt();
56 }
57
58 auto maxLimit = RPC::Tuning::pageLength(isBinary);
59 if ((limit < 0) || ((limit > maxLimit) && (!isUnlimited(context.role))))
60 limit = maxLimit;
61
62 jvResult[jss::ledger_hash] = to_string(lpLedger->header().hash);
63 jvResult[jss::ledger_index] = lpLedger->header().seq;
64
65 if (!isMarker)
66 {
67 // Return base ledger data on first query
68 jvResult[jss::ledger] = getJson(LedgerFill(*lpLedger, &context, isBinary ? LedgerFill::Options::binary : 0));
69 }
70
71 auto [rpcStatus, type] = RPC::chooseLedgerEntryType(params);
72 if (rpcStatus)
73 {
74 jvResult.clear();
75 rpcStatus.inject(jvResult);
76 return jvResult;
77 }
78 Json::Value& nodes = jvResult[jss::state];
79 if (nodes.type() == Json::nullValue)
80 {
82 }
83
84 auto e = lpLedger->sles.end();
85 for (auto i = lpLedger->sles.upper_bound(key); i != e; ++i)
86 {
87 auto sle = lpLedger->read(keylet::unchecked((*i)->key()));
88 if (limit-- <= 0)
89 {
90 // Stop processing before the current key.
91 auto k = sle->key();
92 jvResult[jss::marker] = to_string(--k);
93 break;
94 }
95
96 if (type == ltANY || sle->getType() == type)
97 {
98 if (isBinary)
99 {
100 Json::Value& entry = nodes.append(Json::objectValue);
101 entry[jss::data] = serializeHex(*sle);
102 entry[jss::index] = to_string(sle->key());
103 }
104 else
105 {
106 Json::Value& entry = nodes.append(sle->getJson(JsonOptions::none));
107 entry[jss::index] = to_string(sle->key());
108 }
109 }
110 }
111
112 return jvResult;
113}
114
117{
118 org::xrpl::rpc::v1::GetLedgerDataRequest& request = context.params;
119 org::xrpl::rpc::v1::GetLedgerDataResponse response;
120 grpc::Status status = grpc::Status::OK;
121
123 if (auto status = RPC::ledgerFromRequest(ledger, context))
124 {
125 grpc::Status errorStatus;
126 if (status.toErrorCode() == rpcINVALID_PARAMS)
127 {
128 errorStatus = grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, status.message());
129 }
130 else
131 {
132 errorStatus = grpc::Status(grpc::StatusCode::NOT_FOUND, status.message());
133 }
134 return {response, errorStatus};
135 }
136
137 uint256 startKey;
138 if (auto key = uint256::fromVoidChecked(request.marker()))
139 {
140 startKey = *key;
141 }
142 else if (request.marker().size() != 0)
143 {
144 grpc::Status errorStatus{grpc::StatusCode::INVALID_ARGUMENT, "marker malformed"};
145 return {response, errorStatus};
146 }
147
148 auto e = ledger->sles.end();
149 if (request.end_marker().size() != 0)
150 {
151 auto const key = uint256::fromVoidChecked(request.end_marker());
152
153 if (!key)
154 return {response, {grpc::StatusCode::INVALID_ARGUMENT, "end marker malformed"}};
155
156 if (*key < startKey)
157 return {response, {grpc::StatusCode::INVALID_ARGUMENT, "end marker out of range"}};
158
159 e = ledger->sles.upper_bound(*key);
160 }
161
162 int maxLimit = RPC::Tuning::pageLength(true);
163
164 for (auto i = ledger->sles.upper_bound(startKey); i != e; ++i)
165 {
166 auto sle = ledger->read(keylet::unchecked((*i)->key()));
167 if (maxLimit-- <= 0)
168 {
169 // Stop processing before the current key.
170 auto k = sle->key();
171 --k;
172 response.set_marker(k.data(), k.size());
173 break;
174 }
175 auto stateObject = response.mutable_ledger_objects()->add_objects();
176 Serializer s;
177 sle->add(s);
178 stateObject->set_data(s.peekData().data(), s.getLength());
179 stateObject->set_key(sle->key().data(), sle->key().size());
180 }
181 return {response, status};
182}
183
184} // namespace xrpl
Represents a JSON value.
Definition json_value.h:131
Value & append(Value const &value)
Append value to array at the end.
Int asInt() const
bool isString() const
ValueType type() const
std::string asString() const
Returns the unquoted string value.
bool isIntegral() const
uint256 key_type
Definition ReadView.h:36
Blob const & peekData() const
Definition Serializer.h:177
int getLength() const
Definition Serializer.h:208
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition base_uint.h:472
static std::optional< base_uint > fromVoidChecked(T const &from)
Definition base_uint.h:299
T data(T... args)
@ nullValue
'null' value
Definition json_value.h:20
@ arrayValue
array value (ordered list)
Definition json_value.h:26
@ objectValue
object value (collection of name/value pairs).
Definition json_value.h:27
int constexpr pageLength(bool isBinary)
Maximum number of pages in a LedgerData response.
std::pair< RPC::Status, LedgerEntryType > chooseLedgerEntryType(Json::Value const &params)
Chooses the ledger entry type based on RPC parameters.
Json::Value expected_field_error(std::string const &name, std::string const &type)
Definition ErrorCodes.h:293
Status ledgerFromRequest(T &ledger, GRPCContext< R > const &context)
Retrieves a ledger from a gRPC request context.
Status lookupLedger(std::shared_ptr< ReadView const > &ledger, JsonContext const &context, Json::Value &result)
Looks up a ledger from a request and fills a Json::Value with ledger data.
Keylet unchecked(uint256 const &key) noexcept
Any ledger entry.
Definition Indexes.cpp:319
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
Json::Value doLedgerData(RPC::JsonContext &)
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:598
std::pair< org::xrpl::rpc::v1::GetLedgerDataResponse, grpc::Status > doLedgerDataGrpc(RPC::GRPCContext< org::xrpl::rpc::v1::GetLedgerDataRequest > &context)
std::string serializeHex(STObject const &o)
Serialize an object to a hex string.
Definition serialize.h:22
@ ltANY
A special type, matching any ledger entry type.
bool isUnlimited(Role const &role)
ADMIN and IDENTIFIED roles shall have unlimited resources.
Definition Role.cpp:96
@ rpcINVALID_PARAMS
Definition ErrorCodes.h:65
RequestType params
Definition Context.h:52
Json::Value params
Definition Context.h:44