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

Fallback to bootstrapping #3480

Draft
wants to merge 13 commits into
base: master
Choose a base branch
from
Draft
2 changes: 1 addition & 1 deletion .github/workflows/build-macos-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
# This workflow contains a single job called "build"
build-mac:
# The type of runner that the job will run on
runs-on: macos-12
runs-on: macos-14
permissions:
id-token: write
contents: read
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [macos-12, ubuntu-20.04, ubuntu-22.04, ubuntu-24.04, windows-2022, custom-arm64-jammy, custom-arm64-noble]
os: [macos-14, ubuntu-20.04, ubuntu-22.04, ubuntu-24.04, windows-2022, custom-arm64-jammy, custom-arm64-noble]
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-go-for-project
Expand Down Expand Up @@ -197,7 +197,7 @@ jobs:
- name: Install qemu (required for cross-platform builds)
run: |
sudo apt update
sudo apt -y install qemu qemu-user-static
sudo apt -y install qemu-system qemu-user-static
- name: Check image build
shell: bash
run: bash -x scripts/tests.build_image.sh
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish_docker_image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Install qemu (required for cross-platform builds)
run: |
sudo apt update
sudo apt -y install qemu qemu-user-static
sudo apt -y install qemu-system qemu-user-static
sudo systemctl restart docker
- name: Create multiplatform docker builder
run: docker buildx create --use
Expand Down
200 changes: 115 additions & 85 deletions chains/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"github.com/ava-labs/avalanchego/snow/engine/common/tracker"
"github.com/ava-labs/avalanchego/snow/engine/snowman/block"
"github.com/ava-labs/avalanchego/snow/engine/snowman/syncer"
"github.com/ava-labs/avalanchego/snow/engine/unified"
"github.com/ava-labs/avalanchego/snow/networking/handler"
"github.com/ava-labs/avalanchego/snow/networking/router"
"github.com/ava-labs/avalanchego/snow/networking/sender"
Expand Down Expand Up @@ -63,7 +64,6 @@ import (

p2ppb "github.com/ava-labs/avalanchego/proto/pb/p2p"
smcon "github.com/ava-labs/avalanchego/snow/consensus/snowman"
aveng "github.com/ava-labs/avalanchego/snow/engine/avalanche"
avbootstrap "github.com/ava-labs/avalanchego/snow/engine/avalanche/bootstrap"
avagetter "github.com/ava-labs/avalanchego/snow/engine/avalanche/getter"
smeng "github.com/ava-labs/avalanchego/snow/engine/snowman"
Expand Down Expand Up @@ -588,6 +588,7 @@ func (m *manager) buildChain(chainParams ChainParameters, sb subnets.Subnet) (*c
vm,
chainFxs,
sb,
vmFactory,
)
if err != nil {
return nil, fmt.Errorf("error while creating new snowman vm %w", err)
Expand Down Expand Up @@ -933,23 +934,13 @@ func (m *manager) createAvalancheChain(
// to make sure start callbacks are duly initialized
snowmanEngineConfig := smeng.Config{
Ctx: ctx,
AllGetsServer: snowGetHandler,
VM: vmWrappingProposerVM,
Sender: snowmanMessageSender,
Validators: vdrs,
ConnectedValidators: connectedValidators,
Params: consensusParams,
Consensus: snowmanConsensus,
}
var snowmanEngine common.Engine
snowmanEngine, err = smeng.New(snowmanEngineConfig)
if err != nil {
return nil, fmt.Errorf("error initializing snowman engine: %w", err)
}

if m.TracingEnabled {
snowmanEngine = common.TraceEngine(snowmanEngine, m.Tracer)
}

// create bootstrap gear
bootstrapCfg := smbootstrap.Config{
Expand All @@ -968,18 +959,6 @@ func (m *manager) createAvalancheChain(
DB: blockBootstrappingDB,
VM: vmWrappingProposerVM,
}
var snowmanBootstrapper common.BootstrapableEngine
snowmanBootstrapper, err = smbootstrap.New(
bootstrapCfg,
snowmanEngine.Start,
)
if err != nil {
return nil, fmt.Errorf("error initializing snowman bootstrapper: %w", err)
}

if m.TracingEnabled {
snowmanBootstrapper = common.TraceBootstrapableEngine(snowmanBootstrapper, m.Tracer)
}

avaGetHandler, err := avagetter.New(
vtxManager,
Expand All @@ -993,12 +972,6 @@ func (m *manager) createAvalancheChain(
return nil, fmt.Errorf("couldn't initialize avalanche base message handler: %w", err)
}

// create engine gear
avalancheEngine := aveng.New(ctx, avaGetHandler, linearizableVM)
if m.TracingEnabled {
avalancheEngine = common.TraceEngine(avalancheEngine, m.Tracer)
}

// create bootstrap gear
avalancheBootstrapperConfig := avbootstrap.Config{
AllGetsServer: avaGetHandler,
Expand All @@ -1016,32 +989,34 @@ func (m *manager) createAvalancheChain(
avalancheBootstrapperConfig.StopVertexID = m.Upgrades.CortinaXChainStopVertexID
}

var avalancheBootstrapper common.BootstrapableEngine
avalancheBootstrapper, err = avbootstrap.New(
avalancheBootstrapperConfig,
snowmanBootstrapper.Start,
avalancheMetrics,
)
ef := &unified.EngineFactory{
Reset: sb.ResetChain,
TracingEnabled: m.TracingEnabled,
GetServer: snowGetHandler,
AvaAncestorGetter: avaGetHandler,
AvaMetrics: avalancheMetrics,
Tracer: m.Tracer,
BootConfig: bootstrapCfg,
AvaBootConfig: avalancheBootstrapperConfig,
SnowmanConfig: snowmanEngineConfig,
Logger: ctx.Log,
}

ctx.State.Set(snow.EngineState{
Type: p2ppb.EngineType_ENGINE_TYPE_AVALANCHE,
State: snow.Bootstrapping,
})

ue, err := unified.EngineFromEngines(ctx, ef, vm)
if err != nil {
return nil, fmt.Errorf("error initializing avalanche bootstrapper: %w", err)
return nil, fmt.Errorf("error initializing unified engine: %w", err)
}

engine := common.Engine(ue)
if m.TracingEnabled {
avalancheBootstrapper = common.TraceBootstrapableEngine(avalancheBootstrapper, m.Tracer)
engine = common.TraceEngine(ue, m.Tracer)
}

h.SetEngineManager(&handler.EngineManager{
Avalanche: &handler.Engine{
StateSyncer: nil,
Bootstrapper: avalancheBootstrapper,
Consensus: avalancheEngine,
},
Snowman: &handler.Engine{
StateSyncer: nil,
Bootstrapper: snowmanBootstrapper,
Consensus: snowmanEngine,
},
})
h.SetEngine(engine)

// Register health check for this chain
if err := m.Health.RegisterHealthCheck(primaryAlias, h, ctx.SubnetID.String()); err != nil {
Expand All @@ -1065,6 +1040,7 @@ func (m *manager) createSnowmanChain(
vm block.ChainVM,
fxs []*common.Fx,
sb subnets.Subnet,
vmFactory vms.Factory,
) (*chain, error) {
ctx.Lock.Lock()
defer ctx.Lock.Unlock()
Expand Down Expand Up @@ -1327,7 +1303,6 @@ func (m *manager) createSnowmanChain(
// to make sure start callbacks are duly initialized
engineConfig := smeng.Config{
Ctx: ctx,
AllGetsServer: snowGetHandler,
VM: vm,
Sender: messageSender,
Validators: vdrs,
Expand All @@ -1336,15 +1311,6 @@ func (m *manager) createSnowmanChain(
Consensus: consensus,
PartialSync: m.PartialSyncPrimaryNetwork && ctx.ChainID == constants.PlatformChainID,
}
var engine common.Engine
engine, err = smeng.New(engineConfig)
if err != nil {
return nil, fmt.Errorf("error initializing snowman engine: %w", err)
}

if m.TracingEnabled {
engine = common.TraceEngine(engine, m.Tracer)
}

// create bootstrap gear
bootstrapCfg := smbootstrap.Config{
Expand All @@ -1364,18 +1330,6 @@ func (m *manager) createSnowmanChain(
VM: vm,
Bootstrapped: bootstrapFunc,
}
var bootstrapper common.BootstrapableEngine
bootstrapper, err = smbootstrap.New(
bootstrapCfg,
engine.Start,
)
if err != nil {
return nil, fmt.Errorf("error initializing snowman bootstrapper: %w", err)
}

if m.TracingEnabled {
bootstrapper = common.TraceBootstrapableEngine(bootstrapper, m.Tracer)
}

// create state sync gear
stateSyncCfg, err := syncer.NewConfig(
Expand All @@ -1392,24 +1346,83 @@ func (m *manager) createSnowmanChain(
if err != nil {
return nil, fmt.Errorf("couldn't initialize state syncer configuration: %w", err)
}
stateSyncer := syncer.New(
stateSyncCfg,
bootstrapper.Start,
)

if m.TracingEnabled {
stateSyncer = common.TraceStateSyncer(stateSyncer, m.Tracer)
}
ef := &unified.EngineFactory{
VMFactory: func() (common.VM, error) {
vm, err := vmFactory.New(ctx.Log)
if err != nil {
return nil, err
}

if _, isChainVM := vm.(block.ChainVM); !isChainVM {
return nil, fmt.Errorf("VM for chain %s is not a chain VM", ctx.ChainID)
}

chainVM := vm.(block.ChainVM)

chainVM = proposervm.New(
chainVM,
proposervm.Config{
Upgrades: m.Upgrades,
MinBlkDelay: minBlockDelay,
NumHistoricalBlocks: numHistoricalBlocks,
StakingLeafSigner: m.StakingTLSSigner,
StakingCertLeaf: m.StakingTLSCert,
Registerer: proposervmReg,
},
)

h.SetEngineManager(&handler.EngineManager{
Avalanche: nil,
Snowman: &handler.Engine{
StateSyncer: stateSyncer,
Bootstrapper: bootstrapper,
Consensus: engine,
if err := chainVM.Initialize(
context.TODO(),
ctx.Context,
vmDB,
genesisData,
chainConfig.Upgrade,
chainConfig.Config,
msgChan,
fxs,
messageSender,
); err != nil {
return nil, err
}

return chainVM, nil
},
Reset: sb.ResetChain,
TracingEnabled: m.TracingEnabled,
GetServer: snowGetHandler,
AvaAncestorGetter: invalidEngineAncestorsGetter{},
StateSync: hasStateSync(stateSyncCfg),
Tracer: m.Tracer,
BootConfig: bootstrapCfg,
SnowmanConfig: engineConfig,
StateSyncConfig: stateSyncCfg,
Logger: ctx.Log,
}

ctx.State.Set(snow.EngineState{
Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN,
State: snow.StateSyncing,
})

if !ef.HasStateSync() {
ctx.State.Set(snow.EngineState{
Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN,
State: snow.Bootstrapping,
})
}

ue, err := unified.EngineFromEngines(ctx, ef, vm)
if err != nil {
return nil, fmt.Errorf("error initializing unified engine: %w", err)
}

engine := common.Engine(ue)
if m.TracingEnabled {
engine = common.TraceEngine(ue, m.Tracer)
}
h.SetEngine(engine)

// Register health checks
if err := m.Health.RegisterHealthCheck(primaryAlias, h, ctx.SubnetID.String()); err != nil {
return nil, fmt.Errorf("couldn't add health check for chain %s: %w", primaryAlias, err)
Expand All @@ -1423,6 +1436,17 @@ func (m *manager) createSnowmanChain(
}, nil
}

func hasStateSync(stateSyncCfg syncer.Config) bool {
var hasStateSync bool
ssVM, isStateSyncable := stateSyncCfg.VM.(block.StateSyncableVM)
if isStateSyncable {
if enabled, err := ssVM.StateSyncEnabled(context.Background()); err == nil && enabled {
hasStateSync = true
}
}
return hasStateSync
}

func (m *manager) IsBootstrapped(id ids.ID) bool {
m.chainsLock.Lock()
chain, exists := m.chains[id]
Expand Down Expand Up @@ -1581,3 +1605,9 @@ func (m *manager) getOrMakeVMRegisterer(vmID ids.ID, chainAlias string) (metrics
)
return chainReg, err
}

type invalidEngineAncestorsGetter struct{}

func (invalidEngineAncestorsGetter) GetAncestors(_ context.Context, _ ids.NodeID, _ uint32, _ ids.ID, engineType p2ppb.EngineType) error {
return fmt.Errorf("this engine does not run %s", engineType)
}
2 changes: 1 addition & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -793,8 +793,8 @@ func getTxFeeConfig(v *viper.Viper, networkID uint32) genesis.TxFeeConfig {
MinPrice: gas.Price(v.GetUint64(DynamicFeesMinGasPriceKey)),
ExcessConversionConstant: gas.Gas(v.GetUint64(DynamicFeesExcessConversionConstantKey)),
},
ValidatorFeeCapacity: gas.Gas(v.GetUint64(ValidatorFeesCapacityKey)),
ValidatorFeeConfig: validatorfee.Config{
Capacity: gas.Gas(v.GetUint64(ValidatorFeesCapacityKey)),
Target: gas.Gas(v.GetUint64(ValidatorFeesTargetKey)),
MinPrice: gas.Price(v.GetUint64(ValidatorFeesMinPriceKey)),
ExcessConversionConstant: gas.Gas(v.GetUint64(ValidatorFeesExcessConversionConstantKey)),
Expand Down
2 changes: 1 addition & 1 deletion config/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func addNodeFlags(fs *pflag.FlagSet) {

// AVAX fees:
// Validator fees:
fs.Uint64(ValidatorFeesCapacityKey, uint64(genesis.LocalParams.ValidatorFeeCapacity), "Maximum number of validators")
fs.Uint64(ValidatorFeesCapacityKey, uint64(genesis.LocalParams.ValidatorFeeConfig.Capacity), "Maximum number of validators")
fs.Uint64(ValidatorFeesTargetKey, uint64(genesis.LocalParams.ValidatorFeeConfig.Target), "Target number of validators")
fs.Uint64(ValidatorFeesMinPriceKey, uint64(genesis.LocalParams.ValidatorFeeConfig.MinPrice), "Minimum validator price in nAVAX per second")
fs.Uint64(ValidatorFeesExcessConversionConstantKey, uint64(genesis.LocalParams.ValidatorFeeConfig.ExcessConversionConstant), "Constant to convert validator excess price")
Expand Down
2 changes: 1 addition & 1 deletion genesis/genesis_fuji.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ var (
MinPrice: 1,
ExcessConversionConstant: 5_000,
},
ValidatorFeeCapacity: 20_000,
ValidatorFeeConfig: validatorfee.Config{
Capacity: 20_000,
Target: 10_000,
MinPrice: gas.Price(512 * units.NanoAvax),
// ExcessConversionConstant = (Capacity - Target) * NumberOfSecondsPerDoubling / ln(2)
Expand Down
2 changes: 1 addition & 1 deletion genesis/genesis_local.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ var (
MinPrice: 1,
ExcessConversionConstant: 5_000,
},
ValidatorFeeCapacity: 20_000,
ValidatorFeeConfig: validatorfee.Config{
Capacity: 20_000,
Target: 10_000,
MinPrice: gas.Price(1 * units.NanoAvax),
// ExcessConversionConstant = (Capacity - Target) * NumberOfSecondsPerDoubling / ln(2)
Expand Down
2 changes: 1 addition & 1 deletion genesis/genesis_mainnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ var (
MinPrice: 1,
ExcessConversionConstant: 5_000,
},
ValidatorFeeCapacity: 20_000,
ValidatorFeeConfig: validatorfee.Config{
Capacity: 20_000,
Target: 10_000,
MinPrice: gas.Price(512 * units.NanoAvax),
// ExcessConversionConstant = (Capacity - Target) * NumberOfSecondsPerDoubling / ln(2)
Expand Down
Loading