Skip to content
Draft
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
01053b3
first pass
JonathanOppenheimer Aug 7, 2025
f3fd073
reapply wait changes
JonathanOppenheimer Aug 7, 2025
d04a7fc
add test back
JonathanOppenheimer Aug 7, 2025
239a3b5
attempt 2
JonathanOppenheimer Aug 8, 2025
52e4d26
sync part 3!
JonathanOppenheimer Aug 8, 2025
34e3c48
sync part 4
JonathanOppenheimer Aug 8, 2025
ae531aa
oops broke the clock
JonathanOppenheimer Aug 8, 2025
38ecb7e
Merge branch 'master' into sync-pr-963-atomic-sync-package
JonathanOppenheimer Aug 11, 2025
08bf133
Merge branch 'master' into sync-pr-963-atomic-sync-package
JonathanOppenheimer Aug 11, 2025
a759870
Merge branch 'master' into sync-pr-963-atomic-sync-package
JonathanOppenheimer Aug 19, 2025
912b506
Merge remote-tracking branch 'origin/master' into sync-pr-963-atomic-…
JonathanOppenheimer Aug 21, 2025
892379e
remove duplicate import
JonathanOppenheimer Aug 21, 2025
c7c0c9a
lint
JonathanOppenheimer Aug 21, 2025
4719758
Merge remote-tracking branch 'origin/master' into sync-pr-963-atomic-…
JonathanOppenheimer Aug 25, 2025
434fb4f
lint
JonathanOppenheimer Aug 25, 2025
936aacc
Merge branch 'master' into sync-pr-963-atomic-sync-package
JonathanOppenheimer Aug 27, 2025
0edb94f
lint
JonathanOppenheimer Aug 27, 2025
af00a05
Merge remote-tracking branch 'origin/master' into sync-pr-963-atomic-…
JonathanOppenheimer Aug 29, 2025
3cb3808
Merge remote-tracking branch 'origin/master' into sync-pr-963-atomic-…
JonathanOppenheimer Sep 4, 2025
728620c
align with coreth
JonathanOppenheimer Sep 4, 2025
52aba0c
add back advance clock setting
JonathanOppenheimer Sep 4, 2025
eb25788
simplify registration
JonathanOppenheimer Sep 8, 2025
6ba1bd6
Merge branch 'master' into sync-pr-963-atomic-sync-package
JonathanOppenheimer Sep 8, 2025
59a0ccc
Merge remote-tracking branch 'origin/master' into sync-pr-963-atomic-…
JonathanOppenheimer Sep 9, 2025
07edff7
merge
JonathanOppenheimer Sep 9, 2025
2564286
Merge branch 'master' into sync-pr-963-atomic-sync-package
JonathanOppenheimer Sep 12, 2025
fa8a32d
lint
JonathanOppenheimer Sep 12, 2025
5d911d5
Merge branch 'master' into sync-pr-963-atomic-sync-package
JonathanOppenheimer Sep 15, 2025
14c8028
Merge remote-tracking branch 'origin/master' into sync-pr-963-atomic-…
JonathanOppenheimer Sep 25, 2025
8fa7586
add errors back
JonathanOppenheimer Sep 25, 2025
94c2b46
lint
JonathanOppenheimer Sep 25, 2025
5b7d576
Merge branch 'master' into sync-pr-963-atomic-sync-package
JonathanOppenheimer Sep 29, 2025
8426e2a
Merge branch 'master' into sync-pr-963-atomic-sync-package
JonathanOppenheimer Oct 1, 2025
24e0ae0
Merge branch 'master' into sync-pr-963-atomic-sync-package
JonathanOppenheimer Oct 1, 2025
7e55ada
Merge branch 'master' into sync-pr-963-atomic-sync-package
JonathanOppenheimer Oct 10, 2025
ac0b665
finish merge
JonathanOppenheimer Oct 10, 2025
2a46756
Merge remote-tracking branch 'origin/master' into sync-pr-963-atomic-…
JonathanOppenheimer Oct 10, 2025
40abb33
reduce diff
JonathanOppenheimer Oct 10, 2025
ba927d5
lint
JonathanOppenheimer Oct 10, 2025
0cc7e3b
Merge branch 'master' into sync-pr-963-atomic-sync-package
JonathanOppenheimer Oct 13, 2025
cced3ca
fix merge
JonathanOppenheimer Oct 13, 2025
291003a
Merge branch 'master' into sync-pr-963-atomic-sync-package
JonathanOppenheimer Oct 14, 2025
e84bf4a
Update plugin/evm/message/handler.go
JonathanOppenheimer Oct 14, 2025
2356b60
Update sync/client/test_client.go
JonathanOppenheimer Oct 14, 2025
9e4a453
Merge branch 'master' into sync-pr-963-atomic-sync-package
JonathanOppenheimer Oct 14, 2025
509e349
Update sync/client/stats/stats.go
JonathanOppenheimer Oct 14, 2025
33837af
lint
JonathanOppenheimer Oct 14, 2025
55f46e3
Merge branch 'master' into sync-pr-963-atomic-sync-package
JonathanOppenheimer Oct 14, 2025
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
37 changes: 33 additions & 4 deletions consensus/dummy/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,39 @@ type Mode struct {
ModeSkipCoinbase bool
}

type DummyEngine struct {
consensusMode Mode
desiredDelayExcess *acp226.DelayExcess
}
type (
OnFinalizeAndAssembleCallbackType = func(
header *types.Header,
parent *types.Header,
state *state.StateDB,
txs []*types.Transaction,
) (
extraData []byte,
blockFeeContribution *big.Int,
extDataGasUsed *big.Int,
err error,
)

OnExtraStateChangeType = func(
block *types.Block,
parent *types.Header,
statedb *state.StateDB,
) (
blockFeeContribution *big.Int,
extDataGasUsed *big.Int,
err error,
)

ConsensusCallbacks struct {
OnFinalizeAndAssemble OnFinalizeAndAssembleCallbackType
OnExtraStateChange OnExtraStateChangeType
}

DummyEngine struct {
consensusMode Mode
desiredDelayExcess *acp226.DelayExcess
}
)

func NewDummyEngine(
mode Mode,
Expand Down
6 changes: 4 additions & 2 deletions plugin/evm/block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (

"github.com/ava-labs/subnet-evm/params"
"github.com/ava-labs/subnet-evm/params/extras"
"github.com/ava-labs/subnet-evm/plugin/evm/extension"
"github.com/ava-labs/subnet-evm/precompile/precompileconfig"
)

Expand All @@ -26,8 +27,9 @@ func TestHandlePrecompileAccept(t *testing.T) {

db := rawdb.NewMemoryDatabase()
vm := &VM{
chaindb: db,
chainConfig: params.TestChainConfig,
chaindb: db,
chainConfig: params.TestChainConfig,
extensionConfig: &extension.Config{},
}

precompileAddr := common.Address{0x05}
Expand Down
16 changes: 14 additions & 2 deletions plugin/evm/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"fmt"
"time"

"github.com/ava-labs/avalanchego/utils/constants"
"github.com/ava-labs/libevm/common"
"github.com/ava-labs/libevm/common/hexutil"
"github.com/spf13/cast"
Expand Down Expand Up @@ -129,7 +130,7 @@ type Config struct {
MaxOutboundActiveRequests int64 `json:"max-outbound-active-requests"`

// Sync settings
StateSyncEnabled bool `json:"state-sync-enabled"`
StateSyncEnabled *bool `json:"state-sync-enabled"` // Pointer distinguishes false (no state sync) and not set (state sync only at genesis).
Copy link
Collaborator

Choose a reason for hiding this comment

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

why have we changed this? This is a substantial change for default value, we should have a separate PR for that if we want to align them.

Copy link
Member Author

Choose a reason for hiding this comment

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

We have changed this because this was a change that Darioush made years ago to coreth, that was never synced to subnet-evm, and then was built on top off. This led to some significant divergence.

See ava-labs/coreth@cd3a14e#diff-6c4b2fd34f767685bfc35038a59ea4fbfadaa6060d70031002e3b008e73a06e7.

I have created a targeted PR for this change (and this change does need to be synced):

#1813

StateSyncSkipResume bool `json:"state-sync-skip-resume"` // Forces state sync to use the highest available summary block
StateSyncServerTrieCache int `json:"state-sync-server-trie-cache"`
StateSyncIDs string `json:"state-sync-ids"`
Expand Down Expand Up @@ -236,7 +237,18 @@ func (d Duration) MarshalJSON() ([]byte, error) {
}

// validate returns an error if this is an invalid config.
func (c *Config) validate(_ uint32) error {
func (c *Config) validate(networkID uint32) error {
// Ensure that non-standard commit interval is not allowed for production networks
if constants.ProductionNetworkIDs.Contains(networkID) {
defaultConfig := NewDefaultConfig()
if c.CommitInterval != defaultConfig.CommitInterval {
return fmt.Errorf("cannot start non-local network with commit interval %d different than %d", c.CommitInterval, defaultConfig.CommitInterval)
}
if c.StateSyncCommitInterval != defaultConfig.StateSyncCommitInterval {
return fmt.Errorf("cannot start non-local network with syncable interval %d different than %d", c.StateSyncCommitInterval, defaultConfig.StateSyncCommitInterval)
}
}
Comment on lines +242 to +250
Copy link
Collaborator

Choose a reason for hiding this comment

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

simirlay we should not change these here(I don't think we ever change this in those sync PRs)


if c.PopulateMissingTries != nil && (c.OfflinePruning || c.Pruning) {
return fmt.Errorf("cannot enable populate missing tries while offline pruning (enabled: %t)/pruning (enabled: %t) are enabled", c.OfflinePruning, c.Pruning)
}
Expand Down
8 changes: 7 additions & 1 deletion plugin/evm/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ import (
"github.com/stretchr/testify/require"
)

// newTrue returns a pointer to a bool that is true
func newTrue() *bool {
b := true
return &b
}

func TestUnmarshalConfig(t *testing.T) {
tests := []struct {
name string
Expand Down Expand Up @@ -64,7 +70,7 @@ func TestUnmarshalConfig(t *testing.T) {
{
"state sync enabled",
[]byte(`{"state-sync-enabled":true}`),
Config{StateSyncEnabled: true},
Config{StateSyncEnabled: newTrue()},
false,
},
{
Expand Down
124 changes: 124 additions & 0 deletions plugin/evm/extension/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,30 @@
package extension

import (
"context"
"errors"

"github.com/ava-labs/avalanchego/database"
"github.com/ava-labs/avalanchego/database/versiondb"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/network/p2p"
"github.com/ava-labs/avalanchego/snow/consensus/snowman"
"github.com/ava-labs/avalanchego/snow/engine/snowman/block"
"github.com/ava-labs/avalanchego/utils/timer/mockable"
"github.com/ava-labs/libevm/common"
"github.com/ava-labs/libevm/core/types"
"github.com/prometheus/client_golang/prometheus"

"github.com/ava-labs/subnet-evm/consensus/dummy"
"github.com/ava-labs/subnet-evm/core"
"github.com/ava-labs/subnet-evm/params"
"github.com/ava-labs/subnet-evm/params/extras"
"github.com/ava-labs/subnet-evm/plugin/evm/config"
"github.com/ava-labs/subnet-evm/plugin/evm/message"
"github.com/ava-labs/subnet-evm/plugin/evm/sync"
"github.com/ava-labs/subnet-evm/sync/handlers"

avalanchecommon "github.com/ava-labs/avalanchego/snow/engine/common"
)

var (
Expand All @@ -19,15 +37,121 @@ var (
errNilClock = errors.New("nil clock")
)

type ExtensibleVM interface {
// SetExtensionConfig sets the configuration for the VM extension
// Should be called before any other method and only once
SetExtensionConfig(config *Config) error
// NewClient returns a client to send messages with for the given protocol
NewClient(protocol uint64) *p2p.Client
// AddHandler registers a server handler for an application protocol
AddHandler(protocol uint64, handler p2p.Handler) error
// GetExtendedBlock returns the VMBlock for the given ID or an error if the block is not found
GetExtendedBlock(context.Context, ids.ID) (ExtendedBlock, error)
// LastAcceptedExtendedBlock returns the last accepted VM block
LastAcceptedExtendedBlock() ExtendedBlock
// ChainConfig returns the chain config for the VM
ChainConfig() *params.ChainConfig
// P2PValidators returns the validators for the network
P2PValidators() *p2p.Validators
// Blockchain returns the blockchain client
Blockchain() *core.BlockChain
// Config returns the configuration for the VM
Config() config.Config
// MetricRegistry returns the metric registry for the VM
MetricRegistry() *prometheus.Registry
// ReadLastAccepted returns the last accepted block hash and height
ReadLastAccepted() (common.Hash, uint64, error)
// VersionDB returns the versioned database for the VM
VersionDB() *versiondb.Database
}

// InnerVM is the interface that must be implemented by the VM
// that's being wrapped by the extension
type InnerVM interface {
ExtensibleVM
avalanchecommon.VM
block.ChainVM
block.BuildBlockWithContextChainVM
block.StateSyncableVM
}

// ExtendedBlock is a block that can be used by the extension
type ExtendedBlock interface {
snowman.Block
GetEthBlock() *types.Block
GetBlockExtension() BlockExtension
}

type BlockExtender interface {
// NewBlockExtension is called when a new block is created
NewBlockExtension(b ExtendedBlock) (BlockExtension, error)
}

// BlockExtension allows the VM extension to handle block processing events.
type BlockExtension interface {
// SyntacticVerify verifies the block syntactically
// it can be implemented to extend inner block verification
SyntacticVerify(rules extras.Rules) error
// SemanticVerify verifies the block semantically
// it can be implemented to extend inner block verification
SemanticVerify() error
// CleanupVerified is called when a block has passed SemanticVerify and SynctacticVerify,
// and should be cleaned up due to error or verification runs under non-write mode. This
// does not return an error because the block has already been verified.
CleanupVerified()
// Accept is called when a block is accepted by the block manager. Accept takes a
// database.Batch that contains the changes that were made to the database as a result
// of accepting the block. The changes in the batch should be flushed to the database in this method.
Accept(acceptedBatch database.Batch) error
// Reject is called when a block is rejected by the block manager
Reject() error
}

// BuilderMempool is a mempool that's used in the block builder
type BuilderMempool interface {
// PendingLen returns the number of pending transactions
// that are waiting to be included in a block
PendingLen() int
// SubscribePendingTxs returns a channel that's signaled when there are pending transactions
SubscribePendingTxs() <-chan struct{}
}

// LeafRequestConfig is the configuration to handle leaf requests
// in the network and syncer
type LeafRequestConfig struct {
// LeafType is the type of the leaf node
LeafType message.NodeType
// MetricName is the name of the metric to use for the leaf request
MetricName string
// Handler is the handler to use for the leaf request
Handler handlers.LeafRequestHandler
}

// Config is the configuration for the VM extension
type Config struct {
// ConsensusCallbacks is the consensus callbacks to use
// for the VM to be used in consensus engine.
// Callback functions can be nil.
ConsensusCallbacks dummy.ConsensusCallbacks
// SyncSummaryProvider is the sync summary provider to use
// for the VM to be used in syncer.
// It's required and should be non-nil
SyncSummaryProvider sync.SummaryProvider
// SyncExtender can extend the syncer to handle custom sync logic.
// It's optional and can be nil
SyncExtender sync.Extender
// SyncableParser is to parse summary messages from the network.
// It's required and should be non-nil
SyncableParser message.SyncableParser
// BlockExtender allows the VM extension to create an extension to handle block processing events.
// It's optional and can be nil
BlockExtender BlockExtender
// ExtraSyncLeafHandlerConfig is the extra configuration to handle leaf requests
// in the network and syncer. It's optional and can be nil
ExtraSyncLeafHandlerConfig *LeafRequestConfig
// ExtraMempool is the mempool to be used in the block builder.
// It's optional and can be nil
ExtraMempool BuilderMempool
// Clock is the clock to use for time related operations.
// It's optional and can be nil
Clock *mockable.Clock
Expand Down
44 changes: 44 additions & 0 deletions plugin/evm/message/block_sync_summary_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package message

import (
"context"
"encoding/base64"
"testing"

"github.com/ava-labs/avalanchego/snow/engine/snowman/block"
"github.com/ava-labs/libevm/common"
"github.com/stretchr/testify/require"
)

func TestMarshalBlockSyncSummary(t *testing.T) {
blockSyncSummary, err := NewBlockSyncSummary(common.Hash{1}, 2, common.Hash{3})
require.NoError(t, err)

require.Equal(t, common.Hash{1}, blockSyncSummary.GetBlockHash())
require.Equal(t, uint64(2), blockSyncSummary.Height())
require.Equal(t, common.Hash{3}, blockSyncSummary.GetBlockRoot())

expectedBase64Bytes := "AAAAAAAAAAAAAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
require.Equal(t, expectedBase64Bytes, base64.StdEncoding.EncodeToString(blockSyncSummary.Bytes()))

parser := NewBlockSyncSummaryParser()
called := false
acceptImplTest := func(Syncable) (block.StateSyncMode, error) {
called = true
return block.StateSyncSkipped, nil
}
s, err := parser.Parse(blockSyncSummary.Bytes(), acceptImplTest)
require.NoError(t, err)
require.Equal(t, blockSyncSummary.GetBlockHash(), s.GetBlockHash())
require.Equal(t, blockSyncSummary.Height(), s.Height())
require.Equal(t, blockSyncSummary.GetBlockRoot(), s.GetBlockRoot())
require.Equal(t, blockSyncSummary.Bytes(), s.Bytes())

mode, err := s.Accept(context.TODO())
require.NoError(t, err)
require.Equal(t, block.StateSyncSkipped, mode)
require.True(t, called)
}
6 changes: 2 additions & 4 deletions plugin/evm/message/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,11 @@ func init() {
c := linearcodec.NewDefault()

// Skip registration to keep registeredTypes unchanged after legacy gossip deprecation
c.SkipRegistrations(1)
// Gossip types and sync summary type removed from codec
c.SkipRegistrations(2)

errs := wrappers.Errs{}
errs.Add(
// Types for state sync frontier consensus
c.RegisterType(BlockSyncSummary{}),

// state sync types
c.RegisterType(BlockRequest{}),
c.RegisterType(BlockResponse{}),
Expand Down
5 changes: 2 additions & 3 deletions plugin/evm/message/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ var _ RequestHandler = NoopRequestHandler{}
// Must have methods in format of handleType(context.Context, ids.NodeID, uint32, request Type) error
// so that the Request object of relevant Type can invoke its respective handle method
// on this struct.
// Also see GossipHandler for implementation style.
type RequestHandler interface {
HandleStateTrieLeafsRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, leafsRequest LeafsRequest) ([]byte, error)
HandleLeafsRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, leafsRequest LeafsRequest) ([]byte, error)
HandleBlockRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, request BlockRequest) ([]byte, error)
HandleCodeRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, codeRequest CodeRequest) ([]byte, error)
}
Expand All @@ -33,7 +32,7 @@ type ResponseHandler interface {

type NoopRequestHandler struct{}

func (NoopRequestHandler) HandleStateTrieLeafsRequest(context.Context, ids.NodeID, uint32, LeafsRequest) ([]byte, error) {
func (NoopRequestHandler) HandleLeafsRequest(context.Context, ids.NodeID, uint32, LeafsRequest) ([]byte, error) {
return nil, nil
}

Expand Down
Loading
Loading