#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace xrpl::test { class LedgerMaster_test : public beast::unit_test::suite { static std::unique_ptr makeNetworkConfig(uint32_t networkID) { using namespace jtx; return envconfig([&](std::unique_ptr cfg) { cfg->NETWORK_ID = networkID; // This test relies on ledger hash so must lock it to fee 10. cfg->FEES.reference_fee = 10; return cfg; }); } void testTxnIdFromIndex(FeatureBitset features) { testcase("tx_id_from_index"); using namespace test::jtx; using namespace std::literals; test::jtx::Env env{*this, makeNetworkConfig(11111)}; auto const alice = Account("alice"); env.fund(XRP(1000), alice); env.close(); // build ledgers std::vector> txns; std::vector> metas; auto const startLegSeq = env.current()->header().seq; for (int i = 0; i < 2; ++i) { env(noop(alice)); txns.emplace_back(env.tx()); env.close(); metas.emplace_back(env.closed()->txRead(env.tx()->getTransactionID()).second); } // add last (empty) ledger env.close(); auto const endLegSeq = env.closed()->header().seq; // test invalid range { std::uint32_t const ledgerSeq = -1; std::uint32_t const txnIndex = 0; auto result = env.app().getLedgerMaster().txnIdFromIndex(ledgerSeq, txnIndex); BEAST_EXPECT(!result); } // test not in ledger { uint32_t const txnIndex = metas[0]->getFieldU32(sfTransactionIndex); auto result = env.app().getLedgerMaster().txnIdFromIndex(0, txnIndex); BEAST_EXPECT(!result); } // test empty ledger { auto result = env.app().getLedgerMaster().txnIdFromIndex(endLegSeq, 0); BEAST_EXPECT(!result); } // ended without result { uint32_t const txnIndex = metas[0]->getFieldU32(sfTransactionIndex); auto result = env.app().getLedgerMaster().txnIdFromIndex(endLegSeq + 1, txnIndex); BEAST_EXPECT(!result); } // success (first tx) { uint32_t const txnIndex = metas[0]->getFieldU32(sfTransactionIndex); auto result = env.app().getLedgerMaster().txnIdFromIndex(startLegSeq, txnIndex); BEAST_EXPECT( // NOLINTNEXTLINE(bugprone-unchecked-optional-access) *result == uint256( "277F4FD89C20B92457FEF05FF63F6405563AD0563C73D967A29727" "72679ADC65")); } // success (second tx) { uint32_t const txnIndex = metas[1]->getFieldU32(sfTransactionIndex); auto result = env.app().getLedgerMaster().txnIdFromIndex(startLegSeq + 1, txnIndex); BEAST_EXPECT( // NOLINTNEXTLINE(bugprone-unchecked-optional-access) *result == uint256( "293DF7335EBBAF4420D52E70ABF470EB4C5792CAEA2F91F76193C2" "819F538FDE")); } } public: void run() override { using namespace test::jtx; FeatureBitset const all{testable_amendments()}; testWithFeats(all); } void testWithFeats(FeatureBitset features) { testTxnIdFromIndex(features); } }; BEAST_DEFINE_TESTSUITE(LedgerMaster, app, xrpl); } // namespace xrpl::test