mirror of
https://github.com/Xahau/xahaud.git
synced 2026-09-27 07:36:52 +00:00
fix(consensus): rebuild accepted export witnesses against the round parent
This commit is contained in:
@@ -2569,19 +2569,34 @@ ConsensusExtensions::onPreBuild(
|
||||
auto const parent =
|
||||
app_.getLedgerMaster().getLedgerByHash(roundPrevLedgerHash_);
|
||||
auto const validated = app_.getLedgerMaster().getValidatedLedger();
|
||||
bool parentExtendsValidated =
|
||||
parent && validated && validated->info().seq <= parent->info().seq;
|
||||
if (parentExtendsValidated &&
|
||||
// Rebuild only from this round's exact parent and accepted evidence.
|
||||
// Local validation can lag that parent or already have passed it.
|
||||
// Preserve the competing-ancestry guard in either direction without
|
||||
// making cursor progress itself change the synthetic transaction set.
|
||||
// Live share admission/signing/release retain their validated-ledger
|
||||
// checks; this boundary neither admits nor publishes a new share.
|
||||
bool parentCompatibleWithValidated =
|
||||
parent && validated && seq > 0 && parent->info().seq == seq - 1;
|
||||
if (parentCompatibleWithValidated &&
|
||||
validated->info().seq < parent->info().seq)
|
||||
{
|
||||
auto const validatedHash =
|
||||
hashOfSeq(*parent, validated->info().seq, j_);
|
||||
parentExtendsValidated =
|
||||
parentCompatibleWithValidated =
|
||||
validatedHash && *validatedHash == validated->info().hash;
|
||||
}
|
||||
else if (parentExtendsValidated)
|
||||
else if (
|
||||
parentCompatibleWithValidated &&
|
||||
validated->info().seq > parent->info().seq)
|
||||
{
|
||||
parentExtendsValidated =
|
||||
auto const parentHash =
|
||||
hashOfSeq(*validated, parent->info().seq, j_);
|
||||
parentCompatibleWithValidated =
|
||||
parentHash && *parentHash == parent->info().hash;
|
||||
}
|
||||
else if (parentCompatibleWithValidated)
|
||||
{
|
||||
parentCompatibleWithValidated =
|
||||
parent->info().hash == validated->info().hash;
|
||||
}
|
||||
|
||||
@@ -2593,8 +2608,8 @@ ConsensusExtensions::onPreBuild(
|
||||
<< " validatedHash="
|
||||
<< (validated ? to_string(validated->info().hash)
|
||||
: std::string{"none"})
|
||||
<< " parentExtendsValidated=" << parentExtendsValidated
|
||||
<< " acceptedRoot="
|
||||
<< " parentCompatibleWithValidated="
|
||||
<< parentCompatibleWithValidated << " acceptedRoot="
|
||||
<< (acceptedExportSigSetHash_
|
||||
? to_string(*acceptedExportSigSetHash_)
|
||||
: std::string{"none"})
|
||||
@@ -2604,7 +2619,7 @@ ConsensusExtensions::onPreBuild(
|
||||
: std::string{"none"})
|
||||
<< " convergenceFailed=" << exportSigConvergenceFailed_;
|
||||
|
||||
if (parentExtendsValidated)
|
||||
if (parentCompatibleWithValidated)
|
||||
{
|
||||
auto const pending = pendingExportLatches(*parent, seq);
|
||||
std::size_t materialized = 0;
|
||||
@@ -2626,14 +2641,9 @@ ConsensusExtensions::onPreBuild(
|
||||
|
||||
auto const originSeq = latch->getFieldU32(sfLedgerSequence);
|
||||
auto const originHash = hashOfSeq(*parent, originSeq, j_);
|
||||
auto const validatedOriginHash =
|
||||
originSeq == validated->info().seq
|
||||
? std::optional<uint256>{validated->info().hash}
|
||||
: hashOfSeq(*validated, originSeq, j_);
|
||||
if (!originHash || !validatedOriginHash ||
|
||||
*originHash != *validatedOriginHash)
|
||||
if (!originHash)
|
||||
{
|
||||
skip("origin-ancestry-unavailable-or-mismatched");
|
||||
skip("origin-not-in-round-parent-ancestry");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2752,7 +2762,7 @@ ConsensusExtensions::onPreBuild(
|
||||
JLOG(j_.debug())
|
||||
<< "Export: preBuild witnesses skipped"
|
||||
<< " buildSeq=" << seq
|
||||
<< " reason=parent-not-descendant-of-current-validation";
|
||||
<< " reason=parent-unavailable-or-incompatible-with-validation";
|
||||
}
|
||||
//@@end export-later-ledger-witness-materialization
|
||||
}
|
||||
|
||||
@@ -131,11 +131,18 @@ Standalone test execution substitutes exact possession of its locally verified
|
||||
map; intent admission still requires the UNLReport-backed parent state. Late
|
||||
collector arrivals cannot mutate the accepted root.
|
||||
|
||||
Materialization also requires the consensus parent to descend from the node's
|
||||
validated ledger, the origin ledger hash to agree through both ancestry views,
|
||||
and the exact origin ledger and `ttEXPORT` transaction to be locally available.
|
||||
If any of that validated possession is absent, the latch remains pending; a
|
||||
build cursor ahead of validation never forces witness production.
|
||||
Witness rebuilding resolves the origin through the exact consensus parent's
|
||||
ancestry and requires the exact origin ledger and `ttEXPORT` transaction to be
|
||||
locally available. The local validated ledger must be on compatible ancestry:
|
||||
it may be an ancestor of that parent or already a descendant of it. Known
|
||||
competing ancestry still prevents materialization, but progress of this local
|
||||
cursor alone must not change the synthetic transaction set for a fixed parent
|
||||
and accepted root. Missing accepted-root material or origin-ledger possession
|
||||
still prevents witness construction.
|
||||
|
||||
This rebuild rule does not authorize share admission, signing or release from
|
||||
a merely closed parent. Those live paths retain the source-validation checks
|
||||
in INV-4 and INV-5; an origin ahead of local validation remains deferred there.
|
||||
|
||||
*Anti-pattern:* assembling from the current collector at apply time or treating
|
||||
peer root support as remote payload availability.
|
||||
|
||||
Reference in New Issue
Block a user