From d182d1455eceb862a63163ddec53b98f5b02d595 Mon Sep 17 00:00:00 2001 From: Miguel Portilla Date: Tue, 14 Apr 2015 13:37:06 -0400 Subject: [PATCH] Relax RPC ledger synchronization requirements (RIPD-27, RIPD-840): This enhances the reporting capability of RPC::LookupLedger and reduces the requirement of a current ledger for many RPC commands. The perceived up-time of client handlers improves since requests will not depend on the server being fully synced. --- src/ripple/rpc/handlers/Ledger.h | 2 +- src/ripple/rpc/impl/Handler.cpp | 31 +++++++------- src/ripple/rpc/impl/LookupLedger.cpp | 64 ++++++++++++++++++++++++---- 3 files changed, 73 insertions(+), 24 deletions(-) diff --git a/src/ripple/rpc/handlers/Ledger.h b/src/ripple/rpc/handlers/Ledger.h index de9f919c63..4dfddc0b6d 100644 --- a/src/ripple/rpc/handlers/Ledger.h +++ b/src/ripple/rpc/handlers/Ledger.h @@ -59,7 +59,7 @@ public: static Condition condition() { - return NEEDS_NETWORK_CONNECTION; + return NO_CONDITION; } private: diff --git a/src/ripple/rpc/impl/Handler.cpp b/src/ripple/rpc/impl/Handler.cpp index 44aab9001b..bcfbc64631 100644 --- a/src/ripple/rpc/impl/Handler.cpp +++ b/src/ripple/rpc/impl/Handler.cpp @@ -96,15 +96,16 @@ class HandlerTable { }; HandlerTable HANDLERS({ + // Some handlers not specified here are added to the table via addHandler() // Request-response methods - { "account_info", byRef (&doAccountInfo), Role::USER, NEEDS_CURRENT_LEDGER }, - { "account_currencies", byRef (&doAccountCurrencies), Role::USER, NEEDS_CURRENT_LEDGER }, - { "account_lines", byRef (&doAccountLines), Role::USER, NEEDS_CURRENT_LEDGER }, - { "account_objects", byRef (&doAccountObjects), Role::USER, NEEDS_CURRENT_LEDGER }, - { "account_offers", byRef (&doAccountOffers), Role::USER, NEEDS_CURRENT_LEDGER }, - { "account_tx", byRef (&doAccountTxSwitch), Role::USER, NEEDS_NETWORK_CONNECTION }, + { "account_info", byRef (&doAccountInfo), Role::USER, NO_CONDITION }, + { "account_currencies", byRef (&doAccountCurrencies), Role::USER, NO_CONDITION }, + { "account_lines", byRef (&doAccountLines), Role::USER, NO_CONDITION }, + { "account_objects", byRef (&doAccountObjects), Role::USER, NO_CONDITION }, + { "account_offers", byRef (&doAccountOffers), Role::USER, NO_CONDITION }, + { "account_tx", byRef (&doAccountTxSwitch), Role::USER, NO_CONDITION }, { "blacklist", byRef (&doBlackList), Role::ADMIN, NO_CONDITION }, - { "book_offers", byRef (&doBookOffers), Role::USER, NEEDS_CURRENT_LEDGER }, + { "book_offers", byRef (&doBookOffers), Role::USER, NO_CONDITION }, { "can_delete", byRef (&doCanDelete), Role::ADMIN, NO_CONDITION }, { "connect", byRef (&doConnect), Role::ADMIN, NO_CONDITION }, { "consensus_info", byRef (&doConsensusInfo), Role::ADMIN, NO_CONDITION }, @@ -114,15 +115,15 @@ HandlerTable HANDLERS({ { "fetch_info", byRef (&doFetchInfo), Role::ADMIN, NO_CONDITION }, { "ledger_accept", byRef (&doLedgerAccept), Role::ADMIN, NEEDS_CURRENT_LEDGER }, { "ledger_cleaner", byRef (&doLedgerCleaner), Role::ADMIN, NEEDS_NETWORK_CONNECTION }, - { "ledger_closed", byRef (&doLedgerClosed), Role::USER, NEEDS_CLOSED_LEDGER }, + { "ledger_closed", byRef (&doLedgerClosed), Role::USER, NO_CONDITION }, { "ledger_current", byRef (&doLedgerCurrent), Role::USER, NEEDS_CURRENT_LEDGER }, - { "ledger_data", byRef (&doLedgerData), Role::USER, NEEDS_CURRENT_LEDGER }, - { "ledger_entry", byRef (&doLedgerEntry), Role::USER, NEEDS_CURRENT_LEDGER }, - { "ledger_header", byRef (&doLedgerHeader), Role::USER, NEEDS_CURRENT_LEDGER }, + { "ledger_data", byRef (&doLedgerData), Role::USER, NO_CONDITION }, + { "ledger_entry", byRef (&doLedgerEntry), Role::USER, NO_CONDITION }, + { "ledger_header", byRef (&doLedgerHeader), Role::USER, NO_CONDITION }, { "ledger_request", byRef (&doLedgerRequest), Role::ADMIN, NO_CONDITION }, { "log_level", byRef (&doLogLevel), Role::ADMIN, NO_CONDITION }, { "logrotate", byRef (&doLogRotate), Role::ADMIN, NO_CONDITION }, - { "noripple_check", byRef (&doNoRippleCheck), Role::USER, NEEDS_CURRENT_LEDGER }, + { "noripple_check", byRef (&doNoRippleCheck), Role::USER, NO_CONDITION }, { "owner_info", byRef (&doOwnerInfo), Role::USER, NEEDS_CURRENT_LEDGER }, { "peers", byRef (&doPeers), Role::ADMIN, NO_CONDITION }, { "path_find", byRef (&doPathFind), Role::USER, NEEDS_CURRENT_LEDGER }, @@ -130,13 +131,13 @@ HandlerTable HANDLERS({ { "print", byRef (&doPrint), Role::ADMIN, NO_CONDITION }, // { "profile", byRef (&doProfile), Role::USER, NEEDS_CURRENT_LEDGER }, { "random", byRef (&doRandom), Role::USER, NO_CONDITION }, - { "ripple_path_find", byRef (&doRipplePathFind), Role::USER, NEEDS_CURRENT_LEDGER }, + { "ripple_path_find", byRef (&doRipplePathFind), Role::USER, NO_CONDITION }, { "sign", byRef (&doSign), Role::USER, NO_CONDITION }, { "submit", byRef (&doSubmit), Role::USER, NEEDS_CURRENT_LEDGER }, { "server_info", byRef (&doServerInfo), Role::USER, NO_CONDITION }, { "server_state", byRef (&doServerState), Role::USER, NO_CONDITION }, { "stop", byRef (&doStop), Role::ADMIN, NO_CONDITION }, - { "transaction_entry", byRef (&doTransactionEntry), Role::USER, NEEDS_CURRENT_LEDGER }, + { "transaction_entry", byRef (&doTransactionEntry), Role::USER, NO_CONDITION }, { "tx", byRef (&doTx), Role::USER, NEEDS_NETWORK_CONNECTION }, { "tx_history", byRef (&doTxHistory), Role::USER, NO_CONDITION }, { "unl_add", byRef (&doUnlAdd), Role::ADMIN, NO_CONDITION }, @@ -148,7 +149,7 @@ HandlerTable HANDLERS({ { "unl_score", byRef (&doUnlScore), Role::ADMIN, NO_CONDITION }, { "validation_create", byRef (&doValidationCreate), Role::ADMIN, NO_CONDITION }, { "validation_seed", byRef (&doValidationSeed), Role::ADMIN, NO_CONDITION }, - { "wallet_accounts", byRef (&doWalletAccounts), Role::USER, NEEDS_CURRENT_LEDGER }, + { "wallet_accounts", byRef (&doWalletAccounts), Role::USER, NO_CONDITION }, { "wallet_propose", byRef (&doWalletPropose), Role::ADMIN, NO_CONDITION }, { "wallet_seed", byRef (&doWalletSeed), Role::ADMIN, NO_CONDITION }, diff --git a/src/ripple/rpc/impl/LookupLedger.cpp b/src/ripple/rpc/impl/LookupLedger.cpp index 434dcf69c6..4a49c7555a 100644 --- a/src/ripple/rpc/impl/LookupLedger.cpp +++ b/src/ripple/rpc/impl/LookupLedger.cpp @@ -25,6 +25,36 @@ namespace RPC { namespace { +bool +synced (NetworkOPs& netOps, Ledger::pointer ledger) +{ + static auto const minSequenceGap = 10; + + if (getConfig ().RUN_STANDALONE) + return true; + + if (ledger == netOps.getValidatedLedger ()) + { + return getApp ().getLedgerMaster ().getValidatedLedgerAge () <= + Tuning::maxValidatedLedgerAge; + } + + if (ledger != netOps.getCurrentLedger () && + ledger != netOps.getClosedLedger ()) + { + return true; + } + + if (getApp ().getLedgerMaster ().getValidatedLedgerAge () > + Tuning::maxValidatedLedgerAge) + { + return false; + } + + return ledger->getLedgerSeq () > + (netOps.getValidatedSeq () + minSequenceGap); +} + Status ledgerFromRequest ( Json::Value const& params, Ledger::pointer& ledger, @@ -47,35 +77,53 @@ Status ledgerFromRequest ( if (!hashValue.empty()) { + if (! hashValue.isString ()) + return {rpcINVALID_PARAMS, "ledgerHashNotString"}; + uint256 ledgerHash; - if (hashValue.isString() && ledgerHash.SetHex (hashValue.asString ())) - ledger = netOps.getLedgerByHash (ledgerHash); - else + if (! ledgerHash.SetHex (hashValue.asString ())) return {rpcINVALID_PARAMS, "ledgerHashMalformed"}; + + ledger = netOps.getLedgerByHash (ledgerHash); } else if (indexValue.isNumeric()) { - ledger = netOps.getLedgerBySeq (indexValue.asInt()); + ledger = netOps.getLedgerBySeq (indexValue.asInt ()); } else { - auto index = indexValue.asString(); - auto isCurrent = index.empty() || index == "current"; + auto const index = indexValue.asString (); + auto const isCurrent = index.empty() || index == "current"; if (isCurrent) ledger = netOps.getCurrentLedger (); else if (index == "closed") - ledger = getApp().getLedgerMaster ().getClosedLedger (); + ledger = netOps.getClosedLedger (); else if (index == "validated") ledger = netOps.getValidatedLedger (); else return {rpcINVALID_PARAMS, "ledgerIndexMalformed"}; + if (ledger == nullptr) + return {rpcNO_NETWORK, "InsufficientNetworkMode"}; + assert (ledger->isImmutable()); assert (ledger->isClosed() == !isCurrent); } - if (!ledger) + if (ledger == nullptr) + { + auto cl = netOps.getCurrentLedger (); + if (cl == nullptr || ! synced (netOps, cl)) + return {rpcNO_NETWORK, "InsufficientNetworkMode"}; + return {rpcLGR_NOT_FOUND, "ledgerNotFound"}; + } + + if (! synced (netOps, ledger)) + { + ledger.reset (); + return {rpcNO_NETWORK, "InsufficientNetworkMode"}; + } return Status::OK; }