diff --git a/plugin/evm/config/config.go b/plugin/evm/config/config.go index f750abbd6d..5ac8b2f364 100644 --- a/plugin/evm/config/config.go +++ b/plugin/evm/config/config.go @@ -129,7 +129,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). 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"` diff --git a/plugin/evm/config/config_test.go b/plugin/evm/config/config_test.go index f27d92ff81..75f852dd5c 100644 --- a/plugin/evm/config/config_test.go +++ b/plugin/evm/config/config_test.go @@ -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 @@ -64,7 +70,7 @@ func TestUnmarshalConfig(t *testing.T) { { "state sync enabled", []byte(`{"state-sync-enabled":true}`), - Config{StateSyncEnabled: true}, + Config{StateSyncEnabled: newTrue()}, false, }, { diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go index f922e41668..53ab341e95 100644 --- a/plugin/evm/vm.go +++ b/plugin/evm/vm.go @@ -338,14 +338,21 @@ func (vm *VM) Initialize( return err } + // vm.ChainConfig() should be available for wrapping VMs before vm.initializeChain() + vm.chainConfig = g.Config + vm.ethConfig = ethconfig.NewDefaultConfig() vm.ethConfig.Genesis = g - // NetworkID here is different than Avalanche's NetworkID. - // Avalanche's NetworkID represents the Avalanche network is running on - // like Fuji, Mainnet, Local, etc. - // The NetworkId here is kept same as ChainID to be compatible with - // Ethereum tooling. vm.ethConfig.NetworkId = g.Config.ChainID.Uint64() + vm.genesisHash = vm.ethConfig.Genesis.ToBlock().Hash() // must create genesis hash before [vm.ReadLastAccepted] + lastAcceptedHash, lastAcceptedHeight, err := vm.readLastAccepted() + if err != nil { + return err + } + log.Info("read last accepted", + "hash", lastAcceptedHash, + "height", lastAcceptedHeight, + ) // Set minimum price for mining and default gas price oracle value to the min // gas price to prevent so transactions and blocks all use the correct fees @@ -380,7 +387,7 @@ func (vm *VM) Initialize( vm.ethConfig.PopulateMissingTries = vm.config.PopulateMissingTries vm.ethConfig.PopulateMissingTriesParallelism = vm.config.PopulateMissingTriesParallelism vm.ethConfig.AllowMissingTries = vm.config.AllowMissingTries - vm.ethConfig.SnapshotDelayInit = vm.config.StateSyncEnabled + vm.ethConfig.SnapshotDelayInit = vm.stateSyncEnabled(lastAcceptedHeight) vm.ethConfig.SnapshotWait = vm.config.SnapshotWait vm.ethConfig.SnapshotVerify = vm.config.SnapshotVerify vm.ethConfig.HistoricalProofQueryWindow = vm.config.HistoricalProofQueryWindow @@ -409,7 +416,7 @@ func (vm *VM) Initialize( if vm.config.OfflinePruning { return errFirewoodOfflinePruningUnsupported } - if vm.config.StateSyncEnabled { + if vm.config.StateSyncEnabled == nil || *vm.config.StateSyncEnabled { return errFirewoodStateSyncUnsupported } } @@ -436,20 +443,6 @@ func (vm *VM) Initialize( vm.ethConfig.Miner.Etherbase = constants.BlackholeAddr } - vm.chainConfig = g.Config - - // create genesisHash after applying upgradeBytes in case - // upgradeBytes modifies genesis. - vm.genesisHash = vm.ethConfig.Genesis.ToBlock().Hash() // must create genesis hash before [vm.readLastAccepted] - lastAcceptedHash, lastAcceptedHeight, err := vm.readLastAccepted() - if err != nil { - return err - } - log.Info("read last accepted", - "hash", lastAcceptedHash, - "height", lastAcceptedHeight, - ) - vm.networkCodec = message.Codec vm.Network, err = network.NewNetwork(vm.ctx, appSender, vm.networkCodec, vm.config.MaxOutboundActiveRequests, vm.sdkMetrics) if err != nil { @@ -652,9 +645,10 @@ func (vm *VM) initializeChain(lastAcceptedHash common.Hash, ethConfig ethconfig. // If state sync is disabled, this function will wipe any ongoing summary from // disk to ensure that we do not continue syncing from an invalid snapshot. func (vm *VM) initializeStateSyncClient(lastAcceptedHeight uint64) error { + stateSyncEnabled := vm.stateSyncEnabled(lastAcceptedHeight) // parse nodeIDs from state sync IDs in vm config var stateSyncIDs []ids.NodeID - if vm.config.StateSyncEnabled && len(vm.config.StateSyncIDs) > 0 { + if stateSyncEnabled && len(vm.config.StateSyncIDs) > 0 { nodeIDs := strings.Split(vm.config.StateSyncIDs, ",") stateSyncIDs = make([]ids.NodeID, len(nodeIDs)) for i, nodeIDString := range nodeIDs { @@ -679,7 +673,7 @@ func (vm *VM) initializeStateSyncClient(lastAcceptedHeight uint64) error { BlockParser: vm, }, ), - Enabled: vm.config.StateSyncEnabled, + Enabled: stateSyncEnabled, SkipResume: vm.config.StateSyncSkipResume, MinBlocks: vm.config.StateSyncMinBlocks, RequestSize: vm.config.StateSyncRequestSize, @@ -693,7 +687,7 @@ func (vm *VM) initializeStateSyncClient(lastAcceptedHeight uint64) error { // If StateSync is disabled, clear any ongoing summary so that we will not attempt to resume // sync using a snapshot that has been modified by the node running normal operations. - if !vm.config.StateSyncEnabled { + if !stateSyncEnabled { return vm.Client.ClearOngoingSummary() } @@ -1360,6 +1354,16 @@ func (vm *VM) Disconnected(ctx context.Context, nodeID ids.NodeID) error { return vm.Network.Disconnected(ctx, nodeID) } +func (vm *VM) stateSyncEnabled(lastAcceptedHeight uint64) bool { + if vm.config.StateSyncEnabled != nil { + // if the config is set, use that + return *vm.config.StateSyncEnabled + } + + // enable state sync by default if the chain is empty. + return lastAcceptedHeight == 0 +} + func (vm *VM) PutLastAcceptedID(id ids.ID) error { return vm.acceptedBlockDB.Put(lastAcceptedKey, id[:]) }