From 07030e2b8757334013fd4975b50071e01d0fbb9d Mon Sep 17 00:00:00 2001 From: Nicholas Dudfield Date: Fri, 26 Jun 2026 17:23:19 +0700 Subject: [PATCH] fix(export): retry without parent validator view Network-mode Export apply must build its signer universe from the closed ledger's parent. If that parent ledger is unavailable, retry instead of falling back through makeActiveValidatorView to the node-local latest validated ledger. --- src/xrpld/app/tx/detail/Export.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/xrpld/app/tx/detail/Export.cpp b/src/xrpld/app/tx/detail/Export.cpp index 40586d6a4..90bb65d60 100644 --- a/src/xrpld/app/tx/detail/Export.cpp +++ b/src/xrpld/app/tx/detail/Export.cpp @@ -116,8 +116,17 @@ Export::doApply() } auto& consensusExtensions = ctx_.app.getConsensusExtensions(); + bool const standalone = ctx_.app.config().standalone(); auto const parentLedger = ctx_.app.getLedgerMaster().getLedgerByHash(view().info().parentHash); + if (!standalone && !parentLedger) + { + JLOG(j_.warn()) << "Export: retrying without parent ledger" + << " txHash=" << txId << " ledgerSeq=" << currentSeq + << " parentHash=" << view().info().parentHash; + return terRETRY_EXPORT; + } + auto const validatorView = consensusExtensions.makeActiveValidatorView(parentLedger); auto const isActiveSigner = [&consensusExtensions, @@ -148,7 +157,7 @@ Export::doApply() STTx innerTx(std::ref(sit)); auto upgradeUnverifiedForNextRound = [&]() { - if (ctx_.app.config().standalone()) + if (standalone) return; // Closed-ledger apply must not create new current-round quorum @@ -170,7 +179,7 @@ Export::doApply() // succeeds; the agreed sidecar map is the ledger-defining snapshot. std::optional> collectedSigs; - if (!ctx_.app.config().standalone()) + if (!standalone) { //@@start export-doapply-agreed-signature-snapshot std::size_t const threshold = safeQuorumThreshold(unlSize); @@ -249,7 +258,7 @@ Export::doApply() } ExportResultBuilder::SignatureSnapshot signatures; - if (ctx_.app.config().standalone()) + if (standalone) { // Standalone mode: no consensus proposals, so we sign // the inner tx directly with our own validator keys.