From 9217802ad69dfa9d27175dde137c4a83ba88c096 Mon Sep 17 00:00:00 2001 From: tequ Date: Fri, 15 Nov 2024 19:55:33 +0900 Subject: [PATCH 1/4] HookEmit --- src/ripple/app/hook/applyHook.h | 5 ++ src/ripple/app/hook/impl/applyHook.cpp | 18 ++++++ src/ripple/app/tx/impl/SetHook.cpp | 58 +++++++++++++++++-- src/ripple/app/tx/impl/SetHook.h | 2 +- src/ripple/app/tx/impl/Transactor.cpp | 24 ++++++++ src/ripple/protocol/Feature.h | 3 +- src/ripple/protocol/SField.h | 1 + src/ripple/protocol/impl/Feature.cpp | 1 + .../protocol/impl/InnerObjectFormats.cpp | 2 + src/ripple/protocol/impl/LedgerFormats.cpp | 3 +- src/ripple/protocol/impl/SField.cpp | 1 + src/test/app/SetHook_test.cpp | 26 ++++++--- 12 files changed, 126 insertions(+), 18 deletions(-) diff --git a/src/ripple/app/hook/applyHook.h b/src/ripple/app/hook/applyHook.h index c81514fe42..571a0c6ff1 100644 --- a/src/ripple/app/hook/applyHook.h +++ b/src/ripple/app/hook/applyHook.h @@ -428,6 +428,9 @@ namespace hook { bool canHook(ripple::TxType txType, ripple::uint256 hookOn); +bool +canEmit(ripple::TxType txType, ripple::uint256 hookEmit); + struct HookResult; HookResult @@ -436,6 +439,7 @@ apply( used for caching (one day) */ ripple::uint256 const& hookHash, /* hash of the actual hook byte code, used for metadata */ + ripple::uint256 const& hookEmit, ripple::uint256 const& hookNamespace, ripple::Blob const& wasm, std::map< @@ -472,6 +476,7 @@ struct HookResult { ripple::uint256 const hookSetTxnID; ripple::uint256 const hookHash; + ripple::uint256 const hookEmit; ripple::Keylet const accountKeylet; ripple::Keylet const ownerDirKeylet; ripple::Keylet const hookKeylet; diff --git a/src/ripple/app/hook/impl/applyHook.cpp b/src/ripple/app/hook/impl/applyHook.cpp index abd7ef1361..17ca81f31e 100644 --- a/src/ripple/app/hook/impl/applyHook.cpp +++ b/src/ripple/app/hook/impl/applyHook.cpp @@ -1028,6 +1028,12 @@ hook::canHook(ripple::TxType txType, ripple::uint256 hookOn) return (hookOn & UINT256_BIT[txType]) != beast::zero; } +bool +hook::canEmit(ripple::TxType txType, ripple::uint256 hookEmit) +{ + return hook::canHook(txType, hookEmit); +} + // Update HookState ledger objects for the hook... only called after accept() // assumes the specified acc has already been checked for authoriation (hook // grants) @@ -1179,6 +1185,7 @@ hook::apply( used for caching (one day) */ ripple::uint256 const& hookHash, /* hash of the actual hook byte code, used for metadata */ + ripple::uint256 const& hookEmit, ripple::uint256 const& hookNamespace, ripple::Blob const& wasm, std::map< @@ -1206,6 +1213,7 @@ hook::apply( .result = {.hookSetTxnID = hookSetTxnID, .hookHash = hookHash, + .hookEmit = hookEmit, .accountKeylet = keylet::account(account), .ownerDirKeylet = keylet::ownerDir(account), .hookKeylet = keylet::hook(account), @@ -3269,6 +3277,16 @@ DEFINE_HOOK_FUNCTION( return EMISSION_FAILURE; } + ripple::TxType txType = stpTrans->getTxnType(); + + ripple::uint256 const& hookEmit = hookCtx.result.hookEmit; + if (!hook::canEmit(txType, hookEmit)) + { + JLOG(j.trace()) << "HookEmit[" << HC_ACC() + << "]: Hook cannot emit this txn."; + return EMISSION_FAILURE; + } + // check the emitted txn is valid /* Emitted TXN rules * 0. Account must match the hook account diff --git a/src/ripple/app/tx/impl/SetHook.cpp b/src/ripple/app/tx/impl/SetHook.cpp index aac02753c3..7e3e2bee70 100644 --- a/src/ripple/app/tx/impl/SetHook.cpp +++ b/src/ripple/app/tx/impl/SetHook.cpp @@ -205,7 +205,7 @@ validateHookParams(SetHookCtx& ctx, STArray const& hookParams) // infer which operation the user is attempting to execute from the present and // absent fields HookSetOperation -SetHook::inferOperation(STObject const& hookSetObj) +SetHook::inferOperation(SetHookCtx& ctx, STObject const& hookSetObj) { uint64_t wasmByteCount = hookSetObj.isFieldPresent(sfCreateCode) ? hookSetObj.getFieldVL(sfCreateCode).size() @@ -225,6 +225,8 @@ SetHook::inferOperation(STObject const& hookSetObj) !hookSetObj.isFieldPresent(sfHookNamespace) && !hookSetObj.isFieldPresent(sfHookParameters) && !hookSetObj.isFieldPresent(sfHookOn) && + (!ctx.rules.enabled(featureHookEmit) || + !hookSetObj.isFieldPresent(sfHookEmit)) && !hookSetObj.isFieldPresent(sfHookApiVersion) && !hookSetObj.isFieldPresent(sfFlags)) return hsoNOOP; @@ -248,7 +250,7 @@ SetHook::validateHookSetEntry(SetHookCtx& ctx, STObject const& hookSetObj) ? hookSetObj.getFieldU32(sfFlags) : 0; - switch (inferOperation(hookSetObj)) + switch (inferOperation(ctx, hookSetObj)) { case hsoNOOP: { return true; @@ -259,6 +261,8 @@ SetHook::validateHookSetEntry(SetHookCtx& ctx, STObject const& hookSetObj) if (hookSetObj.isFieldPresent(sfHookGrants) || hookSetObj.isFieldPresent(sfHookParameters) || hookSetObj.isFieldPresent(sfHookOn) || + (ctx.rules.enabled(featureHookEmit) && + hookSetObj.isFieldPresent(sfHookEmit)) || hookSetObj.isFieldPresent(sfHookApiVersion) || !hookSetObj.isFieldPresent(sfFlags) || !hookSetObj.isFieldPresent(sfHookNamespace)) @@ -288,6 +292,8 @@ SetHook::validateHookSetEntry(SetHookCtx& ctx, STObject const& hookSetObj) if (hookSetObj.isFieldPresent(sfHookGrants) || hookSetObj.isFieldPresent(sfHookParameters) || hookSetObj.isFieldPresent(sfHookOn) || + (ctx.rules.enabled(featureHookEmit) && + hookSetObj.isFieldPresent(sfHookEmit)) || hookSetObj.isFieldPresent(sfHookApiVersion) || hookSetObj.isFieldPresent(sfHookNamespace) || !hookSetObj.isFieldPresent(sfFlags)) @@ -452,6 +458,9 @@ SetHook::validateHookSetEntry(SetHookCtx& ctx, STObject const& hookSetObj) return false; } + // validate sfHookEmit + // HookEmit field is an optional field for backward compatibility + // finally validate web assembly byte code { if (!hookSetObj.isFieldPresent(sfCreateCode)) @@ -720,7 +729,8 @@ SetHook::preflight(PreflightContext const& ctx) if (name != sfCreateCode && name != sfHookHash && name != sfHookNamespace && name != sfHookParameters && name != sfHookOn && name != sfHookGrants && - name != sfHookApiVersion && name != sfFlags) + name != sfHookApiVersion && name != sfFlags && + (!ctx.rules.enabled(featureHookEmit) || name != sfHookEmit)) { JLOG(ctx.j.trace()) << "HookSet(" << hook::log::HOOK_INVALID_FIELD << ")[" @@ -1221,6 +1231,10 @@ SetHook::setHook() std::optional newHookOn; std::optional defHookOn; + std::optional oldHookEmit; + std::optional newHookEmit; + std::optional defHookEmit; + // when hsoCREATE is invoked it populates this variable in case the hook // definition already exists and the operation falls through into a // hsoINSTALL operation instead @@ -1243,7 +1257,7 @@ SetHook::setHook() HookSetOperation op = hsoNOOP; if (hookSetObj) - op = inferOperation(hookSetObj->get()); + op = inferOperation(ctx, hookSetObj->get()); // these flags are not able to be passed onto the ledger object int newFlags = 0; @@ -1281,6 +1295,14 @@ SetHook::setHook() oldHookOn = oldHook->get().getFieldH256(sfHookOn); else if (defHookOn) oldHookOn = *defHookOn; + + if (oldDefSLE && oldDefSLE->isFieldPresent(sfHookEmit)) + defHookEmit = oldDefSLE->getFieldH256(sfHookEmit); + + if (oldHook && oldHook->get().isFieldPresent(sfHookEmit)) + oldHookEmit = oldHook->get().getFieldH256(sfHookEmit); + else if (defHookEmit) + oldHookEmit = *defHookEmit; } // in preparation for three way merge populate fields if they are @@ -1297,6 +1319,9 @@ SetHook::setHook() if (hookSetObj->get().isFieldPresent(sfHookOn)) newHookOn = hookSetObj->get().getFieldH256(sfHookOn); + if (hookSetObj->get().isFieldPresent(sfHookEmit)) + newHookEmit = hookSetObj->get().getFieldH256(sfHookEmit); + if (hookSetObj->get().isFieldPresent(sfHookNamespace)) { newNamespace = hookSetObj->get().getFieldH256(sfHookNamespace); @@ -1406,6 +1431,9 @@ SetHook::setHook() if (oldHook->get().isFieldPresent(sfHookOn)) newHook.setFieldH256( sfHookOn, oldHook->get().getFieldH256(sfHookOn)); + if (oldHook->get().isFieldPresent(sfHookEmit)) + newHook.setFieldH256( + sfHookEmit, oldHook->get().getFieldH256(sfHookEmit)); if (oldHook->get().isFieldPresent(sfHookNamespace)) newHook.setFieldH256( sfHookNamespace, @@ -1435,6 +1463,18 @@ SetHook::setHook() newHook.setFieldH256(sfHookOn, *newHookOn); } + // set the hookemit field if it differs from definition + if (newHookEmit) + { + if (*defHookEmit == *newHookEmit) + { + if (newHook.isFieldPresent(sfHookEmit)) + newHook.makeFieldAbsent(sfHookEmit); + } + else + newHook.setFieldH256(sfHookEmit, *newHookEmit); + } + // parameters if (hookSetObj->get().isFieldPresent(sfHookParameters) && hookSetObj->get().getFieldArray(sfHookParameters).empty()) @@ -1584,6 +1624,7 @@ SetHook::setHook() auto newHookDef = std::make_shared(keylet); newHookDef->setFieldH256(sfHookHash, *createHookHash); newHookDef->setFieldH256(sfHookOn, *newHookOn); + newHookDef->setFieldH256(sfHookEmit, *newHookEmit); newHookDef->setFieldH256(sfHookNamespace, *newNamespace); newHookDef->setFieldArray( sfHookParameters, @@ -1677,6 +1718,7 @@ SetHook::setHook() // change which definition we're using to the new target defNamespace = newDefSLE->getFieldH256(sfHookNamespace); defHookOn = newDefSLE->getFieldH256(sfHookOn); + defHookEmit = newDefSLE->getFieldH256(sfHookEmit); // set the namespace if it differs from the definition namespace if (newNamespace && *defNamespace != *newNamespace) @@ -1686,6 +1728,10 @@ SetHook::setHook() if (newHookOn && *defHookOn != *newHookOn) newHook.setFieldH256(sfHookOn, *newHookOn); + // set the hookemit field if it differs from definition + if (newHookEmit && *defHookEmit != *newHookEmit) + newHook.setFieldH256(sfHookEmit, *newHookEmit); + // parameters TER result = updateHookParameters( ctx, @@ -1734,8 +1780,8 @@ SetHook::setHook() // sfHook: 1 reserve PER non-blank entry // sfParameters: 1 reserve PER entry // sfGrants are: 1 reserve PER entry - // sfHookHash, sfHookNamespace, sfHookOn, sfHookApiVersion, sfFlags: - // free + // sfHookHash, sfHookNamespace, sfHookOn, sfHookEmit, sfHookApiVersion, + // sfFlags: free // sfHookDefinition is not reserved because it is an unowned object, // rather the uploader is billed via fee according to the following: diff --git a/src/ripple/app/tx/impl/SetHook.h b/src/ripple/app/tx/impl/SetHook.h index ecfce24100..75e8c7923c 100644 --- a/src/ripple/app/tx/impl/SetHook.h +++ b/src/ripple/app/tx/impl/SetHook.h @@ -86,7 +86,7 @@ class SetHook : public Transactor calculateBaseFee(ReadView const& view, STTx const& tx); static HookSetOperation - inferOperation(STObject const& hookSetObj); + inferOperation(SetHookCtx& ctx, STObject const& hookSetObj); static HookSetValidation validateHookSetEntry(SetHookCtx& ctx, STObject const& hookSetObj); diff --git a/src/ripple/app/tx/impl/Transactor.cpp b/src/ripple/app/tx/impl/Transactor.cpp index 7c2734f208..b47a8a5c71 100644 --- a/src/ripple/app/tx/impl/Transactor.cpp +++ b/src/ripple/app/tx/impl/Transactor.cpp @@ -1212,6 +1212,13 @@ Transactor::executeHookChain( if (!hook::canHook(ctx_.tx.getTxnType(), hookOn)) continue; // skip if it can't + uint256 hookEmit = + (hookObj.isFieldPresent(sfHookEmit) + ? hookObj.getFieldH256(sfHookEmit) + : hookDef->isFieldPresent(sfHookEmit) + ? hookDef->getFieldH256(sfHookEmit) + : uint256()); + uint32_t flags = (hookObj.isFieldPresent(sfFlags) ? hookObj.getFieldU32(sfFlags) : hookDef->getFieldU32(sfFlags)); @@ -1247,6 +1254,7 @@ Transactor::executeHookChain( results.push_back(hook::apply( hookDef->getFieldH256(sfHookSetTxnID), hookHash, + hookEmit, ns, hookDef->getFieldVL(sfCreateCode), parameters, @@ -1369,6 +1377,13 @@ Transactor::doHookCallback( if (hookObj.getFieldH256(sfHookHash) != callbackHookHash) continue; + uint256 hookEmit = + (hookObj.isFieldPresent(sfHookEmit) + ? hookObj.getFieldH256(sfHookEmit) + : hookDef->isFieldPresent(sfHookEmit) + ? hookDef->getFieldH256(sfHookEmit) + : uint256()); + // fetch the namespace either from the hook object of, if absent, the // hook def uint256 const& ns = @@ -1394,6 +1409,7 @@ Transactor::doHookCallback( hook::HookResult callbackResult = hook::apply( hookDef->getFieldH256(sfHookSetTxnID), callbackHookHash, + hookEmit, ns, hookDef->getFieldVL(sfCreateCode), parameters, @@ -1639,6 +1655,13 @@ Transactor::doAgainAsWeak( continue; } + uint256 hookEmit = + (hookObj.isFieldPresent(sfHookEmit) + ? hookObj.getFieldH256(sfHookEmit) + : hookDef->isFieldPresent(sfHookEmit) + ? hookDef->getFieldH256(sfHookEmit) + : uint256()); + // fetch the namespace either from the hook object of, if absent, the // hook def uint256 const& ns = @@ -1659,6 +1682,7 @@ Transactor::doAgainAsWeak( hook::HookResult aawResult = hook::apply( hookDef->getFieldH256(sfHookSetTxnID), hookHash, + hookEmit, ns, hookDef->getFieldVL(sfCreateCode), parameters, diff --git a/src/ripple/protocol/Feature.h b/src/ripple/protocol/Feature.h index 43d510c636..c9d1394511 100644 --- a/src/ripple/protocol/Feature.h +++ b/src/ripple/protocol/Feature.h @@ -74,7 +74,7 @@ namespace detail { // Feature.cpp. Because it's only used to reserve storage, and determine how // large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than // the actual number of amendments. A LogicError on startup will verify this. -static constexpr std::size_t numFeatures = 74; +static constexpr std::size_t numFeatures = 75; /** Amendments that this server supports and the default voting behavior. Whether they are enabled depends on the Rules defined in the validated @@ -362,6 +362,7 @@ extern uint256 const fix240819; extern uint256 const fixPageCap; extern uint256 const fix240911; extern uint256 const fixFloatDivide; +extern uint256 const featureHookEmit; } // namespace ripple diff --git a/src/ripple/protocol/SField.h b/src/ripple/protocol/SField.h index 1f9d153682..e1aa1f7c8c 100644 --- a/src/ripple/protocol/SField.h +++ b/src/ripple/protocol/SField.h @@ -449,6 +449,7 @@ extern SF_UINT256 const sfParentHash; extern SF_UINT256 const sfTransactionHash; extern SF_UINT256 const sfAccountHash; extern SF_UINT256 const sfHookOn; +extern SF_UINT256 const sfHookEmit; extern SF_UINT256 const sfPreviousTxnID; extern SF_UINT256 const sfLedgerIndex; extern SF_UINT256 const sfWalletLocator; diff --git a/src/ripple/protocol/impl/Feature.cpp b/src/ripple/protocol/impl/Feature.cpp index 23cbe236df..a73af88389 100644 --- a/src/ripple/protocol/impl/Feature.cpp +++ b/src/ripple/protocol/impl/Feature.cpp @@ -468,6 +468,7 @@ REGISTER_FIX (fix240819, Supported::yes, VoteBehavior::De REGISTER_FIX (fixPageCap, Supported::yes, VoteBehavior::DefaultYes); REGISTER_FIX (fix240911, Supported::yes, VoteBehavior::DefaultYes); REGISTER_FIX (fixFloatDivide, Supported::yes, VoteBehavior::DefaultYes); +REGISTER_FEATURE(HookEmit, Supported::yes, VoteBehavior::DefaultNo); // The following amendments are obsolete, but must remain supported // because they could potentially get enabled. diff --git a/src/ripple/protocol/impl/InnerObjectFormats.cpp b/src/ripple/protocol/impl/InnerObjectFormats.cpp index e52d6ff8f3..b4a454fdfa 100644 --- a/src/ripple/protocol/impl/InnerObjectFormats.cpp +++ b/src/ripple/protocol/impl/InnerObjectFormats.cpp @@ -88,6 +88,7 @@ InnerObjectFormats::InnerObjectFormats() {sfHookNamespace, soeREQUIRED}, {sfHookParameters, soeREQUIRED}, {sfHookOn, soeREQUIRED}, + {sfHookEmit, soeOPTIONAL}, {sfHookApiVersion, soeREQUIRED}, {sfFlags, soeREQUIRED}, {sfFee, soeREQUIRED}}); @@ -100,6 +101,7 @@ InnerObjectFormats::InnerObjectFormats() {sfHookNamespace, soeOPTIONAL}, {sfHookParameters, soeOPTIONAL}, {sfHookOn, soeOPTIONAL}, + {sfHookEmit, soeOPTIONAL}, {sfHookApiVersion, soeOPTIONAL}, {sfFlags, soeOPTIONAL}}); diff --git a/src/ripple/protocol/impl/LedgerFormats.cpp b/src/ripple/protocol/impl/LedgerFormats.cpp index acb07c4895..a4df34cc28 100644 --- a/src/ripple/protocol/impl/LedgerFormats.cpp +++ b/src/ripple/protocol/impl/LedgerFormats.cpp @@ -224,7 +224,8 @@ LedgerFormats::LedgerFormats() ltHOOK_DEFINITION, { {sfHookHash, soeREQUIRED}, - {sfHookOn, soeREQUIRED}, + {sfHookOn, soeREQUIRED}, + {sfHookEmit, soeOPTIONAL}, {sfHookNamespace, soeREQUIRED}, {sfHookParameters, soeREQUIRED}, {sfHookApiVersion, soeREQUIRED}, diff --git a/src/ripple/protocol/impl/SField.cpp b/src/ripple/protocol/impl/SField.cpp index a72208607f..c74ea3427e 100644 --- a/src/ripple/protocol/impl/SField.cpp +++ b/src/ripple/protocol/impl/SField.cpp @@ -236,6 +236,7 @@ CONSTRUCT_TYPED_SFIELD(sfURITokenID, "URITokenID", UINT256, CONSTRUCT_TYPED_SFIELD(sfGovernanceFlags, "GovernanceFlags", UINT256, 99); CONSTRUCT_TYPED_SFIELD(sfGovernanceMarks, "GovernanceMarks", UINT256, 98); CONSTRUCT_TYPED_SFIELD(sfEmittedTxnID, "EmittedTxnID", UINT256, 97); +CONSTRUCT_TYPED_SFIELD(sfHookEmit, "HookEmit", UINT256, 96); // currency amount (common) CONSTRUCT_TYPED_SFIELD(sfAmount, "Amount", AMOUNT, 1); diff --git a/src/test/app/SetHook_test.cpp b/src/test/app/SetHook_test.cpp index f0e97a8594..b6d3460aa2 100644 --- a/src/test/app/SetHook_test.cpp +++ b/src/test/app/SetHook_test.cpp @@ -1977,28 +1977,36 @@ class SetHook_test : public beast::unit_test::suite } void - testInferHookSetOperation() + testInferHookSetOperation(FeatureBitset features) { testcase("Test operation inference"); + using namespace jtx; + Env env{*this, features}; + + SetHookCtx ctx{ + .j = env.app().journal("View"), + .tx = *env.tx(), + .app = env.app(), + .rules = env.current()->rules()}; // hsoNOOP { STObject hso{sfHook}; - BEAST_EXPECT(SetHook::inferOperation(hso) == hsoNOOP); + BEAST_EXPECT(SetHook::inferOperation(ctx, hso) == hsoNOOP); } // hsoCREATE { STObject hso{sfHook}; hso.setFieldVL(sfCreateCode, {1}); // non-empty create code - BEAST_EXPECT(SetHook::inferOperation(hso) == hsoCREATE); + BEAST_EXPECT(SetHook::inferOperation(ctx, hso) == hsoCREATE); } // hsoDELETE { STObject hso{sfHook}; hso.setFieldVL(sfCreateCode, ripple::Blob{}); // empty create code - BEAST_EXPECT(SetHook::inferOperation(hso) == hsoDELETE); + BEAST_EXPECT(SetHook::inferOperation(ctx, hso) == hsoDELETE); } // hsoINSTALL @@ -2006,7 +2014,7 @@ class SetHook_test : public beast::unit_test::suite STObject hso{sfHook}; hso.setFieldH256( sfHookHash, uint256{beast::zero}); // all zeros hook hash - BEAST_EXPECT(SetHook::inferOperation(hso) == hsoINSTALL); + BEAST_EXPECT(SetHook::inferOperation(ctx, hso) == hsoINSTALL); } // hsoNSDELETE @@ -2015,14 +2023,14 @@ class SetHook_test : public beast::unit_test::suite hso.setFieldH256( sfHookNamespace, uint256{beast::zero}); // all zeros hook hash hso.setFieldU32(sfFlags, hsfNSDELETE); - BEAST_EXPECT(SetHook::inferOperation(hso) == hsoNSDELETE); + BEAST_EXPECT(SetHook::inferOperation(ctx, hso) == hsoNSDELETE); } // hsoUPDATE { STObject hso{sfHook}; hso.setFieldH256(sfHookOn, UINT256_BIT[0]); - BEAST_EXPECT(SetHook::inferOperation(hso) == hsoUPDATE); + BEAST_EXPECT(SetHook::inferOperation(ctx, hso) == hsoUPDATE); } // hsoINVALID @@ -2031,7 +2039,7 @@ class SetHook_test : public beast::unit_test::suite hso.setFieldVL(sfCreateCode, {1}); // non-empty create code hso.setFieldH256( sfHookHash, uint256{beast::zero}); // all zeros hook hash - BEAST_EXPECT(SetHook::inferOperation(hso) == hsoINVALID); + BEAST_EXPECT(SetHook::inferOperation(ctx, hso) == hsoINVALID); } } @@ -11958,7 +11966,7 @@ class SetHook_test : public beast::unit_test::suite testHooksOwnerDir(features); testHooksDisabled(features); testTxStructure(features); - testInferHookSetOperation(); + testInferHookSetOperation(features); testParams(features); testGrants(features); From 721b40fd419da3c5fb648266803801fbb951e89a Mon Sep 17 00:00:00 2001 From: tequ Date: Sat, 16 Nov 2024 00:30:36 +0900 Subject: [PATCH 2/4] fix default HookEmit value --- src/ripple/app/tx/impl/Transactor.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/ripple/app/tx/impl/Transactor.cpp b/src/ripple/app/tx/impl/Transactor.cpp index b47a8a5c71..952e014188 100644 --- a/src/ripple/app/tx/impl/Transactor.cpp +++ b/src/ripple/app/tx/impl/Transactor.cpp @@ -1212,12 +1212,16 @@ Transactor::executeHookChain( if (!hook::canHook(ctx_.tx.getTxnType(), hookOn)) continue; // skip if it can't + // default allows all transaction types + uint256 defaultHookEmit = uint256(); + defaultHookEmit ^= UINT256_BIT[ttHOOK_SET]; + uint256 hookEmit = (hookObj.isFieldPresent(sfHookEmit) ? hookObj.getFieldH256(sfHookEmit) : hookDef->isFieldPresent(sfHookEmit) ? hookDef->getFieldH256(sfHookEmit) - : uint256()); + : defaultHookEmit); uint32_t flags = (hookObj.isFieldPresent(sfFlags) ? hookObj.getFieldU32(sfFlags) @@ -1377,12 +1381,16 @@ Transactor::doHookCallback( if (hookObj.getFieldH256(sfHookHash) != callbackHookHash) continue; + // default allows all transaction types + uint256 defaultHookEmit = uint256(); + defaultHookEmit ^= UINT256_BIT[ttHOOK_SET]; + uint256 hookEmit = (hookObj.isFieldPresent(sfHookEmit) ? hookObj.getFieldH256(sfHookEmit) : hookDef->isFieldPresent(sfHookEmit) ? hookDef->getFieldH256(sfHookEmit) - : uint256()); + : defaultHookEmit); // fetch the namespace either from the hook object of, if absent, the // hook def @@ -1655,12 +1663,16 @@ Transactor::doAgainAsWeak( continue; } + // default allows all transaction types + uint256 defaultHookEmit = uint256(); + defaultHookEmit ^= UINT256_BIT[ttHOOK_SET]; + uint256 hookEmit = (hookObj.isFieldPresent(sfHookEmit) ? hookObj.getFieldH256(sfHookEmit) : hookDef->isFieldPresent(sfHookEmit) ? hookDef->getFieldH256(sfHookEmit) - : uint256()); + : defaultHookEmit); // fetch the namespace either from the hook object of, if absent, the // hook def From a05d58a6e991e0ff0bf4ea5a312a57d3fb2d5850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ekiserrep=C3=A9?= <126416117+Ekiserrepe@users.noreply.github.com> Date: Mon, 25 Nov 2024 23:52:49 +0100 Subject: [PATCH 3/4] Update README.md (#396) Updated Xaman link. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e73c034613..c9335cfc10 100644 --- a/README.md +++ b/README.md @@ -67,5 +67,5 @@ git-subtree. See those directories' README files for more details. - [explorer.xahau.network](https://explorer.xahau.network) - **Testnet & Faucet**: Test applications and obtain test XAH at [xahau-test.net](https://xahau-test.net) and use the testnet explorer at [explorer.xahau.network](https://explorer.xahau.network). - **Supporting Wallets**: A list of wallets that support XAH and Xahau-based assets. - - [Xumm](https://xumm.app) + - [Xaman](https://xaman.app) - [Crossmark](https://crossmark.io) From 3879c529c1815115add77646d9198ffc9ca72e94 Mon Sep 17 00:00:00 2001 From: Denis Angell Date: Thu, 28 Nov 2024 10:20:44 +0100 Subject: [PATCH 4/4] Fix: failing assert (#397) --- src/ripple/nodestore/impl/Shard.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/ripple/nodestore/impl/Shard.cpp b/src/ripple/nodestore/impl/Shard.cpp index 8d0eab8115..ac4af4782b 100644 --- a/src/ripple/nodestore/impl/Shard.cpp +++ b/src/ripple/nodestore/impl/Shard.cpp @@ -710,10 +710,7 @@ Shard::finalize(bool writeSQLite, std::optional const& referenceHash) if (writeSQLite && !storeSQLite(ledger)) return fail("failed storing to SQLite databases"); - assert( - ledger->info().seq == ledgerSeq && - (ledger->info().seq < XRP_LEDGER_EARLIEST_FEES || - ledger->read(keylet::fees()))); + assert(ledger->info().seq == ledgerSeq && ledger->read(keylet::fees())); hash = ledger->info().parentHash; next = std::move(ledger);