diff --git a/src/ripple/app/misc/NegativeUNLVote.cpp b/src/ripple/app/misc/NegativeUNLVote.cpp index d2fa4c121..a9dd477a4 100644 --- a/src/ripple/app/misc/NegativeUNLVote.cpp +++ b/src/ripple/app/misc/NegativeUNLVote.cpp @@ -113,44 +113,40 @@ NegativeUNLVote::addReportingTx( hash_map const& nidToKeyMap, std::shared_ptr const& initalSet) { + // RH NOTE: now that we use one key per txn with lots of txns + // this ordering step is probably not needed std::set ordered; - for (auto const& [n, score]: scoreTable) { if (score > (FLAG_LEDGER_INTERVAL>>1)) ordered.emplace(nidToKeyMap.at(n)); } - std::vector av; for (auto const& k : ordered) { - av.emplace_back(sfActiveValidator); - av.back().setFieldVL(sfPublicKey, k); - } + STTx repUnlTx(ttUNL_REPORT, [&](auto& obj) + { + obj.setFieldVL(sfPublicKey, k); + obj.setFieldU32(sfLedgerSequence, seq); + }); - STTx repUnlTx(ttUNL_REPORT, [&](auto& obj) - { - obj.setFieldArray(sfActiveValidators, STArray(av, sfActiveValidators)); - obj.setFieldU32(sfLedgerSequence, seq); - }); - - - uint256 txID = repUnlTx.getTransactionID(); - Serializer s; - repUnlTx.add(s); - if (!initalSet->addGiveItem( - SHAMapNodeType::tnTRANSACTION_NM, - std::make_shared(txID, s.slice()))) - { - JLOG(j_.warn()) << "R-UNL: ledger seq=" << seq - << ", add ttUNL_REPORT tx failed"; - } - else - { - JLOG(j_.debug()) << "R-UNL: ledger seq=" << seq - << ", add a ttUNL_REPORT Tx with txID: " << txID - << ", size=" << s.size() - << ", " << repUnlTx.getJson(JsonOptions::none); + uint256 txID = repUnlTx.getTransactionID(); + Serializer s; + repUnlTx.add(s); + if (!initalSet->addGiveItem( + SHAMapNodeType::tnTRANSACTION_NM, + std::make_shared(txID, s.slice()))) + { + JLOG(j_.warn()) << "R-UNL: ledger seq=" << seq + << ", add ttUNL_REPORT tx failed"; + } + else + { + JLOG(j_.debug()) << "R-UNL: ledger seq=" << seq + << ", add a ttUNL_REPORT Tx with txID: " << txID + << ", size=" << s.size() + << ", " << repUnlTx.getJson(JsonOptions::none); + } } } diff --git a/src/ripple/app/tx/impl/Change.cpp b/src/ripple/app/tx/impl/Change.cpp index 880e58f9e..36c5dcbb4 100644 --- a/src/ripple/app/tx/impl/Change.cpp +++ b/src/ripple/app/tx/impl/Change.cpp @@ -175,14 +175,44 @@ Change::applyUNLReport() { auto sle = view().peek(keylet::UNLReport()); + auto const seq = view().info().seq; + bool const created = !sle; if (created) sle = std::make_shared(keylet::UNLReport()); + + auto const avExisting = + (sle->isFieldPresent(sfPreviousTxnLgrSeq) && + sle->getFieldU32(sfPreviousTxnLgrSeq) < seq) + ? STArray(sfActiveValidators) + : sle->getFieldArray(sfActiveValidators); - auto const av = ctx_.tx.getFieldArray(sfActiveValidators); + // canonically order using std::set + std::set ordered; + for (auto const& obj: avExisting) + { + auto pk = obj.getFieldVL(sfPublicKey); + if (!publicKeyType(makeSlice(pk))) + continue; - sle->setFieldArray(sfActiveValidators, av); + ordered.emplace(PublicKey(makeSlice(pk))); + }; + + auto pk = ctx_.tx.getFieldVL(sfPublicKey); + if (publicKeyType(makeSlice(pk))) + ordered.emplace(PublicKey(makeSlice(pk))); + + std::vector av; + av.reserve(ordered.size()); + for (auto const& k: ordered) + { + av.emplace_back(sfActiveValidator); + av.back().setFieldVL(sfPublicKey, k); + } + + // update + sle->setFieldArray(sfActiveValidators, STArray(av, sfActiveValidators)); if (created) view().insert(sle); diff --git a/src/ripple/protocol/impl/SField.cpp b/src/ripple/protocol/impl/SField.cpp index dde05c710..2f0157eee 100644 --- a/src/ripple/protocol/impl/SField.cpp +++ b/src/ripple/protocol/impl/SField.cpp @@ -358,8 +358,8 @@ CONSTRUCT_UNTYPED_SFIELD(sfDisabledValidators, "DisabledValidators", ARRAY, CONSTRUCT_UNTYPED_SFIELD(sfHookExecutions, "HookExecutions", ARRAY, 18); CONSTRUCT_UNTYPED_SFIELD(sfHookParameters, "HookParameters", ARRAY, 19); CONSTRUCT_UNTYPED_SFIELD(sfHookGrants, "HookGrants", ARRAY, 20); -CONSTRUCT_UNTYPED_SFIELD(sfActiveValidators, "ActiveValidators", ARRAY, 95); CONSTRUCT_UNTYPED_SFIELD(sfGenesisMints, "GenesisMints", ARRAY, 96); +CONSTRUCT_UNTYPED_SFIELD(sfActiveValidators, "ActiveValidators", ARRAY, 95); // clang-format on diff --git a/src/ripple/protocol/impl/TxFormats.cpp b/src/ripple/protocol/impl/TxFormats.cpp index 3c3633d12..c31996ae5 100644 --- a/src/ripple/protocol/impl/TxFormats.cpp +++ b/src/ripple/protocol/impl/TxFormats.cpp @@ -196,7 +196,7 @@ TxFormats::TxFormats() ttUNL_REPORT, { {sfLedgerSequence, soeREQUIRED}, - {sfActiveValidators, soeREQUIRED}, + {sfPublicKey, soeREQUIRED}, }, commonFields);