Fix Oracle's token pair deterministic order: (#5021)

Price Oracle data-series logic uses `unordered_map` to update the Oracle object.
This results in different servers disagreeing on the order of that hash table.
Consequently, the generated ledgers will have different hashes.
The fix uses `map` instead to guarantee the order of the token pairs
in the data-series.
This commit is contained in:
Gregory Tsipenyuk
2024-05-20 16:33:01 -04:00
committed by tequ
parent 447e6c6c1e
commit ea2e503ef8

View File

@@ -23,7 +23,6 @@
#include <ripple/ledger/View.h> #include <ripple/ledger/View.h>
#include <ripple/protocol/Feature.h> #include <ripple/protocol/Feature.h>
#include <ripple/protocol/InnerObjectFormats.h> #include <ripple/protocol/InnerObjectFormats.h>
#include <ripple/protocol/Rules.h>
#include <ripple/protocol/TxFlags.h> #include <ripple/protocol/TxFlags.h>
#include <ripple/protocol/digest.h> #include <ripple/protocol/digest.h>
@@ -97,10 +96,10 @@ SetOracle::preclaim(PreclaimContext const& ctx)
ctx.tx.getAccountID(sfAccount), ctx.tx[sfOracleDocumentID])); ctx.tx.getAccountID(sfAccount), ctx.tx[sfOracleDocumentID]));
// token pairs to add/update // token pairs to add/update
hash_set<std::pair<Currency, Currency>> pairs; std::set<std::pair<Currency, Currency>> pairs;
// token pairs to delete. if a token pair doesn't include // token pairs to delete. if a token pair doesn't include
// the price then this pair should be deleted from the object. // the price then this pair should be deleted from the object.
hash_set<std::pair<Currency, Currency>> pairsDel; std::set<std::pair<Currency, Currency>> pairsDel;
for (auto const& entry : ctx.tx.getFieldArray(sfPriceDataSeries)) for (auto const& entry : ctx.tx.getFieldArray(sfPriceDataSeries))
{ {
if (entry[sfBaseAsset] == entry[sfQuoteAsset]) if (entry[sfBaseAsset] == entry[sfQuoteAsset])
@@ -216,7 +215,7 @@ SetOracle::doApply()
// the token pair that doesn't have their price updated will not // the token pair that doesn't have their price updated will not
// include neither price nor scale in the updated PriceDataSeries // include neither price nor scale in the updated PriceDataSeries
hash_map<std::pair<Currency, Currency>, STObject> pairs; std::map<std::pair<Currency, Currency>, STObject> pairs;
// collect current token pairs // collect current token pairs
for (auto const& entry : sle->getFieldArray(sfPriceDataSeries)) for (auto const& entry : sle->getFieldArray(sfPriceDataSeries))
{ {