diff --git a/src/ripple/module/rpc/impl/LookupLedger.cpp b/src/ripple/module/rpc/impl/LookupLedger.cpp index dec7c928f8..c73fa3bd96 100644 --- a/src/ripple/module/rpc/impl/LookupLedger.cpp +++ b/src/ripple/module/rpc/impl/LookupLedger.cpp @@ -28,8 +28,8 @@ static const int LEDGER_VALIDATED = -3; // The previous version of the lookupLedger command would accept the // "ledger_index" argument as a string and silently treat it as a request to -// return the current ledger which, while not strictly wrong, could cause a -// lot of confusion. +// return the current ledger which, while not strictly wrong, could cause a lot +// of confusion. // // The code now robustly validates the input and ensures that the only possible // values for the "ledger_index" parameter are the index of a ledger passed as @@ -42,177 +42,155 @@ static const int LEDGER_VALIDATED = -3; // assumes that "ledger_index" has the value "current". Json::Value lookupLedger ( Json::Value const& params, - Ledger::pointer& lpLedger, + Ledger::pointer& ledger, NetworkOPs& netOps) { - Json::Value jvResult; + using RPC::make_error; + ledger.reset(); - Json::Value ledger_hash = params.get (jss::ledger_hash, Json::Value ("0")); - Json::Value ledger_index = params.get (jss::ledger_index, Json::Value ("current")); + auto jsonHash = params.get (jss::ledger_hash, Json::Value ("0")); + auto jsonIndex = params.get (jss::ledger_index, Json::Value ("current")); // Support for DEPRECATED "ledger" - attempt to deduce our input if (params.isMember (jss::ledger)) { if (params[jss::ledger].asString ().size () > 12) { - ledger_hash = params[jss::ledger]; - ledger_index = Json::Value (""); + jsonHash = params[jss::ledger]; + jsonIndex = Json::Value (""); } else if (params[jss::ledger].isNumeric ()) { - ledger_index = params[jss::ledger]; - ledger_hash = Json::Value ("0"); + jsonIndex = params[jss::ledger]; + jsonHash = Json::Value ("0"); } else { - ledger_index = params[jss::ledger]; - ledger_hash = Json::Value ("0"); + jsonIndex = params[jss::ledger]; + jsonHash = Json::Value ("0"); } } - uint256 uLedger (0); + uint256 ledgerHash (0); - if (!ledger_hash.isString() || !uLedger.SetHex (ledger_hash.asString ())) - { - RPC::inject_error(rpcINVALID_PARAMS, "ledgerHashMalformed", jvResult); - return jvResult; - } + if (!jsonHash.isString() || !ledgerHash.SetHex (jsonHash.asString ())) + return make_error(rpcINVALID_PARAMS, "ledgerHashMalformed"); - std::int32_t iLedgerIndex = LEDGER_CURRENT; + std::int32_t ledgerIndex = LEDGER_CURRENT; // We only try to parse a ledger index if we have not already // determined that we have a ledger hash. - if (!uLedger) + if (ledgerHash == zero) { - if (ledger_index.isNumeric ()) - iLedgerIndex = ledger_index.asInt (); + if (jsonIndex.isNumeric ()) + { + ledgerIndex = jsonIndex.asInt (); + } else { - std::string strLedger = ledger_index.asString (); + std::string index = jsonIndex.asString (); - if (strLedger == "current") + if (index == "current") + ledgerIndex = LEDGER_CURRENT; + else if (index == "closed") + ledgerIndex = LEDGER_CLOSED; + else if (index == "validated") + ledgerIndex = LEDGER_VALIDATED; + else + return make_error(rpcINVALID_PARAMS, "ledgerIndexMalformed"); + } + } + else + { + ledger = netOps.getLedgerByHash (ledgerHash); + + if (!ledger) + return make_error(rpcLGR_NOT_FOUND, "ledgerNotFound"); + + ledgerIndex = ledger->getLedgerSeq (); + } + + int ledgerRequest = 0; + + if (ledgerIndex <= 0) { + switch (ledgerIndex) + { + case LEDGER_CURRENT: + ledger = netOps.getCurrentLedger (); + break; + + case LEDGER_CLOSED: + ledger = getApp().getLedgerMaster ().getClosedLedger (); + break; + + case LEDGER_VALIDATED: + ledger = netOps.getValidatedLedger (); + break; + + default: + return make_error(rpcINVALID_PARAMS, "ledgerIndexMalformed"); + } + + assert (ledger->isImmutable()); + assert (ledger->isClosed() == (ledgerIndex != LEDGER_CURRENT)); + ledgerRequest = ledgerIndex; + ledgerIndex = ledger->getLedgerSeq (); + } + + if (!ledger) + { + ledger = netOps.getLedgerBySeq (ledgerIndex); + + if (!ledger) + return make_error(rpcLGR_NOT_FOUND, "ledgerNotFound"); + } + + Json::Value jsonResult; + if (ledger->isClosed ()) + { + if (ledgerHash != zero) + jsonResult[jss::ledger_hash] = to_string (ledgerHash); + + jsonResult[jss::ledger_index] = ledgerIndex; + } + else + { + jsonResult[jss::ledger_current_index] = ledgerIndex; + } + + if (ledger->isValidated ()) + { + jsonResult[jss::validated] = true; + } + else if (!ledger->isClosed ()) + { + jsonResult[jss::validated] = false; + } + else + { + try + { + // Use the skip list in the last validated ledger to see if ledger + // comes after the last validated ledger (and thus has been + // validated). + auto next = getApp().getLedgerMaster ().walkHashBySeq (ledgerIndex); + if (ledgerHash == next) { - iLedgerIndex = LEDGER_CURRENT; - } - else if (strLedger == "closed") - { - iLedgerIndex = LEDGER_CLOSED; - } - else if (strLedger == "validated") - { - iLedgerIndex = LEDGER_VALIDATED; + ledger->setValidated(); + jsonResult[jss::validated] = true; } else { - RPC::inject_error(rpcINVALID_PARAMS, "ledgerIndexMalformed", jvResult); - return jvResult; + jsonResult[jss::validated] = false; } } - } - - // The ledger was directly specified by hash. - if (uLedger.isNonZero ()) - { - lpLedger = netOps.getLedgerByHash (uLedger); - - if (!lpLedger) + catch (SHAMapMissingNode const&) { - RPC::inject_error(rpcLGR_NOT_FOUND, "ledgerNotFound", jvResult); - return jvResult; - } - - iLedgerIndex = lpLedger->getLedgerSeq (); - } - - int ledger_request = 0; - switch (iLedgerIndex) - { - case LEDGER_CURRENT: - lpLedger = netOps.getCurrentLedger (); - iLedgerIndex = lpLedger->getLedgerSeq (); - assert (lpLedger->isImmutable () && !lpLedger->isClosed ()); - ledger_request = LEDGER_CURRENT; - break; - - case LEDGER_CLOSED: - lpLedger = getApp().getLedgerMaster ().getClosedLedger (); - iLedgerIndex = lpLedger->getLedgerSeq (); - assert (lpLedger->isImmutable () && lpLedger->isClosed ()); - ledger_request = LEDGER_CLOSED; - break; - - case LEDGER_VALIDATED: - lpLedger = netOps.getValidatedLedger (); - iLedgerIndex = lpLedger->getLedgerSeq (); - assert (lpLedger->isImmutable () && lpLedger->isClosed ()); - ledger_request = LEDGER_VALIDATED; - break; - } - - if (iLedgerIndex <= 0) - { - RPC::inject_error(rpcINVALID_PARAMS, "ledgerIndexMalformed", jvResult); - return jvResult; - } - - if (!lpLedger) - { - lpLedger = netOps.getLedgerBySeq (iLedgerIndex); - - if (!lpLedger) - { - RPC::inject_error(rpcLGR_NOT_FOUND, "ledgerNotFound", jvResult); - return jvResult; + jsonResult[jss::validated] = false; } } - if (lpLedger->isClosed ()) - { - if (uLedger.isNonZero ()) - jvResult[jss::ledger_hash] = to_string (uLedger); - - jvResult[jss::ledger_index] = iLedgerIndex; - } - else - { - jvResult[jss::ledger_current_index] = iLedgerIndex; - } - - if (lpLedger->isValidated ()) - jvResult[jss::validated] = true; - else - { - if (!lpLedger->isClosed ()) - jvResult[jss::validated] = false; - else if (ledger_request == LEDGER_VALIDATED) - { - lpLedger->setValidated(); - jvResult[jss::validated] = true; - } - else - { - try - { - // Use the skip list in the last validated ledger to see if lpLedger - // comes after the last validated ledger (and thus has been validated) - if (uLedger == getApp().getLedgerMaster ().walkHashBySeq (iLedgerIndex)) - { - lpLedger->setValidated(); - jvResult[jss::validated] = true; - } - else - { - jvResult[jss::validated] = false; - } - } - catch (SHAMapMissingNode const&) - { - jvResult[jss::validated] = false; - } - } - } - - return jvResult; + return jsonResult; } } // RPC