Skip to content

Commit

Permalink
chore(ln): prevent lnd from syning indefinitely by mining a single bl…
Browse files Browse the repository at this point in the history
…ock first
  • Loading branch information
theborakompanioni committed Dec 2, 2023
1 parent e537ea5 commit 4c13721
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ app.description: A spring boot bitcoin demo application
spring.application.name: 'tbk-bitcoin-spring-boot-starter-demo (test)'
spring.http.log-request-details: true

logging.level.org.tbk: DEBUG

spring.docker.compose:
enabled: true
file: ./../../docker/regtest/lightning-regtest-setup-devel/docker-compose.yml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,19 @@ public void run() throws IOException {
}

private void beforeSetup() throws IOException {
onchainFaucet.init();
BitcoindRegtestTestHelper.createDefaultWalletIfNecessary(bitcoinClient);

// it seems to be necessary to mine a single block and wait for the nodes to synchronize.
// otherwise, LND seems to be stuck on regtest indefinitely (last check: 2023-12-02).
log.debug("Mine a single block and await node synchronization…");
bitcoinClient.generateToAddress(1, bitcoinClient.getNewAddress());
waitForNodesBlockHeightSynchronization();
log.debug("Mine a single block and await node synchronization: Done.");

log.debug("Initialize on-chain faucet and await node synchronization…");
onchainFaucet.init();
waitForNodesBlockHeightSynchronization();
log.debug("Initialize on-chain faucet and await node synchronization: Done.");
}

private void afterSetup() {
Expand Down Expand Up @@ -123,7 +133,7 @@ private void setupPeers() {
CommonConnectResponse ignoredOnPurpose = connectPeers(entry.getT1(), entry.getT2());
log.debug("{} is connected to peer {}", originNodeName, targetNodeName);
} catch (Exception e) {
// LND error if peer is already connected `UNKNOWN: already connected to peer: ${pubkey}@${ip}:${port}`
// LND error if peer is already connected: `UNKNOWN: already connected to peer: ${pubkey}@${ip}:${port}`
boolean isAlreadyConnected = e.getMessage().contains("already connected to peer");
if (!isAlreadyConnected) {
throw e;
Expand Down Expand Up @@ -347,12 +357,14 @@ private void waitForNodesBlockHeightSynchronization() throws IOException {
// wait for cln nodes to catch up to the newest block height.
// prevents `io.grpc.StatusRuntimeException: RpcError { code: Some(304), message: "Still syncing with bitcoin network" }`
private static void waitForNodeBlockHeightSynchronization(BitcoinExtendedClient bitcoin, Collection<NodeInfo> lnNodes) throws IOException {
int currentBlockHeight = bitcoin.getBlockChainInfo().getBlocks();
BlockChainInfo blockChainInfo = bitcoin.getBlockChainInfo();
int currentBlockHeight = blockChainInfo.getBlocks();

// does not need to be more often than every 5 seconds - cln can take quite long to synchronize
// does not need to be more often than every 5 seconds - cln can take quite long to synchronize.
Duration checkInterval = Duration.ofSeconds(5);
// cln sometimes takes up to ~30 seconds when catching up to more than 100 blocks
Duration timeout = Duration.ofSeconds(180);
// cln sometimes takes up to ~30 seconds when catching up to more than 100 blocks.
// lnd can take even longer as it fetches blocks every 1 seconds if it missed blocks via zmq.
Duration timeout = Duration.ofMinutes(3).plusSeconds(2L * currentBlockHeight);

lnNodes.forEach(it -> waitForNodeBlockHeightSynchronization(it.getClient(), currentBlockHeight, checkInterval, timeout));
}
Expand All @@ -367,10 +379,13 @@ private static void waitForNodeBlockHeightSynchronization(LightningCommonClient
try {
CommonInfoResponse info = requireNonNull(client.info(CommonInfoRequest.newBuilder().build())
.block(Duration.ofSeconds(30)));
boolean finished = info.getBlockheight() >= minBlockHeight;
boolean hasSyncWarning = !info.getWarningBlockSync().isEmpty();
boolean blockHeightInSync = info.getBlockheight() >= minBlockHeight;
boolean finished = !hasSyncWarning && blockHeightInSync;

log.debug("Waiting for blockheight to reach {} on {}, currently at height {}: {}",
log.debug("Waiting for block height to reach {} on {}, currently at height {} (warning={}): {}",
minBlockHeight, info.getAlias(), info.getBlockheight(),
info.getWarningBlockSync(),
finished ? "Done" : "Still waiting…");

return finished;
Expand Down

0 comments on commit 4c13721

Please sign in to comment.