From ed5a6717c448568cbc26df6be954e9ad61d14c0f Mon Sep 17 00:00:00 2001 From: sneurlax Date: Sun, 1 Mar 2026 14:46:25 -0600 Subject: [PATCH 1/3] fix(mwc): serialize openWallet FFI calls with mutex --- crypto_plugins/flutter_libmwc | 2 +- .../wallet/impl/mimblewimblecoin_wallet.dart | 95 +++++++++++-------- 2 files changed, 55 insertions(+), 42 deletions(-) diff --git a/crypto_plugins/flutter_libmwc b/crypto_plugins/flutter_libmwc index 5b43e0e91..cf9406505 160000 --- a/crypto_plugins/flutter_libmwc +++ b/crypto_plugins/flutter_libmwc @@ -1 +1 @@ -Subproject commit 5b43e0e91f3d04bddfe88bba1d2f6178a18aadf9 +Subproject commit cf94065052b0ff2fd92c6c5b0fc6baed8569ef48 diff --git a/lib/wallets/wallet/impl/mimblewimblecoin_wallet.dart b/lib/wallets/wallet/impl/mimblewimblecoin_wallet.dart index 3850cb750..dad7b3632 100644 --- a/lib/wallets/wallet/impl/mimblewimblecoin_wallet.dart +++ b/lib/wallets/wallet/impl/mimblewimblecoin_wallet.dart @@ -41,6 +41,7 @@ class MimblewimblecoinWallet extends Bip39Wallet { : super(Mimblewimblecoin(network)); final syncMutex = Mutex(); + final _walletOpenMutex = Mutex(); NodeModel? _mimblewimblecoinNode; Timer? timer; @@ -95,24 +96,29 @@ class MimblewimblecoinWallet extends Bip39Wallet { } Future _ensureWalletOpen() async { - final existing = await secureStorageInterface.read( - key: '${walletId}_wallet', - ); - if (existing != null && existing.isNotEmpty) return existing; + return await _walletOpenMutex.protect(() async { + final existing = await secureStorageInterface.read( + key: '${walletId}_wallet', + ); + if (existing != null && existing.isNotEmpty) return existing; - final config = await _getRealConfig(); - final password = await secureStorageInterface.read( - key: '${walletId}_password', - ); - if (password == null) { - throw Exception('Wallet password not found'); - } - final opened = await libMwc.openWallet(config: config, password: password); - await secureStorageInterface.write( - key: '${walletId}_wallet', - value: opened, - ); - return opened; + final config = await _getRealConfig(); + final password = await secureStorageInterface.read( + key: '${walletId}_password', + ); + if (password == null) { + throw Exception('Wallet password not found'); + } + final opened = await libMwc.openWallet( + config: config, + password: password, + ); + await secureStorageInterface.write( + key: '${walletId}_wallet', + value: opened, + ); + return opened; + }); } /// Returns an empty String on success, error message on failure. @@ -894,14 +900,17 @@ class MimblewimblecoinWallet extends Bip39Wallet { ); //Open wallet - encodedWallet = await libMwc.openWallet( - config: stringConfig, - password: password, - ); - await secureStorageInterface.write( - key: '${walletId}_wallet', - value: encodedWallet, - ); + encodedWallet = await _walletOpenMutex.protect(() async { + final opened = await libMwc.openWallet( + config: stringConfig, + password: password, + ); + await secureStorageInterface.write( + key: '${walletId}_wallet', + value: opened, + ); + return opened; + }); //Store MwcMqs address info await _generateAndStoreReceivingAddressForIndex(0); @@ -935,14 +944,16 @@ class MimblewimblecoinWallet extends Bip39Wallet { key: '${walletId}_password', ); - final walletOpen = await libMwc.openWallet( - config: config, - password: password!, - ); - await secureStorageInterface.write( - key: '${walletId}_wallet', - value: walletOpen, - ); + await _walletOpenMutex.protect(() async { + final walletOpen = await libMwc.openWallet( + config: config, + password: password!, + ); + await secureStorageInterface.write( + key: '${walletId}_wallet', + value: walletOpen, + ); + }); await updateNode(); } catch (e, s) { @@ -1144,14 +1155,16 @@ class MimblewimblecoinWallet extends Bip39Wallet { ); //Open Wallet - final walletOpen = await libMwc.openWallet( - config: stringConfig, - password: password, - ); - await secureStorageInterface.write( - key: '${walletId}_wallet', - value: walletOpen, - ); + await _walletOpenMutex.protect(() async { + final walletOpen = await libMwc.openWallet( + config: stringConfig, + password: password, + ); + await secureStorageInterface.write( + key: '${walletId}_wallet', + value: walletOpen, + ); + }); await _generateAndStoreReceivingAddressForIndex( mimblewimblecoinData.receivingIndex, From b66fbd9ef49ea8183724a0f362b03d4fe79c8e81 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 3 Mar 2026 17:40:23 -0600 Subject: [PATCH 2/3] fix(mwc): write .api_secret for default node authentication --- crypto_plugins/flutter_libmwc | 2 +- .../wallet/impl/mimblewimblecoin_wallet.dart | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/crypto_plugins/flutter_libmwc b/crypto_plugins/flutter_libmwc index cf9406505..dc62d292f 160000 --- a/crypto_plugins/flutter_libmwc +++ b/crypto_plugins/flutter_libmwc @@ -1 +1 @@ -Subproject commit cf94065052b0ff2fd92c6c5b0fc6baed8569ef48 +Subproject commit dc62d292f4ff077ca057585edec4d45dd474aba7 diff --git a/lib/wallets/wallet/impl/mimblewimblecoin_wallet.dart b/lib/wallets/wallet/impl/mimblewimblecoin_wallet.dart index dad7b3632..a577b03ff 100644 --- a/lib/wallets/wallet/impl/mimblewimblecoin_wallet.dart +++ b/lib/wallets/wallet/impl/mimblewimblecoin_wallet.dart @@ -582,6 +582,8 @@ class MimblewimblecoinWallet extends Bip39Wallet { final String nodeApiAddress = uri.toString(); final walletDir = await _currentWalletDirPath(); + await _ensureApiSecret(walletDir, nodeApiAddress); + final Map config = {}; config["wallet_dir"] = walletDir; config["check_node_api_http_addr"] = nodeApiAddress; @@ -591,6 +593,21 @@ class MimblewimblecoinWallet extends Bip39Wallet { return stringConfig; } + /// Write the node API secret to .api_secret in the wallet directory so that + /// the Rust HTTPNodeClient can authenticate to the MWC node. + Future _ensureApiSecret(String walletDir, String nodeUrl) async { + const defaultNodeHost = 'mwc713.mwc.mw'; + const defaultNodeSecret = '11ne3EAUtOXVKwhxm84U'; + + final file = File('$walletDir/.api_secret'); + if (nodeUrl.contains(defaultNodeHost)) { + await Directory(walletDir).create(recursive: true); + await file.writeAsString(defaultNodeSecret); + } else if (await file.exists()) { + await file.delete(); + } + } + Future _currentWalletDirPath() async { final Directory appDir = await StackFileSystem.applicationRootDirectory(); From de5f097d33e71f8edae56f33e2a9bed0244429d5 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 3 Mar 2026 17:47:58 -0600 Subject: [PATCH 3/3] refactor(mwc): merge flutter_libmwc#fix/global-chain-type-race --- crypto_plugins/flutter_libmwc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/flutter_libmwc b/crypto_plugins/flutter_libmwc index dc62d292f..f5ad0a99a 160000 --- a/crypto_plugins/flutter_libmwc +++ b/crypto_plugins/flutter_libmwc @@ -1 +1 @@ -Subproject commit dc62d292f4ff077ca057585edec4d45dd474aba7 +Subproject commit f5ad0a99a1781f600742095fee0e47057eafd9c0