Skip to content

Commit

Permalink
2.5.5
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielWeigl committed Oct 21, 2015
1 parent b23ff38 commit fd156f0
Show file tree
Hide file tree
Showing 71 changed files with 1,409 additions and 889 deletions.
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,15 @@ Authors

Credits
=======
Thanks to Jethro for tirelessly testing the app during beta development.
Thanks to all collaborators who provided us with code or helped us with integrations!
Just to name a few:
- Nicolas Bacca from Ledger
- Sipa, Marek and others from Trezor
- Jani and Aleš from Cashila
- Kalle Rosenbaum, Bip120/121
- (if you think you should be mentioned here, just notify us)

Thanks to Jethro for tirelessly testing the app during beta development.
Thanks to our numerous volunteer translators who provide high-quality translations in many languages. Your name should be listed here, please contact me so I know you want to be included.

Thanks to Johannes Zweng for his testing and providing pull requests for fixes.
Thanks to all beta testers to provide early feedback.
Thanks to all beta testers to provide early feedback.
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public String toString() {
return HexUtils.toHex(_pubKeyBytes);
}

public boolean verifyStandardBitcoinSignature(Sha256Hash data, byte[] signature) {
public boolean verifyStandardBitcoinSignature(Sha256Hash data, byte[] signature, boolean forceLowS) {
// Decode parameters r and s
ByteReader reader = new ByteReader(signature);
Signature params = Signatures.decodeSignatureParameters(reader);
Expand All @@ -88,7 +88,12 @@ public boolean verifyStandardBitcoinSignature(Sha256Hash data, byte[] signature)
if (reader.available() != 1) {
return false;
}
return Signatures.verifySignature(data.getBytes(), params, getQ());
if (forceLowS) {
return Signatures.verifySignatureLowS(data.getBytes(), params, getQ());
} else {
return Signatures.verifySignature(data.getBytes(), params, getQ());
}

}

// same as verifyStandardBitcoinSignature, but dont enforce the hash-type check
Expand Down
26 changes: 26 additions & 0 deletions public/bitlib/src/main/java/com/mrd/bitlib/crypto/Signatures.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,28 @@ private static byte[] makePositive(byte[] bytes) {
return bytes;
}

// checks the signature and enforces a Low-S Value - to counter the bitcoin
// transaction malleability problem, according to Bip62
// https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki#New_rules, pt5
static boolean verifySignatureLowS(byte[] message, Signature signature, Point Q) {
BigInteger n = Parameters.n;
BigInteger e = calculateE(n, message);
BigInteger r = signature.r;
BigInteger s = signature.s;

// r in the range [1,n-1]
if (r.compareTo(BigInteger.ONE) < 0 || r.compareTo(n) >= 0) {
return false;
}

// s in the range [1,n/2]
if (s.compareTo(BigInteger.ONE) < 0 || s.compareTo(Parameters.MAX_SIG_S) > 0) {
return false;
}

return checkSignature(Q, n, e, r, s);
}

static boolean verifySignature(byte[] message, Signature signature, Point Q) {
BigInteger n = Parameters.n;
BigInteger e = calculateE(n, message);
Expand All @@ -125,6 +147,10 @@ static boolean verifySignature(byte[] message, Signature signature, Point Q) {
return false;
}

return checkSignature(Q, n, e, r, s);
}

private static boolean checkSignature(Point Q, BigInteger n, BigInteger e, BigInteger r, BigInteger s) {
BigInteger c = s.modInverse(n);

BigInteger u1 = e.multiply(c).mod(n);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class HdKeyPath implements Serializable {

public static final HdKeyPath ROOT = new HdKeyPath();
public static final Bip44Purpose BIP44 = ROOT.getBip44Purpose();
public static final HdKeyPath BIP32_ROOT = ROOT.getHardenedChild(0);
public static final Bip44CoinType BIP44_TESTNET = BIP44.getCoinTypeBitcoinTestnet();
public static final Bip44CoinType BIP44_PRODNET = BIP44.getCoinTypeBitcoin();

Expand All @@ -42,7 +43,7 @@ private HdKeyPath getChild(Iterator<String> path){
if (!path.hasNext()) return this;

String ak = path.next();
int index = Integer.valueOf(ak.replace(HARDENED_MARKER,""));
int index = Integer.valueOf(ak.replace(HARDENED_MARKER, ""));

if (ak.endsWith(HARDENED_MARKER)){
return this.getHardenedChild(index).getChild(path);
Expand Down Expand Up @@ -111,6 +112,7 @@ public Bip44Purpose getBip44Purpose(){
return new Bip44Purpose(this, UnsignedInteger.valueOf(44), true);
}


private int getValue(){
return index.intValue() | (isHardened() ? 1<<31 : 0);
}
Expand Down Expand Up @@ -154,8 +156,13 @@ public int hashCode() {
return result;
}

public int getLastIndex() {
// returns the raw index (including the hardened bit, if set) of the last path element
public int getLastRawIndex() {
return getValue();
}

// returns the index of the last path element
public int getLastIndex() {
return index.intValue();
}
}
4 changes: 2 additions & 2 deletions public/mbw/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ android {
buildToolsVersion androidSdkBuildVersion

defaultConfig {
versionCode 25400
versionName '2.5.4'
versionCode 25502
versionName '2.5.5'
multiDexEnabled true
}

Expand Down
46 changes: 32 additions & 14 deletions public/mbw/src/main/java/com/mycelium/wallet/CoinapultManager.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.mycelium.wallet;

import android.os.AsyncTask;
import android.os.Handler;
import android.util.Log;
import com.coinapult.api.httpclient.*;
Expand Down Expand Up @@ -38,7 +39,7 @@
import java.security.NoSuchAlgorithmException;
import java.util.*;

import static com.coinapult.api.httpclient.CoinapultClient.*;
import static com.coinapult.api.httpclient.CoinapultClient.CoinapultBackendException;

public class CoinapultManager implements WalletAccount {

Expand Down Expand Up @@ -126,7 +127,7 @@ private void initBalance() {
try {
String address;
Optional<Address> lastCoinapultAddress = metadataStorage.getCoinapultAddress();
if (!lastCoinapultAddress.isPresent()){
if (!lastCoinapultAddress.isPresent()) {
//requesting fresh address
address = coinapultClient.getBitcoinAddress().address;
} else {
Expand All @@ -136,7 +137,7 @@ private void initBalance() {
criteria.put("to", lastCoinapultAddress.get().toString());
com.coinapult.api.httpclient.Transaction.Json search = coinapultClient.search(criteria);
boolean alreadyUsed = search.containsKey("transaction_id");
if (alreadyUsed){
if (alreadyUsed) {
// get a new one
address = coinapultClient.getBitcoinAddress().address;
} else {
Expand Down Expand Up @@ -336,7 +337,6 @@ private boolean isSending(com.coinapult.api.httpclient.Transaction.Json input) {
if (isInvoice) {
return false;
}

// other unexpected tx type - but ignore it
return false;
}
Expand Down Expand Up @@ -383,7 +383,26 @@ public void activateAccount() {

@Override
public void dropCachedData() {
// try to recreate the coinapult account, this fails if it already exists
// otherwise it will fix a locked state where the wallet thinks it has an account
// but it does not
new AddCoinapultAsyncTask().execute();
}

private class AddCoinapultAsyncTask extends AsyncTask<Void, Integer, UUID> {
@Override
protected UUID doInBackground(Void... params) {
try {
addUSD(Optional.<String>absent());
} catch (CoinapultClient.CoinapultBackendException e) {
return null;
}
return getId();
}

@Override
protected void onPostExecute(UUID account) {
}
}

@Override
Expand All @@ -410,7 +429,7 @@ public boolean broadcastOutgoingTransactions() {
public boolean isMine(Address address) {
// there might be more, but currently we only know about this one...
Optional<Address> receivingAddress = getReceivingAddress();
return receivingAddress.isPresent() && receivingAddress.get().equals(address);
return receivingAddress.isPresent() && receivingAddress.get().equals(address);
}

@Override
Expand Down Expand Up @@ -591,14 +610,6 @@ public PreparedCoinapult prepareCoinapultTx(Receiver receiver) throws StandardTr
}
}

public PreparedCoinapult prepareCoinapultTx(Address receivingAddress, ExactFiatValue amountEntered) throws StandardTransactionBuilder.InsufficientFundsException {
if (balanceUSD.confirmed.getValue().compareTo(amountEntered.getValue()) < 0) {
throw new StandardTransactionBuilder.InsufficientFundsException(getSatoshis(amountEntered), 0);
}
return new PreparedCoinapult(receivingAddress, amountEntered);
}


public boolean broadcast(PreparedCoinapult preparedCoinapult) {
try {
final com.coinapult.api.httpclient.Transaction.Json send;
Expand Down Expand Up @@ -635,6 +646,13 @@ public CurrencyBasedBalance getCurrencyBasedBalance() {
return new CurrencyBasedBalance(zero, zero, zero, true);
}

public PreparedCoinapult prepareCoinapultTx(Address receivingAddress, ExactFiatValue amountEntered) throws StandardTransactionBuilder.InsufficientFundsException {
if (balanceUSD.confirmed.getValue().compareTo(amountEntered.getValue()) < 0) {
throw new StandardTransactionBuilder.InsufficientFundsException(getSatoshis(amountEntered), 0);
}
return new PreparedCoinapult(receivingAddress, amountEntered);
}

public boolean setMail(Optional<String> mail) {
if (!mail.isPresent()) {
return false;
Expand All @@ -652,7 +670,7 @@ public boolean setMail(Optional<String> mail) {
public boolean verifyMail(String link, String email) {
try {
EmailAddress.Json result = coinapultClient.verifyMail(link, email);
if (!result.verified){
if (!result.verified) {
logger.logError("Coinapult email error: " + result.error);
}
return result.verified;
Expand Down
17 changes: 15 additions & 2 deletions public/mbw/src/main/java/com/mycelium/wallet/MbwManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ private MbwManager(Context evilContext) {
_walletManager.addObserver(_eventTranslator);
_exchangeRateManager.subscribe(_eventTranslator);
_coinapultManager = createCoinapultManager();
_walletManager.setExtraAccount(_coinapultManager);
setExtraAccount(_coinapultManager);
migrateOldKeys();
createTempWalletManager();

Expand All @@ -271,8 +271,13 @@ private MbwManager(Context evilContext) {
_environment.getBlockExplorerList().get(0).getIdentifier()));
}

public void setExtraAccount(Optional<CoinapultManager> coinapultManager) {
_walletManager.setExtraAccount(coinapultManager);
_hasUsdAccount = null; // invalidate cache
}

private Optional<CoinapultManager> createCoinapultManager() {
if (_walletManager.hasBip32MasterSeed() && _storage.isPairedService("coinapult")) {
if (_walletManager.hasBip32MasterSeed() && _storage.isPairedService(MetadataStorage.PAIRED_SERVICE_COINAPULT)) {
BitidKeyDerivation derivation = new BitidKeyDerivation() {
@Override
public InMemoryPrivateKey deriveKey(int accountIndex, String site) {
Expand Down Expand Up @@ -1211,4 +1216,12 @@ public Cache<String, Object> getBackgroundObjectsCache() {
public void switchServer() {
_environment.getWapiEndpoints().switchToNextEndpoint();
}

Boolean _hasUsdAccount = null;
public boolean hasUsdAccount() {
if (_hasUsdAccount == null){
_hasUsdAccount = getMetadataStorage().isPairedService(MetadataStorage.PAIRED_SERVICE_COINAPULT);
}
return _hasUsdAccount;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -855,7 +855,7 @@ public boolean handle(StringHandlerActivity handlerActivity, String content) {
if (!Bip39.isValidWordList(words)) {
return false;
}
InstantMasterseedActivity.callMe(handlerActivity, words);
InstantMasterseedActivity.callMe(handlerActivity, words, null);
handlerActivity.finishOk();
return true;
}
Expand Down
12 changes: 9 additions & 3 deletions public/mbw/src/main/java/com/mycelium/wallet/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.support.annotation.StringRes;
import android.text.ClipboardManager;
import android.text.format.DateFormat;
import android.view.LayoutInflater;
Expand Down Expand Up @@ -78,8 +79,8 @@
import com.mrd.bitlib.model.Address;
import com.mrd.bitlib.model.NetworkParameters;
import com.mrd.bitlib.util.CoinUtil;
import com.mycelium.wallet.activity.BackupWordListActivity;
import com.mycelium.wallet.activity.AdditionalBackupWarningActivity;
import com.mycelium.wallet.activity.BackupWordListActivity;
import com.mycelium.wallet.activity.export.BackupToPdfActivity;
import com.mycelium.wallet.activity.export.ExportAsQrCodeActivity;
import com.mycelium.wapi.wallet.AesKeyCipher;
Expand All @@ -99,7 +100,12 @@
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.*;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;

@SuppressWarnings("deprecation")
public class Utils {
Expand Down Expand Up @@ -263,7 +269,7 @@ public static void showSimpleMessageDialog(final Context context, String message
* Show a dialog with a buttons that displays a message. Click the message
* or the back button to make it disappear.
*/
public static void showSimpleMessageDialog(final Context context, String message, final Runnable okayRunner, int okayButtonText, final Runnable postRunner) {
public static void showSimpleMessageDialog(final Context context, String message, final Runnable okayRunner, @StringRes int okayButtonText, final Runnable postRunner) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View layout = inflater.inflate(R.layout.simple_message_dialog, null);
AlertDialog.Builder builder = new AlertDialog.Builder(context).setView(layout);
Expand Down
Loading

0 comments on commit fd156f0

Please sign in to comment.