diff --git a/include/xrpl/protocol/Indexes.h b/include/xrpl/protocol/Indexes.h index dc37066c68..13f50d9dbf 100644 --- a/include/xrpl/protocol/Indexes.h +++ b/include/xrpl/protocol/Indexes.h @@ -372,6 +372,10 @@ permissionedDomain(AccountID const& account, std::uint32_t seq) noexcept; Keylet permissionedDomain(uint256 const& domainID) noexcept; + +Keylet +manifest(PublicKey const& pk) noexcept; + } // namespace keylet // Everything below is deprecated and should be removed in favor of keylets: diff --git a/include/xrpl/protocol/detail/ledger_entries.macro b/include/xrpl/protocol/detail/ledger_entries.macro index 05d277e0b3..3f055d2fcf 100644 --- a/include/xrpl/protocol/detail/ledger_entries.macro +++ b/include/xrpl/protocol/detail/ledger_entries.macro @@ -262,7 +262,7 @@ LEDGER_ENTRY(ltACCOUNT_ROOT, 0x0061, AccountRoot, account, ({ {sfHookStateScale, soeOPTIONAL}, {sfCron, soeOPTIONAL}, {sfAMMID, soeOPTIONAL}, - {sfManifestID soeOPTIONAL}, + {sfManifestID, soeOPTIONAL}, })) /** A ledger object which contains a list of object identifiers. @@ -593,7 +593,7 @@ LEDGER_ENTRY(ltDID, 0x008D, DID, did, ({ {sfPreviousTxnLgrSeq, soeREQUIRED}, })) -LEDGER_ENTRY(ltMANIFEST, 0x004D, Manifest, manifest, ({ +LEDGER_ENTRY(ltMANIFEST, 0x004D, Manifest, manifest_entry, ({ {sfAccount, soeREQUIRED}, {sfPublicKey, soeREQUIRED}, {sfSigningPubKey, soeOPTIONAL}, /* may be absent if the master is revoked */ diff --git a/include/xrpl/protocol/detail/sfields.macro b/include/xrpl/protocol/detail/sfields.macro index 6fab4d39a1..9238225772 100644 --- a/include/xrpl/protocol/detail/sfields.macro +++ b/include/xrpl/protocol/detail/sfields.macro @@ -210,7 +210,7 @@ TYPED_SFIELD(sfOfferID, UINT256, 34) TYPED_SFIELD(sfEscrowID, UINT256, 35) TYPED_SFIELD(sfURITokenID, UINT256, 36) TYPED_SFIELD(sfDomainID, UINT256, 37) -TYPED_SFIELD(sfManfiestID, UINT256, 91) +TYPED_SFIELD(sfManifestID, UINT256, 91) TYPED_SFIELD(sfHookOnOutgoing, UINT256, 93) TYPED_SFIELD(sfHookOnIncoming, UINT256, 94) TYPED_SFIELD(sfCron, UINT256, 95) diff --git a/include/xrpl/protocol/detail/transactions.macro b/include/xrpl/protocol/detail/transactions.macro index 0e44c733a9..781500db7a 100644 --- a/include/xrpl/protocol/detail/transactions.macro +++ b/include/xrpl/protocol/detail/transactions.macro @@ -500,7 +500,7 @@ TRANSACTION(ttPERMISSIONED_DOMAIN_DELETE, 72, PermissionedDomainDelete, ({ {sfDomainID, soeREQUIRED}, })) -TRANSACTION(ttMANIFEST_SET, 91, ManifestSet, ({ +TRANSACTION(ttMANIFEST_SET, 91, SetManifest, ({ {sfAccount, soeREQUIRED}, {sfManifest, soeREQUIRED}, })) diff --git a/src/libxrpl/protocol/Indexes.cpp b/src/libxrpl/protocol/Indexes.cpp index 183421d624..a197bcd978 100644 --- a/src/libxrpl/protocol/Indexes.cpp +++ b/src/libxrpl/protocol/Indexes.cpp @@ -89,6 +89,7 @@ enum class LedgerNameSpace : std::uint16_t { ORACLE = LEDGER_NAMESPACE2(0x01, 'R'), MPTOKEN_ISSUANCE = '~', MPTOKEN = 't', + MANIFEST = 'M', CREDENTIAL = LEDGER_NAMESPACE2(0x01, 'D'), PERMISSIONED_DOMAIN = 'm', @@ -671,9 +672,9 @@ permissionedDomain(uint256 const& domainID) noexcept } Keylet -manifest(PublicKey const& pk) +manifest(PublicKey const& pk) noexcept { - return {ltMANIFEST, pk}; + return {ltMANIFEST, indexHash(LedgerNameSpace::MANIFEST, pk.slice())}; } } // namespace keylet diff --git a/src/test/app/SetHookTSH_test.cpp b/src/test/app/SetHookTSH_test.cpp index f4ef10ed86..772e690d18 100644 --- a/src/test/app/SetHookTSH_test.cpp +++ b/src/test/app/SetHookTSH_test.cpp @@ -8445,6 +8445,11 @@ private: } } + void testSetManifestTSH(FeatureBitset features) + { + // RH TODO + } + void testTSH(FeatureBitset features) { diff --git a/src/xrpld/app/misc/Manifest.h b/src/xrpld/app/misc/Manifest.h index 70a6b1daf3..6c103db161 100644 --- a/src/xrpld/app/misc/Manifest.h +++ b/src/xrpld/app/misc/Manifest.h @@ -173,6 +173,16 @@ deserializeManifest( return deserializeManifest(makeSlice(s), journal); } +inline std::optional +deserializeManifest( + STObject const& st, + beast::Journal journal = beast::Journal(beast::Journal::getNullSink())) +{ + Serializer s; + st.add(s); + return deserializeManifest(makeSlice(s.peekData()), journal); +} + template < class T, class = std::enable_if_t< diff --git a/src/xrpld/app/tx/detail/SetManifest.cpp b/src/xrpld/app/tx/detail/SetManifest.cpp index a2e16c8252..500446faad 100644 --- a/src/xrpld/app/tx/detail/SetManifest.cpp +++ b/src/xrpld/app/tx/detail/SetManifest.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include namespace ripple { @@ -65,7 +65,7 @@ SetManifest::preflight(PreflightContext const& ctx) .downcast(); // 1. sfManifest must match the manifest template and be validly signed - auto manifest = Manifest::deserializeManifest(obj, j); + auto manifest = deserializeManifest(obj, j); if (!manifest.has_value()) { @@ -118,10 +118,10 @@ SetManifest::preclaim(PreclaimContext const& ctx) .getField(sfManifest) .downcast(); - auto newManifest = Manifest::deserializeManifest(newObj, j); + auto newManifest = deserializeManifest(newObj, ctx.j); - auto const sleOld = view.read(Keylet{ltMANIFEST, sle->getFieldH256(sfManifestID)); + auto const sleOld = ctx.view.read(Keylet{ltMANIFEST, sle->getFieldH256(sfManifestID)}); if (!sleOld) { @@ -166,7 +166,7 @@ SetManifest::doApply() auto sleMan1 = view().peek(Keylet{ltMANIFEST, firstID}); if (!sleMan1) { - JLOG(ctx.j.error()) + JLOG(j_.error()) << "SetManifest: Old manifest object referenced but missing (ID1) !! " << strHex(firstID); return tefBAD_LEDGER; } @@ -174,7 +174,7 @@ SetManifest::doApply() uint256 const secondID = sle->getFieldH256(sfManifestID); if (secondID == firstID) { - JLOG(ctx.j.error()) + JLOG(j_.error()) << "SetManifest: Manifest second ID references first object!! " << strHex(firstID); return tefBAD_LEDGER; } @@ -182,7 +182,7 @@ SetManifest::doApply() auto sleMan2 = view().peek(Keylet{ltMANIFEST, secondID}); if (!sleMan2) { - JLOG(ctx.j.error()) + JLOG(j_.error()) << "SetManifest: Old manifest object referenced but missing (ID2) !! " << strHex(secondID); return tefBAD_LEDGER; } @@ -190,7 +190,7 @@ SetManifest::doApply() if (sleMan1->getAccountID(sfAccount) != account_ || sleMan2->getAccountID(sfAccount) != account_) { - JLOG(ctx.j.error()) + JLOG(j_.error()) << "SetManifest: One or more manifest IDs point at incorrect account!!"; return tefBAD_LEDGER; } @@ -206,21 +206,21 @@ SetManifest::doApply() .getField(sfManifest) .downcast(); - auto manifest = Manifest::deserializeManifest(obj, j); + auto manifest = deserializeManifest(obj, j_); if (!manifest.has_value()) { - JLOG(j.warn()) << "SetManifest: invalid manifest passed (parseManifest failed)."; + JLOG(j_.warn()) << "SetManifest: invalid manifest passed (parseManifest failed)."; return temMALFORMED; } if (calcAccountID(manifest->masterKey) != account_) return tefINTERNAL; - Keylet klMan1 = Keylet::manifest(manifest->masterKey); + Keylet klMan1 = keylet::manifest(manifest->masterKey); std::optional klMan2; if (!manifest->revoked() && manifest->signingKey.has_value()) - klMan2 = Keylet::manifest(manifest->signingKey); + klMan2 = keylet::manifest(*manifest->signingKey); auto setManifest = [&](std::shared_ptr& sle, std::optional otherKey) -> void { @@ -230,19 +230,19 @@ SetManifest::doApply() sle->setFieldVL(sfSigningPubKey, *(manifest->signingKey)); sle->setFieldU32(sfSequence, manifest->sequence); sle->setFieldU16(sfVersion, 0); - if (manifest->domain.has_value() && manifest->domain != "") - sle->setFieldVL(sfDomain, manifest->domain); + if (manifest->domain != "") + sle->setFieldVL(sfDomain, makeSlice(manifest->domain)); if (otherKey.has_value()) - sle>setFieldH256(sfManifestID, *otherKey); + sle->setFieldH256(sfManifestID, *otherKey); }; - std::shared_ptr sleMan1 = std::make_shared(klMan1); - setManifest(sleMan1, klMan2); + auto sleMan1 = std::make_shared(klMan1); + setManifest(sleMan1, klMan2->key); if (klMan2.has_value()) { - sleMan2 = std::make_shared(*klMan2); - setManifest(sleMan2, klMan1); + auto sleMan2 = std::make_shared(*klMan2); + setManifest(sleMan2, klMan1.key); view().insert(sleMan2); } @@ -265,6 +265,8 @@ SetManifest::calculateBaseFee(ReadView const& view, STTx const& tx) .getField(sfManifest) .downcast(); + + // one drop per byte manifestFee = XRPAmount { newObj.getSerializer().getDataLength() }; } diff --git a/src/xrpld/app/tx/detail/apply.cpp b/src/xrpld/app/tx/detail/apply.cpp index 41e75b936a..c5267e12da 100644 --- a/src/xrpld/app/tx/detail/apply.cpp +++ b/src/xrpld/app/tx/detail/apply.cpp @@ -22,6 +22,7 @@ #include #include #include +#include namespace ripple { @@ -74,7 +75,7 @@ checkValidity( } if (rules.enabled(featureOnChainManifests) && - tx.getTxType() == ttMANIFEST_SET && + tx.getTxnType() == ttMANIFEST_SET && tx.isFieldPresent(sfTxnSignature) && tx.getFieldVL(sfTxnSignature).empty() && tx.isFieldPresent(sfSigningPubKey) && @@ -82,12 +83,12 @@ checkValidity( tx.isFieldPresent(sfManifest)) { // perform alternative signature check over manifest - STObject const& man = const_cast(ctx.tx) + STObject const& manObj = const_cast(tx) .getField(sfManifest) .downcast(); - auto man = Manifest::deserializeManifest(newObj, j); - if (!man->valid()) + auto man = deserializeManifest(manObj); + if (!man.has_value() || !man->verify()) return { Validity::SigBad, "Manifest signature is bad"}; diff --git a/src/xrpld/app/tx/detail/applySteps.cpp b/src/xrpld/app/tx/detail/applySteps.cpp index 8c9c1ef546..2d2469877d 100644 --- a/src/xrpld/app/tx/detail/applySteps.cpp +++ b/src/xrpld/app/tx/detail/applySteps.cpp @@ -72,6 +72,7 @@ #include #include #include +#include #include #include diff --git a/src/xrpld/rpc/handlers/Submit.cpp b/src/xrpld/rpc/handlers/Submit.cpp index e448804086..f1b8ded02b 100644 --- a/src/xrpld/rpc/handlers/Submit.cpp +++ b/src/xrpld/rpc/handlers/Submit.cpp @@ -30,6 +30,8 @@ #include #include #include +#include +#include namespace ripple { @@ -94,7 +96,7 @@ doSubmit(RPC::JsonContext& context) context.loadType = Resource::feeMediumBurdenRPC; - bool const hasManifest = context.params.isMemeber(jss::manifest); + bool const hasManifest = context.params.isMember(jss::manifest); bool const hasTxBlob = context.params.isMember(jss::tx_blob); if (hasManifest && hasTxBlob) @@ -143,7 +145,7 @@ doSubmit(RPC::JsonContext& context) try { - man = deserializeManifest(makeSlice(*ret), context.app.journal("Submit")); + man = deserializeManifest(makeSlice(*raw), context.app.journal("Submit")); } catch (std::exception& e) { @@ -174,17 +176,17 @@ doSubmit(RPC::JsonContext& context) // forward compatible with a future manifest format change, even if that change is into a PQ opaque blob. STTx tx = STTx(ttMANIFEST_SET, [&](STObject& obj) { - obj.setAccountID(sfAccount, calcAccountID(manifest->masterKey)); + obj.setAccountID(sfAccount, calcAccountID(man->masterKey)); obj.setFieldU32(sfSequence, 0); - obj.setFieldU32(sfNetworkID, context.app.overlay().networkID()); + obj.setFieldU32(sfNetworkID, context.app.config().NETWORK_ID); obj.setFieldAmount(sfFee, XRPAmount{0}); - obj.setFieldVL(sfSigningPubkey, std::vector{}); + obj.setFieldVL(sfSigningPubKey, std::vector{}); obj.setFieldVL(sfTxnSignature, std::vector{}); }); std::string const manifestHex = + "E05A" /* object marker for sfManfiest ... this goes at the end of the tx canonically */ - + strHex(raw) /* re-encode the original slice as fresh hex to match case etc */ + + strHex(*raw) /* re-encode the original slice as fresh hex to match case etc */ + "E1"; /* object end marker for sfManifest */ std::string const txHex = serializeHex(tx) + manifestHex;