Merge pull request #3868 from BlueWallet/tordisabled

ADD: Toggle for disabling Tor daemon
This commit is contained in:
GLaDOS 2021-09-22 19:48:03 +01:00 committed by GitHub
commit 1370838343
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 85 additions and 43 deletions

View file

@ -4,8 +4,8 @@ import { Alert } from 'react-native';
import { LegacyWallet, SegwitBech32Wallet, SegwitP2SHWallet } from '../class';
import DefaultPreference from 'react-native-default-preference';
import loc from '../loc';
import { isTorCapable } from './environment';
import WidgetCommunication from './WidgetCommunication';
import { isTorDaemonDisabled } from './environment';
const bitcoin = require('bitcoinjs-lib');
const ElectrumClient = require('electrum-client');
const reverse = require('buffer-reverse');
@ -127,7 +127,7 @@ async function connectMain() {
try {
console.log('begin connection:', JSON.stringify(usingPeer));
mainClient = new ElectrumClient(
usingPeer.host.endsWith('.onion') && isTorCapable ? torrific : global.net,
usingPeer.host.endsWith('.onion') && !(await isTorDaemonDisabled()) ? torrific : global.net,
global.tls,
usingPeer.ssl || usingPeer.tcp,
usingPeer.host,
@ -854,8 +854,9 @@ module.exports.calculateBlockTime = function (height) {
* @returns {Promise<boolean>} Whether provided host:port is a valid electrum server
*/
module.exports.testConnection = async function (host, tcpPort, sslPort) {
const isTorDisabled = await isTorDaemonDisabled();
const client = new ElectrumClient(
host.endsWith('.onion') && isTorCapable ? torrific : global.net,
host.endsWith('.onion') && !isTorDisabled ? torrific : global.net,
global.tls,
sslPort || tcpPort,
host,
@ -867,7 +868,7 @@ module.exports.testConnection = async function (host, tcpPort, sslPort) {
try {
const rez = await Promise.race([
new Promise(resolve => {
timeoutId = setTimeout(() => resolve('timeout'), host.endsWith('.onion') && isTorCapable ? 21000 : 5000);
timeoutId = setTimeout(() => resolve('timeout'), host.endsWith('.onion') && !isTorDisabled ? 21000 : 5000);
}),
client.connect(),
]);

View file

@ -1,3 +1,4 @@
import AsyncStorage from '@react-native-async-storage/async-storage';
import { Platform } from 'react-native';
import { getSystemName, isTablet, getDeviceType } from 'react-native-device-info';
@ -13,6 +14,27 @@ const getIsTorCapable = () => {
return capable;
};
const IS_TOR_DAEMON_DISABLED = 'is_tor_daemon_disabled';
export async function setIsTorDaemonDisabled(disabled = true) {
return AsyncStorage.setItem(IS_TOR_DAEMON_DISABLED, disabled ? '1' : '');
}
export async function isTorDaemonDisabled() {
let isTorDaemonDisabled;
try {
const savedValue = await AsyncStorage.getItem(IS_TOR_DAEMON_DISABLED);
if (savedValue === null) {
isTorDaemonDisabled = false;
} else {
isTorDaemonDisabled = savedValue;
}
} catch {
isTorDaemonDisabled = true;
}
return !!isTorDaemonDisabled;
}
export const isHandset = getDeviceType() === 'Handset';
export const isTorCapable = getIsTorCapable();
export { isMacCatalina, isDesktop, isTablet };

View file

@ -3,6 +3,7 @@ import { useAsyncStorage } from '@react-native-async-storage/async-storage';
import React, { createContext, useEffect, useState } from 'react';
import { FiatUnit } from '../models/fiatUnit';
import loc from '../loc';
import { isTorDaemonDisabled, setIsTorDaemonDisabled } from './environment';
const BlueApp = require('../BlueApp');
const BlueElectrum = require('./BlueElectrum');
const currency = require('../blue_modules/currency');
@ -23,11 +24,17 @@ export const BlueStorageProvider = ({ children }) => {
const getLanguageAsyncStorage = useAsyncStorage(loc.LANG).getItem;
const [isHandOffUseEnabled, setIsHandOffUseEnabled] = useState(false);
const [isElectrumDisabled, setIsElectrumDisabled] = useState(true);
const [isTorDisabled, setIsTorDisabled] = useState(false);
useEffect(() => {
BlueElectrum.isDisabled().then(setIsElectrumDisabled);
isTorDaemonDisabled().then(setIsTorDisabled);
}, []);
useEffect(() => {
setIsTorDaemonDisabled(isTorDisabled);
}, [isTorDisabled]);
const setIsHandOffUseEnabledAsyncStorage = value => {
setIsHandOffUseEnabled(value);
return BlueApp.setIsHandoffEnabled(value);
@ -234,6 +241,8 @@ export const BlueStorageProvider = ({ children }) => {
isDoNotTrackEnabled,
isElectrumDisabled,
setIsElectrumDisabled,
isTorDisabled,
setIsTorDisabled,
}}
>
{children}

View file

@ -2,9 +2,8 @@ import { LegacyWallet } from './legacy-wallet';
import Frisbee from 'frisbee';
import bolt11 from 'bolt11';
import { BitcoinUnit, Chain } from '../../models/bitcoinUnits';
import { isTorCapable } from '../../blue_modules/environment';
import { isTorDaemonDisabled } from '../../blue_modules/environment';
const torrific = require('../../blue_modules/torrific');
export class LightningCustodianWallet extends LegacyWallet {
static type = 'lightningCustodianWallet';
static typeReadable = 'Lightning';
@ -72,12 +71,13 @@ export class LightningCustodianWallet extends LegacyWallet {
this._api = new Frisbee({
baseURI: this.baseURI,
});
if (isTorCapable && this.baseURI && this.baseURI?.indexOf('.onion') !== -1) {
this._api = new torrific.Torsbee({
baseURI: this.baseURI,
});
}
isTorDaemonDisabled().then(isDisabled => {
if (!isDisabled && this.baseURI && this.baseURI?.indexOf('.onion') !== -1) {
this._api = new torrific.Torsbee({
baseURI: this.baseURI,
});
}
});
}
accessTokenExpired() {

View file

@ -5,6 +5,7 @@
"continue": "Continue",
"enter_password": "Enter password",
"never": "Never",
"disabled": "Disabled",
"of": "{number} of {total}",
"ok": "OK",
"storage_is_encrypted": "Your storage is encrypted. Password is required to decrypt it.",

View file

@ -28,12 +28,11 @@ import loc, { formatBalanceWithoutSuffix, formatBalancePlain } from '../../loc';
import Lnurl from '../../class/lnurl';
import { BlueStorageContext } from '../../blue_modules/storage-context';
import Notifications from '../../blue_modules/notifications';
import { isTorCapable } from '../../blue_modules/environment';
const currency = require('../../blue_modules/currency');
const torrific = require('../../blue_modules/torrific');
const LNDCreateInvoice = () => {
const { wallets, saveToDisk, setSelectedWallet } = useContext(BlueStorageContext);
const { wallets, saveToDisk, setSelectedWallet, isTorDisabled } = useContext(BlueStorageContext);
const { walletID, uri } = useRoute().params;
const wallet = useRef(wallets.find(item => item.getID() === walletID) || wallets.find(item => item.chain === Chain.OFFCHAIN));
const { name } = useRoute();
@ -177,7 +176,7 @@ const LNDCreateInvoice = () => {
const callbackUrl = callback + (callback.indexOf('?') !== -1 ? '&' : '?') + 'k1=' + k1 + '&pr=' + invoiceRequest;
let reply;
if (isTorCapable && callbackUrl.includes('.onion')) {
if (!isTorDisabled && callbackUrl.includes('.onion')) {
const api = new torrific.Torsbee();
const torResponse = await api.get(callbackUrl);
reply = torResponse.body;
@ -228,7 +227,7 @@ const LNDCreateInvoice = () => {
// calling the url
let reply;
try {
if (isTorCapable && url.includes('.onion')) {
if (!isTorDisabled && url.includes('.onion')) {
const api = new torrific.Torsbee();
const torResponse = await api.get(url);
reply = torResponse.body;

View file

@ -15,7 +15,6 @@ import loc, { formatBalance, formatBalanceWithoutSuffix } from '../../loc';
import Notifications from '../../blue_modules/notifications';
import { BlueStorageContext } from '../../blue_modules/storage-context';
import { Psbt } from 'bitcoinjs-lib';
import { isTorCapable } from '../../blue_modules/environment';
import { useNavigation, useRoute, useTheme } from '@react-navigation/native';
const currency = require('../../blue_modules/currency');
const BlueElectrum = require('../../blue_modules/BlueElectrum');
@ -24,7 +23,7 @@ const bitcoin = require('bitcoinjs-lib');
const torrific = require('../../blue_modules/torrific');
const Confirm = () => {
const { wallets, fetchAndSaveWalletTransactions, isElectrumDisabled } = useContext(BlueStorageContext);
const { wallets, fetchAndSaveWalletTransactions, isElectrumDisabled, isTorDisabled } = useContext(BlueStorageContext);
const [isBiometricUseCapableAndEnabled, setIsBiometricUseCapableAndEnabled] = useState(false);
const { params } = useRoute();
const { recipients = [], walletID, fee, memo, tx, satoshiPerByte, psbt } = params;
@ -121,7 +120,7 @@ const Confirm = () => {
const payJoinWallet = new PayjoinTransaction(psbt, txHex => broadcast(txHex), wallet);
const paymentScript = getPaymentScript();
let payjoinClient;
if (isTorCapable && payjoinUrl.includes('.onion')) {
if (!isTorDisabled && payjoinUrl.includes('.onion')) {
console.warn('trying TOR....');
// working through TOR - crafting custom requester that will handle TOR http request
const customPayjoinRequester = {

View file

@ -162,10 +162,6 @@ export default class ElectrumSettings extends Component {
const sslPort = this.state.sslPort ? this.state.sslPort : '';
const serverHistory = this.state.serverHistory || [];
if (host.endsWith('.onion') && !isTorCapable) {
return alert(loc.settings.tor_unsupported);
}
this.setState({ isLoading: true }, async () => {
try {
if (!host && !port && !sslPort) {

View file

@ -96,10 +96,6 @@ const LightningSettings: React.FC & { navigationOptions: NavigationOptionsGetter
setIsLoading(true);
try {
if (URI) {
if (URI.endsWith('.onion') && !isTorCapable) {
setIsLoading(false);
return alert(loc.settings.tor_unsupported);
}
await LightningCustodianWallet.isValidNodeAddress(URI);
// validating only if its not empty. empty means use default
}

View file

@ -1,10 +1,11 @@
/* global alert */
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useContext } from 'react';
import { View, StyleSheet } from 'react-native';
import navigationStyle from '../../components/navigationStyle';
import { BlueButton, BlueCard, BlueLoading, BlueSpacing20, BlueText, SafeBlueArea } from '../../BlueComponents';
import { BlueButton, BlueCard, BlueListItem, BlueLoading, BlueSpacing20, BlueText, SafeBlueArea } from '../../BlueComponents';
import loc from '../../loc';
import { BlueStorageContext } from '../../blue_modules/storage-context';
const torrific = require('../../blue_modules/torrific');
@ -20,6 +21,7 @@ const styles = StyleSheet.create({
const TorSettings = () => {
const [isLoading, setIsLoading] = useState(false);
const [daemonStatus, setDaemonStatus] = useState('');
const { isTorDisabled, setIsTorDisabled } = useContext(BlueStorageContext);
const updateStatus = async () => {
const status = await torrific.getDaemonStatus();
@ -38,7 +40,7 @@ const TorSettings = () => {
try {
setIsLoading(true);
await torrific.testSocket();
alert('OK');
alert(loc._.ok);
} catch (error) {
alert(error.message);
} finally {
@ -50,7 +52,7 @@ const TorSettings = () => {
try {
setIsLoading(true);
await torrific.testHttp();
alert('OK');
alert(loc._.ok);
} catch (error) {
alert(error.message);
} finally {
@ -60,12 +62,19 @@ const TorSettings = () => {
useEffect(() => {
const interval = setInterval(updateStatus, 1000);
return () => {
clearInterval(interval);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
if (isTorDisabled) {
stopIfRunning();
}
}, [isTorDisabled]);
if (isLoading) {
return (
<View style={[styles.root]}>
@ -76,18 +85,28 @@ const TorSettings = () => {
return (
<SafeBlueArea>
<BlueCard>
<BlueText>Daemon Status: {daemonStatus}</BlueText>
</BlueCard>
<BlueCard>
<BlueButton title="start" onPress={startIfNotStarted} />
<BlueSpacing20 />
<BlueButton title="stop" onPress={stopIfRunning} />
<BlueSpacing20 />
<BlueButton title="test socket" onPress={testSocket} />
<BlueSpacing20 />
<BlueButton title="test http" onPress={testHttp} />
</BlueCard>
<BlueListItem
hideChevron
title={loc._.disabled}
Component={View}
switch={{ onValueChange: setIsTorDisabled, value: isTorDisabled }}
/>
{!isTorDisabled && (
<>
<BlueCard>
<BlueText>Daemon Status: {daemonStatus}</BlueText>
</BlueCard>
<BlueCard>
<BlueButton title={loc.send.dynamic_start} onPress={startIfNotStarted} />
<BlueSpacing20 />
<BlueButton title={loc.send.dynamic_stop} onPress={stopIfRunning} />
<BlueSpacing20 />
<BlueButton title="Test Socket" onPress={testSocket} />
<BlueSpacing20 />
<BlueButton title="Test HTTP" onPress={testHttp} />
</BlueCard>
</>
)}
</SafeBlueArea>
);
};