diff --git a/src/ripple/app/ledger/Ledger.cpp b/src/ripple/app/ledger/Ledger.cpp index 82b24a1372..f97a7da6f1 100644 --- a/src/ripple/app/ledger/Ledger.cpp +++ b/src/ripple/app/ledger/Ledger.cpp @@ -288,7 +288,7 @@ Ledger::Ledger (Ledger const& prevLedger, prevLedger.info_.closeTimeResolution, getCloseAgree(prevLedger.info()), info_.seq); - if (stateMap_->get_version() == SHAMap::version{2}) + if (stateMap_->is_v2()) { info_.closeFlags |= sLCF_SHAMapV2; } diff --git a/src/ripple/app/ledger/impl/LedgerToJson.cpp b/src/ripple/app/ledger/impl/LedgerToJson.cpp index dbdec22236..67c94d5850 100644 --- a/src/ripple/app/ledger/impl/LedgerToJson.cpp +++ b/src/ripple/app/ledger/impl/LedgerToJson.cpp @@ -80,6 +80,21 @@ void fillJson(Object& json, bool closed, LedgerInfo const& info, bool bFull) } } +template +void fillJsonBinary(Object& json, bool closed, LedgerInfo const& info) +{ + if (! closed) + json[jss::closed] = false; + else + { + json[jss::closed] = true; + + Serializer s; + addRaw (info, s); + json[jss::ledger_data] = strHex (s.peekData ()); + } +} + template void fillJsonTx (Object& json, LedgerFill const& fill) { @@ -164,7 +179,10 @@ void fillJson (Object& json, LedgerFill const& fill) // TODO: what happens if bBinary and bExtracted are both set? // Is there a way to report this back? auto bFull = isFull(fill); - fillJson(json, !fill.ledger.open(), fill.ledger.info(), bFull); + if (isBinary(fill)) + fillJsonBinary(json, !fill.ledger.open(), fill.ledger.info()); + else + fillJson(json, !fill.ledger.open(), fill.ledger.info(), bFull); if (bFull || fill.options & LedgerFill::dumpTxrp) fillJsonTx(json, fill); diff --git a/src/ripple/app/misc/impl/AmendmentTable.cpp b/src/ripple/app/misc/impl/AmendmentTable.cpp index 4542485294..10820e23ba 100644 --- a/src/ripple/app/misc/impl/AmendmentTable.cpp +++ b/src/ripple/app/misc/impl/AmendmentTable.cpp @@ -393,7 +393,7 @@ AmendmentTableImpl::doValidation ( } } - if (!amendments.empty()) + if (! amendments.empty()) std::sort (amendments.begin (), amendments.end ()); return amendments; @@ -402,26 +402,8 @@ AmendmentTableImpl::doValidation ( std::vector AmendmentTableImpl::getDesired () { - // Get the list of amendments we support and do not - // veto - std::vector amendments; - amendments.reserve (amendmentMap_.size()); - - { - std::lock_guard sl (mutex_); - for (auto const& e : amendmentMap_) - { - if (e.second.supported && ! e.second.vetoed) - { - amendments.push_back (e.first); - } - } - } - - if (!amendments.empty()) - std::sort (amendments.begin (), amendments.end ()); - - return amendments; + // Get the list of amendments we support and do not veto + return doValidation({}); } std::map diff --git a/src/ripple/rpc/handlers/LedgerData.cpp b/src/ripple/rpc/handlers/LedgerData.cpp index 56935eff43..89877012d2 100644 --- a/src/ripple/rpc/handlers/LedgerData.cpp +++ b/src/ripple/rpc/handlers/LedgerData.cpp @@ -48,15 +48,16 @@ Json::Value doLedgerData (RPC::Context& context) if (!lpLedger) return jvResult; - boost::optional key = ReadView::key_type(); - if (params.isMember (jss::marker)) + bool const isMarker = params.isMember (jss::marker); + ReadView::key_type key = ReadView::key_type(); + if (isMarker) { Json::Value const& jMarker = params[jss::marker]; - if (! (jMarker.isString () && key->SetHex (jMarker.asString ()))) + if (! (jMarker.isString () && key.SetHex (jMarker.asString ()))) return RPC::expected_field_error (jss::marker, "valid"); } - bool isBinary = params[jss::binary].asBool(); + bool const isBinary = params[jss::binary].asBool(); int limit = -1; if (params.isMember (jss::limit)) @@ -75,10 +76,18 @@ Json::Value doLedgerData (RPC::Context& context) jvResult[jss::ledger_hash] = to_string (lpLedger->info().hash); jvResult[jss::ledger_index] = lpLedger->info().seq; + if (! isMarker) + { + // Return base ledger data on first query + jvResult[jss::ledger] = getJson ( + LedgerFill (*lpLedger, isBinary ? + LedgerFill::Options::binary : 0)); + } + Json::Value& nodes = jvResult[jss::state]; auto e = lpLedger->sles.end(); - for (auto i = lpLedger->sles.upper_bound(*key); i != e; ++i) + for (auto i = lpLedger->sles.upper_bound(key); i != e; ++i) { auto sle = lpLedger->read(keylet::unchecked((*i)->key())); if (limit-- <= 0) diff --git a/src/test/ledger/SHAMapV2_test.cpp b/src/test/ledger/SHAMapV2_test.cpp index 8ec546680c..e3e383fea9 100644 --- a/src/test/ledger/SHAMapV2_test.cpp +++ b/src/test/ledger/SHAMapV2_test.cpp @@ -43,7 +43,6 @@ class SHAMapV2_test : public beast::unit_test::suite auto ledger = std::make_shared(create_genesis, config, - amendments_v, env.app().family()); BEAST_EXPECT(! getSHAMapV2 (ledger->info())); BEAST_EXPECT(ledger->stateMap().get_version() == SHAMap::version{1}); diff --git a/src/test/rpc/LedgerData_test.cpp b/src/test/rpc/LedgerData_test.cpp index 68f8c2ea65..8753321fa4 100644 --- a/src/test/rpc/LedgerData_test.cpp +++ b/src/test/rpc/LedgerData_test.cpp @@ -17,6 +17,7 @@ */ //============================================================================== +#include #include #include @@ -80,7 +81,8 @@ public: Json::Value jvParams; jvParams[jss::ledger_index] = "current"; jvParams[jss::binary] = false; - auto const jrr = env.rpc ( "json", "ledger_data", jvParams.toStyledString() ) [jss::result]; + auto const jrr = env.rpc ( "json", "ledger_data", + boost::lexical_cast(jvParams)) [jss::result]; BEAST_EXPECT( jrr[jss::ledger_current_index].isIntegral() && jrr[jss::ledger_current_index].asInt() > 0 ); @@ -91,7 +93,8 @@ public: for (auto delta = -1; delta <= 1; delta++) { jvParams[jss::limit] = max_limit + delta; - auto const jrr = env.rpc ( "json", "ledger_data", jvParams.toStyledString() ) [jss::result]; + auto const jrr = env.rpc ( "json", "ledger_data", + boost::lexical_cast(jvParams)) [jss::result]; BEAST_EXPECT( checkArraySize( jrr[jss::state], (delta > 0 && !as_admin) ? max_limit : max_limit + delta )); @@ -121,7 +124,8 @@ public: Json::Value jvParams; jvParams[jss::ledger_index] = "current"; jvParams[jss::binary] = true; - auto const jrr = env.rpc ( "json", "ledger_data", jvParams.toStyledString() ) [jss::result]; + auto const jrr = env.rpc ( "json", "ledger_data", + boost::lexical_cast(jvParams)) [jss::result]; BEAST_EXPECT( jrr[jss::ledger_current_index].isIntegral() && jrr[jss::ledger_current_index].asInt() > 0); @@ -144,7 +148,8 @@ public: // bad limit Json::Value jvParams; jvParams[jss::limit] = "0"; // NOT an integer - auto const jrr = env.rpc ( "json", "ledger_data", jvParams.toStyledString() ) [jss::result]; + auto const jrr = env.rpc ( "json", "ledger_data", + boost::lexical_cast(jvParams)) [jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); BEAST_EXPECT(jrr[jss::status] == "error"); BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'limit', not integer."); @@ -154,7 +159,8 @@ public: // invalid marker Json::Value jvParams; jvParams[jss::marker] = "NOT_A_MARKER"; - auto const jrr = env.rpc ( "json", "ledger_data", jvParams.toStyledString() ) [jss::result]; + auto const jrr = env.rpc ( "json", "ledger_data", + boost::lexical_cast(jvParams)) [jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); BEAST_EXPECT(jrr[jss::status] == "error"); BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'marker', not valid."); @@ -164,7 +170,8 @@ public: // invalid marker - not a string Json::Value jvParams; jvParams[jss::marker] = 1; - auto const jrr = env.rpc ( "json", "ledger_data", jvParams.toStyledString() ) [jss::result]; + auto const jrr = env.rpc ( "json", "ledger_data", + boost::lexical_cast(jvParams)) [jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); BEAST_EXPECT(jrr[jss::status] == "error"); BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'marker', not valid."); @@ -174,7 +181,8 @@ public: // ask for a bad ledger index Json::Value jvParams; jvParams[jss::ledger_index] = 10u; - auto const jrr = env.rpc ( "json", "ledger_data", jvParams.toStyledString() ) [jss::result]; + auto const jrr = env.rpc ( "json", "ledger_data", + boost::lexical_cast(jvParams)) [jss::result]; BEAST_EXPECT(jrr[jss::error] == "lgrNotFound"); BEAST_EXPECT(jrr[jss::status] == "error"); BEAST_EXPECT(jrr[jss::error_message] == "ledgerNotFound"); @@ -204,23 +212,75 @@ public: Json::Value jvParams; jvParams[jss::ledger_index] = "current"; jvParams[jss::binary] = false; - auto jrr = env.rpc ( "json", "ledger_data", jvParams.toStyledString() ) [jss::result]; + auto jrr = env.rpc ( "json", "ledger_data", + boost::lexical_cast(jvParams)) [jss::result]; auto const total_count = jrr[jss::state].size(); // now make request with a limit and loop until we get all jvParams[jss::limit] = 5; - jrr = env.rpc ( "json", "ledger_data", jvParams.toStyledString() ) [jss::result]; + jrr = env.rpc ( "json", "ledger_data", + boost::lexical_cast(jvParams)) [jss::result]; BEAST_EXPECT( checkMarker(jrr) ); auto running_total = jrr[jss::state].size(); while ( jrr.isMember(jss::marker) ) { jvParams[jss::marker] = jrr[jss::marker]; - jrr = env.rpc ( "json", "ledger_data", jvParams.toStyledString() ) [jss::result]; + jrr = env.rpc ( "json", "ledger_data", + boost::lexical_cast(jvParams)) [jss::result]; running_total += jrr[jss::state].size(); } BEAST_EXPECT( running_total == total_count ); } + void testLedgerHeader() + { + using namespace test::jtx; + Env env { *this }; + env.fund(XRP(100000), "alice"); + env.close(); + + // Ledger header should be present in the first query + { + // Closed ledger with non binary form + Json::Value jvParams; + jvParams[jss::ledger_index] = "closed"; + auto jrr = env.rpc("json", "ledger_data", + boost::lexical_cast(jvParams))[jss::result]; + if (BEAST_EXPECT(jrr.isMember(jss::ledger))) + BEAST_EXPECT(jrr[jss::ledger][jss::ledger_hash] == + to_string(env.closed()->info().hash)); + } + { + // Closed ledger with binary form + Json::Value jvParams; + jvParams[jss::ledger_index] = "closed"; + jvParams[jss::binary] = true; + auto jrr = env.rpc("json", "ledger_data", + boost::lexical_cast(jvParams))[jss::result]; + if (BEAST_EXPECT(jrr.isMember(jss::ledger))) + { + auto data = strUnHex( + jrr[jss::ledger][jss::ledger_data].asString()); + if (BEAST_EXPECT(data.second)) + { + Serializer s(data.first.data(), data.first.size()); + std::uint32_t seq = 0; + BEAST_EXPECT(s.getInteger(seq, 0)); + BEAST_EXPECT(seq == 3); + } + } + } + { + // Current ledger with binary form + Json::Value jvParams; + jvParams[jss::binary] = true; + auto jrr = env.rpc("json", "ledger_data", + boost::lexical_cast(jvParams))[jss::result]; + BEAST_EXPECT(jrr.isMember(jss::ledger)); + BEAST_EXPECT(! jrr[jss::ledger].isMember(jss::ledger_data)); + } + } + void run() { testCurrentLedgerToLimits(true); @@ -228,8 +288,8 @@ public: testCurrentLedgerBinary(); testBadInput(); testMarkerFollow(); + testLedgerHeader(); } - }; BEAST_DEFINE_TESTSUITE(LedgerData,app,ripple);