diff --git a/src/xrpld/app/consensus/ConsensusExtensions.cpp b/src/xrpld/app/consensus/ConsensusExtensions.cpp index db66ef0db..392e24867 100644 --- a/src/xrpld/app/consensus/ConsensusExtensions.cpp +++ b/src/xrpld/app/consensus/ConsensusExtensions.cpp @@ -72,7 +72,7 @@ namespace { struct ResolvedExportShare { std::shared_ptr latch; - STTx releaseTarget; + STTx exportSigningPayload; }; enum class ExportShareResolutionStatus { @@ -230,28 +230,28 @@ resolveExportShare( return {ExportShareResolutionStatus::duplicate, std::nullopt}; } - auto const inner = ExportLedgerOps::innerExportedTx(*outer); - if (!inner) + auto const baseTarget = ExportLedgerOps::exportIntentTarget(*outer); + if (!baseTarget) return {ExportShareResolutionStatus::invalid, std::nullopt}; - auto const targetNetworkID = inner->isFieldPresent(sfNetworkID) - ? inner->getFieldU32(sfNetworkID) + auto const targetNetworkID = baseTarget->isFieldPresent(sfNetworkID) + ? baseTarget->getFieldU32(sfNetworkID) : std::uint32_t{0}; ExportOriginMemo::Origin const origin{ app.config().NETWORK_ID, targetNetworkID, share.originTxn}; - auto const identity = ExportOriginMemo::identityForm(*inner, origin); - auto release = ExportOriginMemo::releaseForm( - *inner, + auto const identity = ExportOriginMemo::identityForm(*baseTarget, origin); + auto signingPayload = ExportOriginMemo::releaseForm( + *baseTarget, origin, ExportOriginMemo::Anchor{ share.originLedgerSeq, share.originLedgerHash}); - if (!identity || !release || + if (!identity || !signingPayload || ExportResultBuilder::exportIntentHash(identity.value()) != latch->getFieldH256(sfDigest)) return {ExportShareResolutionStatus::invalid, std::nullopt}; return { ExportShareResolutionStatus::resolved, - ResolvedExportShare{latch, std::move(release.value())}}; + ResolvedExportShare{latch, std::move(signingPayload.value())}}; } ExportShare @@ -519,7 +519,7 @@ ConsensusExtensions::admitExportShare( auto const signer = calcAccountID(share.signingKey); auto const data = - buildMultiSigningData(resolved.value->releaseTarget, signer); + buildMultiSigningData(resolved.value->exportSigningPayload, signer); auto const signatureVerified = verify( share.signingKey, data.slice(), @@ -719,28 +719,28 @@ ConsensusExtensions::onValidatedLedger( auto const [outer, _] = originLedger->txRead(origin); if (!outer) return; - auto const inner = - ExportLedgerOps::innerExportedTx(*outer); - if (!inner) + auto const baseTarget = + ExportLedgerOps::exportIntentTarget(*outer); + if (!baseTarget) return; auto const targetNetworkID = - inner->isFieldPresent(sfNetworkID) - ? inner->getFieldU32(sfNetworkID) + baseTarget->isFieldPresent(sfNetworkID) + ? baseTarget->getFieldU32(sfNetworkID) : std::uint32_t{0}; - auto release = ExportOriginMemo::releaseForm( - *inner, + auto signingPayload = ExportOriginMemo::releaseForm( + *baseTarget, ExportOriginMemo::Origin{ app_.config().NETWORK_ID, targetNetworkID, origin}, ExportOriginMemo::Anchor{originSeq, *originHash}); - if (!release) + if (!signingPayload) return; auto const signer = calcAccountID(keys.keys->publicKey); - auto const data = - buildMultiSigningData(release.value(), signer); + auto const data = buildMultiSigningData( + signingPayload.value(), signer); auto const signature = sign( keys.keys->publicKey, keys.keys->secretKey, @@ -2175,7 +2175,7 @@ ConsensusExtensions::agreedExportSignatures( std::optional ConsensusExtensions::agreedExportWitness( - STTx const& releaseTarget, + STTx const& exportSigningPayload, uint256 const& origin, Blob const& committeeBitmap, std::size_t universeSize, @@ -2266,7 +2266,8 @@ ConsensusExtensions::agreedExportWitness( } auto const signature = sidecar.getFieldVL(sfTxnSignature); - auto const data = buildMultiSigningData(releaseTarget, signer); + auto const data = + buildMultiSigningData(exportSigningPayload, signer); if (signature.empty() || signature.size() > ExportSigCollectorV2::maxSignatureBytes || @@ -2804,8 +2805,9 @@ ConsensusExtensions::onPreBuild( auto const [outer, _] = originLedger->txRead(origin); if (!outer || outer->getTxnType() != ttEXPORT) continue; - auto const inner = ExportLedgerOps::innerExportedTx(*outer); - if (!inner) + auto const baseTarget = + ExportLedgerOps::exportIntentTarget(*outer); + if (!baseTarget) continue; auto const universeHash = @@ -2831,19 +2833,20 @@ ConsensusExtensions::onPreBuild( if (!committee) continue; - auto const targetNetworkID = inner->isFieldPresent(sfNetworkID) - ? inner->getFieldU32(sfNetworkID) + auto const targetNetworkID = + baseTarget->isFieldPresent(sfNetworkID) + ? baseTarget->getFieldU32(sfNetworkID) : std::uint32_t{0}; - auto const release = ExportOriginMemo::releaseForm( - *inner, + auto const signingPayload = ExportOriginMemo::releaseForm( + *baseTarget, ExportOriginMemo::Origin{ app_.config().NETWORK_ID, targetNetworkID, origin}, ExportOriginMemo::Anchor{originSeq, *originHash}); - if (!release) + if (!signingPayload) continue; auto material = agreedExportWitness( - release.value(), + signingPayload.value(), origin, committeeBitmap, validatorView->orderedOriginalMasterKeys.size(), @@ -2853,7 +2856,7 @@ ConsensusExtensions::onPreBuild( auto witness = ExportResultBuilder::buildSignatureWitness( origin, - release.value(), + signingPayload.value(), material->signatures, validatorView->orderedOriginalMasterKeys.size(), seq); diff --git a/src/xrpld/app/consensus/ConsensusExtensions.h b/src/xrpld/app/consensus/ConsensusExtensions.h index 5b86da7cd..44419aa14 100644 --- a/src/xrpld/app/consensus/ConsensusExtensions.h +++ b/src/xrpld/app/consensus/ConsensusExtensions.h @@ -434,7 +434,7 @@ public: std::optional agreedExportWitness( - STTx const& releaseTarget, + STTx const& exportSigningPayload, uint256 const& origin, Blob const& committee, std::size_t universeSize, diff --git a/src/xrpld/app/consensus/ExportSignatureHarvester.cpp b/src/xrpld/app/consensus/ExportSignatureHarvester.cpp index de72aa0eb..481f690ab 100644 --- a/src/xrpld/app/consensus/ExportSignatureHarvester.cpp +++ b/src/xrpld/app/consensus/ExportSignatureHarvester.cpp @@ -48,8 +48,8 @@ verifyExportSignatureAgainstTx( return false; } - auto innerTx = ExportLedgerOps::innerExportedTx(exportTx); - if (!innerTx) + auto embeddedTarget = ExportLedgerOps::embeddedExportedTxn(exportTx); + if (!embeddedTarget) { JLOG(j.warn()) << "Export: failed to verify sig" << " txHash=" << txHash << " source=" << source @@ -61,7 +61,8 @@ verifyExportSignatureAgainstTx( try { auto const signerAcctID = calcAccountID(validator); - auto const sigData = buildMultiSigningData(*innerTx, signerAcctID); + auto const sigData = + buildMultiSigningData(*embeddedTarget, signerAcctID); if (!verify(validator, sigData.slice(), sigSlice)) { JLOG(j.warn()) << "Export: invalid multisign sig" diff --git a/src/xrpld/app/tx/detail/Change.cpp b/src/xrpld/app/tx/detail/Change.cpp index 32bb59e1e..9f2299011 100644 --- a/src/xrpld/app/tx/detail/Change.cpp +++ b/src/xrpld/app/tx/detail/Change.cpp @@ -355,25 +355,25 @@ Change::applyExportSignatures() return tefFAILURE; auto const origin = ctx_.tx.getFieldH256(sfTransactionHash); - auto target = ExportLedgerOps::innerExportedTx(ctx_.tx); + auto signingPayload = ExportLedgerOps::exportWitnessSigningPayload(ctx_.tx); auto signatures = ExportResultBuilder::signaturesFromWitness(ctx_.tx); - if (!target || !signatures || signatures->empty()) + if (!signingPayload || !signatures || signatures->empty()) return tefFAILURE; - auto const stamp = ExportOriginMemo::parse(*target); + auto const stamp = ExportOriginMemo::parse(*signingPayload); if (!stamp || !stamp.value().anchor || stamp.value().origin.sourceDomain != ctx_.app.config().NETWORK_ID || stamp.value().origin.transactionHash != origin) return tefFAILURE; - auto const targetDomain = target->isFieldPresent(sfNetworkID) - ? target->getFieldU32(sfNetworkID) + auto const targetDomain = signingPayload->isFieldPresent(sfNetworkID) + ? signingPayload->getFieldU32(sfNetworkID) : std::uint32_t{0}; if (stamp.value().origin.targetDomain != targetDomain || - !target->isFieldPresent(sfTicketSequence)) + !signingPayload->isFieldPresent(sfTicketSequence)) return tefFAILURE; - auto const account = target->getAccountID(sfAccount); + auto const account = signingPayload->getAccountID(sfAccount); auto const latchKey = keylet::exportLatch(account, origin); auto const latch = view().read(latchKey); // A concurrently ordered explicit erase may remove the latch after the @@ -387,7 +387,7 @@ Change::applyExportSignatures() latch->getAccountID(sfAccount) != account || latch->getFieldH256(sfTransactionHash) != origin || latch->getFieldU32(sfTicketSequence) != - target->getFieldU32(sfTicketSequence) || + signingPayload->getFieldU32(sfTicketSequence) || stamp.value().anchor->ledgerSequence != latch->getFieldU32(sfLedgerSequence)) return tefFAILURE; @@ -397,7 +397,7 @@ Change::applyExportSignatures() // The origin-keyed latch can only exist on descendants of the ledger that // created it. Do not query mutable local history here: qC authenticated the // anchor bytes, while replay must depend only on transaction and state. - auto const identity = ExportOriginMemo::projectIdentity(*target); + auto const identity = ExportOriginMemo::projectIdentity(*signingPayload); if (!identity || ExportResultBuilder::exportIntentHash(identity.value()) != latch->getFieldH256(sfDigest)) @@ -435,7 +435,7 @@ Change::applyExportSignatures() auto const signer = calcAccountID(witness.signingKey); if (!signerAccounts.insert(signer).second) return tefFAILURE; - auto const data = buildMultiSigningData(*target, signer); + auto const data = buildMultiSigningData(*signingPayload, signer); if (!verify( witness.signingKey, data.slice(), diff --git a/src/xrpld/app/tx/detail/Export.cpp b/src/xrpld/app/tx/detail/Export.cpp index 593bf9310..b283b2c85 100644 --- a/src/xrpld/app/tx/detail/Export.cpp +++ b/src/xrpld/app/tx/detail/Export.cpp @@ -88,31 +88,31 @@ Export::preclaim(PreclaimContext const& ctx) ctx.tx.getFieldH256(sfExportUniverseHash) != ctx.view.info().parentHash) return tecEXPORT_UNIVERSE_MISMATCH; - auto innerTx = ExportLedgerOps::innerExportedTx(ctx.tx); - if (!innerTx) + auto baseTarget = ExportLedgerOps::exportIntentTarget(ctx.tx); + if (!baseTarget) return temMALFORMED; if (auto ter = - ExportLedgerOps::validateExportSigningFields(*innerTx, ctx.j); + ExportLedgerOps::validateExportSigningFields(*baseTarget, ctx.j); !isTesSuccess(ter)) return ter; if (auto ter = ExportLedgerOps::validateExportAccount( - *innerTx, ctx.tx.getAccountID(sfAccount), ctx.j); + *baseTarget, ctx.tx.getAccountID(sfAccount), ctx.j); !isTesSuccess(ter)) return ter; if (auto ter = ExportLedgerOps::validateNetworkID( - *innerTx, ctx.app.config().NETWORK_ID, ctx.j); + *baseTarget, ctx.app.config().NETWORK_ID, ctx.j); !isTesSuccess(ter)) return ter; if (auto ter = ExportLedgerOps::validateOriginMemoProjection( - *innerTx, ctx.app.config().NETWORK_ID, ctx.j); + *baseTarget, ctx.app.config().NETWORK_ID, ctx.j); !isTesSuccess(ter)) return ter; - if (auto ter = ExportLedgerOps::validateTicketSequence(*innerTx, ctx.j); + if (auto ter = ExportLedgerOps::validateTicketSequence(*baseTarget, ctx.j); !isTesSuccess(ter)) return ter; @@ -145,8 +145,8 @@ Export::doApply() // --- Export intent path --- auto const txId = ctx_.tx.getTransactionID(); auto const currentSeq = view().info().seq; - auto innerTx = ExportLedgerOps::innerExportedTx(ctx_.tx); - if (!innerTx) + auto baseTarget = ExportLedgerOps::exportIntentTarget(ctx_.tx); + if (!baseTarget) return temMALFORMED; auto parentLedger = ctx_.replayParentLedger(); @@ -183,11 +183,11 @@ Export::doApply() if (!committee) return tecEXPORT_UNIVERSE_MISMATCH; - auto const targetNetworkID = innerTx->isFieldPresent(sfNetworkID) - ? innerTx->getFieldU32(sfNetworkID) + auto const targetNetworkID = baseTarget->isFieldPresent(sfNetworkID) + ? baseTarget->getFieldU32(sfNetworkID) : std::uint32_t{0}; auto identity = ExportOriginMemo::identityForm( - *innerTx, + *baseTarget, ExportOriginMemo::Origin{ ctx_.app.config().NETWORK_ID, targetNetworkID, txId}); if (!identity) diff --git a/src/xrpld/app/tx/detail/ExportLedgerOps.h b/src/xrpld/app/tx/detail/ExportLedgerOps.h index 857a32ecd..efa65fd48 100644 --- a/src/xrpld/app/tx/detail/ExportLedgerOps.h +++ b/src/xrpld/app/tx/detail/ExportLedgerOps.h @@ -82,7 +82,7 @@ isPendingExportWorkTxn(STTx const& stx) } inline std::optional -innerExportedTx(STTx const& stx) +embeddedExportedTxn(STTx const& stx) { if (!stx.isFieldPresent(sfExportedTxn)) return std::nullopt; @@ -103,6 +103,22 @@ innerExportedTx(STTx const& stx) } } +inline std::optional +exportIntentTarget(STTx const& stx) +{ + if (stx.getTxnType() != ttEXPORT) + return std::nullopt; + return embeddedExportedTxn(stx); +} + +inline std::optional +exportWitnessSigningPayload(STTx const& stx) +{ + if (stx.getTxnType() != ttEXPORT_SIGNATURES) + return std::nullopt; + return embeddedExportedTxn(stx); +} + inline std::size_t exportTxnCount(ReadView const& view) { diff --git a/src/xrpld/app/tx/detail/ExportResultBuilder.cpp b/src/xrpld/app/tx/detail/ExportResultBuilder.cpp index cbda7cecc..c6d9cf557 100644 --- a/src/xrpld/app/tx/detail/ExportResultBuilder.cpp +++ b/src/xrpld/app/tx/detail/ExportResultBuilder.cpp @@ -156,13 +156,13 @@ buildMultiSignedExportedTxn( STTx buildSignatureWitness( uint256 const& exportTxHash, - STTx const& releaseTarget, + STTx const& exportSigningPayload, PositionedSignatureSnapshot const& signatures, std::size_t const universeSize, LedgerIndex currentSeq) { auto witnessSignatures = buildWitnessSignatures(signatures, universeSize); - auto const target = normalizeAuthorizationEnvelope(releaseTarget); + auto const target = normalizeAuthorizationEnvelope(exportSigningPayload); return STTx(ttEXPORT_SIGNATURES, [&](auto& obj) { obj.setFieldU32(sfLedgerSequence, currentSeq); obj.setAccountID(sfAccount, AccountID{}); diff --git a/src/xrpld/app/tx/detail/ExportResultBuilder.h b/src/xrpld/app/tx/detail/ExportResultBuilder.h index 76bb7eb2a..c8cb2c0ad 100644 --- a/src/xrpld/app/tx/detail/ExportResultBuilder.h +++ b/src/xrpld/app/tx/detail/ExportResultBuilder.h @@ -61,7 +61,7 @@ buildMultiSignedExportedTxn( STTx buildSignatureWitness( uint256 const& exportTxHash, - STTx const& releaseTarget, + STTx const& exportSigningPayload, PositionedSignatureSnapshot const& signatures, std::size_t universeSize, LedgerIndex currentSeq);