Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add additional block lag for better sync mode switching for chain with shorter block processing time #7892

Merged
merged 8 commits into from
Dec 19, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,7 @@ public interface ISyncConfig : IConfig

[ConfigItem(Description = "_Technical._ Run explicit GC after state sync finished.", DefaultValue = "true", HiddenFromDocs = true)]
bool GCOnFeedFinished { get; set; }

[ConfigItem(Description = "_Technical._ Max distance between best suggested header and available state to assume state is synced.", DefaultValue = "0", HiddenFromDocs = true)]
int HeaderStateDistance { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ public string? PivotHash
public int StateMinDistanceFromHead { get; set; } = 32;
public bool GCOnFeedFinished { get; set; } = true;

/// Additional delay in blocks between best suggested header and synced state to allow faster state switching for PoW chains
/// with higher block processing frequency. Effectively this is the max allowed difference between best header (used as sync
/// pivot) and synced state block, to assume that state is synced and node can start processing blocks
damian-orzechowski marked this conversation as resolved.
Show resolved Hide resolved
public int HeaderStateDistance { get; set; } = 0;

public override string ToString()
{
return
Expand Down
5 changes: 3 additions & 2 deletions src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
"SnapSync": true,
"PivotNumber": 13310000,
"PivotHash": "0x4f899c26f26ac8e85272864201f46e030ffed46372dd052998bee8463255fcff",
"PivotTotalDifficulty": "26620001"
"PivotTotalDifficulty": "26620001",
"HeaderStateDistance": 6
},
"JsonRpc": {
"Enabled": true,
"Port": 8545
}
}
}
5 changes: 3 additions & 2 deletions src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
"SnapSync": true,
"PivotNumber": 7090000,
"PivotHash": "0xf8e4888bd895671f2290cce1caa4ac326d896df16136476b97a3c3abdb866ada",
"PivotTotalDifficulty": "14180001"
"PivotTotalDifficulty": "14180001",
"HeaderStateDistance": 6
},
"JsonRpc": {
"Enabled": true,
"Port": 8545
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,18 @@ public void When_just_started_full_sync()
.TheSyncModeShouldBe(GetBeaconSyncExpectations(SyncMode.Full));
}

[Test]
public void When_finished_state_sync_and_header_moved_forward()
{
Scenario.GoesLikeThis(_needToWaitForHeaders)
.WhenInBeaconSyncMode(BeaconSync.None)
.IfThisNodeJustFinishedStateSyncButBehindHeader(FastBlocksState.FinishedHeaders)
.AndGoodPeersAreKnown()
.WhenSnapSyncIsConfigured()
.WhenStateAndBestHeaderCanBeBeDifferent(6) //allow best state to be max 6 block apart from best block header
.TheSyncModeShouldBe(SyncMode.Full | SyncMode.FastBodies);
}

[TestCase(FastBlocksState.None)]
[TestCase(FastBlocksState.FinishedHeaders)]
[TestCase(FastBlocksState.FinishedBodies)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,25 @@ public ScenarioBuilder IfThisNodeJustStartedFullSyncProcessing(FastBlocksState f
return this;
}

public ScenarioBuilder IfThisNodeJustFinishedStateSyncButBehindHeader(FastBlocksState fastBlocksState = FastBlocksState.FinishedReceipts)
{
long currentBlock = ChainHead.Number - MultiSyncModeSelector.FastSyncLag;
_syncProgressSetups.Add(
() =>
{
SyncProgressResolver.FindBestHeader().Returns(currentBlock);
SyncProgressResolver.FindBestFullBlock().Returns(0); //no full blocks available
SyncProgressResolver.FindBestFullState().Returns(currentBlock - 4); //pivot is set to header, but then header follows the head of the chain
SyncProgressResolver.FindBestProcessedBlock().Returns(0);
SyncProgressResolver.IsFastBlocksFinished().Returns(fastBlocksState);
SyncProgressResolver.ChainDifficulty.Returns((UInt256)currentBlock);
SyncProgressResolver.IsSnapGetRangesFinished().Returns(true);
return "just started full sync";
}
);
return this;
}

public ScenarioBuilder IfThisNodeRecentlyStartedFullSyncProcessing(FastBlocksState fastBlocksState = FastBlocksState.FinishedReceipts)
{
long currentBlock = ChainHead.Number - MultiSyncModeSelector.FastSyncLag / 2;
Expand Down Expand Up @@ -673,6 +692,12 @@ public ScenarioBuilder WhenThisNodeIsLoadingBlocksFromDb()
return this;
}

public ScenarioBuilder WhenStateAndBestHeaderCanBeBeDifferent(int maxBlockDiff)
{
_overwrites.Add(() => SyncConfig.HeaderStateDistance = maxBlockDiff);
return this;
}

public ScenarioBuilder ThenInAnySyncConfiguration()
{
WhenFullArchiveSyncIsConfigured();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ private bool ShouldBeInFastSyncMode(Snapshot best)
// and we need to sync away from it.
// Note: its ok if target block height is not accurate as long as long full sync downloader does not stop
// earlier than this condition below which would cause a hang.
bool notReachedFullSyncTransition = best.Header < best.TargetBlock - FastSyncLag;
bool notReachedFullSyncTransition = best.Header < best.TargetBlock - FastSyncLag - _syncConfig.HeaderStateDistance;
damian-orzechowski marked this conversation as resolved.
Show resolved Hide resolved

bool notInAStickyFullSync = !IsInAStickyFullSyncMode(best);
bool notHasJustStartedFullSync = !HasJustStartedFullSync(best);
Expand Down Expand Up @@ -589,8 +589,8 @@ private bool ShouldBeInStateSyncMode(Snapshot best)
bool notInFastSync = !best.IsInFastSync;
bool notNeedToWaitForHeaders = NotNeedToWaitForHeaders;
bool stickyStateNodes = best.TargetBlock - best.Header < (FastSyncLag + StickyStateNodesDelta);
bool stateNotDownloadedYet = (best.TargetBlock - best.State > FastSyncLag ||
best.Header > best.State && best.Header > best.Block);
bool stateNotDownloadedYet = (best.TargetBlock - best.State > (FastSyncLag + _syncConfig.HeaderStateDistance) ||
best.Header > (best.State + _syncConfig.HeaderStateDistance) && best.Header > best.Block);
bool notInAStickyFullSync = !IsInAStickyFullSyncMode(best);
bool notHasJustStartedFullSync = !HasJustStartedFullSync(best);

Expand Down Expand Up @@ -644,7 +644,7 @@ private bool ShouldBeInStateNodesMode(Snapshot best)
private bool ShouldBeInSnapRangesPhase(Snapshot best)
{
bool isInStateSync = best.IsInStateSync;
bool isCloseToHead = best.TargetBlock >= best.Header && (best.TargetBlock - best.Header) <= FastSyncLag;
bool isCloseToHead = best.TargetBlock >= best.Header && (best.TargetBlock - best.Header) <= FastSyncLag + _syncConfig.HeaderStateDistance;
bool snapNotFinished = !_syncProgressResolver.IsSnapGetRangesFinished();

if (_logger.IsTrace)
Expand Down
Loading