tor fusion service

This commit is contained in:
julian 2023-09-22 15:44:40 -06:00
parent 59ac1563bc
commit 5527678b94
2 changed files with 101 additions and 29 deletions

View file

@ -0,0 +1,71 @@
import 'dart:io';
import 'package:stackwallet/utilities/logger.dart';
import 'package:tor_ffi_plugin/tor_ffi_plugin.dart';
class FusionTorService {
Tor? _tor;
String? _torDataDirPath;
TorStatus get status => _tor!.status;
/// Singleton instance of the TorService.
///
/// Use this to access the TorService and its properties.
static final sharedInstance = FusionTorService._();
// private constructor for singleton
FusionTorService._();
/// Getter for the proxyInfo.
///
/// Throws if Tor is not connected.
({
InternetAddress host,
int port,
}) getProxyInfo() {
try {
return (
host: InternetAddress.loopbackIPv4,
port: _tor!.port,
);
} catch (_) {
throw Exception("Tor proxy info fetched while not connected!");
}
}
/// Initialize the tor ffi lib instance if it hasn't already been set. Nothing
/// changes if _tor is already been set.
void init({
required String torDataDirPath,
Tor? mockableOverride,
}) {
_tor ??= mockableOverride ?? Tor.instance;
_torDataDirPath ??= torDataDirPath;
}
/// Start the Tor service.
///
/// This will start the Tor service and establish a Tor circuit.
///
/// Throws an exception if the Tor library was not inited or if the Tor
/// service fails to start.
///
/// Returns a Future that completes when the Tor service has started.
Future<void> start() async {
if (_tor == null || _torDataDirPath == null) {
throw Exception("FusionTorService.init has not been called!");
}
// Start the Tor service.
try {
await _tor!.start(torDataDirPath: _torDataDirPath!);
} catch (e, s) {
Logging.instance.log(
"FusionTorService.start failed: $e\n$s",
level: LogLevel.Warning,
);
rethrow;
}
}
}

View file

@ -12,7 +12,7 @@ import 'package:isar/isar.dart';
import 'package:stackwallet/db/isar/main_db.dart'; import 'package:stackwallet/db/isar/main_db.dart';
import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart'; import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/services/fusion_tor_service.dart';
import 'package:stackwallet/utilities/amount/amount.dart'; import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
@ -28,7 +28,7 @@ mixin FusionWalletInterface {
late final Coin _coin; late final Coin _coin;
late final MainDB _db; late final MainDB _db;
late final CachedElectrumX _cachedElectrumX; late final CachedElectrumX _cachedElectrumX;
late final TorService _torService; late final FusionTorService _torService;
// Passed in wallet functions. // Passed in wallet functions.
late final Future<Address> Function( late final Future<Address> Function(
@ -58,25 +58,8 @@ mixin FusionWalletInterface {
_coin = coin; _coin = coin;
_db = db; _db = db;
_generateAddressForChain = generateAddressForChain; _generateAddressForChain = generateAddressForChain;
_torService = TorService.sharedInstance; _torService = FusionTorService.sharedInstance;
_cachedElectrumX = cachedElectrumX; _cachedElectrumX = cachedElectrumX;
// Try getting the proxy info.
//
// Start the Tor service if it's not already running. Returns if Tor is already
// connected or else after Tor returns from start().
try {
_torService.getProxyInfo();
// Proxy info successfully retrieved, Tor is connected.
return;
} catch (e) {
// Init the Tor service if it hasn't already been.
final torDir = await StackFileSystem.applicationTorDirectory();
_torService.init(torDataDirPath: torDir.path);
// Start the Tor service.
return await _torService.start();
}
} }
/// Returns a list of all addresses in the wallet. /// Returns a list of all addresses in the wallet.
@ -198,20 +181,38 @@ mixin FusionWalletInterface {
return unusedAddresses; return unusedAddresses;
} }
int _torStartCount = 0;
/// Returns the current Tor proxy address. /// Returns the current Tor proxy address.
Future<({InternetAddress host, int port})> getSocksProxyAddress() async { Future<({InternetAddress host, int port})> getSocksProxyAddress() async {
/* if (_torStartCount > 5) {
// Start the Tor service if it's not already running. // something is quite broken so stop trying to recursively fetch
if (_torService.proxyInfo.port == -1) { // -1 indicates that the proxy is not running. // start up tor and fetch proxy info
await _torService.start(); // We already unawaited this in initFusionInterface... throw Exception(
"Fusion interface attempted to start tor $_torStartCount times and failed!",
);
} }
*/
// TODO make sure we've properly awaited the Tor service starting before try {
// returning the proxy address. final info = _torService.getProxyInfo();
// Return the proxy address. // reset counter before return info;
return _torService.getProxyInfo(); _torStartCount = 0;
return info;
} catch (_) {
// tor is probably not running so lets fix that
final torDir = await StackFileSystem.applicationTorDirectory();
_torService.init(torDataDirPath: torDir.path);
// increment start attempt count
_torStartCount++;
await _torService.start();
// try again to fetch proxy info
return await getSocksProxyAddress();
}
} }
// Initial attempt for CashFusion integration goes here. // Initial attempt for CashFusion integration goes here.