Skip to content

Commit

Permalink
Tor
Browse files Browse the repository at this point in the history
  • Loading branch information
hsjoberg committed Jul 24, 2020
1 parent 11c0f48 commit e08667e
Show file tree
Hide file tree
Showing 33 changed files with 690 additions and 95 deletions.
7 changes: 5 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ jobs:
- run: gomobile init
- run: go get -u -v github.com/lightninglabs/falafel
- run: go get -d github.com/lightningnetwork/lnd
- run: cd $GOPATH/src/github.com/lightningnetwork/lnd && git checkout v0.10.1-beta && sed -i 's/use_prefix="0"/use_prefix="1"/g' mobile/gen_bindings.sh && make android
- run: cd $GOPATH/src/github.com/lightninglabs/falafel && git checkout v0.7 && go install
- run: cd $GOPATH/src/github.com/lightningnetwork/lnd && git checkout v0.10.2-beta && sed -i 's/use_prefix="0"/use_prefix="1"/g' mobile/gen_bindings.sh && make android tags="routerrpc walletrpc signrpc"
- persist_to_workspace:
root: /go/src/github.com/lightningnetwork/lnd
paths:
Expand All @@ -24,11 +25,13 @@ jobs:
- checkout
- run: cp /go/src/github.com/lightningnetwork/lnd/mobile/build/android/Lndmobile.aar android/lndmobile
- run: yarn
- run: git submodule update --init
- run: yarn build-tor-lib
- run: yarn gen-proto
- run: yarn test
# Compile a bundled dev build https://stackoverflow.com/a/56520746
- run: ./node_modules/.bin/react-native bundle --platform android --dev false --entry-file index.ts --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/
- run: cd android && ./gradlew assembleDebug
- run: cd android && ./gradlew assembleChainmainnetNormalDebug && ./gradlew assembleChaintestnetNormalDebug
- store_artifacts:
path: android/app/build/outputs
workflows:
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "tor"]
path = tor
url = https://github.com/thaliproject/Tor_Onion_Proxy_Library
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ powered by lnd and Neutrino SPV.
- [x] Channel backup to Google Drive
- [x] [WebLN](https://webln.dev/) browser
- [x] Support for [Multi-Part Payments (MPP)](https://lightning.engineering/posts/2020-05-07-mpp/)
- [x] Integrated Tor support
- [ ] NFC
- [ ] WatchTower
- [ ] URL Payments
Expand All @@ -43,10 +44,14 @@ Do you like React Native, Java or Lightning? Come and help out!
- Install [Node](https://nodejs.org), [Yarn](https://classic.yarnpkg.com/), [Android Studio + Android SDK (including NDK)](https://developer.android.com/studio/)
- If needed, install an emulated android device inside Android Studio
- (Optional) Build lnd for Android by following the steps in [build-android-aar.md](build-android-aar.md)
- Get the tor sub-module: `git submodule update --init`
- Install Node packages: `yarn`
- Compile the Tor Android lib: `yarn install-tor-lib`
- Generate proto files: `yarn gen-proto`

To start the application:
- Run: `yarn start-metro`
- Run: `yarn testnet-debug`
- Run: `yarn mainnet-debug or `yarn testnet-debug`

## Commit and Code-Style

Expand Down
17 changes: 16 additions & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ android {
applicationId MYAPP_APP_ID
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 49
versionCode 52
versionName "0.1-alpha"
missingDimensionStrategy 'react-native-camera', 'general'
multiDexEnabled true
Expand Down Expand Up @@ -176,6 +176,7 @@ android {
release {
// Caution! In production, you need to generate your own keystore file.
// see https://facebook.github.io/react-native/docs/signed-apk-android.
// debuggable true
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
Expand Down Expand Up @@ -210,6 +211,11 @@ android {
dimension "custom"
manifestPlaceholders = [custom: ""]
}
experiment1 {
applicationIdSuffix ".experiment1"
dimension "custom"
manifestPlaceholders = [custom: " Experiment 1"]
}
}

packagingOptions {
Expand Down Expand Up @@ -285,6 +291,15 @@ dependencies {
implementation "com.github.mmin18:realtimeblurview:1.2.1"

implementation project(":lndmobile")

// Tor
implementation "com.msopentech.thali:universal:0.0.3"
implementation "org.torproject:tor-android-binary:0.4.2.7a"
implementation "com.msopentech.thali.toronionproxy.android:android:0.0.3@aar"
implementation "org.slf4j:slf4j-android:1.7.7"
implementation "net.freehaven.tor.control:jtorctl:0.2" // controlling tor instance via its control port

implementation "com.jakewharton:process-phoenix:2.0.0"
}

configurations {
Expand Down
1 change: 1 addition & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>

<intent-filter android:label="${appName}${chain}${custom}${buildType}">
Expand Down
84 changes: 65 additions & 19 deletions android/app/src/main/java/com/blixtwallet/LndMobile.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.blixtwallet;

import com.blixtwallet.PromiseWrapper;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import android.Manifest;
import android.app.ActivityManager;
import android.os.Process;
import android.util.Base64;
import android.util.Log;
import android.content.ComponentName;
Expand All @@ -25,7 +25,6 @@
import android.nfc.NdefMessage;
import android.nfc.tech.Ndef;
import android.nfc.NdefRecord;
import android.os.Parcelable;
import java.util.Arrays;
import java.io.UnsupportedEncodingException;

Expand All @@ -41,20 +40,12 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.EnumSet;

import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkInfo;
import androidx.work.WorkManager;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Promise;
Expand All @@ -63,11 +54,7 @@
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.modules.permissions.PermissionsModule;

import com.facebook.react.modules.storage.ReactDatabaseSupplier;
import com.facebook.react.modules.storage.AsyncLocalStorageUtil;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;

import com.jakewharton.processphoenix.ProcessPhoenix;
import com.oblador.keychain.KeychainModule;

import com.hypertrack.hyperlog.HyperLog;
Expand Down Expand Up @@ -110,7 +97,8 @@ public void handleMessage(Message msg) {
switch (msg.what) {
case LndMobileService.MSG_GRPC_COMMAND_RESULT:
case LndMobileService.MSG_START_LND_RESULT:
case LndMobileService.MSG_REGISTER_CLIENT_ACK: {
case LndMobileService.MSG_REGISTER_CLIENT_ACK:
case LndMobileService.MSG_STOP_LND_RESULT: {
final int request = msg.arg1;

if (!requests.containsKey(request)) {
Expand Down Expand Up @@ -146,6 +134,7 @@ public void handleMessage(Message msg) {
break;
}
case LndMobileService.MSG_GRPC_STREAM_RESULT: {
// TODO handle when error is returned
final byte[] bytes = (byte[]) bundle.get("response");
final String method = (String) bundle.get("method");

Expand Down Expand Up @@ -292,15 +281,33 @@ public void checkStatus(Promise promise) {
}

@ReactMethod
public void startLnd(Promise promise) {
public void startLnd(boolean torEnabled, Promise promise) {
int req = new Random().nextInt();
requests.put(req, promise);

Message message = Message.obtain(null, LndMobileService.MSG_START_LND, req, 0);
message.replyTo = messenger;

Bundle bundle = new Bundle();
bundle.putString("args", "--lnddir=" + getReactApplicationContext().getFilesDir().getPath());

String params = "--lnddir=" + getReactApplicationContext().getFilesDir().getPath();
if (torEnabled) {
int socksPort = 9070;
int controlPort = 9071;
if (BuildConfig.CHAIN.equals("testnet")) {
socksPort += 10;
controlPort += 10;
}
if (BuildConfig.DEBUG) {
socksPort += 100;
controlPort += 100;
}
params += " --tor.active --tor.socks=127.0.0.1:" + socksPort + " --tor.control=127.0.0.1:" + controlPort;
}
bundle.putString(
"args",
params
);
message.setData(bundle);

try {
Expand All @@ -310,6 +317,45 @@ public void startLnd(Promise promise) {
}
}

@ReactMethod
public void stopLnd(Promise promise) {
int req = new Random().nextInt();
requests.put(req, promise);

Message message = Message.obtain(null, LndMobileService.MSG_STOP_LND, req, 0);
message.replyTo = messenger;

try {
lndMobileServiceMessenger.send(message);
} catch (RemoteException e) {
promise.reject(TAG, "Could not Send MSG_STOP_LND to LndMobileService", e);
}
}

@ReactMethod
public void killLnd(Promise promise) {
killLndProcess();
promise.resolve(true);
}

private boolean killLndProcess() {
String packageName = getReactApplicationContext().getPackageName();
ActivityManager am = (ActivityManager) getCurrentActivity().getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningAppProcessInfo p : am.getRunningAppProcesses()) {
if (p.processName.equals(packageName + ":blixtLndMobile")) {
HyperLog.i(TAG, "Killing " + packageName + ":blixtLndMobile with pid: " + String.valueOf(p.pid));
Process.killProcess(p.pid);
return true;
}
}
return false;
}

@ReactMethod
public void restartApp() {
ProcessPhoenix.triggerRebirth(getReactApplicationContext());
}

@ReactMethod
void writeConfigFile(Promise promise) {
String filename = getReactApplicationContext().getFilesDir().toString() + "/lnd.conf";
Expand Down
86 changes: 64 additions & 22 deletions android/app/src/main/java/com/blixtwallet/LndMobileService.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ public class LndMobileService extends Service {
static final int MSG_UNLOCKWALLET = 14;
static final int MSG_INITWALLET = 15;
static final int MSG_GRPC_STREAM_STARTED = 16;
static final int MSG_STOP_LND = 17;
static final int MSG_STOP_LND_RESULT = 18;

int unlockWalletRequest = -1;

Expand Down Expand Up @@ -149,7 +151,10 @@ public void handleMessage(Message msg) {
sendToClient(msg.replyTo, message);
}

} catch (IllegalAccessException | InvocationTargetException e) {
} catch (IllegalAccessException e) {
Log.e(TAG, "Could not invoke lndmobile method " + method, e);
// TODO(hsjoberg) send error response to client?
} catch (InvocationTargetException e) {
Log.e(TAG, "Could not invoke lndmobile method " + method, e);
// TODO(hsjoberg) send error response to client?
}
Expand Down Expand Up @@ -224,6 +229,11 @@ public void handleMessage(Message msg) {
);
break;

case MSG_STOP_LND:
HyperLog.d(TAG, "Got MSG_STOP_LND");
stopLnd(msg.replyTo, request);
break;

default:
super.handleMessage(msg);
}
Expand Down Expand Up @@ -449,27 +459,11 @@ public boolean onUnbind(Intent intent) {

if (checkLndProcessExists()) {
HyperLog.i(TAG, "Lnd exists, attempting to stop it");
Lndmobile.stopDaemon(
Rpc.StopRequest.newBuilder().build().toByteArray(),
new Callback() {
@Override
public void onError(Exception e) {
HyperLog.e(TAG, "Got Error when trying to stop lnd", e);
try {
Thread.sleep(10000);
} catch (Throwable t) {}
killLndProcess();
}

@Override
public void onResponse(byte[] bytes) {
try {
Thread.sleep(10000);
} catch (Throwable t) {}
killLndProcess();
}
}
);
stopLnd(null, -1);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
killLndProcess();
}
}

Expand Down Expand Up @@ -498,6 +492,12 @@ public LndMobileService() {
syncMethods.put(name, m);
}
}

/*if (checkLndProcessExists()) {
HyperLog.w(TAG, "WARNING: Found lnd process while in LndMobileService constructor.");
HyperLog.w(TAG, "Going to kill lnd process");
killLndProcess();
}*/
}

private boolean checkLndProcessExists() {
Expand All @@ -524,4 +524,46 @@ private boolean killLndProcess() {
}
return false;
}

private void stopLnd(Messenger recipient, int request) {
Lndmobile.stopDaemon(
Rpc.StopRequest.newBuilder().build().toByteArray(),
new Callback() {
@Override
public void onError(Exception e) {
HyperLog.e(TAG, "Got Error when trying to stop lnd", e);

lndStarted = false;

if (recipient != null) {
Message msg = Message.obtain(null, MSG_STOP_LND_RESULT, request, 0);

Bundle bundle = new Bundle();
bundle.putString("error_code", "Lnd Stop Error");
bundle.putString("error_desc", e.toString());
msg.setData(bundle);

sendToClient(recipient, msg);
}
}

@Override
public void onResponse(byte[] bytes) {
HyperLog.e(TAG, "onReponse for stopDaemon");

lndStarted = false;

if (recipient != null) {
Message msg = Message.obtain(null, MSG_STOP_LND_RESULT, request, 0);

Bundle bundle = new Bundle();
bundle.putByteArray("response", bytes);
msg.setData(bundle);

sendToClient(recipient, msg);
}
}
}
);
}
}
Loading

0 comments on commit e08667e

Please sign in to comment.