add missing mutex in monero (#3188)
* add missing mutex in monero * wrap critical block in try-finally * Update lib/view_model/dashboard/dashboard_view_model.dart [skip ci] --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
malik1004x committed
Apr 16, 2026 at 12:54 UTC
21847cd95806b5be3d581cadb510aa39dd258f42
5 files changed
+43
-38
cw_monero/lib/api/subaddress_list.dart
+26
-18
@@ -65,25 +65,33 @@ int lastWptr = 0;
65
int lastTxCount = 0;
66
List<TinyTransactionDetails> ttDetails = [];
67
68
-List<Subaddress> getAllSubaddresses() {
69
- txhistory = currentWallet!.history();
70
- final txCount = txhistory!.count();
71
- if (lastTxCount != txCount && lastWptr != currentWallet!.ffiAddress()) {
72
- final List<TinyTransactionDetails> newttDetails = [];
73
- lastTxCount = txCount;
74
- lastWptr = currentWallet!.ffiAddress();
75
- for (var i = 0; i < txCount; i++) {
76
- final tx = txhistory!.transaction(i);
77
- if (tx.direction() == TransactionInfo_Direction.Out.index) continue;
78
- final subaddrs = tx.subaddrIndex().split(",");
79
- final account = tx.subaddrAccount();
80
- newttDetails.add(TinyTransactionDetails(
81
- address: List.generate(subaddrs.length, (index) => getAddress(accountIndex: account, addressIndex: int.tryParse(subaddrs[index])??0)),
82
- amount: tx.amount(),
83
- ));
68
+Future<List<Subaddress>> getAllSubaddresses() async {
69
+ try {
70
+ await txHistoryMutex.acquire();
71
+ txhistory = currentWallet!.history();
72
+ final txCount = txhistory!.count();
73
+ if (lastTxCount != txCount && lastWptr != currentWallet!.ffiAddress()) {
74
+ final List<TinyTransactionDetails> newttDetails = [];
75
+ lastTxCount = txCount;
76
+ lastWptr = currentWallet!.ffiAddress();
77
+ for (var i = 0; i < txCount; i++) {
78
+ final tx = txhistory!.transaction(i);
79
+ if (tx.direction() == TransactionInfo_Direction.Out.index) continue;
80
+ final subaddrs = tx.subaddrIndex().split(",");
81
+ final account = tx.subaddrAccount();
82
+ newttDetails.add(TinyTransactionDetails(
83
+ address: List.generate(
84
+ subaddrs.length,
85
+ (index) => getAddress(
86
+ accountIndex: account, addressIndex: int.tryParse(subaddrs[index]) ?? 0)),
87
+ amount: tx.amount(),
88
+ ));
89
+ }
90
+ ttDetails.clear();
91
+ ttDetails.addAll(newttDetails);
92
}
85
- ttDetails.clear();
86
- ttDetails.addAll(newttDetails);
93
+ } finally {
94
+ txHistoryMutex.release();
95
}
96
final size = currentWallet!.numSubaddresses(accountIndex: subaddress!.accountIndex);
97
final list = List.generate(size, (index) {
cw_monero/lib/monero_subaddress_list.dart
+10
-13
@@ -2,7 +2,7 @@ import 'package:cw_core/subaddress.dart';
2
import 'package:cw_core/utils/print_verbose.dart';
3
import 'package:cw_monero/api/coins_info.dart';
4
import 'package:cw_monero/api/subaddress_list.dart' as subaddress_list;
5
-import 'package:cw_monero/api/wallet.dart';
5
+
6
import 'package:flutter/services.dart';
7
import 'package:mobx/mobx.dart';
8
@@ -24,7 +24,7 @@ abstract class MoneroSubaddressListBase with Store {
24
bool _isRefreshing;
25
bool _isUpdating;
26
27
- void update({required int accountIndex}) {
27
+ Future<void> update({required int accountIndex}) async {
28
refreshCoins(accountIndex);
29
30
if (_isUpdating) {
@@ -35,7 +35,7 @@ abstract class MoneroSubaddressListBase with Store {
35
_isUpdating = true;
36
refresh(accountIndex: accountIndex);
37
subaddresses.clear();
38
- subaddresses.addAll(getAll());
38
+ subaddresses.addAll(await getAll());
39
_isUpdating = false;
40
} catch (e) {
41
_isUpdating = false;
@@ -43,8 +43,8 @@ abstract class MoneroSubaddressListBase with Store {
43
}
44
}
45
46
- List<Subaddress> getAll() {
47
- var subaddresses = subaddress_list.getAllSubaddresses();
46
+ Future<List<Subaddress>> getAll() async {
47
+ var subaddresses = await subaddress_list.getAllSubaddresses();
48
49
if (subaddresses.length > 2) {
50
final primary = subaddresses.first;
@@ -122,7 +122,7 @@ abstract class MoneroSubaddressListBase with Store {
122
123
Future<List<Subaddress>> _getAllUnusedAddresses(
124
{required int accountIndex, required String label}) async {
125
- final allAddresses = subaddress_list.getAllSubaddresses();
125
+ final allAddresses = await subaddress_list.getAllSubaddresses();
126
// first because addresses come in reversed order.
127
if (allAddresses.isEmpty || _usedAddresses.contains(allAddresses.first.address)) {
128
final isAddressUnused = await _newSubaddress(accountIndex: accountIndex, label: label);
@@ -151,12 +151,9 @@ abstract class MoneroSubaddressListBase with Store {
151
Future<bool> _newSubaddress({required int accountIndex, required String label}) async {
152
await subaddress_list.addSubaddress(accountIndex: accountIndex, label: label);
153
154
- return subaddress_list
155
- .getAllSubaddresses()
156
- .where((s) {
157
- final address = s.address;
158
- return !_usedAddresses.contains(address);
159
- })
160
- .isNotEmpty;
154
+ return (await subaddress_list.getAllSubaddresses()).where((s) {
155
+ final address = s.address;
156
+ return !_usedAddresses.contains(address);
157
+ }).isNotEmpty;
158
}
159
}
lib/monero/cw_monero.dart
+3
-3
@@ -89,10 +89,10 @@ class CWMoneroSubaddressList extends MoneroSubaddressList {
89
}
90
91
@override
92
- List<Subaddress> getAll(Object wallet) {
92
+ Future<List<Subaddress>> getAll(Object wallet) async {
93
final moneroWallet = wallet as MoneroWallet;
94
- return moneroWallet.walletAddresses.subaddressList
95
- .getAll()
94
+ return (await moneroWallet.walletAddresses.subaddressList
95
+ .getAll())
96
.map((sub) => Subaddress(
97
id: sub.id,
98
label: sub.label,
lib/view_model/dashboard/dashboard_view_model.dart
+3
-3
@@ -770,9 +770,9 @@ abstract class DashboardViewModelBase with Store {
770
"public view key is 0",
771
// if (wallet.seed == null) "wallet seed is null",
772
// if (wallet.seed == "") "wallet seed is empty",
773
- if (monero!.getSubaddressList(wallet).getAll(wallet)[0].address ==
774
- "41d7FXjswpK1111111111111111111111111111111111111111111111111111111111111111111111111111112KhNi4")
775
- "primary address is invalid, you won't be able to receive / spend funds",
773
+ // if (monero!.getSubaddressList(wallet).getAll(wallet)[0].address ==
774
+ // "41d7FXjswpK1111111111111111111111111111111111111111111111111111111111111111111111111111112KhNi4")
775
+ // "primary address is invalid, you won't be able to receive / spend funds",
776
];
777
return errors;
778
}
tool/configure.dart
+1
-1
@@ -492,7 +492,7 @@ abstract class MoneroSubaddressList {
492
ObservableList<Subaddress> get subaddresses;
493
void update(Object wallet, {required int accountIndex});
494
void refresh(Object wallet, {required int accountIndex});
495
- List<Subaddress> getAll(Object wallet);
495
+ Future<List<Subaddress>> getAll(Object wallet);
496
Future<void> addSubaddress(Object wallet, {required int accountIndex, required String label});
497
Future<void> setLabelSubaddress(Object wallet,
498
{required int accountIndex, required int addressIndex, required String label});