mirror of https://github.com/m2049r/xmrwallet
183 lines
7.9 KiB
Java
183 lines
7.9 KiB
Java
/*
|
|
* Copyright (c) 2018 m2049r
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.m2049r.xmrwallet.ledger;
|
|
|
|
import android.content.Context;
|
|
import android.os.Handler;
|
|
import android.os.Looper;
|
|
|
|
import com.m2049r.xmrwallet.R;
|
|
import com.m2049r.xmrwallet.dialog.ProgressDialog;
|
|
|
|
import timber.log.Timber;
|
|
|
|
public class LedgerProgressDialog extends ProgressDialog implements Ledger.Listener {
|
|
|
|
static public final int TYPE_DEBUG = 0;
|
|
static public final int TYPE_RESTORE = 1;
|
|
static public final int TYPE_SUBADDRESS = 2;
|
|
static public final int TYPE_ACCOUNT = 3;
|
|
static public final int TYPE_SEND = 4;
|
|
|
|
private final int type;
|
|
private Handler uiHandler = new Handler(Looper.getMainLooper());
|
|
|
|
public LedgerProgressDialog(Context context, int type) {
|
|
super(context);
|
|
this.type = type;
|
|
setCancelable(false);
|
|
if (type == TYPE_SEND)
|
|
setMessage(context.getString(R.string.info_prepare_tx));
|
|
else
|
|
setMessage(context.getString(R.string.progress_ledger_progress));
|
|
}
|
|
|
|
@Override
|
|
public void onBackPressed() {
|
|
// prevent back button
|
|
}
|
|
|
|
private int firstSubaddress = Integer.MAX_VALUE;
|
|
|
|
private boolean validate = false;
|
|
private boolean validated = false;
|
|
|
|
@Override
|
|
public void onInstructionSend(final Instruction ins, final byte[] apdu) {
|
|
Timber.d("LedgerProgressDialog SEND %s", ins);
|
|
uiHandler.post(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
if (type > TYPE_DEBUG) {
|
|
validate = false;
|
|
switch (ins) {
|
|
case INS_RESET: // ledger may ask for confirmation - maybe a bug?
|
|
case INS_GET_KEY: // ledger asks for confirmation to send keys
|
|
case INS_DISPLAY_ADDRESS:
|
|
setIndeterminate(true);
|
|
setMessage(getContext().getString(R.string.progress_ledger_confirm));
|
|
break;
|
|
case INS_GET_SUBADDRESS_SPEND_PUBLIC_KEY: // lookahead
|
|
//00 4a 00 00 09 00 01000000 30000000
|
|
// 0 1 2 3 4 5 6 7 8 9 a b c d
|
|
int account = bytesToInteger(apdu, 6);
|
|
int subaddress = bytesToInteger(apdu, 10);
|
|
Timber.d("fetching subaddress (%d, %d)", account, subaddress);
|
|
switch (type) {
|
|
case TYPE_RESTORE:
|
|
setProgress(account * Ledger.LOOKAHEAD_SUBADDRESSES + subaddress + 1,
|
|
Ledger.LOOKAHEAD_ACCOUNTS * Ledger.LOOKAHEAD_SUBADDRESSES);
|
|
setIndeterminate(false);
|
|
break;
|
|
case TYPE_ACCOUNT:
|
|
final int requestedSubaddress = account * Ledger.LOOKAHEAD_SUBADDRESSES + subaddress;
|
|
if (firstSubaddress > requestedSubaddress) {
|
|
firstSubaddress = requestedSubaddress;
|
|
}
|
|
setProgress(requestedSubaddress - firstSubaddress + 1,
|
|
Ledger.LOOKAHEAD_ACCOUNTS * Ledger.LOOKAHEAD_SUBADDRESSES);
|
|
setIndeterminate(false);
|
|
break;
|
|
case TYPE_SUBADDRESS:
|
|
if (firstSubaddress > subaddress) {
|
|
firstSubaddress = subaddress;
|
|
}
|
|
setProgress(subaddress - firstSubaddress + 1, Ledger.LOOKAHEAD_SUBADDRESSES);
|
|
setIndeterminate(false);
|
|
break;
|
|
default:
|
|
setIndeterminate(true);
|
|
break;
|
|
}
|
|
setMessage(getContext().getString(R.string.progress_ledger_lookahead));
|
|
break;
|
|
case INS_VERIFY_KEY:
|
|
setIndeterminate(true);
|
|
setMessage(getContext().getString(R.string.progress_ledger_verify));
|
|
break;
|
|
case INS_OPEN_TX:
|
|
setIndeterminate(true);
|
|
setMessage(getContext().getString(R.string.progress_ledger_opentx));
|
|
break;
|
|
case INS_MLSAG:
|
|
if (validated) {
|
|
setIndeterminate(true);
|
|
setMessage(getContext().getString(R.string.progress_ledger_mlsag));
|
|
}
|
|
break;
|
|
case INS_PREFIX_HASH:
|
|
if ((apdu[2] != 1) || (apdu[3] != 0)) break;
|
|
setIndeterminate(true);
|
|
setMessage(getContext().getString(R.string.progress_ledger_confirm));
|
|
break;
|
|
case INS_VALIDATE:
|
|
if ((apdu[2] != 1) || (apdu[3] != 1)) break;
|
|
validate = true;
|
|
uiHandler.postDelayed(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
if (validate) {
|
|
setIndeterminate(true);
|
|
setMessage(getContext().getString(R.string.progress_ledger_confirm));
|
|
validated = true;
|
|
}
|
|
}
|
|
}, 250);
|
|
break;
|
|
default:
|
|
// ignore others and maintain state
|
|
}
|
|
} else {
|
|
setMessage(ins.name());
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void onInstructionReceive(final Instruction ins, final byte[] data) {
|
|
Timber.d("LedgerProgressDialog RECV %s", ins);
|
|
uiHandler.post(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
if (type > TYPE_DEBUG) {
|
|
switch (ins) {
|
|
case INS_GET_SUBADDRESS_SPEND_PUBLIC_KEY: // lookahead
|
|
case INS_VERIFY_KEY:
|
|
case INS_GET_CHACHA8_PREKEY:
|
|
break;
|
|
default:
|
|
if (type != TYPE_SEND)
|
|
setMessage(getContext().getString(R.string.progress_ledger_progress));
|
|
}
|
|
} else {
|
|
setMessage("Returned from " + ins.name());
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// TODO: we use ints in Java but the are signed; accounts & subaddresses are unsigned ...
|
|
private int bytesToInteger(byte[] bytes, int offset) {
|
|
int result = 0;
|
|
for (int i = 3; i >= 0; i--) {
|
|
result <<= 8;
|
|
result |= (bytes[offset + i] & 0xFF);
|
|
}
|
|
return result;
|
|
}
|
|
} |