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