diff --git a/config/config.go b/config/config.go index ac43d0441..95e1f5d06 100644 --- a/config/config.go +++ b/config/config.go @@ -234,6 +234,12 @@ type BaseConfig struct { //nolint: maligned // Default: 0 DeadlockDetection time.Duration `mapstructure:"deadlock-detection"` + // SyncTimeout is the timeout for the initial sync process, before switching to consensus. + // + // Default: 60s + SyncTimeout time.Duration `mapstructure:"sync-timeout"` + + // Other options should be empty Other map[string]interface{} `mapstructure:",remain"` } @@ -250,6 +256,7 @@ func DefaultBaseConfig() BaseConfig { DBBackend: "goleveldb", DBPath: "data", DeadlockDetection: 0, + SyncTimeout: 60 * time.Second, } } @@ -353,6 +360,10 @@ func (cfg BaseConfig) ValidateBasic() error { return fmt.Errorf("unsupported db backend: %s, only goleveldb is supported", cfg.DBBackend) } + if cfg.SyncTimeout < 0 { + return errors.New("sync-timeout can't be negative, got: " + cfg.SyncTimeout.String()) + } + return nil } diff --git a/config/config_test.go b/config/config_test.go index 03c70fe81..a667aabd3 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -24,6 +24,8 @@ func TestDefaultConfig(t *testing.T) { assert.Equal(t, "/foo/bar", cfg.GenesisFile()) assert.Equal(t, "/opt/data", cfg.DBDir()) + + assert.Equal(t, 60*time.Second, cfg.BaseConfig.SyncTimeout) } func TestConfigValidateBasic(t *testing.T) { diff --git a/config/toml.go b/config/toml.go index b6be127b2..8ec31e01a 100644 --- a/config/toml.go +++ b/config/toml.go @@ -137,6 +137,11 @@ filter-peers = {{ .BaseConfig.FilterPeers }} # Default: 0 deadlock-detection = "{{ .BaseConfig.DeadlockDetection }}" +# Timeout for the initial sync process, before switching to consensus. +# +# Default: 60s +sync-timeout = "{{ .BaseConfig.SyncTimeout }}" + ####################################################### ### ABCI App Connection Options ### ####################################################### diff --git a/go.mod b/go.mod index 60e978200..6eda79b64 100644 --- a/go.mod +++ b/go.mod @@ -9,8 +9,8 @@ require ( github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce github.com/containerd/continuity v0.4.4 // indirect github.com/dashpay/bls-signatures/go-bindings v0.0.0-20230207105415-06df92693ac8 - github.com/dashpay/dashd-go v0.25.0 - github.com/dashpay/dashd-go/btcec/v2 v2.1.0 // indirect + github.com/dashpay/dashd-go v0.26.0 + github.com/dashpay/dashd-go/btcec/v2 v2.2.0 // indirect github.com/fortytw2/leaktest v1.3.0 github.com/fxamacker/cbor/v2 v2.4.0 github.com/go-chi/chi v4.1.2+incompatible // indirect @@ -38,7 +38,7 @@ require ( github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.10.0 - golang.org/x/crypto v0.30.0 + golang.org/x/crypto v0.31.0 golang.org/x/net v0.32.0 golang.org/x/sync v0.10.0 google.golang.org/grpc v1.69.0 @@ -80,7 +80,7 @@ require ( github.com/alexkohler/nakedret/v2 v2.0.5 // indirect github.com/antlr4-go/antlr/v4 v4.13.1 // indirect github.com/bombsimon/wsl/v4 v4.4.1 // indirect - github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect + github.com/btcsuite/btclog v1.0.0 // indirect github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect github.com/bufbuild/protocompile v0.14.1 // indirect @@ -108,7 +108,7 @@ require ( github.com/containerd/ttrpc v1.2.6 // indirect github.com/containerd/typeurl/v2 v2.2.3 // indirect github.com/curioswitch/go-reassign v0.2.0 // indirect - github.com/dashpay/dashd-go/btcutil v1.2.0 // indirect + github.com/dashpay/dashd-go/btcutil v1.3.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/dgraph-io/badger/v4 v4.3.1 // indirect github.com/didip/tollbooth/v6 v6.0.1 // indirect diff --git a/go.sum b/go.sum index 37fc4a36b..a93a53e43 100644 --- a/go.sum +++ b/go.sum @@ -104,8 +104,9 @@ github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btclog v1.0.0 h1:sEkpKJMmfGiyZjADwEIgB1NSwMyfdD1FB8v6+w1T0Ns= +github.com/btcsuite/btclog v1.0.0/go.mod h1:w7xnGOhwT3lmrS4H3b/D1XAXxvh+tbhUm8xeHN2y3TQ= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= @@ -217,12 +218,12 @@ github.com/daixiang0/gci v0.13.5 h1:kThgmH1yBmZSBCh1EJVxQ7JsHpm5Oms0AMed/0LaH4c= github.com/daixiang0/gci v0.13.5/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk= github.com/dashpay/bls-signatures/go-bindings v0.0.0-20230207105415-06df92693ac8 h1:v4K3CiDoFY1gjcWL/scRcwzyjBwh8TVG3ek8cWolK1g= github.com/dashpay/bls-signatures/go-bindings v0.0.0-20230207105415-06df92693ac8/go.mod h1:auvGS60NBZ+a21aCCQh366PdsjDvHinsCvl28VrYPu4= -github.com/dashpay/dashd-go v0.25.0 h1:tswVRmM2fLHC/JhpuAZ5Oa0TpOO6L+tqiE+QLTCvIQc= -github.com/dashpay/dashd-go v0.25.0/go.mod h1:4yuk/laGME2RnQRTdqTbw87PhT+42hE1anLCnpkgls8= -github.com/dashpay/dashd-go/btcec/v2 v2.1.0 h1:fXwlLf5H+TtgHxjGMU74NesKzk6NisjKMPF04pBcygk= -github.com/dashpay/dashd-go/btcec/v2 v2.1.0/go.mod h1:1i8XtxdOmvK6mYEUCneVXTzFbrCUw3wq1u91j8gvsns= -github.com/dashpay/dashd-go/btcutil v1.2.0 h1:YMq7L0V0au5bbphIhpsBBc+nfOZqU+gJ4pkgRZB7Eiw= -github.com/dashpay/dashd-go/btcutil v1.2.0/go.mod h1:7UHoqUh3LY3OI4mEcogx0CnL3rtzDQyoqvsOCZZtvzE= +github.com/dashpay/dashd-go v0.26.0 h1:Sbd49FUqapKqk8NBCR7U1hglopA6psAMSIk4bTm3f5g= +github.com/dashpay/dashd-go v0.26.0/go.mod h1:7KKS2jSPkC1pTz9WLXpiXZ96wT5bUqKTRuk35AyRQ74= +github.com/dashpay/dashd-go/btcec/v2 v2.2.0 h1:tk54BC++OvOUu0vcPoG8+45dGoJXKsmupYAawBO/1Vk= +github.com/dashpay/dashd-go/btcec/v2 v2.2.0/go.mod h1:uOmCM/hVoJ1x6w+3SX+zQv+2LdrK3aO59RV41jNvTF4= +github.com/dashpay/dashd-go/btcutil v1.3.0 h1:yDX8tz7C/KhFHbGlRXBpNN+zlkmAgwkICD9DlAv/Vsc= +github.com/dashpay/dashd-go/btcutil v1.3.0/go.mod h1:sMWZ0iR8a/wmIA6b5+ccjOGUfq+iZvi5t6ECaLCW+kw= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -918,8 +919,8 @@ golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= -golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= diff --git a/internal/blocksync/reactor.go b/internal/blocksync/reactor.go index 822550f16..3c83fe665 100644 --- a/internal/blocksync/reactor.go +++ b/internal/blocksync/reactor.go @@ -30,7 +30,7 @@ const ( switchToConsensusIntervalSeconds = 1 // switch to consensus after this duration of inactivity - syncTimeout = 60 * time.Second + defaultSyncTimeout = 60 * time.Second ) type consensusReactor interface { @@ -62,6 +62,8 @@ type Reactor struct { eventBus *eventbus.EventBus syncStartTime time.Time + // syncTimeout defines how much time we will try to start sync before switching to consensus + syncTimeout time.Duration nodeProTxHash types.ProTxHash @@ -94,6 +96,7 @@ func NewReactor( metrics: metrics, eventBus: eventBus, nodeProTxHash: nodeProTxHash, + syncTimeout: defaultSyncTimeout, executor: newBlockApplier( blockExec, store, @@ -106,6 +109,12 @@ func NewReactor( return r } +func (r *Reactor) WithSyncTimeout(timeout time.Duration) *Reactor { + r.syncTimeout = timeout + + return r +} + // OnStart starts separate go routines for each p2p Channel and listens for // envelopes on each. In addition, it also listens for peer updates and handles // messages on that p2p channel accordingly. The caller must be sure to execute @@ -130,7 +139,10 @@ func (r *Reactor) OnStart(ctx context.Context) error { startHeight = state.InitialHeight } - r.synchronizer = NewSynchronizer(startHeight, r.p2pClient, r.executor, WithLogger(r.logger)) + r.synchronizer = NewSynchronizer(startHeight, r.p2pClient, r.executor, + WithLogger(r.logger), + WithSyncTimeout(r.syncTimeout), + ) if r.blockSyncFlag.Load() { if err := r.synchronizer.Start(ctx); err != nil { return err diff --git a/internal/blocksync/synchronizer.go b/internal/blocksync/synchronizer.go index d4812731c..aed6670ad 100644 --- a/internal/blocksync/synchronizer.go +++ b/internal/blocksync/synchronizer.go @@ -70,6 +70,8 @@ type ( logger log.Logger lastAdvance time.Time + // syncTimeout defines how much time we will try to sync; defaults to 60 seconds + syncTimeout time.Duration mtx sync.RWMutex @@ -112,6 +114,12 @@ func WithClock(clock clockwork.Clock) OptionFunc { } } +func WithSyncTimeout(timeout time.Duration) OptionFunc { + return func(v *Synchronizer) { + v.syncTimeout = timeout + } +} + // NewSynchronizer returns a new Synchronizer with the height equal to start func NewSynchronizer(start int64, client client.BlockClient, blockExec *blockApplier, opts ...OptionFunc) *Synchronizer { peerStore := NewInMemPeerStore() @@ -127,6 +135,7 @@ func NewSynchronizer(start int64, client client.BlockClient, blockExec *blockApp height: start, workerPool: workerpool.New(poolWorkerSize, workerpool.WithLogger(logger)), pendingToApply: map[int64]BlockResponse{}, + syncTimeout: defaultSyncTimeout, } for _, opt := range opts { opt(bp) @@ -239,14 +248,14 @@ func (s *Synchronizer) WaitForSync(ctx context.Context) { lastAdvance = s.LastAdvance() isCaughtUp = s.IsCaughtUp() ) - if isCaughtUp || time.Since(lastAdvance) > syncTimeout { + if isCaughtUp || time.Since(lastAdvance) > s.syncTimeout { return } s.logger.Info( "not caught up yet", "height", height, "max_peer_height", s.MaxPeerHeight(), - "timeout_in", syncTimeout-time.Since(lastAdvance), + "timeout_in", s.syncTimeout-time.Since(lastAdvance), ) } } diff --git a/node/node.go b/node/node.go index f69b7d196..83ef4c8ba 100644 --- a/node/node.go +++ b/node/node.go @@ -367,7 +367,7 @@ func makeNode( blockSync && !stateSync, nodeMetrics.consensus, eventBus, - ) + ).WithSyncTimeout(cfg.SyncTimeout) node.services = append(node.services, bcReactor) node.rpcEnv.BlockSyncReactor = bcReactor