46 auto const& params =
context_.params;
49 if (!params.isMember(field))
53 if (!params[field].isBool())
58 return params[field].asBool();
61 auto const full = getBool(jss::full);
63 auto const accounts = getBool(jss::accounts);
64 auto const expand = getBool(jss::expand);
65 auto const binary = getBool(jss::binary);
66 auto const ownerFunds = getBool(jss::owner_funds);
67 auto const queue = getBool(jss::queue);
69 if (!full.has_value())
73 if (!accounts.has_value())
74 return accounts.error();
75 if (!expand.has_value())
76 return expand.error();
77 if (!binary.has_value())
78 return binary.error();
79 if (!ownerFunds.has_value())
80 return ownerFunds.error();
81 if (!queue.has_value())
92 bool const needsLedger = params.isMember(jss::ledger) || params.isMember(jss::ledger_hash) ||
93 params.isMember(jss::ledger_index);
99 if (*full || *accounts)
171 org::xrpl::rpc::v1::GetLedgerRequest
const& request = context.
params;
172 org::xrpl::rpc::v1::GetLedgerResponse response;
173 grpc::Status
const status = grpc::Status::OK;
178 grpc::Status errorStatus;
181 errorStatus = grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, status.message());
185 errorStatus = grpc::Status(grpc::StatusCode::NOT_FOUND, status.message());
187 return {response, errorStatus};
191 addRaw(ledger->header(), s,
true);
195 if (request.transactions())
199 for (
auto& i : ledger->txs)
201 XRPL_ASSERT(i.first,
"xrpl::doLedgerGrpc : non-null transaction");
202 if (request.expand())
204 auto txn = response.mutable_transactions_list()->add_transactions();
205 Serializer const sTxn = i.first->getSerializer();
209 Serializer const sMeta = i.second->getSerializer();
215 auto const& hash = i.first->getTransactionID();
216 response.mutable_hashes_list()->add_hashes(hash.data(), hash.size());
222 JLOG(context.
j.
error()) << __func__ <<
" - Error deserializing transaction in ledger "
223 << ledger->header().seq
224 <<
" . skipping transaction and following transactions. You "
225 "should look into this further";
229 if (request.get_objects())
237 grpc::Status
const errorStatus{
238 grpc::StatusCode::NOT_FOUND,
"parent ledger not validated"};
239 return {response, errorStatus};
246 grpc::Status
const errorStatus{grpc::StatusCode::NOT_FOUND,
"ledger not validated"};
247 return {response, errorStatus};
253 bool const res = base->stateMap().compare(desired->stateMap(), differences, maxDifferences);
256 grpc::Status
const errorStatus{
257 grpc::StatusCode::RESOURCE_EXHAUSTED,
258 "too many differences between specified ledgers"};
259 return {response, errorStatus};
262 for (
auto& [k, v] : differences)
264 auto obj = response.mutable_ledger_objects()->add_objects();
265 auto inBase = v.first;
266 auto inDesired = v.second;
268 obj->set_key(k.data(), k.size());
271 XRPL_ASSERT(inDesired->size() > 0,
"xrpl::doLedgerGrpc : non-empty desired");
272 obj->set_data(inDesired->data(), inDesired->size());
274 if (inBase && inDesired)
276 obj->set_mod_type(org::xrpl::rpc::v1::RawLedgerObject::MODIFIED);
278 else if (inBase && !inDesired)
280 obj->set_mod_type(org::xrpl::rpc::v1::RawLedgerObject::DELETED);
284 obj->set_mod_type(org::xrpl::rpc::v1::RawLedgerObject::CREATED);
286 auto const blob = inDesired ? inDesired->slice() : inBase->slice();
287 auto const objectType =
static_cast<LedgerEntryType>(blob[1] << 8 | blob[2]);
289 if (request.get_object_neighbors())
291 if (!(inBase && inDesired))
293 auto lb = desired->stateMap().lowerBound(k);
294 auto ub = desired->stateMap().upperBound(k);
295 if (lb != desired->stateMap().end())
296 obj->set_predecessor(lb->key().data(), lb->key().size());
297 if (ub != desired->stateMap().end())
298 obj->set_successor(ub->key().data(), ub->key().size());
299 if (objectType == ltDIR_NODE)
302 if (!sle->isFieldPresent(sfOwner))
305 if (!inBase && inDesired)
307 auto firstBook = desired->stateMap().upperBound(bookBase.key);
308 if (firstBook != desired->stateMap().end() &&
310 firstBook->key() == k)
312 auto succ = response.add_book_successors();
313 succ->set_book_base(bookBase.key.data(), bookBase.key.size());
314 succ->set_first_book(
315 firstBook->key().data(), firstBook->key().size());
318 if (inBase && !inDesired)
320 auto oldFirstBook = base->stateMap().upperBound(bookBase.key);
321 if (oldFirstBook != base->stateMap().end() &&
323 oldFirstBook->key() == k)
325 auto succ = response.add_book_successors();
326 succ->set_book_base(bookBase.key.data(), bookBase.key.size());
328 desired->stateMap().upperBound(bookBase.key);
330 if (newFirstBook != desired->stateMap().end() &&
333 succ->set_first_book(
334 newFirstBook->key().data(), newFirstBook->key().size());
343 response.set_objects_included(
true);
344 response.set_object_neighbors_included(request.get_object_neighbors());
345 response.set_skiplist_included(
true);
355 auto const numObjects = response.ledger_objects().objects_size();
356 auto const numTxns = response.transactions_list().transactions_size();
359 JLOG(context.
j.
warn()) << __func__ <<
" - Extract time = " << duration
360 <<
" - num objects = " << numObjects <<
" - num txns = " << numTxns
361 <<
" - ms per obj " << msPerObj <<
" - ms per txn " << msPerTxn;
363 return {response, status};
LedgerMaster & ledgerMaster