Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
525903a
feat(evm/sync): implement dynamic state sync orchestration
powerslider Mar 5, 2026
7b62f83
Merge branch 'master' into powerslider/dynamic-state-sync-poc
powerslider Mar 5, 2026
9246b21
feat(evm/sync): add sessioned code queue for pivot-anytime dynamic st…
powerslider Mar 5, 2026
23af203
Merge branch 'master' into powerslider/dynamic-state-sync-poc
powerslider Mar 5, 2026
a15da5a
fix: lint error
powerslider Mar 5, 2026
cfce189
fix(evm/sync): prevent re-entrancy infinite loop during batch replay
powerslider Mar 9, 2026
a51375a
Merge branch 'master' into powerslider/dynamic-state-sync-poc
powerslider Mar 9, 2026
94d7cf8
feat(evm/sync): harden coordinator state transitions and update seria…
powerslider Mar 9, 2026
74c1d27
feat(sync): add block syncer UpdateTarget with bounded catch-up
powerslider Mar 10, 2026
2847a9a
Merge branch 'master' into powerslider/dynamic-state-sync-poc
powerslider Mar 11, 2026
944845b
Merge branch 'master' into powerslider/dynamic-state-sync-poc
powerslider Mar 11, 2026
97b1107
refactor(evm/sync): implement dynamic sync as a lifecycle wrapper aro…
powerslider Mar 12, 2026
6789c82
Merge branch 'master' into powerslider/dynamic-state-sync-poc
powerslider Mar 12, 2026
e2915dc
feat(sync): enable atomic syncer to operate within dynamic sync
powerslider Mar 12, 2026
c1ed252
Merge branch 'master' into powerslider/dynamic-state-sync-poc
powerslider Mar 19, 2026
266e826
Merge branch 'master' into powerslider/dynamic-state-sync-poc
powerslider Mar 19, 2026
f4d4da4
feat(sync): enable firewood syncer for dynamic state sync
powerslider Mar 19, 2026
4df5cfe
Merge branch 'master' into powerslider/dynamic-state-sync-poc
powerslider Mar 23, 2026
af5c78d
chore: regenerate Bazel metadata
powerslider Mar 24, 2026
eb4e98e
test(sync): add pivot and fault-injection coordinator tests
powerslider Mar 26, 2026
d139492
Merge branch 'master' into powerslider/dynamic-state-sync-poc
powerslider Mar 26, 2026
e1d85b8
build(session) add BUILD.bazel
powerslider Mar 26, 2026
2d20520
build: re-generate bazel metadata
powerslider Mar 26, 2026
09d1dab
Merge branch 'master' into powerslider/dynamic-state-sync-poc
powerslider Mar 30, 2026
9d4049e
fix(sync): prevent double-accept of commit-target block during batch …
powerslider Mar 30, 2026
df38656
test(sync): add VM-level block injection test for dynamic state sync
powerslider Mar 31, 2026
aaf03b5
Merge branch 'master' into powerslider/dynamic-state-sync-poc
powerslider Mar 31, 2026
8621572
test(sync): add dynamic sync block injection test for subnet-evm and …
powerslider Mar 31, 2026
a1a72f0
fix(sync): use test deadline for gated AppRequests
powerslider Apr 7, 2026
9c63664
feat(sync): add dynamic pivot support for atomic syncer
powerslider Apr 7, 2026
0dea4f5
Merge branch 'master' into powerslider/dynamic-state-sync-poc
powerslider Apr 7, 2026
7a046aa
debug(sync): log sync client error on block injection failure
powerslider Apr 7, 2026
e4dcf65
fix(sync): inject blocks inside response interceptor to prevent sched…
powerslider Apr 8, 2026
4d849cc
fix(sync): reconcile chain.State after batch replay for correct engin…
powerslider Apr 14, 2026
e1b15aa
Merge branch 'master' into powerslider/dynamic-state-sync-poc
powerslider Apr 14, 2026
11e04ff
refactor(sync): remove TargetReporter since all syncers now pivot tog…
powerslider Apr 14, 2026
503e5c2
refactor(sync): simplify dynamic code syncer by removing session infr…
powerslider Apr 14, 2026
2148d63
Merge branch 'master' into powerslider/dynamic-state-sync-poc
powerslider Apr 14, 2026
2a66ff8
fix(sync): prevent commit target from advancing after syncers complete
powerslider Apr 14, 2026
7f60ee1
refactor(sync): reorder coordinator methods and tighten comments
powerslider Apr 14, 2026
8663962
Merge branch 'master' into powerslider/dynamic-state-sync-poc
powerslider Apr 27, 2026
6e4b514
fix(bootstrap): enable dynamic state sync pivots
powerslider Apr 27, 2026
771fb40
fix(bootstrap): pass sync target height via ConsensusContext
powerslider Apr 27, 2026
cfaf433
fix(bootstrap): skip BootstrapTracker wait during dynamic state sync
powerslider Apr 27, 2026
485035e
feat(bootstrap): skip bootstrapper during dynamic state sync
powerslider Apr 28, 2026
78ad231
fix(bootstrap): bound ancestor walk at sync target height
powerslider Apr 28, 2026
89946bf
fix(bootstrap): revert premature NormalOp transition
powerslider Apr 28, 2026
ccaa60d
refactor(proposervm): move sync target awareness to VM level
powerslider Apr 28, 2026
2fd45d3
chore(sync): add coordinator state transition logging
powerslider Apr 28, 2026
3d63829
fix(sync): more diagnostic logging
powerslider Apr 28, 2026
54d04a6
fix(bootstrap): defer NormalOp until dynamic state sync completes
powerslider Apr 28, 2026
cad23ff
feat(sync): incremental storage trie pivoting for dynamic state sync
powerslider Apr 28, 2026
4d6e8ea
chore(sync): add diagnostic logging for storage trie filter
powerslider Apr 28, 2026
231ddbd
chore(sync): add more diagnostic logging
powerslider Apr 29, 2026
b4a79d1
Merge branch 'master' into powerslider/dynamic-state-sync-poc
powerslider Apr 29, 2026
fd49583
chore(sync): more diagnostics
powerslider Apr 29, 2026
15a292e
fix(sync): clear only main trie segments on pivot, keep storage trie …
powerslider Apr 29, 2026
9622af3
fix(sync): clear stale main trie segments on pivot in dynamic syncer
powerslider Apr 29, 2026
2b5d1da
Merge branch 'master' into powerslider/dynamic-state-sync-poc
powerslider Apr 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ diff --git a/BUILD.bazel b/BUILD.bazel
new file mode 100644
--- /dev/null
+++ b/BUILD.bazel
@@ -0,0 +1,59 @@
@@ -0,0 +1, 59 @@
+# gazelle:ignore
+load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
+
Expand Down
4 changes: 2 additions & 2 deletions .bazel/patches/com_github_ava_labs_libevm.patch
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ diff --git a/crypto/secp256k1/BUILD.bazel b/crypto/secp256k1/BUILD.bazel
new file mode 100644
--- /dev/null
+++ b/crypto/secp256k1/BUILD.bazel
@@ -0,0 +1,27 @@
@@ -0,0 +1, 27 @@
+# gazelle:ignore
+load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
+
Expand Down Expand Up @@ -34,7 +34,7 @@ diff --git a/crypto/secp256k1/libsecp256k1/BUILD.bazel b/crypto/secp256k1/libsec
new file mode 100644
--- /dev/null
+++ b/crypto/secp256k1/libsecp256k1/BUILD.bazel
@@ -0,0 +1,9 @@
@@ -0,0 +1, 9 @@
+# gazelle:ignore
+cc_library(
+ name = "libsecp256k1",
Expand Down
10 changes: 5 additions & 5 deletions .bazel/patches/com_github_supranational_blst.patch
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ diff --git a/bindings/BUILD.bazel b/bindings/BUILD.bazel
new file mode 100644
--- /dev/null
+++ b/bindings/BUILD.bazel
@@ -0,0 +1,9 @@
@@ -0,0 +1, 9 @@
+# gazelle:ignore
+# Header library for blst C bindings
+
Expand All @@ -16,7 +16,7 @@ diff --git a/bindings/go/BUILD.bazel b/bindings/go/BUILD.bazel
new file mode 100644
--- /dev/null
+++ b/bindings/go/BUILD.bazel
@@ -0,0 +1,60 @@
@@ -0,0 +1, 60 @@
+# gazelle:ignore
+# Go bindings for blst library
+#
Expand Down Expand Up @@ -81,7 +81,7 @@ diff --git a/bindings/vectors/BUILD.bazel b/bindings/vectors/BUILD.bazel
new file mode 100644
--- /dev/null
+++ b/bindings/vectors/BUILD.bazel
@@ -0,0 +1,8 @@
@@ -0,0 +1, 8 @@
+# gazelle:ignore
+# Test vectors for blst
+
Expand All @@ -94,7 +94,7 @@ diff --git a/build/BUILD.bazel b/build/BUILD.bazel
new file mode 100644
--- /dev/null
+++ b/build/BUILD.bazel
@@ -0,0 +1,20 @@
@@ -0,0 +1, 20 @@
+# gazelle:ignore
+# Assembly and build file library for blst
+#
Expand All @@ -119,7 +119,7 @@ diff --git a/src/BUILD.bazel b/src/BUILD.bazel
new file mode 100644
--- /dev/null
+++ b/src/BUILD.bazel
@@ -0,0 +1,10 @@
@@ -0,0 +1, 10 @@
+# gazelle:ignore
+# Source library for blst - headers and C files for unity build
+
Expand Down
39 changes: 39 additions & 0 deletions go.work.sum

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions graft/coreth/core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -2163,6 +2163,12 @@ func (bc *BlockChain) ResetToStateSyncedBlock(block *types.Block) error {
bc.chainmu.Lock()
defer bc.chainmu.Unlock()

// Persist the block to the raw DB. During dynamic sync the commit-target
// block may not have been fetched by the block syncer if the target
// advanced beyond its initial fetch window.
rawdb.WriteBlock(bc.db, block)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting edge case. I do think this should be handled by the block syncer

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The block syncer is the right layer conceptually, but there's a timing gap that makes it insufficient on its own.

The block syncer runs concurrently with the state syncer and finishes independently. Its UpdateTarget records the new height, but the catch-up pass only triggers when drift exceeds blocksToFetch (256). With small advances during dynamic sync, no catch-up fires. You can envision it the following way:

  1. Block syncer starts, fetches blocks 1-256
  2. Block syncer's UpdateTarget records height 265
  3. Block syncer checks: drift (9) < blocksToFetch (256), no catch-up
  4. Block syncer finishes Sync, returns nil
  5. State syncer still running...
  6. Another block arrives, UpdateTarget(268)
  7. State syncer finishes
  8. Coordinator sets commitTarget = 268
  9. AcceptSync -> ResetToStateSyncedBlock(block 268) -> needs block 268 in DB

At step 9, the block syncer is long gone. We could add a targeted fetch of the latest target block before the syncer returns (between steps 3 and 4), but that only covers the target at the time the syncer finishes, not later pivots like step 6. The commit target can advance after the block syncer finishes from late block injections while the state syncer is still running.

ResetToStateSyncedBlock is the one place that has the correct block object and runs at the exact moment the block is needed. The write is two lines (WriteBlock + WriteCanonicalHash) and is idempotent if the block syncer did fetch it. I'd rather have a reliable two-line write in the right place at the right time than a more complex block syncer change that still needs a fallback for the timing gap. I hope this makes it clear. I am open to other suggestions, but at the time being I don't see a better practical solution.

rawdb.WriteCanonicalHash(bc.db, block.Hash(), block.NumberU64())

// Update head block and snapshot pointers on disk
batch := bc.db.NewBatch()
if err := bc.batchBlockAcceptedIndices(batch, block); err != nil {
Expand Down
7 changes: 7 additions & 0 deletions graft/coreth/plugin/evm/atomic/state/atomic_trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,13 @@ func (a *AtomicTrie) LastAcceptedRoot() common.Hash {
return a.lastAcceptedRoot
}

// ResetToLastCommitted resets lastAcceptedRoot to the last committed root.
// Called between dynamic syncer sessions to clear stale references from a
// cancelled session.
func (a *AtomicTrie) ResetToLastCommitted() {
a.lastAcceptedRoot = a.lastCommittedRoot
}

func (a *AtomicTrie) InsertTrie(nodes *trienode.NodeSet, root common.Hash) error {
if nodes != nil {
if err := a.trieDB.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil); err != nil {
Expand Down
1 change: 1 addition & 0 deletions graft/coreth/plugin/evm/atomic/sync/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ go_library(
"@com_github_ava_labs_libevm//core/types",
"@com_github_ava_labs_libevm//crypto",
"@com_github_ava_labs_libevm//libevm/options",
"@com_github_ava_labs_libevm//log",
"@com_github_ava_labs_libevm//metrics",
"@com_github_ava_labs_libevm//trie",
"@com_github_ava_labs_libevm//triedb",
Expand Down
100 changes: 100 additions & 0 deletions graft/coreth/plugin/evm/atomic/sync/dynamic_syncer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (C) 2019, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package sync

import (
"context"

"github.com/ava-labs/libevm/common"
"github.com/ava-labs/libevm/log"

"github.com/ava-labs/avalanchego/database/versiondb"
"github.com/ava-labs/avalanchego/graft/evm/sync/types"

atomicstate "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/atomic/state"
)

const (
atomicDynamicSyncerName = "Atomic State Syncer (dynamic)"
atomicDynamicSyncerID = "state_atomic_sync"
)

var _ types.PivotSession = (*atomicPivotSession)(nil)

// atomicPivotSession implements types.PivotSession for atomic trie sync.
type atomicPivotSession struct {
inner *Syncer
client types.LeafClient
db *versiondb.Database
atomicTrie *atomicstate.AtomicTrie
opts []SyncerOption
}

func (s *atomicPivotSession) Run(ctx context.Context) error {
return s.inner.Sync(ctx)
}

func (*atomicPivotSession) ShouldPivot(common.Hash) bool {
// Always returns true because the incoming root is a block root
// (proxy), not the actual atomic root, so comparing it is meaningless.
return true
}

func (s *atomicPivotSession) Rebuild(newRoot common.Hash, newHeight uint64) (types.PivotSession, error) {
log.Info("atomic syncer pivoting", "newHeight", newHeight, "newRoot", newRoot)

if err := s.inner.Finalize(); err != nil {
log.Error("failed to flush atomic syncer during pivot", "err", err)
}
s.atomicTrie.ResetToLastCommitted()

newInner, err := NewSyncer(s.client, s.db, s.atomicTrie, newRoot, newHeight, s.opts...)
if err != nil {
return nil, err
}
return &atomicPivotSession{
inner: newInner,
client: s.client,
db: s.db,
atomicTrie: s.atomicTrie,
opts: s.opts,
}, nil
}

func (*atomicPivotSession) OnSessionComplete() error {
return nil
}

// Finalize flushes the inner syncer's in-progress work.
func (s *atomicPivotSession) Finalize() error {
return s.inner.Finalize()
}

// NewAtomicDynamicSyncer creates a DynamicSyncer backed by an
// atomicPivotSession. The returned syncer supports pivoting to new
// targets during sync.
func NewAtomicDynamicSyncer(
inner *Syncer,
client types.LeafClient,
db *versiondb.Database,
atomicTrie *atomicstate.AtomicTrie,
initialRoot common.Hash,
initialHeight uint64,
opts ...SyncerOption,
) *types.DynamicSyncer {
session := &atomicPivotSession{
inner: inner,
client: client,
db: db,
atomicTrie: atomicTrie,
opts: opts,
}
return types.NewDynamicSyncer(
atomicDynamicSyncerName,
atomicDynamicSyncerID,
session,
initialRoot,
initialHeight,
)
}
51 changes: 51 additions & 0 deletions graft/coreth/plugin/evm/atomic/sync/dynamic_syncer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (C) 2019, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package sync

import (
"math/rand"
"testing"

"github.com/ava-labs/libevm/common"
"github.com/ava-labs/libevm/core/rawdb"
"github.com/ava-labs/libevm/triedb"
"github.com/stretchr/testify/require"

"github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/atomic/state"
"github.com/ava-labs/avalanchego/graft/evm/sync/synctest"
"github.com/ava-labs/avalanchego/graft/evm/sync/types"
)

// TestAtomicDynamicSyncer_CompletesWithoutPivot verifies that the dynamic
// wrapper completes a full sync when no pivot is triggered.
func TestAtomicDynamicSyncer_CompletesWithoutPivot(t *testing.T) {
targetHeight := 2 * uint64(testCommitInterval)
r := rand.New(rand.NewSource(1))
serverTrieDB := triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil)
root, _, _ := synctest.GenerateIndependentTrie(t, r, serverTrieDB, int(targetHeight), state.TrieKeyLength)

ctx, mockClient, atomicBackend, clientDB := setupTestInfrastructure(t, serverTrieDB)
atomicTrie := atomicBackend.AtomicTrie()

inner, err := NewSyncer(mockClient, clientDB, atomicTrie, root, targetHeight)
require.NoError(t, err)

ds := NewAtomicDynamicSyncer(inner, mockClient, clientDB, atomicTrie, root, targetHeight)

require.NoError(t, ds.Sync(ctx))
require.Equal(t, targetHeight, ds.TargetHeight())
}

// TestAtomicDynamicSyncer_UpdateTarget_StaleIgnored verifies that UpdateTarget
// with a height at or below the current desired height is a no-op.
func TestAtomicDynamicSyncer_UpdateTarget_StaleIgnored(t *testing.T) {
ds := types.NewDynamicSyncer("test", "test", &synctest.PivotSession{}, common.Hash{1}, 100)

require.NoError(t, ds.UpdateTarget(&synctest.SyncTarget{BlockRoot: common.Hash{2}, BlockHeight: 100}))
require.Equal(t, common.Hash{1}, ds.DesiredRoot())

require.NoError(t, ds.UpdateTarget(&synctest.SyncTarget{BlockRoot: common.Hash{3}, BlockHeight: 50}))
require.Equal(t, common.Hash{1}, ds.DesiredRoot())
require.Equal(t, uint64(100), ds.TargetHeight())
}
54 changes: 42 additions & 12 deletions graft/coreth/plugin/evm/atomic/sync/extender.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ package sync
import (
"fmt"

"github.com/ava-labs/libevm/log"

"github.com/ava-labs/avalanchego/database/versiondb"
"github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/atomic/state"
"github.com/ava-labs/avalanchego/graft/evm/message"
Expand All @@ -14,37 +16,49 @@ import (

// Extender is the sync extender for the atomic VM.
type Extender struct {
backend *state.AtomicBackend
trie *state.AtomicTrie
requestSize uint16 // maximum number of leaves to sync in a single request
backend *state.AtomicBackend
trie *state.AtomicTrie
requestSize uint16 // maximum number of leaves to sync in a single request
dynamicEnabled bool // whether to create a dynamic syncer that supports pivoting
}

// Initialize initializes the sync extender with the backend and trie and request size.
func (e *Extender) Initialize(backend *state.AtomicBackend, trie *state.AtomicTrie, requestSize uint16) {
func (e *Extender) Initialize(backend *state.AtomicBackend, trie *state.AtomicTrie, requestSize uint16, dynamicEnabled bool) {
e.backend = backend
e.trie = trie
e.requestSize = requestSize
e.dynamicEnabled = dynamicEnabled
}

// CreateSyncer creates the atomic syncer with the given client and verDB.
// When dynamic mode is enabled, wraps the static syncer in an
// AtomicDynamicSyncer that supports pivoting to new targets.
func (e *Extender) CreateSyncer(client types.LeafClient, verDB *versiondb.Database, summary message.Syncable) (types.Syncer, error) {
atomicSummary, ok := summary.(*Summary)
if !ok {
return nil, fmt.Errorf("atomic sync extender: expected *Summary, got %T", summary)
}

opts := []SyncerOption{WithRequestSize(e.requestSize)}
syncer, err := NewSyncer(
client,
verDB,
e.trie,
atomicSummary.AtomicRoot,
atomicSummary.BlockNumber,
WithRequestSize(e.requestSize),
opts...,
)
if err != nil {
return nil, fmt.Errorf("atomic.NewSyncer failed: %w", err)
}
return syncer, nil
if !e.dynamicEnabled {
return syncer, nil
}
return NewAtomicDynamicSyncer(
syncer, client, verDB, e.trie,
atomicSummary.AtomicRoot, atomicSummary.BlockNumber,
opts...,
), nil
}

// OnFinishBeforeCommit implements the sync.Extender interface by marking the previously last accepted block for the shared memory cursor.
Expand All @@ -61,12 +75,28 @@ func (e *Extender) OnFinishBeforeCommit(lastAcceptedHeight uint64, summary messa

// OnFinishAfterCommit implements the sync.Extender interface by applying the atomic trie to the shared memory.
func (e *Extender) OnFinishAfterCommit(summaryHeight uint64) error {
// the chain state is already restored, and, from this point on,
// the block synced to is the accepted block. The last operation
// is updating shared memory with the atomic trie.
// ApplyToSharedMemory does this, and, even if the VM is stopped
// (gracefully or ungracefully), since MarkApplyToSharedMemoryCursor
// is called, VM will resume ApplyToSharedMemory on Initialize.
// Check if the atomic trie has complete data up to summaryHeight.
// During dynamic sync the coordinator's commitTarget may be ahead of the
// atomic syncer's fixed target. In that case the trie only covers up to
// the atomic syncer's target, so we must skip ApplyToSharedMemory and
// keep the cursor alive. The gap is filled during batch replay (each
// replayed block's Accept applies atomic ops to shared memory inline)
// and the cursor is cleaned up on the next VM restart via
// NewAtomicBackend -> ApplyToSharedMemory(lastAcceptedHeight).
_, lastCommittedHeight := e.trie.LastCommitted()
if lastCommittedHeight < summaryHeight {
log.Info(
"skipping ApplyToSharedMemory: atomic trie has partial data",
"lastCommittedHeight", lastCommittedHeight,
"summaryHeight", summaryHeight,
)
return nil
}

// The atomic trie covers the full range. Apply to shared memory now.
// Even if the VM is stopped (gracefully or ungracefully), since
// MarkApplyToSharedMemoryCursor was called in OnFinishBeforeCommit,
// the VM will resume ApplyToSharedMemory on Initialize.
if err := e.backend.ApplyToSharedMemory(summaryHeight); err != nil {
return fmt.Errorf("failed to apply atomic trie to shared memory after commit: %w", err)
}
Expand Down
8 changes: 4 additions & 4 deletions graft/coreth/plugin/evm/atomic/sync/summary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ func TestMarshalSummary(t *testing.T) {
require.Equal(t, uint64(2), atomicSummary.Height())
require.Equal(t, common.Hash{3}, atomicSummary.GetBlockRoot())

expectedBase64Bytes := "AAAAAAAAAAAAAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
require.Equal(t, expectedBase64Bytes, base64.StdEncoding.EncodeToString(atomicSummary.Bytes()))
expectedID := ids.FromStringOrPanic("256pj4a3SBG5kervhxKfeKpNRcVR1xk5BzTpkTkybkM8uMPu6Q")
require.Equal(t, expectedID, atomicSummary.ID())
wantBase64Bytes := "AAAAAAAAAAAAAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
require.Equal(t, wantBase64Bytes, base64.StdEncoding.EncodeToString(atomicSummary.Bytes()))
wantID := ids.FromStringOrPanic("256pj4a3SBG5kervhxKfeKpNRcVR1xk5BzTpkTkybkM8uMPu6Q")
require.Equal(t, wantID, atomicSummary.ID())

provider := &SummaryProvider{}
called := false
Expand Down
7 changes: 7 additions & 0 deletions graft/coreth/plugin/evm/atomic/sync/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,13 @@ func (s *Syncer) Sync(ctx context.Context) error {
return s.syncer.Sync(ctx)
}

func (*Syncer) UpdateTarget(message.Syncable) error {
// The atomic syncer does not pivot. It syncs to the initial target from
// the peer summary and relies on batch replay to fill the gap between
// its target and the coordinator's commitTarget.
return nil
}

// Finalize commits any pending database changes to disk.
// This ensures that even if the sync is cancelled or fails, we preserve
// the progress up to the last fully synced height.
Expand Down
Loading
Loading