diff --git a/src/ripple/app/tx/impl/Import.cpp b/src/ripple/app/tx/impl/Import.cpp index 7527f5683..98d13ba4b 100644 --- a/src/ripple/app/tx/impl/Import.cpp +++ b/src/ripple/app/tx/impl/Import.cpp @@ -1169,10 +1169,11 @@ Import::doApply() // get xahau genesis start ledger, or just assume the current ledger is the start seq if it's not set. uint32_t curLgrSeq = view().info().seq; uint32_t startLgrSeq = curLgrSeq; - auto sleFees = view().read(keylet::fees()); + auto sleFees = view().peek(keylet::fees()); if (sleFees && sleFees->isFieldPresent(sfXahauActivationLgrSeq)) startLgrSeq = sleFees->getFieldU32(sfXahauActivationLgrSeq); + uint32_t elapsed = curLgrSeq - startLgrSeq; bool const create = !sle; @@ -1234,6 +1235,12 @@ Import::doApply() sle->setFieldU32(sfSequence, seqno); sle->setFieldU32(sfOwnerCount, 0); + if (sleFees) + { + uint64_t accIdx = sleFees->isFieldPresent(sfAccountCount) ? sleFees->getFieldU64(sfAccountCount) : 0; + sle->setFieldU64(sfAccountIndex, accIdx); + sleFees->setFieldU64(sfAccountCount, accIdx + 1); + } if (ctx_.tx.getSigningPubKey().empty() || calcAccountID(PublicKey(makeSlice(ctx_.tx.getSigningPubKey()))) != id) @@ -1249,7 +1256,11 @@ Import::doApply() sle->setFieldAmount(sfBalance, finalBal); if (create) + { view().insert(sle); + if (sleFees) + view().update(sleFees); + } else view().update(sle); diff --git a/src/ripple/app/tx/impl/Payment.cpp b/src/ripple/app/tx/impl/Payment.cpp index f0f9a8eab..3de724149 100644 --- a/src/ripple/app/tx/impl/Payment.cpp +++ b/src/ripple/app/tx/impl/Payment.cpp @@ -343,6 +343,15 @@ Payment::doApply() sleDst->setAccountID(sfAccount, uDstAccountID); sleDst->setFieldU32(sfSequence, seqno); + auto sleFees = view().peek(keylet::fees()); + if (sleFees) + { + auto actIdx = sleFees->isFieldPresent(sfAccountCount) ? sleFees->getFieldU64(sfAccountCount) : 0; + sleDst->setFieldU64(sfAccountIndex, actIdx); + sleFees->setFieldU64(sfAccountCount, actIdx + 1); + view().update(sleFees); + } + view().insert(sleDst); } else diff --git a/src/ripple/protocol/SField.h b/src/ripple/protocol/SField.h index 75bc3a99c..cd5dda504 100644 --- a/src/ripple/protocol/SField.h +++ b/src/ripple/protocol/SField.h @@ -431,6 +431,8 @@ extern SF_UINT64 const sfHookInstructionCount; extern SF_UINT64 const sfHookReturnCode; extern SF_UINT64 const sfReferenceCount; extern SF_UINT64 const sfRewardAccumulator; +extern SF_UINT64 const sfAccountCount; +extern SF_UINT64 const sfAccountIndex; // 128-bit extern SF_UINT128 const sfEmailHash; diff --git a/src/ripple/protocol/impl/LedgerFormats.cpp b/src/ripple/protocol/impl/LedgerFormats.cpp index 838e307f8..55e2a4c5d 100644 --- a/src/ripple/protocol/impl/LedgerFormats.cpp +++ b/src/ripple/protocol/impl/LedgerFormats.cpp @@ -65,6 +65,7 @@ LedgerFormats::LedgerFormats() {sfImportSequence, soeOPTIONAL}, {sfGovernanceFlags, soeOPTIONAL}, {sfGovernanceMarks, soeOPTIONAL}, + {sfAccountIndex, soeOPTIONAL}, }, commonFields); @@ -178,6 +179,7 @@ LedgerFormats::LedgerFormats() {sfReserveBaseDrops, soeOPTIONAL}, {sfReserveIncrementDrops, soeOPTIONAL}, {sfXahauActivationLgrSeq, soeOPTIONAL}, + {sfAccountCount, soeOPTIONAL}, }, commonFields); diff --git a/src/ripple/protocol/impl/SField.cpp b/src/ripple/protocol/impl/SField.cpp index c5d47dc78..889885442 100644 --- a/src/ripple/protocol/impl/SField.cpp +++ b/src/ripple/protocol/impl/SField.cpp @@ -183,6 +183,8 @@ CONSTRUCT_TYPED_SFIELD(sfEmitBurden, "EmitBurden", UINT64, CONSTRUCT_TYPED_SFIELD(sfHookInstructionCount, "HookInstructionCount", UINT64, 17); CONSTRUCT_TYPED_SFIELD(sfHookReturnCode, "HookReturnCode", UINT64, 18); CONSTRUCT_TYPED_SFIELD(sfReferenceCount, "ReferenceCount", UINT64, 19); +CONSTRUCT_TYPED_SFIELD(sfAccountIndex, "AccountIndex", UINT64, 98); +CONSTRUCT_TYPED_SFIELD(sfAccountCount, "AccountCount", UINT64, 99); CONSTRUCT_TYPED_SFIELD(sfRewardAccumulator, "RewardAccumulator", UINT64, 100); // 128-bit diff --git a/src/test/app/XahauGenesis_test.cpp b/src/test/app/XahauGenesis_test.cpp index 8a8a29383..d4ad4f93f 100644 --- a/src/test/app/XahauGenesis_test.cpp +++ b/src/test/app/XahauGenesis_test.cpp @@ -36,7 +36,7 @@ struct XahauGenesis_test : public beast::unit_test::suite { testcase("Test activation"); using namespace jtx; - Env env{*this, envconfig(), supported_amendments() - featureXahauGenesis, nullptr, + Env env{*this, envconfig(), supported_amendments() - featureXahauGenesis, nullptr, beast::severities::kTrace }; @@ -46,29 +46,29 @@ struct XahauGenesis_test : public beast::unit_test::suite if (!obj) return false; STVector256 amendments = obj->getFieldV256(sfAmendments); - return + return std::find(amendments.begin(), amendments.end(), featureXahauGenesis) != amendments.end(); }; BEAST_EXPECT(!isEnabled()); - - // insert a ttAMENDMENT pseudo into the open ledger + + // insert a ttAMENDMENT pseudo into the open ledger env.app().openLedger().modify( [&](OpenView& view, beast::Journal j) -> bool { - + STTx tx (ttAMENDMENT, [&](auto& obj) { obj.setAccountID(sfAccount, AccountID()); obj.setFieldH256(sfAmendment, featureXahauGenesis); obj.setFieldU32(sfLedgerSequence, env.app().getLedgerMaster().getClosedLedger()->info().seq + 1); }); - + uint256 txID = tx.getTransactionID(); auto s = std::make_shared(); tx.add(*s); env.app().getHashRouter().setFlags(txID, SF_PRIVATE2); view.rawTxInsert(txID, std::move(s), nullptr); - - return true; + + return true; }); // close the ledger @@ -92,7 +92,7 @@ struct XahauGenesis_test : public beast::unit_test::suite } BEAST_EXPECT(!!id); - + auto const root = env.le(keylet::account(*id)); BEAST_EXPECT(root); @@ -104,8 +104,72 @@ struct XahauGenesis_test : public beast::unit_test::suite BEAST_EXPECT(env.app().getLedgerMaster().getClosedLedger()->info().drops == total); + // ensure the definitions are correctly set + { + auto const govHash = ripple::sha512Half_s(ripple::Slice(GovernanceHook.data(), GovernanceHook.size())); + auto const govKL = keylet::hookDefinition(govHash); + auto govSLE = env.le(govKL); + + std::cout << "01\n"; + BEAST_EXPECT(!!govSLE); + std::cout << "02\n"; + BEAST_EXPECT(govSLE->getFieldH256(sfHookHash) == govHash); + + auto const govVL = govSLE->getFieldVL(sfCreateCode); + std::cout << "03\n"; + BEAST_EXPECT(govHash == ripple::sha512Half_s(ripple::Slice(govVL.data(), govVL.size()))); + std::cout << "04\n"; + BEAST_EXPECT(govSLE->getFieldU64(sfReferenceCount) == 1); + std::cout << "05\n"; + BEAST_EXPECT(govSLE->getFieldH256(sfHookOn) == + ripple::uint256("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFFFFFFBFFFFF")); + std::cout << "06\n"; + BEAST_EXPECT(govSLE->getFieldH256(sfHookNamespace) == + ripple::uint256("0000000000000000000000000000000000000000000000000000000000000001")); + std::cout << "07\n"; + BEAST_EXPECT(govSLE->getFieldU16(sfHookApiVersion) == 0); + auto const govFee = govSLE->getFieldAmount(sfFee); + + std::cout << "08\n"; + BEAST_EXPECT(isXRP(govFee) && govFee > beast::zero); + std::cout << "09\n"; + BEAST_EXPECT(!govSLE->isFieldPresent(sfHookCallbackFee)); + std::cout << "10\n"; + BEAST_EXPECT(govSLE->getFieldH256(sfHookSetTxnID) != beast::zero); + + auto const rwdHash = ripple::sha512Half_s(ripple::Slice(RewardHook.data(), RewardHook.size())); + auto const rwdKL = keylet::hookDefinition(rwdHash); + auto rwdSLE = env.le(rwdKL); + + std::cout << "11\n"; + BEAST_EXPECT(!!rwdSLE); + std::cout << "12\n"; + BEAST_EXPECT(rwdSLE->getFieldH256(sfHookHash) == rwdHash); + + auto const rwdVL = rwdSLE->getFieldVL(sfCreateCode); + std::cout << "13\n"; + BEAST_EXPECT(rwdHash == ripple::sha512Half_s(ripple::Slice(rwdVL.data(), rwdVL.size()))); + std::cout << "14\n"; + BEAST_EXPECT(rwdSLE->getFieldU64(sfReferenceCount) == 1); + std::cout << "15\n"; + BEAST_EXPECT(rwdSLE->getFieldH256(sfHookOn) == + ripple::uint256("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFFFFFFBFFFFF")); + std::cout << "16\n"; + BEAST_EXPECT(rwdSLE->getFieldH256(sfHookNamespace) == + ripple::uint256("0000000000000000000000000000000000000000000000000000000000000010")); + std::cout << "17\n"; + BEAST_EXPECT(rwdSLE->getFieldU16(sfHookApiVersion) == 0); + auto const rwdFee = rwdSLE->getFieldAmount(sfFee); + std::cout << "18\n"; + BEAST_EXPECT(isXRP(rwdFee) && rwdFee > beast::zero); + std::cout << "19\n"; + BEAST_EXPECT(!rwdSLE->isFieldPresent(sfHookCallbackFee)); + std::cout << "20\n"; + BEAST_EXPECT(rwdSLE->getFieldH256(sfHookSetTxnID) != beast::zero); + std::cout << "21\n"; + } + // RH TODO: - // check hookdefinitions // check hookparameters // check wasm hash // check gensis hooks array