-
Notifications
You must be signed in to change notification settings - Fork 0
Attempt to fix progression halting via tainted SyncStatus #435
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
base: celo-integration-rebase-17
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -243,6 +243,8 @@ func TestE2eDevnetWithL1Reorg(t *testing.T) { | |
| if have, want := err, error(nil); have != want { | ||
| t.Fatalf("failed to start dev environment with espresso dev node:\nhave:\n\t\"%v\"\nwant:\n\t\"%v\"\n", have, want) | ||
| } | ||
| defer env.Stop(t, system) | ||
| defer env.Stop(t, devNode) | ||
|
|
||
| caffNode, err := env.LaunchCaffNode(t, system, devNode) | ||
| if have, want := err, error(nil); have != want { | ||
|
|
@@ -254,3 +256,35 @@ func TestE2eDevnetWithL1Reorg(t *testing.T) { | |
|
|
||
| runL1Reorg(ctx, t, system) | ||
| } | ||
|
|
||
| // TestE2eEspressoStreamerSyncStatusTainting is a test that is meant to ensure | ||
| // that a tainted `SyncStatus` coming in to set the `safeBatchNumber` of the | ||
| // `Refresh` call to something like `0`, will ultimately not result in halting | ||
| // the progression of the chain through `Espresso`. | ||
| func TestE2eEspressoStreamerSyncStatusTainting(t *testing.T) { | ||
| ctx, cancel := context.WithCancel(context.Background()) | ||
| defer cancel() | ||
|
|
||
| launcher := new(env.EspressoDevNodeLauncherDocker) | ||
|
|
||
| system, devNode, err := launcher.StartE2eDevnet(ctx, t) | ||
| require.NoError(t, err) | ||
|
|
||
| defer env.Stop(t, system) | ||
| defer env.Stop(t, devNode) | ||
|
|
||
| l2Seq := system.NodeClient(e2esys.RoleSeq) | ||
| // l1Client := system.NodeClient(e2esys.RoleL1) | ||
| // caffClient := system.NodeClient(env.RoleCaffNode) | ||
| geth.WaitForBlockToBeFinalized(big.NewInt(5), l2Seq, time.Minute*2) | ||
|
|
||
| l2Node := system.RollupClient(e2esys.RoleSeq) | ||
|
|
||
| status, err := l2Node.SyncStatus(ctx) | ||
| require.NoError(t, err) | ||
|
|
||
| err = system.BatchSubmitter.EspressoStreamer().Refresh(ctx, status.FinalizedL1, 0, status.FinalizedL2.L1Origin) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good test — this directly exercises the tainted SyncStatus path by calling One consideration: with a 5-minute timeout and only needing 2 more blocks finalized, this should be robust. But if the devnet is slow to start, the initial |
||
| require.NoError(t, err) | ||
|
|
||
| geth.WaitForBlockToBeFinalized(big.NewInt(int64(status.UnsafeL2.Number)+2), l2Seq, time.Minute*5) | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -859,6 +859,28 @@ func (l *BatchSubmitter) espressoSyncAndRefresh(ctx context.Context, newSyncStat | |||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| // skipStreamerToTargetBlockHeight will consume batches from the | ||||||||||||||||
| // `EspressoStreamer` until we reach the target block height, or run out | ||||||||||||||||
| // of batches to consume. | ||||||||||||||||
| // | ||||||||||||||||
| // NOTE: this is **NOT** guaranteed to ensure that the next `Batch` will | ||||||||||||||||
| // be the expected height, it's just a best effort. | ||||||||||||||||
| func (l *BatchSubmitter) skipStreamerToTargetBlockHeight(ctx context.Context, targetHeight uint64) { | ||||||||||||||||
| streamer := l.EspressoStreamer() | ||||||||||||||||
| batch := streamer.Peek(ctx) | ||||||||||||||||
| for batch != nil && batch.Number() < targetHeight { | ||||||||||||||||
| // Consume the Batch | ||||||||||||||||
| streamer.Next(ctx) | ||||||||||||||||
| batch = streamer.Peek(ctx) | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| // isHashNoptSet is a helper function to check if a hash is the zero | ||||||||||||||||
|
Comment on lines
+877
to
+878
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: the doc comment says
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||
| // value (not set). | ||||||||||||||||
| func isHashEmpty(hash common.Hash) bool { | ||||||||||||||||
| return hash == (common.Hash{}) | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| // peekNextBatch returns the next batch from the streamer, performing a fork check | ||||||||||||||||
| // against an expected parent hash. | ||||||||||||||||
| // | ||||||||||||||||
|
|
@@ -867,26 +889,36 @@ func (l *BatchSubmitter) espressoSyncAndRefresh(ctx context.Context, newSyncStat | |||||||||||||||
| // the one position where we can set tip to the known safe head. Otherwise we accept the batch as-is. | ||||||||||||||||
| func (l *BatchSubmitter) peekNextBatch(ctx context.Context, syncStatus *eth.SyncStatus) *derive.EspressoBatch { | ||||||||||||||||
| l.channelMgrMutex.Lock() | ||||||||||||||||
| tip := l.channelMgr.tip | ||||||||||||||||
| var tipBlock SizedBlock | ||||||||||||||||
| if len(l.channelMgr.blocks) > 0 { | ||||||||||||||||
| tipBlock = l.channelMgr.blocks[len(l.channelMgr.blocks)-1] | ||||||||||||||||
|
Comment on lines
+893
to
+894
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is an inconsistency in how the length of
Suggested change
|
||||||||||||||||
| } | ||||||||||||||||
| l.channelMgrMutex.Unlock() | ||||||||||||||||
|
|
||||||||||||||||
| targetBlock := syncStatus.SafeL2.Number + 1 | ||||||||||||||||
| tipHash := syncStatus.SafeL2.Hash | ||||||||||||||||
| if tipBlock != (SizedBlock{}) && tipBlock.Block != nil { | ||||||||||||||||
|
Comment on lines
+898
to
+900
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the core logic change and the heart of the fix. In the old code, The new approach improves on this significantly:
This should handle the tainted SyncStatus case well — if One question: when I think this is fine because There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The check
Suggested change
|
||||||||||||||||
| targetBlock = tipBlock.NumberU64() + 1 | ||||||||||||||||
| tipHash = tipBlock.Hash() | ||||||||||||||||
| } else if batch := l.EspressoStreamer().Peek(ctx); batch != nil && batch.Number() == targetBlock { | ||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This In practice this may be safe because |
||||||||||||||||
| // Log indicating that we utilized the SafeL2 Hash as the next | ||||||||||||||||
| // Streamer entry matched our expected Safe L2, and we didn't | ||||||||||||||||
| // have any tip information from the Channel Manager. | ||||||||||||||||
| l.Log.Debug( | ||||||||||||||||
| "setting tip to safe l2 hash", | ||||||||||||||||
| "batchNr", batch.Number(), | ||||||||||||||||
| "batchParent", batch.Header().ParentHash.Hex(), | ||||||||||||||||
| "tip", tipHash, | ||||||||||||||||
|
Comment on lines
+909
to
+911
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For consistency in logging, it is recommended to use
Suggested change
|
||||||||||||||||
| ) | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| l.skipStreamerToTargetBlockHeight(ctx, targetBlock) | ||||||||||||||||
| batch := l.EspressoStreamer().Peek(ctx) | ||||||||||||||||
| if batch == nil { | ||||||||||||||||
| return nil | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| // Check if we can set the tip if not set | ||||||||||||||||
| if tip == (common.Hash{}) && (*batch).Number() == syncStatus.SafeL2.Number+1 { | ||||||||||||||||
| l.Log.Info( | ||||||||||||||||
| "setting tip to safe l2 hash", | ||||||||||||||||
| "batchNr", (*batch).Number(), | ||||||||||||||||
| "batchParent", (*batch).Header().ParentHash.Hex(), | ||||||||||||||||
| "tip", tip, | ||||||||||||||||
| ) | ||||||||||||||||
| tip = syncStatus.SafeL2.Hash | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| if tip == (common.Hash{}) { | ||||||||||||||||
| if isHashEmpty(tipHash) { | ||||||||||||||||
| l.Log.Warn( | ||||||||||||||||
| "tip is not set, taking available batch", | ||||||||||||||||
| "blockParentHash", (*batch).Header().ParentHash.Hex(), | ||||||||||||||||
|
|
@@ -895,14 +927,14 @@ func (l *BatchSubmitter) peekNextBatch(ctx context.Context, syncStatus *eth.Sync | |||||||||||||||
| return batch | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| if (*batch).Header().ParentHash != tip { | ||||||||||||||||
| if batch.Header().ParentHash != tipHash { | ||||||||||||||||
| l.Log.Warn( | ||||||||||||||||
| "head batch fork mismatch, seeking to proper head", | ||||||||||||||||
| "batchNr", (*batch).Number(), | ||||||||||||||||
| "batchParent", (*batch).Header().ParentHash, | ||||||||||||||||
| "tip", tip, | ||||||||||||||||
| "tip", tipHash, | ||||||||||||||||
|
Comment on lines
933
to
+935
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The logging here is inconsistent with previous log entries in the same function (e.g., line 910). It is recommended to use
Suggested change
|
||||||||||||||||
| ) | ||||||||||||||||
| l.EspressoStreamer().SetProperHead(tip) | ||||||||||||||||
| l.EspressoStreamer().SetProperHead(tipHash) | ||||||||||||||||
| return nil | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: these commented-out client declarations suggest the test may be incomplete or these were used during development. If they're planned for future use, that's fine; otherwise consider removing them to keep the test clean.