Skip to content

Commit 59759f8

Browse files
committed
rpcserver: check blockbeatDispatcher when deciding isSynced
This commit changes `GetInfo` to include `blockbeatDispatcher`'s current state when deciding whether the system is synced to chain. Previously we check the best height against the wallet and the channel graph, we should also do this to the blockbeat dispatcher to make sure the internal consumers are also synced to the best block.
1 parent 89c4a8d commit 59759f8

File tree

1 file changed

+85
-25
lines changed

1 file changed

+85
-25
lines changed

rpcserver.go

Lines changed: 85 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3225,28 +3225,10 @@ func (r *rpcServer) GetInfo(_ context.Context,
32253225
idPub := r.server.identityECDH.PubKey().SerializeCompressed()
32263226
encodedIDPub := hex.EncodeToString(idPub)
32273227

3228-
bestHash, bestHeight, err := r.server.cc.ChainIO.GetBestBlock()
3229-
if err != nil {
3230-
return nil, fmt.Errorf("unable to get best block info: %w", err)
3231-
}
3232-
3233-
isSynced, bestHeaderTimestamp, err := r.server.cc.Wallet.IsSynced()
3228+
// Get the system's chain sync info.
3229+
syncInfo, err := r.getChainSyncInfo()
32343230
if err != nil {
3235-
return nil, fmt.Errorf("unable to sync PoV of the wallet "+
3236-
"with current best block in the main chain: %v", err)
3237-
}
3238-
3239-
// If the router does full channel validation, it has a lot of work to
3240-
// do for each block. So it might be possible that it isn't yet up to
3241-
// date with the most recent block, even if the wallet is. This can
3242-
// happen in environments with high CPU load (such as parallel itests).
3243-
// Since the `synced_to_chain` flag in the response of this call is used
3244-
// by many wallets (and also our itests) to make sure everything's up to
3245-
// date, we add the router's state to it. So the flag will only toggle
3246-
// to true once the router was also able to catch up.
3247-
if !r.cfg.Routing.AssumeChannelValid {
3248-
routerHeight := r.server.graphBuilder.SyncedHeight()
3249-
isSynced = isSynced && uint32(bestHeight) == routerHeight
3231+
return nil, err
32503232
}
32513233

32523234
network := lncfg.NormalizeNetwork(r.cfg.ActiveNetParams.Name)
@@ -3297,15 +3279,15 @@ func (r *rpcServer) GetInfo(_ context.Context,
32973279
NumActiveChannels: activeChannels,
32983280
NumInactiveChannels: inactiveChannels,
32993281
NumPeers: uint32(len(serverPeers)),
3300-
BlockHeight: uint32(bestHeight),
3301-
BlockHash: bestHash.String(),
3302-
SyncedToChain: isSynced,
3282+
BlockHeight: uint32(syncInfo.bestHeight),
3283+
BlockHash: syncInfo.blockHash.String(),
3284+
SyncedToChain: syncInfo.isSynced,
33033285
Testnet: isTestNet,
33043286
Chains: activeChains,
33053287
Uris: uris,
33063288
Alias: nodeAnn.Alias.String(),
33073289
Color: nodeColor,
3308-
BestHeaderTimestamp: bestHeaderTimestamp,
3290+
BestHeaderTimestamp: syncInfo.timestamp,
33093291
Version: version,
33103292
CommitHash: build.CommitHash,
33113293
SyncedToGraph: isGraphSynced,
@@ -8929,3 +8911,81 @@ func rpcInitiator(isInitiator bool) lnrpc.Initiator {
89298911

89308912
return lnrpc.Initiator_INITIATOR_REMOTE
89318913
}
8914+
8915+
// chainSyncInfo wraps info about the best block and whether the system is
8916+
// synced to that block.
8917+
type chainSyncInfo struct {
8918+
// isSynced specifies whether the whole system is considered synced.
8919+
// When true, it means the following subsystems are at the best height
8920+
// reported by the chain backend,
8921+
// - wallet.
8922+
// - channel graph.
8923+
// - blockbeat dispatcher.
8924+
isSynced bool
8925+
8926+
// bestHeight is the current height known to the chain backend.
8927+
bestHeight int32
8928+
8929+
// blockHash is the hash of the current block known to the chain
8930+
// backend.
8931+
blockHash chainhash.Hash
8932+
8933+
// timestamp is the block's timestamp the wallet has synced to.
8934+
timestamp int64
8935+
}
8936+
8937+
// getChainSyncInfo queries the chain backend, the wallet, the channel router
8938+
// and the blockbeat dispatcher to determine the best block and whether the
8939+
// system is considered synced.
8940+
func (r *rpcServer) getChainSyncInfo() (*chainSyncInfo, error) {
8941+
bestHash, bestHeight, err := r.server.cc.ChainIO.GetBestBlock()
8942+
if err != nil {
8943+
return nil, fmt.Errorf("unable to get best block info: %w", err)
8944+
}
8945+
8946+
isSynced, bestHeaderTimestamp, err := r.server.cc.Wallet.IsSynced()
8947+
if err != nil {
8948+
return nil, fmt.Errorf("unable to sync PoV of the wallet "+
8949+
"with current best block in the main chain: %v", err)
8950+
}
8951+
8952+
// Create an info to be returned.
8953+
info := &chainSyncInfo{
8954+
isSynced: isSynced,
8955+
bestHeight: bestHeight,
8956+
blockHash: *bestHash,
8957+
timestamp: bestHeaderTimestamp,
8958+
}
8959+
8960+
// Exit early if the wallet is not synced.
8961+
if !isSynced {
8962+
return info, nil
8963+
}
8964+
8965+
// If the router does full channel validation, it has a lot of work to
8966+
// do for each block. So it might be possible that it isn't yet up to
8967+
// date with the most recent block, even if the wallet is. This can
8968+
// happen in environments with high CPU load (such as parallel itests).
8969+
// Since the `synced_to_chain` flag in the response of this call is used
8970+
// by many wallets (and also our itests) to make sure everything's up to
8971+
// date, we add the router's state to it. So the flag will only toggle
8972+
// to true once the router was also able to catch up.
8973+
if !r.cfg.Routing.AssumeChannelValid {
8974+
routerHeight := r.server.graphBuilder.SyncedHeight()
8975+
isSynced = uint32(bestHeight) == routerHeight
8976+
}
8977+
8978+
// Exit early if the channel graph is not synced.
8979+
if !isSynced {
8980+
return info, nil
8981+
}
8982+
8983+
// Given the wallet and the channel router are synced, we now check
8984+
// whether the blockbeat dispatcher is synced.
8985+
height := r.server.blockbeatDispatcher.CurrentHeight()
8986+
8987+
// Overwrite isSynced and return.
8988+
info.isSynced = height == bestHeight
8989+
8990+
return info, nil
8991+
}

0 commit comments

Comments
 (0)