diff --git a/src/ripple/app/misc/NetworkOPs.cpp b/src/ripple/app/misc/NetworkOPs.cpp index 73719c4a96..cae1b6163f 100644 --- a/src/ripple/app/misc/NetworkOPs.cpp +++ b/src/ripple/app/misc/NetworkOPs.cpp @@ -2009,6 +2009,15 @@ NetworkOPsImp::pubValidation(std::shared_ptr const& val) jvObj[jss::signing_time] = *(*val)[~sfSigningTime]; jvObj[jss::data] = strHex(val->getSerializer().slice()); + if (auto version = (*val)[~sfServerVersion]) + jvObj[jss::server_version] = std::to_string(*version); + + if (auto cookie = (*val)[~sfCookie]) + jvObj[jss::cookie] = std::to_string(*cookie); + + if (auto hash = (*val)[~sfValidatedHash]) + jvObj[jss::validated_hash] = strHex(*hash); + auto const masterKey = app_.validatorManifests().getMasterKey(signerPublic); diff --git a/src/ripple/protocol/jss.h b/src/ripple/protocol/jss.h index b9b782a6a2..1b0c4793aa 100644 --- a/src/ripple/protocol/jss.h +++ b/src/ripple/protocol/jss.h @@ -178,6 +178,7 @@ JSS(complete_shards); // out: OverlayImpl, PeerImp JSS(consensus); // out: NetworkOPs, LedgerConsensus JSS(converge_time); // out: NetworkOPs JSS(converge_time_s); // out: NetworkOPs +JSS(cookie); // out: NetworkOPs JSS(count); // in: AccountTx*, ValidatorList JSS(counters); // in/out: retrieve counters JSS(currentShard); // out: NodeToShardStatus @@ -498,6 +499,7 @@ JSS(server_domain); // out: NetworkOPs JSS(server_state); // out: NetworkOPs JSS(server_state_duration_us); // out: NetworkOPs JSS(server_status); // out: NetworkOPs +JSS(server_version); // out: NetworkOPs JSS(settle_delay); // out: AccountChannels JSS(severity); // in: LogLevel JSS(shards); // in/out: GetCounts, DownloadShard @@ -587,6 +589,7 @@ JSS(validated); // out: NetworkOPs, RPCHelpers, AccountTx* JSS(validator_list_expires); // out: NetworkOps, ValidatorList JSS(validator_list); // out: NetworkOps, ValidatorList JSS(validators); +JSS(validated_hash); // out: NetworkOPs JSS(validated_ledger); // out: NetworkOPs JSS(validated_ledger_index); // out: SubmitTransaction JSS(validated_ledgers); // out: NetworkOPs diff --git a/src/test/rpc/Subscribe_test.cpp b/src/test/rpc/Subscribe_test.cpp index 3e1916caf4..65a85ef25e 100644 --- a/src/test/rpc/Subscribe_test.cpp +++ b/src/test/rpc/Subscribe_test.cpp @@ -365,24 +365,68 @@ public: } { - // Accept a ledger - env.close(); + // Lambda to check ledger validations from the stream. + auto validValidationFields = [&env, &valPublicKey]( + Json::Value const& jv) { + if (jv[jss::type] != "validationReceived") + return false; - // Check stream update - using namespace std::chrono_literals; + if (jv[jss::validation_public_key].asString() != valPublicKey) + return false; - BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - return jv[jss::type] == "validationReceived" && - jv[jss::validation_public_key].asString() == valPublicKey && - jv[jss::ledger_hash] == - to_string(env.closed()->info().hash) && - jv[jss::ledger_index] == - std::to_string(env.closed()->info().seq) && - jv[jss::flags] == - (vfFullyCanonicalSig | vfFullValidation) && - jv[jss::full] == true && !jv.isMember(jss::load_fee) && - jv[jss::signature] && jv[jss::signing_time]; - })); + if (jv[jss::ledger_hash] != + to_string(env.closed()->info().hash)) + return false; + + if (jv[jss::ledger_index] != + std::to_string(env.closed()->info().seq)) + return false; + + if (jv[jss::flags] != (vfFullyCanonicalSig | vfFullValidation)) + return false; + + if (jv[jss::full] != true) + return false; + + if (jv.isMember(jss::load_fee)) + return false; + + if (!jv.isMember(jss::signature)) + return false; + + if (!jv.isMember(jss::signing_time)) + return false; + + if (!jv.isMember(jss::cookie)) + return false; + + if (!jv.isMember(jss::validated_hash)) + return false; + + // Certain fields are only added on a flag ledger. + bool const isFlagLedger = + (env.closed()->info().seq + 1) % 256 == 0; + + if (jv.isMember(jss::server_version) != isFlagLedger) + return false; + + if (jv.isMember(jss::reserve_base) != isFlagLedger) + return false; + + if (jv.isMember(jss::reserve_inc) != isFlagLedger) + return false; + + return true; + }; + + // Check stream update. Look at enough stream entries so we see + // at least one flag ledger. + while (env.closed()->info().seq < 300) + { + env.close(); + using namespace std::chrono_literals; + BEAST_EXPECT(wsc->findMsg(5s, validValidationFields)); + } } // RPC unsubscribe