add guard Lightning usage with isInitialized check (#3128)
What changed, and why it matters
This commit adds a safety check to prevent the app from using a Lightning wallet before it has finished initializing. Previously, the app only checked whether a Lightning wallet existed, not whether it was ready. This could have caused crashes or incorrect balance/update behavior if the app tried to use the wallet while it was still starting up.
Treat as a routine hardening fix. No immediate incident response is warranted, but users should update to a build containing this commit to avoid potential instability or balance-display issues related to Lightning wallet initialization races.
Security signals we found
Race condition mitigation
Null/initialization-state guard
Defensive hardening
Potential crash/DoS reduction
Evidence from the diff
The patch introduces an isInitialized getter on LightningWallet (true when _eventStream != null) and a corresponding isLightningInitialized getter on BitcoinWalletBase. It then guards fetchBalances() and subscribeForUpdates() so they skip Lightning operations unless the wallet is both non-null and initialized. This is a defensive hardening change that narrows the window for race conditions between wallet creation and Lightning node readiness.
Changed components
cw_bitcoin/lib/bitcoin_wallet.dartcw_bitcoin/lib/lightning/lightning_wallet.dartInspect captured patch +6 / −2
diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart
index 0616f340..84758a1c 100644
--- a/cw_bitcoin/lib/bitcoin_wallet.dart
+++ b/cw_bitcoin/lib/bitcoin_wallet.dart
@@ -164,6 +164,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
}
}
+ bool get isLightningInitialized => lightningWallet?.isInitialized == true;
+
@override
bool get hasRescan => true;
@@ -339,7 +341,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
@override
Future<ElectrumBalance> fetchBalances() async {
final balance = await super.fetchBalances();
- if (lightningWallet == null) {
+ if (!isLightningInitialized || lightningWallet == null) {
return balance;
}
@@ -358,7 +360,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
@override
@action
Future<void> subscribeForUpdates() async {
- if (lightningWallet != null) {
+ if (isLightningInitialized && lightningWallet != null) {
lightningWallet!.setEventListener(
onTransactionEvent: (tx) async {
if (transactionHistory.transactions[tx.id]?.isPending != tx.isPending) {
diff --git a/cw_bitcoin/lib/lightning/lightning_wallet.dart b/cw_bitcoin/lib/lightning/lightning_wallet.dart
index 12a28776..bfc5647f 100644
--- a/cw_bitcoin/lib/lightning/lightning_wallet.dart
+++ b/cw_bitcoin/lib/lightning/lightning_wallet.dart
@@ -41,6 +41,8 @@ class LightningWallet {
StreamSubscription<LogEntry>? _logSubscription;
+ bool get isInitialized => _eventStream != null;
+
void _subscribeToLogStream(File logFile) {
_logSubscription = _logStream?.listen((logEntry) {
logFile.writeAsStringSync("[${logEntry.level}] ${logEntry.line}\n", mode: FileMode.append);
Why this scored 32/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.