@@ -3225,28 +3225,10 @@ func (r *rpcServer) GetInfo(_ context.Context,
3225
3225
idPub := r .server .identityECDH .PubKey ().SerializeCompressed ()
3226
3226
encodedIDPub := hex .EncodeToString (idPub )
3227
3227
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 ()
3234
3230
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
3250
3232
}
3251
3233
3252
3234
network := lncfg .NormalizeNetwork (r .cfg .ActiveNetParams .Name )
@@ -3297,15 +3279,15 @@ func (r *rpcServer) GetInfo(_ context.Context,
3297
3279
NumActiveChannels : activeChannels ,
3298
3280
NumInactiveChannels : inactiveChannels ,
3299
3281
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 ,
3303
3285
Testnet : isTestNet ,
3304
3286
Chains : activeChains ,
3305
3287
Uris : uris ,
3306
3288
Alias : nodeAnn .Alias .String (),
3307
3289
Color : nodeColor ,
3308
- BestHeaderTimestamp : bestHeaderTimestamp ,
3290
+ BestHeaderTimestamp : syncInfo . timestamp ,
3309
3291
Version : version ,
3310
3292
CommitHash : build .CommitHash ,
3311
3293
SyncedToGraph : isGraphSynced ,
@@ -8929,3 +8911,81 @@ func rpcInitiator(isInitiator bool) lnrpc.Initiator {
8929
8911
8930
8912
return lnrpc .Initiator_INITIATOR_REMOTE
8931
8913
}
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