diff --git a/src/handlers/methods/impl/AccountTx.cpp b/src/handlers/methods/impl/AccountTx.cpp index 60279d77..5253dfb5 100644 --- a/src/handlers/methods/impl/AccountTx.cpp +++ b/src/handlers/methods/impl/AccountTx.cpp @@ -50,14 +50,13 @@ doAccountTx(Context const& context) binary = request.at("binary").as_bool(); } - - auto minIndex = context.range.minSequence; - if (request.contains("ledger_index_min")) + bool forward = false; + if (request.contains("forward")) { - if (!request.at("ledger_index_min").is_int64()) - return Status{Error::rpcINVALID_PARAMS, "ledgerSeqMinNotNumber"}; + if (!request.at("forward").is_bool()) + return Status{Error::rpcINVALID_PARAMS, "forwardNotBool"}; - minIndex = value_to(request.at("ledger_index_min")); + forward = request.at("forward").as_bool(); } std::optional cursor; @@ -90,17 +89,59 @@ doAccountTx(Context const& context) cursor = {*ledgerIndex, *transactionIndex}; } - else if (request.contains("ledger_index_max")) + + auto minIndex = context.range.minSequence; + if (request.contains("ledger_index_min")) + { + if (!request.at("ledger_index_min").is_int64()) + return Status{Error::rpcINVALID_PARAMS, "ledgerSeqMinNotNumber"}; + + minIndex = value_to(request.at("ledger_index_min")); + if (forward && !cursor) + cursor = {minIndex, 0}; + } + + auto maxIndex = context.range.maxSequence; + if (request.contains("ledger_index_max")) { if (!request.at("ledger_index_max").is_int64()) return Status{Error::rpcINVALID_PARAMS, "ledgerSeqMaxNotNumber"}; - auto maxIndex = value_to(request.at("ledger_index_max")); + maxIndex = value_to(request.at("ledger_index_max")); if (minIndex > maxIndex) return Status{Error::rpcINVALID_PARAMS, "invalidIndex"}; + if (!forward && !cursor) + cursor = {maxIndex, INT32_MAX}; + } + if (request.contains("ledger_index")) + { + if (!request.at("ledger_index").is_int64()) + return Status{Error::rpcINVALID_PARAMS, "ledgerIndexNotNumber"}; - cursor = {maxIndex, 0}; + auto ledgerIndex = value_to(request.at("ledger_index")); + maxIndex = minIndex = ledgerIndex; + } + if (request.contains("ledger_hash")) + { + if (!request.at("ledger_hash").is_string()) + return RPC::Status{ + RPC::Error::rpcINVALID_PARAMS, "ledgerHashNotString"}; + + ripple::uint256 ledgerHash; + if (!ledgerHash.parseHex(request.at("ledger_hash").as_string().c_str())) + return RPC::Status{ + RPC::Error::rpcINVALID_PARAMS, "ledgerHashMalformed"}; + + auto lgrInfo = context.backend->fetchLedgerByHash(ledgerHash); + maxIndex = minIndex = lgrInfo->seq; + } + if (!cursor) + { + if (forward) + cursor = {minIndex, 0}; + else + cursor = {maxIndex, INT32_MAX}; } std::uint32_t limit = 200; @@ -115,14 +156,6 @@ doAccountTx(Context const& context) response["limit"] = limit; } - bool forward = false; - if (request.contains("forward")) - { - if (!request.at("forward").is_bool()) - return Status{Error::rpcINVALID_PARAMS, "forwardNotBool"}; - - forward = request.at("forward").as_bool(); - } boost::json::array txns; auto start = std::chrono::system_clock::now(); @@ -135,21 +168,21 @@ doAccountTx(Context const& context) << " num blobs = " << blobs.size(); response["account"] = ripple::to_string(*accountID); - response["ledger_index_min"] = minIndex; - response["ledger_index_max"] = cursor->ledgerSequence; if (retCursor) { - BOOST_LOG_TRIVIAL(debug) << "setting json cursor"; boost::json::object cursorJson; cursorJson["ledger"] = retCursor->ledgerSequence; cursorJson["seq"] = retCursor->transactionIndex; response["marker"] = cursorJson; } + std::optional maxReturnedIndex; + std::optional minReturnedIndex; for (auto const& txnPlusMeta : blobs) { - if (txnPlusMeta.ledgerSequence < minIndex) + if (txnPlusMeta.ledgerSequence < minIndex || + txnPlusMeta.ledgerSequence > maxIndex) { BOOST_LOG_TRIVIAL(debug) << __func__ @@ -177,6 +210,28 @@ doAccountTx(Context const& context) obj["validated"] = true; txns.push_back(obj); + if (!minReturnedIndex || txnPlusMeta.ledgerSequence < *minReturnedIndex) + minReturnedIndex = txnPlusMeta.ledgerSequence; + if (!maxReturnedIndex || txnPlusMeta.ledgerSequence > *maxReturnedIndex) + maxReturnedIndex = txnPlusMeta.ledgerSequence; + } + + assert(cursor); + if (forward) + { + response["ledger_index_min"] = cursor->ledgerSequence; + if (blobs.size() >= limit) + response["ledger_index_max"] = *maxReturnedIndex; + else + response["ledger_index_max"] = maxIndex; + } + else + { + response["ledger_index_max"] = cursor->ledgerSequence; + if (blobs.size() >= limit) + response["ledger_index_min"] = *minReturnedIndex; + else + response["ledger_index_min"] = minIndex; } response["transactions"] = txns; @@ -186,6 +241,6 @@ doAccountTx(Context const& context) << ((end2 - end).count() / 1000000000.0); return response; -} +} // namespace RPC } // namespace RPC