Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CW-519 Enable built-in Tor #1950

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 24 additions & 21 deletions cw_bitcoin/lib/electrum_wallet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'dart:io';
import 'dart:isolate';

import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:cw_core/utils/http_client.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_bitcoin/bitcoin_wallet.dart';
import 'package:cw_bitcoin/litecoin_wallet.dart';
Expand Down Expand Up @@ -491,11 +492,12 @@ abstract class ElectrumWalletBase
Future<void> updateFeeRates() async {
if (await checkIfMempoolAPIIsEnabled() && type == WalletType.bitcoin) {
try {
final response = await http
.get(Uri.parse("https://mempool.cakewallet.com/api/v1/fees/recommended"))
.timeout(Duration(seconds: 5));

final result = json.decode(response.body) as Map<String, dynamic>;
final req = await getHttpClient()
.getUrl(Uri.parse("https://mempool.cakewallet.com/api/v1/fees/recommended"))
.timeout(Duration(seconds: 15));
final response = await req.close();
final stringData = await response.transform(utf8.decoder).join();
final result = json.decode(stringData) as Map<String, dynamic>;
final slowFee = (result['economyFee'] as num?)?.toInt() ?? 0;
int mediumFee = (result['hourFee'] as num?)?.toInt() ?? 0;
int fastFee = (result['fastestFee'] as num?)?.toInt() ?? 0;
Expand Down Expand Up @@ -1873,24 +1875,25 @@ abstract class ElectrumWalletBase

if (height != null && height > 0 && await checkIfMempoolAPIIsEnabled()) {
try {
final blockHash = await http.get(
Uri.parse(
"https://mempool.cakewallet.com/api/v1/block-height/$height",
),
);
final req = await getHttpClient()
.getUrl(Uri.parse("https://mempool.cakewallet.com/api/v1/block-height/$height"))
.timeout(Duration(seconds: 15));
final blockHash = await req.close();
final stringData = await blockHash.transform(utf8.decoder).join();

if (blockHash.statusCode == 200 &&
blockHash.body.isNotEmpty &&
jsonDecode(blockHash.body) != null) {
final blockResponse = await http.get(
Uri.parse(
"https://mempool.cakewallet.com/api/v1/block/${blockHash.body}",
),
);
if (blockResponse.statusCode == 200 &&
blockResponse.body.isNotEmpty &&
jsonDecode(blockResponse.body)['timestamp'] != null) {
time = int.parse(jsonDecode(blockResponse.body)['timestamp'].toString());
stringData.isNotEmpty &&
jsonDecode(stringData) != null) {
final blockResponseReq = await getHttpClient()
.getUrl(Uri.parse("https://mempool.cakewallet.com/api/v1/block/${stringData}"))
.timeout(Duration(seconds: 15));
final blockResponseRes = await blockResponseReq.close();
final blockResponse = await blockResponseRes.transform(utf8.decoder).join();

if (blockResponseRes == 200 &&
blockResponse.isNotEmpty &&
jsonDecode(blockResponse)['timestamp'] != null) {
time = int.parse(jsonDecode(blockResponse)['timestamp'].toString());
}
}
} catch (_) {}
Expand Down
8 changes: 8 additions & 0 deletions cw_bitcoin/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -979,6 +979,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.1"
tor:
dependency: transitive
description:
name: tor
sha256: eeed80e5c912a1806c2f81825c12e84f4dc5a0b50aebedea59e3a8ba53df3142
url: "https://pub.dev"
source: hosted
version: "0.0.8"
tuple:
dependency: transitive
description:
Expand Down
21 changes: 13 additions & 8 deletions cw_core/lib/get_height_by_date.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:cw_core/utils/http_client.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:intl/intl.dart';
import 'dart:convert';
Expand Down Expand Up @@ -234,10 +235,14 @@ int getHavenHeightByDate({required DateTime date}) {
}

Future<int> getHavenCurrentHeight() async {
final response = await http.get(Uri.parse('https://explorer.havenprotocol.org/api/networkinfo'));
final req = await getHttpClient()
.getUrl(Uri.parse('https://explorer.havenprotocol.org/api/networkinfo'))
.timeout(Duration(seconds: 15));
final response = await req.close();
final stringResponse = await response.transform(utf8.decoder).join();

if (response.statusCode == 200) {
final info = jsonDecode(response.body);
final info = jsonDecode(stringResponse);
return info['data']['height'] as int;
} else {
throw Exception('Failed to load current blockchain height');
Expand Down Expand Up @@ -269,13 +274,13 @@ const bitcoinDates = {
};

Future<int> getBitcoinHeightByDateAPI({required DateTime date}) async {
final response = await http.get(
Uri.parse(
"https://mempool.cakewallet.com/api/v1/mining/blocks/timestamp/${(date.millisecondsSinceEpoch / 1000).round()}",
),
);
final req = await getHttpClient()
.getUrl(Uri.parse("https://mempool.cakewallet.com/api/v1/mining/blocks/timestamp/${(date.millisecondsSinceEpoch / 1000).round()}"))
.timeout(Duration(seconds: 15));
final response = await req.close();
final stringResponse = await response.transform(utf8.decoder).join();

return jsonDecode(response.body)['height'] as int;
return jsonDecode(stringResponse)['height'] as int;
}

int getBitcoinHeightByDate({required DateTime date}) {
Expand Down
27 changes: 15 additions & 12 deletions cw_core/lib/node.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import 'dart:io';
import 'package:cw_core/keyable.dart';
import 'package:cw_core/utils/http_client.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:hive/hive.dart';
import 'package:cw_core/hive_type_ids.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:http/io_client.dart' as ioc;

// import 'package:tor/tor.dart';
import 'package:tor/tor.dart' as tor;

part 'node.g.dart';

Expand Down Expand Up @@ -179,7 +180,7 @@ class Node extends HiveObject with Keyable {
final body = {'jsonrpc': '2.0', 'id': '0', 'method': 'get_info'};

try {
final authenticatingClient = HttpClient();
final authenticatingClient = getHttpClient();

authenticatingClient.badCertificateCallback =
((X509Certificate cert, String host, int port) => true);
Expand Down Expand Up @@ -231,15 +232,16 @@ class Node extends HiveObject with Keyable {
}

Future<bool> requestNodeWithProxy() async {
if (!isValidProxyAddress /* && !Tor.instance.enabled*/) {
if (!isValidProxyAddress && !tor.Tor.instance.enabled) {
return false;
}

String? proxy = socksProxyAddress;

// if ((proxy?.isEmpty ?? true) && Tor.instance.enabled) {
// proxy = "${InternetAddress.loopbackIPv4.address}:${Tor.instance.port}";
// }
if ((proxy?.isEmpty ?? true) && tor.Tor.instance.enabled) {
proxy = "${InternetAddress.loopbackIPv4.address}:${tor.Tor.instance.port}";
}
printV("proxy: $proxy");
if (proxy == null) {
return false;
}
Expand Down Expand Up @@ -305,13 +307,14 @@ class Node extends HiveObject with Keyable {

Future<bool> requestEthereumServer() async {
try {
final response = await http.get(
uri,
headers: {'Content-Type': 'application/json'},
);
final req = await getHttpClient()
.getUrl(uri,)
.timeout(Duration(seconds: 15));
final response = await req.close();

return response.statusCode >= 200 && response.statusCode < 300;
} catch (_) {
} catch (err) {
printV("Failed to request ethereum server: $err");
return false;
}
}
Expand Down
19 changes: 19 additions & 0 deletions cw_core/lib/utils/http_client.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'dart:io';
import 'package:http/http.dart';
import 'package:socks5_proxy/socks_client.dart';
import 'package:tor/tor.dart';

HttpClient getHttpClient() {
final client = HttpClient();

if (Tor.instance.enabled) {
SocksTCPClient.assignToHttpClient(client, [
ProxySettings(InternetAddress.loopbackIPv4,
Tor.instance.port,
password: null,
),
]);
}

return client;
}
8 changes: 8 additions & 0 deletions cw_core/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.1"
tor:
dependency: "direct main"
description:
name: tor
sha256: eeed80e5c912a1806c2f81825c12e84f4dc5a0b50aebedea59e3a8ba53df3142
url: "https://pub.dev"
source: hosted
version: "0.0.8"
tuple:
dependency: transitive
description:
Expand Down
5 changes: 1 addition & 4 deletions cw_core/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@ dependencies:
version: 1.0.0
socks5_proxy: ^1.0.4
unorm_dart: ^0.3.0
# tor:
# git:
# url: https://github.com/cake-tech/tor.git
# ref: main
tor: any

dev_dependencies:
flutter_test:
Expand Down
8 changes: 8 additions & 0 deletions cw_haven/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.1"
tor:
dependency: transitive
description:
name: tor
sha256: eeed80e5c912a1806c2f81825c12e84f4dc5a0b50aebedea59e3a8ba53df3142
url: "https://pub.dev"
source: hosted
version: "0.0.8"
tuple:
dependency: transitive
description:
Expand Down
14 changes: 12 additions & 2 deletions cw_monero/lib/api/wallet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,17 @@ int getUnlockedBalance({int accountIndex = 0}) =>

int getCurrentHeight() => monero.Wallet_blockChainHeight(wptr!);

int getNodeHeightSync() => monero.Wallet_daemonBlockChainHeight(wptr!);
int cachedNodeHeight = 0;
int getNodeHeightSync() {
printV("getNodeHeightSync: $cachedNodeHeight");
(() async {
final wptrAddress = wptr!.address;
cachedNodeHeight = await Isolate.run(() async {
return monero.Wallet_daemonBlockChainHeight(Pointer.fromAddress(wptrAddress));
});
})();
return cachedNodeHeight;
}

bool isConnectedSync() => monero.Wallet_connected(wptr!) != 0;

Expand Down Expand Up @@ -147,7 +157,7 @@ Future<bool> setupNodeSync(
}

void startRefreshSync() {
monero.Wallet_refreshAsync(wptr!);
// monero.Wallet_refreshAsync(wptr!);
monero.Wallet_startRefresh(wptr!);
}

Expand Down
11 changes: 10 additions & 1 deletion cw_monero/lib/monero_wallet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import 'package:hive/hive.dart';
import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
import 'package:mobx/mobx.dart';
import 'package:monero/monero.dart' as monero;
import 'package:tor/tor.dart';

part 'monero_wallet.g.dart';

Expand Down Expand Up @@ -183,6 +184,14 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,

@override
Future<void> connectToNode({required Node node}) async {
String socksProxy = node.socksProxyAddress ?? '';
printV("bootstrapped: ${Tor.instance.bootstrapped}");
printV(" enabled: ${Tor.instance.enabled}");
printV(" port: ${Tor.instance.port}");
printV(" started: ${Tor.instance.started}");
if (Tor.instance.enabled) {
socksProxy = "127.0.0.1:${Tor.instance.port}";
}
try {
syncStatus = ConnectingSyncStatus();
await monero_wallet.setupNode(
Expand All @@ -192,7 +201,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
useSSL: node.isSSL,
isLightWallet: false,
// FIXME: hardcoded value
socksProxyAddress: node.socksProxyAddress);
socksProxyAddress: socksProxy);

monero_wallet.setTrustedDaemon(node.trusted);
syncStatus = ConnectedSyncStatus();
Expand Down
1 change: 1 addition & 0 deletions cw_monero/linux/flutter/ephemeral/.plugin_symlinks/tor
1 change: 1 addition & 0 deletions cw_monero/linux/flutter/generated_plugins.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
)

list(APPEND FLUTTER_FFI_PLUGIN_LIST
tor
)

set(PLUGIN_BUNDLED_LIBRARIES)
Expand Down
8 changes: 8 additions & 0 deletions cw_monero/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.1"
tor:
dependency: "direct main"
description:
name: tor
sha256: eeed80e5c912a1806c2f81825c12e84f4dc5a0b50aebedea59e3a8ba53df3142
url: "https://pub.dev"
source: hosted
version: "0.0.8"
tuple:
dependency: transitive
description:
Expand Down
1 change: 1 addition & 0 deletions cw_monero/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ dependencies:
path: impls/monero.dart
mutex: ^3.1.0
ledger_flutter_plus: ^1.4.1
tor: any

dev_dependencies:
flutter_test:
Expand Down
8 changes: 8 additions & 0 deletions cw_nano/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.1"
tor:
dependency: transitive
description:
name: tor
sha256: eeed80e5c912a1806c2f81825c12e84f4dc5a0b50aebedea59e3a8ba53df3142
url: "https://pub.dev"
source: hosted
version: "0.0.8"
tuple:
dependency: transitive
description:
Expand Down
Loading