workaround for lnd rescan bug
This commit is contained in:
parent
ce94b316fb
commit
3b8ec65c67
6 changed files with 92 additions and 2 deletions
|
|
@ -8,6 +8,7 @@
|
||||||
#LND_ADDRESS=127.0.0.1:10009
|
#LND_ADDRESS=127.0.0.1:10009
|
||||||
#LND_CERT_PATH=~/.lnd/tls.cert
|
#LND_CERT_PATH=~/.lnd/tls.cert
|
||||||
#LND_MACAROON_PATH=~/.lnd/data/chain/bitcoin/mainnet/admin.macaroon
|
#LND_MACAROON_PATH=~/.lnd/data/chain/bitcoin/mainnet/admin.macaroon
|
||||||
|
#LND_LOG_DIR=~/.lnd/logs/bitcoin/mainnet/lnd.log
|
||||||
|
|
||||||
#BOOTSTRAP_PEER
|
#BOOTSTRAP_PEER
|
||||||
# A trusted peer that will hold a node-level account until channel automation becomes affordable
|
# A trusted peer that will hold a node-level account until channel automation becomes affordable
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ get_log_info() {
|
||||||
LOG_DIR="$USER_HOME/lightning_pub/logs"
|
LOG_DIR="$USER_HOME/lightning_pub/logs"
|
||||||
DATA_DIR="$USER_HOME/lightning_pub/"
|
DATA_DIR="$USER_HOME/lightning_pub/"
|
||||||
START_TIME=$(date +%s)
|
START_TIME=$(date +%s)
|
||||||
MAX_WAIT_TIME=120 # Maximum wait time in seconds
|
MAX_WAIT_TIME=360 # Maximum wait time in seconds (6 minutes)
|
||||||
WAIT_INTERVAL=5 # Time to wait between checks in seconds
|
WAIT_INTERVAL=5 # Time to wait between checks in seconds
|
||||||
|
|
||||||
log "Checking wallet status... This may take a moment."
|
log "Checking wallet status... This may take a moment."
|
||||||
|
|
@ -50,7 +50,24 @@ get_log_info() {
|
||||||
START_TIME=$(date +%s)
|
START_TIME=$(date +%s)
|
||||||
while [ $(($(date +%s) - START_TIME)) -lt $MAX_WAIT_TIME ]; do
|
while [ $(($(date +%s) - START_TIME)) -lt $MAX_WAIT_TIME ]; do
|
||||||
latest_entry=$(grep -E "unlocker >> (the wallet is already unlocked|created wallet with pub:|unlocked wallet with pub)" "$latest_unlocker_log" | tail -n 1)
|
latest_entry=$(grep -E "unlocker >> (the wallet is already unlocked|created wallet with pub:|unlocked wallet with pub)" "$latest_unlocker_log" | tail -n 1)
|
||||||
|
|
||||||
|
# Show dynamic header sync progress if available from unlocker logs
|
||||||
|
progress_line=$(grep -E "LND header sync [0-9]+% \(height=" "$latest_unlocker_log" | tail -n 1)
|
||||||
|
if [ -n "$progress_line" ]; then
|
||||||
|
percent=$(echo "$progress_line" | sed -E 's/.*LND header sync ([0-9]+)%.*/\1/')
|
||||||
|
if [[ "$percent" =~ ^[0-9]+$ ]]; then
|
||||||
|
bar_len=30
|
||||||
|
filled=$((percent*bar_len/100))
|
||||||
|
if [ $filled -gt $bar_len ]; then filled=$bar_len; fi
|
||||||
|
empty=$((bar_len-filled))
|
||||||
|
filled_bar=$(printf '%*s' "$filled" | tr ' ' '#')
|
||||||
|
empty_bar=$(printf '%*s' "$empty" | tr ' ' ' ')
|
||||||
|
echo -ne "Header sync: [${filled_bar}${empty_bar}] ${percent}%\r"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
if [ -n "$latest_entry" ]; then
|
if [ -n "$latest_entry" ]; then
|
||||||
|
# End the progress line cleanly
|
||||||
|
echo ""
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
sleep $WAIT_INTERVAL
|
sleep $WAIT_INTERVAL
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,7 @@ else
|
||||||
# Only start services if it was a fresh install or an upgrade.
|
# Only start services if it was a fresh install or an upgrade.
|
||||||
if [ "$pub_upgrade_status" -eq 0 ] || [ "$pub_upgrade_status" -eq 100 ]; then
|
if [ "$pub_upgrade_status" -eq 0 ] || [ "$pub_upgrade_status" -eq 100 ]; then
|
||||||
log "Starting services..."
|
log "Starting services..."
|
||||||
|
log "Note: LND may take several minutes to sync block headers depending on network conditions."
|
||||||
touch /tmp/pub_install_timestamp
|
touch /tmp/pub_install_timestamp
|
||||||
start_services $lnd_status $pub_upgrade_status || log_error "Failed to start services" 1
|
start_services $lnd_status $pub_upgrade_status || log_error "Failed to start services" 1
|
||||||
get_log_info || log_error "Failed to get log info" 1
|
get_log_info || log_error "Failed to get log info" 1
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,10 @@ export const LoadLndSettingsFromEnv = (): LndSettings => {
|
||||||
const lndAddr = process.env.LND_ADDRESS || "127.0.0.1:10009"
|
const lndAddr = process.env.LND_ADDRESS || "127.0.0.1:10009"
|
||||||
const lndCertPath = process.env.LND_CERT_PATH || resolveHome("/.lnd/tls.cert")
|
const lndCertPath = process.env.LND_CERT_PATH || resolveHome("/.lnd/tls.cert")
|
||||||
const lndMacaroonPath = process.env.LND_MACAROON_PATH || resolveHome("/.lnd/data/chain/bitcoin/mainnet/admin.macaroon")
|
const lndMacaroonPath = process.env.LND_MACAROON_PATH || resolveHome("/.lnd/data/chain/bitcoin/mainnet/admin.macaroon")
|
||||||
|
const lndLogDir = process.env.LND_LOG_DIR || resolveHome("/.lnd/logs/bitcoin/mainnet/lnd.log")
|
||||||
const feeRateBps = EnvCanBeInteger("OUTBOUND_MAX_FEE_BPS", 60)
|
const feeRateBps = EnvCanBeInteger("OUTBOUND_MAX_FEE_BPS", 60)
|
||||||
const feeRateLimit = feeRateBps / 10000
|
const feeRateLimit = feeRateBps / 10000
|
||||||
const feeFixedLimit = EnvCanBeInteger("OUTBOUND_MAX_FEE_EXTRA_SATS", 100)
|
const feeFixedLimit = EnvCanBeInteger("OUTBOUND_MAX_FEE_EXTRA_SATS", 100)
|
||||||
const mockLnd = EnvCanBeBoolean("MOCK_LND")
|
const mockLnd = EnvCanBeBoolean("MOCK_LND")
|
||||||
return { mainNode: { lndAddr, lndCertPath, lndMacaroonPath }, feeRateLimit, feeFixedLimit, feeRateBps, mockLnd }
|
return { mainNode: { lndAddr, lndCertPath, lndMacaroonPath }, lndLogDir, feeRateLimit, feeFixedLimit, feeRateBps, mockLnd }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ export type NodeSettings = {
|
||||||
}
|
}
|
||||||
export type LndSettings = {
|
export type LndSettings = {
|
||||||
mainNode: NodeSettings
|
mainNode: NodeSettings
|
||||||
|
lndLogDir: string
|
||||||
feeRateLimit: number
|
feeRateLimit: number
|
||||||
feeFixedLimit: number
|
feeFixedLimit: number
|
||||||
feeRateBps: number
|
feeRateBps: number
|
||||||
|
|
@ -15,6 +16,7 @@ export type LndSettings = {
|
||||||
otherNode?: NodeSettings
|
otherNode?: NodeSettings
|
||||||
thirdNode?: NodeSettings
|
thirdNode?: NodeSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
type TxOutput = {
|
type TxOutput = {
|
||||||
hash: string
|
hash: string
|
||||||
index: number
|
index: number
|
||||||
|
|
|
||||||
|
|
@ -95,8 +95,76 @@ export class Unlocker {
|
||||||
return { ln, pub: infoAfter.pub, action: 'unlocked' }
|
return { ln, pub: infoAfter.pub, action: 'unlocked' }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private waitForLndSync = async (timeoutSeconds: number): Promise<void> => {
|
||||||
|
const lndLogPath = this.settings.lndSettings.lndLogDir;
|
||||||
|
if (this.settings.lndSettings.mockLnd) {
|
||||||
|
this.log("MOCK_LND set, skipping header sync wait.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let targetHeight = 0;
|
||||||
|
this.log(`Waiting for LND to sync headers (timeout: ${timeoutSeconds}s). Log: ${lndLogPath} (discovering target height...)`);
|
||||||
|
|
||||||
|
let lastPercentReported = -1;
|
||||||
|
const startTime = Date.now();
|
||||||
|
const checkLog = async (resolve: () => void, reject: (reason?: any) => void) => {
|
||||||
|
const elapsedTime = (Date.now() - startTime) / 1000;
|
||||||
|
if (elapsedTime > timeoutSeconds) {
|
||||||
|
return reject(new Error("Timed out waiting for LND to sync."));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (fs.existsSync(lndLogPath)) {
|
||||||
|
const logContent = fs.readFileSync(lndLogPath, 'utf8');
|
||||||
|
|
||||||
|
if (logContent.includes("Fully caught up with cfheaders")) {
|
||||||
|
this.log("LND sync complete.");
|
||||||
|
return resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If target height isn't known yet, try to derive it from the log
|
||||||
|
if (targetHeight === 0) {
|
||||||
|
const targetMatch = [...logContent.matchAll(/Syncing to block height\s+(\d+)\s+from peer/gi)];
|
||||||
|
if (targetMatch.length > 0) {
|
||||||
|
const lastTarget = targetMatch[targetMatch.length - 1];
|
||||||
|
const parsedTarget = Number.parseInt(lastTarget[1], 10);
|
||||||
|
if (!Number.isNaN(parsedTarget) && parsedTarget > 0) {
|
||||||
|
targetHeight = parsedTarget;
|
||||||
|
this.log(`Detected target header height: ${targetHeight}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse latest reported height: look for "height=NNNN" occurrences
|
||||||
|
const matches = [...logContent.matchAll(/height=(\d+)/g)];
|
||||||
|
if (matches.length > 0) {
|
||||||
|
const lastMatch = matches[matches.length - 1];
|
||||||
|
const currentHeight = Number.parseInt(lastMatch[1], 10);
|
||||||
|
if (!Number.isNaN(currentHeight) && currentHeight > 0 && targetHeight > 0) {
|
||||||
|
const percent = Math.min(99, Math.max(0, Math.floor((Math.min(currentHeight, targetHeight) * 100) / targetHeight)));
|
||||||
|
// Report only on first run and on >=5% increments to reduce noise
|
||||||
|
if (lastPercentReported === -1 || percent >= lastPercentReported + 5) {
|
||||||
|
this.log(`LND header sync ${percent}% (height=${currentHeight}/${targetHeight})`);
|
||||||
|
lastPercentReported = percent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// Log file might not exist yet, which is fine.
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => checkLog(resolve, reject), 3000);
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
checkLog(resolve, reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
InitFlow = async (lndCert: Buffer) => {
|
InitFlow = async (lndCert: Buffer) => {
|
||||||
this.log("macaroon not found, creating wallet...")
|
this.log("macaroon not found, creating wallet...")
|
||||||
|
await this.waitForLndSync(300); // Wait up to 5 minutes
|
||||||
const unlocker = this.GetUnlockerClient(lndCert)
|
const unlocker = this.GetUnlockerClient(lndCert)
|
||||||
const { plaintextSeed, encryptedSeed } = await this.genSeed(unlocker)
|
const { plaintextSeed, encryptedSeed } = await this.genSeed(unlocker)
|
||||||
return this.initWallet(lndCert, unlocker, { plaintextSeed, encryptedSeed })
|
return this.initWallet(lndCert, unlocker, { plaintextSeed, encryptedSeed })
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue