From 9f0228b21c99093851b7167761549a865798b5c6 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 7 May 2021 19:11:19 +0200 Subject: [PATCH 1/4] router: add SyncedHeight() method The router subsystem has its own goroutine that receives chain updates and then does its (quite time consuming) work on each new block. To make it possible to find out what block the router currently is synced to, we export its internal best height through a new method. --- routing/router.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/routing/router.go b/routing/router.go index 76d1291d..aab8e7d6 100644 --- a/routing/router.go +++ b/routing/router.go @@ -2479,6 +2479,13 @@ func (r *ChannelRouter) CurrentBlockHeight() (uint32, error) { return uint32(height), err } +// SyncedHeight returns the block height to which the router subsystem currently +// is synced to. This can differ from the above chain height if the goroutine +// responsible for processing the blocks isn't yet up to speed. +func (r *ChannelRouter) SyncedHeight() uint32 { + return atomic.LoadUint32(&r.bestHeight) +} + // GetChannelByID return the channel by the channel id. // // NOTE: This method is part of the ChannelGraphSource interface. From ea4ef204a0836724b8564ae9d74cfe8e0d7261ad Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 7 May 2021 19:11:20 +0200 Subject: [PATCH 2/4] rpcserver: add router synced to synced_to_chain flag The router has a lot of work to do for each block. So it might be possible that it isn't yet up to date with the most recent block, even if the wallet is. This can happen in environments with high CPU load (such as parallel itests). Since the `synced_to_chain` flag in the response of this call is used by many wallets (and also our itests) to make sure everything's up to date, we add the router's state to it. So the flag will only toggle to true once the router was also able to catch up. --- rpcserver.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/rpcserver.go b/rpcserver.go index 1bb95aa0..611fb5d7 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2507,6 +2507,17 @@ func (r *rpcServer) GetInfo(ctx context.Context, "with current best block in the main chain: %v", err) } + // The router has a lot of work to do for each block. So it might be + // possible that it isn't yet up to date with the most recent block, + // even if the wallet is. This can happen in environments with high CPU + // load (such as parallel itests). Since the `synced_to_chain` flag in + // the response of this call is used by many wallets (and also our + // itests) to make sure everything's up to date, we add the router's + // state to it. So the flag will only toggle to true once the router was + // also able to catch up. + routerHeight := r.server.chanRouter.SyncedHeight() + isSynced = isSynced && uint32(bestHeight) == routerHeight + network := lncfg.NormalizeNetwork(r.cfg.ActiveNetParams.Name) activeChains := make([]*lnrpc.Chain, r.cfg.registeredChains.NumActiveChains()) for i, chain := range r.cfg.registeredChains.ActiveChains() { From 8147b270d4716d81054c7fc54bff154fd215298a Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 7 May 2021 19:11:22 +0200 Subject: [PATCH 3/4] lntest: wait for chain sync in switch test --- lntest/itest/lnd_test.go | 20 +++++++++++++++++++- lntest/itest/log_error_whitelist.txt | 1 + lntest/itest/log_substitutions.txt | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index d3a86d4f..fcf21ea0 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -11787,7 +11787,15 @@ func testSwitchOfflineDelivery(net *lntest.NetworkHarness, t *harnessTest) { err) } - time.Sleep(time.Millisecond * 50) + // Make sure all nodes are fully synced before we continue. + ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout) + defer cancel() + for _, node := range nodes { + err := node.WaitForBlockchainSync(ctxt) + if err != nil { + t.Fatalf("unable to wait for sync: %v", err) + } + } // Using Carol as the source, pay to the 5 invoices from Bob created // above. @@ -11856,6 +11864,16 @@ func testSwitchOfflineDelivery(net *lntest.NetworkHarness, t *harnessTest) { t.Fatalf("htlc mismatch: %v", predErr) } + // Make sure all nodes are fully synced again. + ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout) + defer cancel() + for _, node := range nodes { + err := node.WaitForBlockchainSync(ctxt) + if err != nil { + t.Fatalf("unable to wait for sync: %v", err) + } + } + // Now that the settles have reached Dave, reconnect him with Alice, // allowing the settles to return to the sender. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) diff --git a/lntest/itest/log_error_whitelist.txt b/lntest/itest/log_error_whitelist.txt index 2496b070..665b3266 100644 --- a/lntest/itest/log_error_whitelist.txt +++ b/lntest/itest/log_error_whitelist.txt @@ -155,6 +155,7 @@