20#include <xrpld/app/ledger/LedgerToJson.h>
21#include <xrpld/app/main/Application.h>
22#include <xrpld/app/misc/LoadFeeTrack.h>
23#include <xrpld/rpc/GRPCHandlers.h>
24#include <xrpld/rpc/Role.h>
25#include <xrpld/rpc/handlers/LedgerHandler.h>
27#include <xrpl/protocol/ErrorCodes.h>
28#include <xrpl/protocol/jss.h>
29#include <xrpl/resource/Fees.h>
42 bool needsLedger = params.
isMember(jss::ledger) ||
43 params.isMember(jss::ledger_hash) || params.isMember(jss::ledger_index);
50 bool const full = params[jss::full].asBool();
51 bool const transactions = params[jss::transactions].asBool();
52 bool const accounts = params[jss::accounts].asBool();
53 bool const expand = params[jss::expand].asBool();
54 bool const binary = params[jss::binary].asBool();
55 bool const owner_funds = params[jss::owner_funds].asBool();
56 bool const queue = params[jss::queue].asBool();
106 org::xrpl::rpc::v1::GetLedgerRequest& request = context.
params;
107 org::xrpl::rpc::v1::GetLedgerResponse response;
108 grpc::Status status = grpc::Status::OK;
113 grpc::Status errorStatus;
116 errorStatus = grpc::Status(
117 grpc::StatusCode::INVALID_ARGUMENT, status.message());
122 grpc::Status(grpc::StatusCode::NOT_FOUND, status.message());
124 return {response, errorStatus};
128 addRaw(ledger->info(), s,
true);
132 if (request.transactions())
136 for (
auto& i : ledger->txs)
139 i.first,
"ripple::doLedgerGrpc : non-null transaction");
140 if (request.expand())
142 auto txn = response.mutable_transactions_list()
143 ->add_transactions();
154 auto const& hash = i.first->getTransactionID();
155 response.mutable_hashes_list()->add_hashes(
156 hash.data(), hash.size());
163 << __func__ <<
" - Error deserializing transaction in ledger "
164 << ledger->info().seq
165 <<
" . skipping transaction and following transactions. You "
166 "should look into this further";
170 if (request.get_objects())
176 std::dynamic_pointer_cast<Ledger const>(parent);
179 grpc::Status errorStatus{
180 grpc::StatusCode::NOT_FOUND,
"parent ledger not validated"};
181 return {response, errorStatus};
185 std::dynamic_pointer_cast<Ledger const>(ledger);
188 grpc::Status errorStatus{
189 grpc::StatusCode::NOT_FOUND,
"ledger not validated"};
190 return {response, errorStatus};
196 bool res = base->stateMap().compare(
197 desired->stateMap(), differences, maxDifferences);
200 grpc::Status errorStatus{
201 grpc::StatusCode::RESOURCE_EXHAUSTED,
202 "too many differences between specified ledgers"};
203 return {response, errorStatus};
206 for (
auto& [k, v] : differences)
208 auto obj = response.mutable_ledger_objects()->add_objects();
209 auto inBase = v.first;
210 auto inDesired = v.second;
212 obj->set_key(k.data(), k.size());
216 inDesired->size() > 0,
217 "ripple::doLedgerGrpc : non-empty desired");
218 obj->set_data(inDesired->data(), inDesired->size());
220 if (inBase && inDesired)
222 org::xrpl::rpc::v1::RawLedgerObject::MODIFIED);
223 else if (inBase && !inDesired)
224 obj->set_mod_type(org::xrpl::rpc::v1::RawLedgerObject::DELETED);
226 obj->set_mod_type(org::xrpl::rpc::v1::RawLedgerObject::CREATED);
227 auto const blob = inDesired ? inDesired->slice() : inBase->slice();
228 auto const objectType =
231 if (request.get_object_neighbors())
233 if (!(inBase && inDesired))
235 auto lb = desired->stateMap().lower_bound(k);
236 auto ub = desired->stateMap().upper_bound(k);
237 if (lb != desired->stateMap().end())
238 obj->set_predecessor(
239 lb->key().data(), lb->key().size());
240 if (ub != desired->stateMap().end())
241 obj->set_successor(ub->key().data(), ub->key().size());
242 if (objectType == ltDIR_NODE)
244 auto sle = std::make_shared<SLE>(
SerialIter{blob}, k);
245 if (!sle->isFieldPresent(sfOwner))
248 if (!inBase && inDesired)
251 desired->stateMap().upper_bound(
253 if (firstBook != desired->stateMap().end() &&
256 firstBook->key() == k)
258 auto succ = response.add_book_successors();
261 bookBase.key.size());
262 succ->set_first_book(
263 firstBook->key().data(),
264 firstBook->key().size());
267 if (inBase && !inDesired)
270 base->stateMap().upper_bound(bookBase.key);
271 if (oldFirstBook != base->stateMap().end() &&
272 oldFirstBook->key() <
274 oldFirstBook->key() == k)
276 auto succ = response.add_book_successors();
279 bookBase.key.size());
281 desired->stateMap().upper_bound(
285 desired->stateMap().end() &&
286 newFirstBook->key() <
289 succ->set_first_book(
290 newFirstBook->key().data(),
291 newFirstBook->key().size());
300 response.set_objects_included(
true);
301 response.set_object_neighbors_included(request.get_object_neighbors());
302 response.set_skiplist_included(
true);
309 std::chrono::duration_cast<std::chrono::milliseconds>(end - begin)
312 JLOG(context.
j.
warn())
313 << __func__ <<
" - Extract time = " << duration
314 <<
" - num objects = " << response.ledger_objects().objects_size()
315 <<
" - num txns = " << response.transactions_list().transactions_size()
317 << duration / response.ledger_objects().objects_size()
319 << duration / response.transactions_list().transactions_size();
321 return {response, status};
bool isMember(char const *key) const
Return true if the object has a member named key.
virtual LoadFeeTrack & getFeeTrack()=0
virtual LedgerMaster & getLedgerMaster()=0
bool isValidated(ReadView const &ledger)
std::shared_ptr< Ledger const > getLedgerBySeq(std::uint32_t index)
bool isLoadedLocal() const
std::shared_ptr< ReadView const > ledger_
std::vector< TxQ::TxDetails > queueTxs_
LedgerHandler(JsonContext &)
void const * data() const noexcept
Blob const & peekData() const
std::vector< TxDetails > getTxs() const
Returns information about all transactions currently in the queue.
Status ledgerFromRequest(T &ledger, GRPCContext< R > &context)
std::pair< RPC::Status, LedgerEntryType > chooseLedgerEntryType(Json::Value const ¶ms)
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.
Charge const feeMediumBurdenRPC
Charge const feeHeavyBurdenRPC
Keylet quality(Keylet const &k, std::uint64_t q) noexcept
The initial directory page for a specific quality.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
bool isUnlimited(Role const &role)
ADMIN and IDENTIFIED roles shall have unlimited resources.
std::pair< org::xrpl::rpc::v1::GetLedgerResponse, grpc::Status > doLedgerGrpc(RPC::GRPCContext< org::xrpl::rpc::v1::GetLedgerRequest > &context)
uint256 getQualityNext(uint256 const &uBase)
LedgerEntryType
Identifiers for on-ledger objects.
void addRaw(LedgerHeader const &, Serializer &, bool includeHash=false)
Resource::Charge & loadType
LedgerMaster & ledgerMaster
Status represents the results of an operation that might fail.