From ede561cea37ca80de8a5dcb2a54472129503aae5 Mon Sep 17 00:00:00 2001 From: Richard Holland Date: Tue, 29 Aug 2023 13:04:24 +0000 Subject: [PATCH] add tfTestSuite flag to ttEnableAmendment to allow governance game to be installed with test accounts --- src/ripple/app/tx/impl/Change.cpp | 60 ++++++++++++++-------- src/ripple/app/tx/impl/XahauGenesis.h | 7 +++ src/ripple/protocol/TxFlags.h | 1 + src/test/app/XahauGenesis_test.cpp | 73 +++++++++------------------ 4 files changed, 73 insertions(+), 68 deletions(-) diff --git a/src/ripple/app/tx/impl/Change.cpp b/src/ripple/app/tx/impl/Change.cpp index 89907f7d1..1e552cf0d 100644 --- a/src/ripple/app/tx/impl/Change.cpp +++ b/src/ripple/app/tx/impl/Change.cpp @@ -294,32 +294,48 @@ normalizeXahauGenesis( uint8_t mc = 0; for (auto const& [rn, x]: entries) { - if (rn.c_str()[0] != 'n') - { - amounts.emplace(rn, x); - continue; - } + auto getID = [](std::string const& rn) -> std::optional> + { + if (rn.c_str()[0] == 'r') + { + auto parsed = parseBase58(rn); + if (!parsed) + return {}; + return {{toBase58(*parsed), *parsed}}; + } + + if (rn.c_str()[0] == 'n') + { + auto const parsed = parseBase58(TokenType::NodePublic, rn); + if (!parsed) + return {}; + AccountID id = calcAccountID(*parsed); + return {{toBase58(id), id}}; + } + + return {}; + }; - auto const pk = parseBase58(TokenType::NodePublic, rn); - if (!pk) + if (auto parsed = getID(rn); parsed) { + std::string& idStr = parsed->first; + AccountID& id = parsed->second; + + amounts.emplace(idStr, x); JLOG(j.warn()) - << "featureXahauGenesis could not parse nodepub: " << rn; + << "featureXahauGenesis: " + << "initial validator: " << rn + << " =>accid: " << idStr; + + // initial member enumeration + params.emplace( + std::vector{'I', 'S', mc++}, + std::vector(id.data(), id.data() + 20)); continue; } - AccountID id = calcAccountID(*pk); - std::string idStr = toBase58(id); - amounts.emplace(idStr, x); JLOG(j.warn()) - << "featureXahauGenesis: " - << "initial validator: " << rn - << " =>accid: " << idStr; - - // initial member enumeration - params.emplace( - std::vector{'I', 'S', mc++}, - std::vector(id.data(), id.data() + 20)); + << "featureXahauGenesis could not parse distribution address: " << rn; } // initial member count @@ -339,7 +355,11 @@ Change::activateXahauGenesis() using namespace XahauGenesis; auto [initial_distribution, gov_params] = - normalizeXahauGenesis(Distribution, GovernanceParameters, j_); + normalizeXahauGenesis( + ctx_.tx.getFlags() & tfTestSuite + ? TestDistribution + : Distribution, + GovernanceParameters, j_); const static std::vector< std::tuple< diff --git a/src/ripple/app/tx/impl/XahauGenesis.h b/src/ripple/app/tx/impl/XahauGenesis.h index 8387d8474..a43c08355 100644 --- a/src/ripple/app/tx/impl/XahauGenesis.h +++ b/src/ripple/app/tx/impl/XahauGenesis.h @@ -26,6 +26,13 @@ namespace XahauGenesis {"nHUubQ7fqxkwPtwS4pQb2ENZ6fdUcAt7aJRiYcPXjxbbkC778Zjk", InfraAmount}, }; + // this data structure is used for testing the amendment only, + // if the ttEnableAmendment has an optional flag (that cannot be added in production) + // then whatever is in this array is used + inline + std::map + TestDistribution; + // For the Governance Hook: HookOn is set to ttINVOKE only inline diff --git a/src/ripple/protocol/TxFlags.h b/src/ripple/protocol/TxFlags.h index c37b8ca49..1d9a60c4b 100644 --- a/src/ripple/protocol/TxFlags.h +++ b/src/ripple/protocol/TxFlags.h @@ -115,6 +115,7 @@ constexpr std::uint32_t tfTrustSetMask = // EnableAmendment flags: constexpr std::uint32_t tfGotMajority = 0x00010000; constexpr std::uint32_t tfLostMajority = 0x00020000; +constexpr std::uint32_t tfTestSuite = 0x80000000; // PaymentChannelClaim flags: constexpr std::uint32_t tfRenew = 0x00010000; diff --git a/src/test/app/XahauGenesis_test.cpp b/src/test/app/XahauGenesis_test.cpp index 478c16417..b8f95a7c9 100644 --- a/src/test/app/XahauGenesis_test.cpp +++ b/src/test/app/XahauGenesis_test.cpp @@ -33,15 +33,16 @@ struct XahauGenesis_test : public beast::unit_test::suite { + AccountID const genesisAccID = calcAccountID( + generateKeyPair(KeyType::secp256k1, generateSeed("masterpassphrase")) + .first); + // the test cases in this test suite are based on changing the state of the ledger before // xahaugenesis is activated, to do this they call this templated function with an "execute-first" lambda void - activate(jtx::Env& env, bool burnedViaTest = false, bool skipTests = false) + activate(jtx::Env& env, bool burnedViaTest = false, bool skipTests = false, bool testFlag = false) { using namespace jtx; - AccountID const genesisAccID = calcAccountID( - generateKeyPair(KeyType::secp256k1, generateSeed("masterpassphrase")) - .first); auto isEnabled = [&](void)->bool { @@ -59,12 +60,14 @@ struct XahauGenesis_test : public beast::unit_test::suite // insert a ttAMENDMENT pseudo into the open ledger env.app().openLedger().modify( - [&](OpenView& view, beast::Journal j) -> bool { - + [&](OpenView& view, beast::Journal j) -> bool + { STTx tx (ttAMENDMENT, [&](auto& obj) { obj.setAccountID(sfAccount, AccountID()); obj.setFieldH256(sfAmendment, featureXahauGenesis); obj.setFieldU32(sfLedgerSequence, startLgr); + if (testFlag) + obj.setFieldU32(sfFlags, tfTestSuite); }); uint256 txID = tx.getTransactionID(); @@ -196,11 +199,10 @@ struct XahauGenesis_test : public beast::unit_test::suite std::vector{'I', 'M', 'C'}, std::vector{member_count}); - // check parameters - BEAST_REQUIRE(genesisHookArray[0].isFieldPresent(sfHookParameters)); auto leParams = genesisHookArray[0].getFieldArray(sfHookParameters); BEAST_EXPECT(leParams.size() == params.size()); + // these should be recorded in the same order std::set> keys_used; for (auto& param : leParams) @@ -245,7 +247,8 @@ struct XahauGenesis_test : public beast::unit_test::suite testcase("Test activation"); using namespace jtx; Env env{*this, envconfig(), supported_amendments() - featureXahauGenesis, nullptr, - beast::severities::kTrace + beast::severities::kWarning + //beast::severities::kTrace }; activate(env); @@ -257,7 +260,8 @@ struct XahauGenesis_test : public beast::unit_test::suite using namespace jtx; testcase("Test signerlist"); Env env{*this, envconfig(), supported_amendments() - featureXahauGenesis, nullptr, - beast::severities::kTrace + beast::severities::kWarning + //beast::severities::kTrace }; Account const alice{"alice", KeyType::ed25519}; @@ -275,7 +279,8 @@ struct XahauGenesis_test : public beast::unit_test::suite using namespace jtx; testcase("Test regkey"); Env env{*this, envconfig(), supported_amendments() - featureXahauGenesis, nullptr, - beast::severities::kTrace + beast::severities::kWarning + //beast::severities::kTrace }; env.memoize(env.master); @@ -295,54 +300,26 @@ struct XahauGenesis_test : public beast::unit_test::suite auto const invoker = Account("invoker"); env.fund(XRP(10000), invoker); + env.close(); - activate(env, true, true); + XahauGenesis::TestDistribution.clear(); - AccountID const genesisAccID = calcAccountID( - generateKeyPair(KeyType::secp256k1, generateSeed("masterpassphrase")) - .first); - - // gov hook is installed but not yet activated, so we can still change the parameters - auto hookSLE = env.le(keylet::hook(genesisAccID)); - SLE& hooks = const_cast(*hookSLE); - STArray hooksArray = hooks.getFieldArray(sfHookParameters); - - // keep first two entries - auto it = hooksArray.begin(); - it++; it++; - // erase further entries - hooksArray.erase(it, hooksArray.end()); - - // add participants - uint8_t mc = 0; - for (AccountID const& id : members) + for (auto& m: members) { - STObject param(sfHookParameter); - param.setFieldVL(sfHookParameterName, std::vector{'I', 'S', mc}); - param.setFieldVL(sfHookParameterValue, std::vector(id.data(), id.data() + 20)); - hooksArray[mc + 2] = param; - mc++; + std::string acc = toBase58(m); + XahauGenesis::TestDistribution[acc] = XRPAmount(10000); } - STObject param(sfHookParameter); - param.setFieldVL(sfHookParameterName, std::vector{'I', 'M', 'C'}); - param.setFieldVL(sfHookParameterValue, std::vector{mc}); - hooksArray[mc + 2] = param; + activate(env, true, true, true); - hooks.setFieldArray(sfHooks, hooksArray); - - env.app().openLedger().modify([&](OpenView& view, beast::Journal) - { - view.rawReplace(std::make_shared(*hookSLE)); - return true; - }); - - env.close(); + XahauGenesis::TestDistribution.clear(); Json::Value invoke; invoke[jss::TransactionType] = "Invoke"; invoke[jss::Account] = invoker.human(); + invoke[jss::Destination] = env.master.human(); env(invoke, fee(XRP(1))); + env.close(); } void