Skip to content

Commit

Permalink
Remove avalanche bootstrapping -> avalanche consensus transition (ava…
Browse files Browse the repository at this point in the history
  • Loading branch information
StephenButtolph authored Apr 25, 2023
1 parent 8ad9ee8 commit 28aa2cb
Show file tree
Hide file tree
Showing 11 changed files with 188 additions and 1,285 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/test.e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,3 @@ jobs:
- name: Run e2e tests
shell: bash
run: scripts/tests.e2e.sh ./build/avalanchego
- name: Run e2e tests for whitelist vtx
shell: bash
run: ENABLE_WHITELIST_VTX_TESTS=true ./scripts/tests.e2e.sh ./build/avalanchego
24 changes: 13 additions & 11 deletions chains/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -920,16 +920,6 @@ func (m *manager) createAvalancheChain(
return nil, fmt.Errorf("couldn't initialize avalanche base message handler: %w", err)
}

// create bootstrap gear
avalancheBootstrapperConfig := avbootstrap.Config{
Config: avalancheCommonCfg,
AllGetsServer: avaGetHandler,
VtxBlocked: vtxBlocker,
TxBlocked: txBlocker,
Manager: vtxManager,
VM: linearizableVM,
}

var avalancheConsensus avcon.Consensus = &avcon.Topological{}
if m.TracingEnabled {
avalancheConsensus = avcon.Trace(avalancheConsensus, m.Tracer)
Expand Down Expand Up @@ -958,10 +948,22 @@ func (m *manager) createAvalancheChain(
avalancheEngine = aveng.TraceEngine(avalancheEngine, m.Tracer)
}

// create bootstrap gear
_, specifiedLinearizationTime := version.CortinaTimes[ctx.NetworkID]
specifiedLinearizationTime = specifiedLinearizationTime && ctx.ChainID == m.XChainID
avalancheBootstrapperConfig := avbootstrap.Config{
Config: avalancheCommonCfg,
AllGetsServer: avaGetHandler,
VtxBlocked: vtxBlocker,
TxBlocked: txBlocker,
Manager: vtxManager,
VM: linearizableVM,
LinearizeOnStartup: !specifiedLinearizationTime,
}

avalancheBootstrapper, err := avbootstrap.New(
context.TODO(),
avalancheBootstrapperConfig,
avalancheEngine.Start,
snowmanBootstrapper.Start,
)
if err != nil {
Expand Down
12 changes: 1 addition & 11 deletions scripts/tests.e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ set -o pipefail
# e.g.,
# ./scripts/build.sh
# ./scripts/tests.e2e.sh ./build/avalanchego
# ENABLE_WHITELIST_VTX_TESTS=true ./scripts/tests.e2e.sh ./build/avalanchego
if ! [[ "$0" =~ scripts/tests.e2e.sh ]]; then
echo "must be run from repository root"
exit 255
Expand All @@ -28,15 +27,6 @@ export CGO_CFLAGS="-O -D__BLST_PORTABLE__"
# clear error due to the default value change in go1.20.
export CGO_ENABLED=1

ENABLE_WHITELIST_VTX_TESTS=${ENABLE_WHITELIST_VTX_TESTS:-false}
# ref. https://onsi.github.io/ginkgo/#spec-labels
GINKGO_LABEL_FILTER="!whitelist-tx"
if [[ ${ENABLE_WHITELIST_VTX_TESTS} == true ]]; then
# run only "whitelist-tx" tests, no other test
GINKGO_LABEL_FILTER="whitelist-tx"
fi
echo GINKGO_LABEL_FILTER: ${GINKGO_LABEL_FILTER}

#################################
# download avalanche-network-runner
# https://github.com/ava-labs/avalanche-network-runner
Expand Down Expand Up @@ -85,7 +75,7 @@ echo "running e2e tests against the local cluster with ${AVALANCHEGO_PATH}"
--network-runner-grpc-endpoint="0.0.0.0:12342" \
--network-runner-avalanchego-path=${AVALANCHEGO_PATH} \
--network-runner-avalanchego-log-level="WARN" \
--test-keys-file=tests/test.insecure.secp256k1.keys --ginkgo.label-filter="${GINKGO_LABEL_FILTER}" \
--test-keys-file=tests/test.insecure.secp256k1.keys \
&& EXIT_CODE=$? || EXIT_CODE=$?

kill ${PID}
Expand Down
128 changes: 51 additions & 77 deletions snow/engine/avalanche/bootstrap/bootstrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ package bootstrap

import (
"context"
"errors"
"fmt"
"math"
"time"

"go.uber.org/zap"

Expand All @@ -31,22 +28,14 @@ const (
stripeDistance = 2000
stripeWidth = 5
cacheSize = 100000

// Parameters for delaying bootstrapping to avoid potential CPU burns
bootstrappingDelay = 10 * time.Second
)

var (
_ common.BootstrapableEngine = (*bootstrapper)(nil)

errUnexpectedTimeout = errors.New("unexpected timeout fired")
)
var _ common.BootstrapableEngine = (*bootstrapper)(nil)

func New(
ctx context.Context,
config Config,
startAvalancheConsensus func(ctx context.Context, lastReqID uint32) error,
startSnowmanBootstrapping func(ctx context.Context, lastReqID uint32) error,
onFinished func(ctx context.Context, lastReqID uint32) error,
) (common.BootstrapableEngine, error) {
b := &bootstrapper{
Config: config,
Expand All @@ -60,26 +49,8 @@ func New(

processedCache: &cache.LRU[ids.ID, struct{}]{Size: cacheSize},
Fetcher: common.Fetcher{
OnFinished: func(ctx context.Context, lastReqID uint32) error {
linearized, err := config.Manager.StopVertexAccepted(ctx)
if err != nil {
return err
}
if !linearized {
return startAvalancheConsensus(ctx, lastReqID)
}

// Invariant: edge will only be the stop vertex after its
// acceptance.
edge := config.Manager.Edge(ctx)
stopVertexID := edge[0]
if err := config.VM.Linearize(ctx, stopVertexID); err != nil {
return err
}
return startSnowmanBootstrapping(ctx, lastReqID)
},
OnFinished: onFinished,
},
executedStateTransitions: math.MaxInt32,
}

if err := b.metrics.Initialize("bs", config.Ctx.AvalancheRegisterer); err != nil {
Expand Down Expand Up @@ -132,10 +103,6 @@ type bootstrapper struct {

// Contains IDs of vertices that have recently been processed
processedCache *cache.LRU[ids.ID, struct{}]
// number of state transitions executed
executedStateTransitions int

awaitingTimeout bool
}

func (b *bootstrapper) Clear() error {
Expand Down Expand Up @@ -319,16 +286,8 @@ func (b *bootstrapper) Disconnected(ctx context.Context, nodeID ids.NodeID) erro
return b.StartupTracker.Disconnected(ctx, nodeID)
}

func (b *bootstrapper) Timeout(ctx context.Context) error {
if !b.awaitingTimeout {
return errUnexpectedTimeout
}
b.awaitingTimeout = false

if !b.Config.BootstrapTracker.IsBootstrapped() {
return b.Restart(ctx, true)
}
return b.OnFinished(ctx, b.Config.SharedCfg.RequestID)
func (*bootstrapper) Timeout(context.Context) error {
return nil
}

func (*bootstrapper) Gossip(context.Context) error {
Expand Down Expand Up @@ -358,6 +317,42 @@ func (b *bootstrapper) Start(ctx context.Context, startReqID uint32) error {

b.Config.SharedCfg.RequestID = startReqID

// If the network was already linearized, don't attempt to linearize it
// again.
linearized, err := b.Manager.StopVertexAccepted(ctx)
if err != nil {
return fmt.Errorf("failed to get linearization status: %w", err)
}
if linearized {
edge := b.Manager.Edge(ctx)
return b.ForceAccepted(ctx, edge)
}

// If requested, assume the currently accepted state is what was linearized.
//
// Note: This is used to linearize networks that were created after the
// linearization occurred.
if b.Config.LinearizeOnStartup {
edge := b.Manager.Edge(ctx)
stopVertex, err := b.Manager.BuildStopVtx(ctx, edge)
if err != nil {
return fmt.Errorf("failed to create stop vertex: %w", err)
}
if err := stopVertex.Verify(ctx); err != nil {
return fmt.Errorf("failed to verify stop vertex: %w", err)
}
if err := stopVertex.Accept(ctx); err != nil {
return fmt.Errorf("failed to accept stop vertex: %w", err)
}

stopVertexID := stopVertex.ID()
b.Ctx.Log.Info("accepted stop vertex",
zap.Stringer("vtxID", stopVertexID),
)

return b.ForceAccepted(ctx, []ids.ID{stopVertexID})
}

if !b.StartupTracker.ShouldStart() {
return nil
}
Expand Down Expand Up @@ -570,7 +565,7 @@ func (b *bootstrapper) ForceAccepted(ctx context.Context, acceptedContainerIDs [
func (b *bootstrapper) checkFinish(ctx context.Context) error {
// If there are outstanding requests for vertices or we still need to fetch vertices, we can't finish
pendingJobs := b.VtxBlocked.MissingIDs()
if b.IsBootstrapped() || len(pendingJobs) > 0 || b.awaitingTimeout {
if b.IsBootstrapped() || len(pendingJobs) > 0 {
return nil
}

Expand All @@ -597,7 +592,7 @@ func (b *bootstrapper) checkFinish(ctx context.Context) error {
b.Ctx.Log.Debug("executing vertices")
}

executedVts, err := b.VtxBlocked.ExecuteAll(
_, err = b.VtxBlocked.ExecuteAll(
ctx,
b.Config.Ctx,
b,
Expand All @@ -614,39 +609,18 @@ func (b *bootstrapper) checkFinish(ctx context.Context) error {
if err != nil {
return err
}
if linearized {
b.processedCache.Flush()
return b.OnFinished(ctx, b.Config.SharedCfg.RequestID)
if !linearized {
b.Ctx.Log.Debug("checking for stop vertex before finishing bootstrapping")
return b.Restart(ctx, true)
}

previouslyExecuted := b.executedStateTransitions
b.executedStateTransitions = executedVts

// Note that executedVts < c*previouslyExecuted is enforced so that the
// bootstrapping process will terminate even as new vertices are being
// issued.
if executedVts > 0 && executedVts < previouslyExecuted/2 && b.Config.RetryBootstrap {
b.Ctx.Log.Debug("checking for more vertices before finishing bootstrapping")
return b.Restart(ctx, true)
// Invariant: edge will only be the stop vertex after its acceptance.
edge := b.Manager.Edge(ctx)
stopVertexID := edge[0]
if err := b.VM.Linearize(ctx, stopVertexID); err != nil {
return err
}

// Notify the subnet that this chain is synced
b.Config.BootstrapTracker.Bootstrapped(b.Ctx.ChainID)
b.processedCache.Flush()

// If the subnet hasn't finished bootstrapping, this chain should remain
// syncing.
if !b.Config.BootstrapTracker.IsBootstrapped() {
if !b.Config.SharedCfg.Restarted {
b.Ctx.Log.Info("waiting for the remaining chains in this subnet to finish syncing")
} else {
b.Ctx.Log.Debug("waiting for the remaining chains in this subnet to finish syncing")
}
// Restart bootstrapping after [bootstrappingDelay] to keep up to date
// on the latest tip.
b.Config.Timer.RegisterTimeout(bootstrappingDelay)
b.awaitingTimeout = true
return nil
}
return b.OnFinished(ctx, b.Config.SharedCfg.RequestID)
}
Loading

0 comments on commit 28aa2cb

Please sign in to comment.