Fixed problem with proof of work
This commit is contained in:
parent
491a8a0ccb
commit
adfb3a920a
@ -9,7 +9,7 @@ android {
|
|||||||
applicationId "ch.dissem.apps.abit"
|
applicationId "ch.dissem.apps.abit"
|
||||||
minSdkVersion 19
|
minSdkVersion 19
|
||||||
targetSdkVersion 23
|
targetSdkVersion 23
|
||||||
versionCode 3
|
versionCode 5
|
||||||
versionName "1.0-beta"
|
versionName "1.0-beta"
|
||||||
}
|
}
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
@ -29,16 +29,17 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ext.jabitVersion = '1.0.0'
|
||||||
dependencies {
|
dependencies {
|
||||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
compile 'com.android.support:appcompat-v7:23.1.1'
|
compile 'com.android.support:appcompat-v7:23.1.1'
|
||||||
compile 'com.android.support:support-v4:23.1.1'
|
compile 'com.android.support:support-v4:23.1.1'
|
||||||
compile 'com.android.support:design:23.1.1'
|
compile 'com.android.support:design:23.1.1'
|
||||||
|
|
||||||
compile 'ch.dissem.jabit:jabit-core:0.2.1-SNAPSHOT'
|
compile "ch.dissem.jabit:jabit-core:$jabitVersion"
|
||||||
compile 'ch.dissem.jabit:jabit-networking:0.2.1-SNAPSHOT'
|
compile "ch.dissem.jabit:jabit-networking:$jabitVersion"
|
||||||
compile 'ch.dissem.jabit:jabit-cryptography-spongy:0.2.1-SNAPSHOT'
|
compile "ch.dissem.jabit:jabit-cryptography-spongy:$jabitVersion"
|
||||||
compile 'ch.dissem.jabit:jabit-extensions:0.2.1-SNAPSHOT'
|
compile "ch.dissem.jabit:jabit-extensions:$jabitVersion"
|
||||||
|
|
||||||
compile 'org.slf4j:slf4j-android:1.7.12'
|
compile 'org.slf4j:slf4j-android:1.7.12'
|
||||||
|
|
||||||
|
@ -32,23 +32,30 @@ public class ProofOfWorkNotification extends AbstractNotification {
|
|||||||
|
|
||||||
public ProofOfWorkNotification(Context ctx) {
|
public ProofOfWorkNotification(Context ctx) {
|
||||||
super(ctx);
|
super(ctx);
|
||||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx);
|
update(1);
|
||||||
|
|
||||||
Intent showMessageIntent = new Intent(ctx, MainActivity.class);
|
|
||||||
PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 0, showMessageIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
||||||
|
|
||||||
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
|
||||||
.setUsesChronometer(true)
|
|
||||||
.setSmallIcon(R.drawable.ic_notification_proof_of_work)
|
|
||||||
.setContentTitle(ctx.getString(R.string.proof_of_work_title))
|
|
||||||
.setContentText(ctx.getString(R.string.proof_of_work_text))
|
|
||||||
.setContentIntent(pendingIntent);
|
|
||||||
|
|
||||||
notification = builder.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getNotificationId() {
|
protected int getNotificationId() {
|
||||||
return ONGOING_NOTIFICATION_ID;
|
return ONGOING_NOTIFICATION_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ProofOfWorkNotification update(int numberOfItems) {
|
||||||
|
NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx);
|
||||||
|
|
||||||
|
Intent showMessageIntent = new Intent(ctx, MainActivity.class);
|
||||||
|
PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 0, showMessageIntent,
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
|
||||||
|
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||||
|
.setUsesChronometer(true)
|
||||||
|
.setOngoing(true)
|
||||||
|
.setSmallIcon(R.drawable.ic_notification_proof_of_work)
|
||||||
|
.setContentTitle(ctx.getString(R.string.proof_of_work_title))
|
||||||
|
.setContentText(ctx.getString(R.string.proof_of_work_text, numberOfItems))
|
||||||
|
.setContentIntent(pendingIntent);
|
||||||
|
|
||||||
|
notification = builder.build();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,8 @@ import android.os.Binder;
|
|||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import java.util.LinkedList;
|
||||||
import org.slf4j.LoggerFactory;
|
import java.util.Queue;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
|
|
||||||
import ch.dissem.apps.abit.notification.ProofOfWorkNotification;
|
import ch.dissem.apps.abit.notification.ProofOfWorkNotification;
|
||||||
import ch.dissem.bitmessage.ports.MultiThreadedPOWEngine;
|
import ch.dissem.bitmessage.ports.MultiThreadedPOWEngine;
|
||||||
@ -38,11 +36,12 @@ import static ch.dissem.apps.abit.notification.ProofOfWorkNotification.ONGOING_N
|
|||||||
* killed by the system before the nonce is found.
|
* killed by the system before the nonce is found.
|
||||||
*/
|
*/
|
||||||
public class ProofOfWorkService extends Service {
|
public class ProofOfWorkService extends Service {
|
||||||
public static final Logger LOG = LoggerFactory.getLogger(ProofOfWorkService.class);
|
|
||||||
|
|
||||||
// Object to use as a thread-safe lock
|
// Object to use as a thread-safe lock
|
||||||
private static final Object lock = new Object();
|
private static final Object lock = new Object();
|
||||||
private static ProofOfWorkEngine engine;
|
private static ProofOfWorkEngine engine;
|
||||||
|
private static boolean calculating;
|
||||||
|
private static final Queue<PowItem> queue = new LinkedList<>();
|
||||||
|
private static ProofOfWorkNotification notification;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
@ -51,54 +50,74 @@ public class ProofOfWorkService extends Service {
|
|||||||
engine = new MultiThreadedPOWEngine();
|
engine = new MultiThreadedPOWEngine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
notification = new ProofOfWorkNotification(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
return new PowBinder(engine, this);
|
return new PowBinder(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PowBinder extends Binder {
|
public static class PowBinder extends Binder {
|
||||||
private final ProofOfWorkEngine engine;
|
private final ProofOfWorkService service;
|
||||||
|
|
||||||
private PowBinder(ProofOfWorkEngine engine, ProofOfWorkService service) {
|
private PowBinder(ProofOfWorkService service) {
|
||||||
this.engine = new EngineWrapper(engine, service);
|
this.service = service;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProofOfWorkEngine getEngine() {
|
public void process(PowItem item) {
|
||||||
return engine;
|
synchronized (queue) {
|
||||||
|
service.startService(new Intent(service, ProofOfWorkService.class));
|
||||||
|
service.startForeground(ONGOING_NOTIFICATION_ID,
|
||||||
|
notification.getNotification());
|
||||||
|
if (!calculating) {
|
||||||
|
calculating = true;
|
||||||
|
service.calculateNonce(item);
|
||||||
|
} else {
|
||||||
|
queue.add(item);
|
||||||
|
notification.update(queue.size()).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class EngineWrapper implements ProofOfWorkEngine {
|
|
||||||
private final ProofOfWorkNotification notification;
|
|
||||||
private final ProofOfWorkEngine engine;
|
|
||||||
private final WeakReference<ProofOfWorkService> serviceRef;
|
|
||||||
|
|
||||||
private EngineWrapper(ProofOfWorkEngine engine, ProofOfWorkService service) {
|
static class PowItem {
|
||||||
this.engine = engine;
|
private final byte[] initialHash;
|
||||||
this.serviceRef = new WeakReference<>(service);
|
private final byte[] targetValue;
|
||||||
this.notification = new ProofOfWorkNotification(service);
|
private final ProofOfWorkEngine.Callback callback;
|
||||||
|
|
||||||
|
PowItem(byte[] initialHash, byte[] targetValue, ProofOfWorkEngine.Callback callback) {
|
||||||
|
this.initialHash = initialHash;
|
||||||
|
this.targetValue = targetValue;
|
||||||
|
this.callback = callback;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
private void calculateNonce(final PowItem item) {
|
||||||
public void calculateNonce(byte[] initialHash, byte[] target, final Callback callback) {
|
engine.calculateNonce(item.initialHash, item.targetValue, new ProofOfWorkEngine.Callback() {
|
||||||
final ProofOfWorkService service = serviceRef.get();
|
@Override
|
||||||
service.startService(new Intent(service, ProofOfWorkService.class));
|
public void onNonceCalculated(byte[] initialHash, byte[] nonce) {
|
||||||
service.startForeground(ONGOING_NOTIFICATION_ID, notification.getNotification());
|
try {
|
||||||
engine.calculateNonce(initialHash, target, new ProofOfWorkEngine.Callback() {
|
item.callback.onNonceCalculated(initialHash, nonce);
|
||||||
@Override
|
} finally {
|
||||||
public void onNonceCalculated(byte[] initialHash, byte[] nonce) {
|
PowItem item;
|
||||||
try {
|
synchronized (queue) {
|
||||||
callback.onNonceCalculated(initialHash, nonce);
|
item = queue.poll();
|
||||||
} finally {
|
if (item == null) {
|
||||||
service.stopForeground(true);
|
calculating = false;
|
||||||
service.stopSelf();
|
stopForeground(true);
|
||||||
|
stopSelf();
|
||||||
|
} else {
|
||||||
|
notification.update(queue.size()).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (item != null) {
|
||||||
|
calculateNonce(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -22,9 +22,11 @@ import android.content.Intent;
|
|||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.LinkedList;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
import ch.dissem.apps.abit.service.ProofOfWorkService.PowBinder;
|
import ch.dissem.apps.abit.service.ProofOfWorkService.PowBinder;
|
||||||
|
import ch.dissem.apps.abit.service.ProofOfWorkService.PowItem;
|
||||||
import ch.dissem.bitmessage.ports.ProofOfWorkEngine;
|
import ch.dissem.bitmessage.ports.ProofOfWorkEngine;
|
||||||
|
|
||||||
import static android.content.Context.BIND_AUTO_CREATE;
|
import static android.content.Context.BIND_AUTO_CREATE;
|
||||||
@ -32,12 +34,12 @@ import static android.content.Context.BIND_AUTO_CREATE;
|
|||||||
/**
|
/**
|
||||||
* Proof of Work engine that uses the Proof of Work service.
|
* Proof of Work engine that uses the Proof of Work service.
|
||||||
*/
|
*/
|
||||||
public class ServicePowEngine implements ProofOfWorkEngine, ProofOfWorkEngine.Callback {
|
public class ServicePowEngine implements ProofOfWorkEngine {
|
||||||
private final Semaphore semaphore = new Semaphore(1, true);
|
|
||||||
private final Context ctx;
|
private final Context ctx;
|
||||||
|
|
||||||
private byte[] initialHash, targetValue;
|
private static final Object lock = new Object();
|
||||||
private Callback callback;
|
private Queue<PowItem> queue = new LinkedList<>();
|
||||||
|
private PowBinder service;
|
||||||
|
|
||||||
public ServicePowEngine(Context ctx) {
|
public ServicePowEngine(Context ctx) {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
@ -46,32 +48,31 @@ public class ServicePowEngine implements ProofOfWorkEngine, ProofOfWorkEngine.Ca
|
|||||||
private ServiceConnection connection = new ServiceConnection() {
|
private ServiceConnection connection = new ServiceConnection() {
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
((PowBinder) service).getEngine().calculateNonce(initialHash, targetValue, ServicePowEngine.this);
|
synchronized (lock) {
|
||||||
|
ServicePowEngine.this.service = (PowBinder) service;
|
||||||
|
while (!queue.isEmpty()) {
|
||||||
|
ServicePowEngine.this.service.process(queue.poll());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceDisconnected(ComponentName name) {
|
public void onServiceDisconnected(ComponentName name) {
|
||||||
semaphore.release();
|
service = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void calculateNonce(byte[] initialHash, byte[] targetValue, Callback callback) {
|
public void calculateNonce(byte[] initialHash, byte[] targetValue, Callback callback) {
|
||||||
try {
|
PowItem item = new PowItem(initialHash, targetValue, callback);
|
||||||
semaphore.acquire();
|
synchronized (lock) {
|
||||||
} catch (InterruptedException e) {
|
if (service != null) {
|
||||||
throw new RuntimeException(e);
|
service.process(item);
|
||||||
|
} else {
|
||||||
|
queue.add(item);
|
||||||
|
ctx.bindService(new Intent(ctx, ProofOfWorkService.class), connection,
|
||||||
|
BIND_AUTO_CREATE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.initialHash = initialHash;
|
|
||||||
this.targetValue = targetValue;
|
|
||||||
this.callback = callback;
|
|
||||||
ctx.bindService(new Intent(ctx, ProofOfWorkService.class), connection, BIND_AUTO_CREATE);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public void onNonceCalculated(byte[] initialHash, byte[] bytes) {
|
|
||||||
callback.onNonceCalculated(initialHash, bytes);
|
|
||||||
ctx.unbindService(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -42,7 +42,7 @@
|
|||||||
<string name="connection_info_n">Stream %1$d: %2$d Verbindungen</string>
|
<string name="connection_info_n">Stream %1$d: %2$d Verbindungen</string>
|
||||||
<string name="connection_info_disconnected">Getrennt</string>
|
<string name="connection_info_disconnected">Getrennt</string>
|
||||||
<string name="connection_info_pending">Verbindung wird aufgebaut…</string>
|
<string name="connection_info_pending">Verbindung wird aufgebaut…</string>
|
||||||
<string name="proof_of_work_text">Warnung: dies könnte das Gerät erwärmen bis die Batterie leer ist.</string>
|
<string name="proof_of_work_text">Arbeite am Versenden (%1$d in Warteschlange)</string>
|
||||||
<string name="proof_of_work_title">Proof of Work</string>
|
<string name="proof_of_work_title">Proof of Work</string>
|
||||||
<string name="error_invalid_sync_host">Synchronisation fehlgeschlagen: der vertrauenswürdige Knoten konnte nicht erreicht werden.</string>
|
<string name="error_invalid_sync_host">Synchronisation fehlgeschlagen: der vertrauenswürdige Knoten konnte nicht erreicht werden.</string>
|
||||||
<string name="error_invalid_sync_port">Ungültiger Port in den Synchronisationseinstellungen: %s</string>
|
<string name="error_invalid_sync_port">Ungültiger Port in den Synchronisationseinstellungen: %s</string>
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
<string name="connection_info_disconnected">Disconnected</string>
|
<string name="connection_info_disconnected">Disconnected</string>
|
||||||
<string name="connection_info_pending">Connecting…</string>
|
<string name="connection_info_pending">Connecting…</string>
|
||||||
<string name="proof_of_work_title">Proof of Work</string>
|
<string name="proof_of_work_title">Proof of Work</string>
|
||||||
<string name="proof_of_work_text">Warning: This might heat your device until the battery\'s dead.</string>
|
<string name="proof_of_work_text">Doing work to send message (%1$d queued)</string>
|
||||||
<string name="error_invalid_sync_port">Invalid port in synchronization settings: %s</string>
|
<string name="error_invalid_sync_port">Invalid port in synchronization settings: %s</string>
|
||||||
<string name="error_invalid_sync_host">Synchronization failed: Trusted node could not be reached.</string>
|
<string name="error_invalid_sync_host">Synchronization failed: Trusted node could not be reached.</string>
|
||||||
<string name="compose_body_hint">Write message</string>
|
<string name="compose_body_hint">Write message</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user