mirror of
https://github.com/Xahau/xahaud.git
synced 2026-07-27 00:50:20 +00:00
refactor(export): name transaction phases explicitly
This commit is contained in:
@@ -72,7 +72,7 @@ namespace {
|
||||
struct ResolvedExportShare
|
||||
{
|
||||
std::shared_ptr<SLE const> 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::ExportWitnessMaterial>
|
||||
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);
|
||||
|
||||
@@ -434,7 +434,7 @@ public:
|
||||
|
||||
std::optional<ExportWitnessMaterial>
|
||||
agreedExportWitness(
|
||||
STTx const& releaseTarget,
|
||||
STTx const& exportSigningPayload,
|
||||
uint256 const& origin,
|
||||
Blob const& committee,
|
||||
std::size_t universeSize,
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -82,7 +82,7 @@ isPendingExportWorkTxn(STTx const& stx)
|
||||
}
|
||||
|
||||
inline std::optional<STTx>
|
||||
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<STTx>
|
||||
exportIntentTarget(STTx const& stx)
|
||||
{
|
||||
if (stx.getTxnType() != ttEXPORT)
|
||||
return std::nullopt;
|
||||
return embeddedExportedTxn(stx);
|
||||
}
|
||||
|
||||
inline std::optional<STTx>
|
||||
exportWitnessSigningPayload(STTx const& stx)
|
||||
{
|
||||
if (stx.getTxnType() != ttEXPORT_SIGNATURES)
|
||||
return std::nullopt;
|
||||
return embeddedExportedTxn(stx);
|
||||
}
|
||||
|
||||
inline std::size_t
|
||||
exportTxnCount(ReadView const& view)
|
||||
{
|
||||
|
||||
@@ -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{});
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user