@ -63,26 +63,25 @@ type nodeImpl struct {
isListening bool
isListening bool
// services
// services
eventBus * types . EventBus // pub/sub for services
stateStore sm . Store
blockStore * store . BlockStore // store the blockchain to disk
bcReactor service . Service // for fast-syncing
mempoolReactor service . Service // for gossipping transactions
mempool mempool . Mempool
stateSync bool // whether the node should state sync on startup
stateSyncReactor * statesync . Reactor // for hosting and restoring state sync snapshots
stateSyncProvider statesync . StateProvider // provides state data for bootstrapping a node
consensusState * cs . State // latest consensus state
consensusReactor * cs . Reactor // for participating in the consensus
pexReactor * pex . Reactor // for exchanging peer addresses
pexReactorV2 * pex . ReactorV2 // for exchanging peer addresses
evidenceReactor * evidence . Reactor
evidencePool * evidence . Pool // tracking evidence
proxyApp proxy . AppConns // connection to the application
rpcListeners [ ] net . Listener // rpc servers
eventSinks [ ] indexer . EventSink
indexerService * indexer . Service
prometheusSrv * http . Server
eventBus * types . EventBus // pub/sub for services
stateStore sm . Store
blockStore * store . BlockStore // store the blockchain to disk
bcReactor service . Service // for fast-syncing
mempoolReactor service . Service // for gossipping transactions
mempool mempool . Mempool
stateSync bool // whether the node should state sync on startup
stateSyncReactor * statesync . Reactor // for hosting and restoring state sync snapshots
consensusState * cs . State // latest consensus state
consensusReactor * cs . Reactor // for participating in the consensus
pexReactor * pex . Reactor // for exchanging peer addresses
pexReactorV2 * pex . ReactorV2 // for exchanging peer addresses
evidenceReactor * evidence . Reactor
evidencePool * evidence . Pool // tracking evidence
proxyApp proxy . AppConns // connection to the application
rpcListeners [ ] net . Listener // rpc servers
eventSinks [ ] indexer . EventSink
indexerService * indexer . Service
prometheusSrv * http . Server
}
}
// newDefaultNode returns a Tendermint node with default settings for the
// newDefaultNode returns a Tendermint node with default settings for the
@ -663,9 +662,15 @@ func (n *nodeImpl) OnStart() error {
return fmt . Errorf ( "unable to derive state: %w" , err )
return fmt . Errorf ( "unable to derive state: %w" , err )
}
}
err = startStateSync ( n . stateSyncReactor , bcR , n . consensusReactor , n . stateSyncProvider ,
n . config . StateSync , n . config . FastSyncMode , n . stateStore , n . blockStore , state , n . eventBus )
ssc := n . config . StateSync
sp , err := constructStateProvider ( ssc , state , n . Logger . With ( "module" , "light" ) )
if err != nil {
if err != nil {
return fmt . Errorf ( "failed to set up light client state provider: %w" , err )
}
if err := startStateSync ( n . stateSyncReactor , bcR , n . consensusReactor , sp ,
ssc , n . config . FastSyncMode , state . InitialHeight , n . eventBus ) ; err != nil {
return fmt . Errorf ( "failed to start state sync: %w" , err )
return fmt . Errorf ( "failed to start state sync: %w" , err )
}
}
}
}
@ -1027,54 +1032,57 @@ func (n *nodeImpl) NodeInfo() types.NodeInfo {
}
}
// startStateSync starts an asynchronous state sync process, then switches to fast sync mode.
// startStateSync starts an asynchronous state sync process, then switches to fast sync mode.
func startStateSync ( ssR * statesync . Reactor , bcR cs . FastSyncReactor , conR * cs . Reactor ,
stateProvider statesync . StateProvider , config * cfg . StateSyncConfig , fastSync bool ,
stateStore sm . Store , blockStore * store . BlockStore , state sm . State , eventbus * types . EventBus ) error {
ssR . Logger . Info ( "starting state sync..." )
if stateProvider == nil {
var err error
ctx , cancel := context . WithTimeout ( context . Background ( ) , 10 * time . Second )
defer cancel ( )
stateProvider , err = statesync . NewLightClientStateProvider (
ctx ,
state . ChainID , state . Version , state . InitialHeight ,
config . RPCServers , light . TrustOptions {
Period : config . TrustPeriod ,
Height : config . TrustHeight ,
Hash : config . TrustHashBytes ( ) ,
} , ssR . Logger . With ( "module" , "light" ) )
if err != nil {
return fmt . Errorf ( "failed to set up light client state provider: %w" , err )
}
func startStateSync (
ssR statesync . SyncReactor ,
bcR cs . FastSyncReactor ,
conR cs . ConsSyncReactor ,
sp statesync . StateProvider ,
config * cfg . StateSyncConfig ,
fastSync bool ,
stateInitHeight int64 ,
eb * types . EventBus ,
) error {
stateSyncLogger := eb . Logger . With ( "module" , "statesync" )
stateSyncLogger . Info ( "starting state sync..." )
// at the beginning of the statesync start, we use the initialHeight as the event height
// because of the statesync doesn't have the concreate state height before fetched the snapshot.
d := types . EventDataStateSyncStatus { Complete : false , Height : stateInitHeight }
if err := eb . PublishEventStateSyncStatus ( d ) ; err != nil {
stateSyncLogger . Error ( "failed to emit the statesync start event" , "err" , err )
}
}
go func ( ) {
go func ( ) {
state , err := ssR . Sync ( context . TODO ( ) , stateProvider , config . DiscoveryTime )
state , err := ssR . Sync ( context . TODO ( ) , sp , config . DiscoveryTime )
if err != nil {
if err != nil {
ssR . Logger . Error ( "state sync failed" , "err" , err )
stateSync Logger . Error ( "state sync failed" , "err" , err )
return
return
}
}
err = ssR . Backfill ( state )
if err != nil {
ssR . Logger . Error ( "backfill failed; node has insufficient history to verify all evidence;" +
if err := ssR . Backfill ( state ) ; err != nil {
stateSyncLogger . Error ( "backfill failed; node has insufficient history to verify all evidence;" +
" proceeding optimistically..." , "err" , err )
" proceeding optimistically..." , "err" , err )
}
}
conR . Metrics . StateSyncing . Set ( 0 )
conR . SetStateSyncingMetrics ( 0 )
d := types . EventDataStateSyncStatus { Complete : true , Height : state . LastBlockHeight }
if err := eb . PublishEventStateSyncStatus ( d ) ; err != nil {
stateSyncLogger . Error ( "failed to emit the statesync start event" , "err" , err )
}
if fastSync {
if fastSync {
// FIXME Very ugly to have these metrics bleed through here.
// FIXME Very ugly to have these metrics bleed through here.
conR . Metrics . FastSyncing . Set ( 1 )
err = bcR . SwitchToFastSync ( state )
if err != nil {
ssR . Logger . Error ( "failed to switch to fast sync" , "err" , err )
conR . SetFastSyncingMetrics ( 1 )
if err := bcR . SwitchToFastSync ( state ) ; err != nil {
stateSyncLogger . Error ( "failed to switch to fast sync" , "err" , err )
return
return
}
}
d := types . EventDataFastSyncStatus { Complete : false , Height : state . LastBlockHeight }
d := types . EventDataFastSyncStatus { Complete : false , Height : state . LastBlockHeight }
if err := event bus . PublishEventFastSyncStatus ( d ) ; err != nil {
ssR . Logger . Error ( "failed to emit the fastsync starting event" , "err" , err )
if err := eb . PublishEventFastSyncStatus ( d ) ; err != nil {
stateSync Logger . Error ( "failed to emit the fastsync starting event" , "err" , err )
}
}
} else {
} else {
@ -1266,3 +1274,24 @@ func getChannelsFromShim(reactorShim *p2p.ReactorShim) map[p2p.ChannelID]*p2p.Ch
return channels
return channels
}
}
func constructStateProvider (
ssc * cfg . StateSyncConfig ,
state sm . State ,
logger log . Logger ,
) ( statesync . StateProvider , error ) {
ctx , cancel := context . WithTimeout ( context . TODO ( ) , 10 * time . Second )
defer cancel ( )
to := light . TrustOptions {
Period : ssc . TrustPeriod ,
Height : ssc . TrustHeight ,
Hash : ssc . TrustHashBytes ( ) ,
}
return statesync . NewLightClientStateProvider (
ctx ,
state . ChainID , state . Version , state . InitialHeight ,
ssc . RPCServers , to , logger ,
)
}