diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 0000000000..8b7f4afdab --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/tangem/data/network/ServerApiElectrum.java b/app/src/main/java/com/tangem/data/network/ServerApiElectrum.java index 732d67c72e..e61d44dff5 100644 --- a/app/src/main/java/com/tangem/data/network/ServerApiElectrum.java +++ b/app/src/main/java/com/tangem/data/network/ServerApiElectrum.java @@ -124,11 +124,16 @@ public class ServerApiElectrum { BitcoinCashNode bitcoinCashNode = BitcoinCashNode.values()[new Random().nextInt(BitcoinCashNode.values().length)]; host = bitcoinCashNode.getHost(); port = bitcoinCashNode.getPort(); + proto = bitcoinCashNode.getProto(); this.host = host; this.port = port; - return doElectrumRequestTcp(electrumRequest, host, port); + if (proto.equals("tcp")) { + return doElectrumRequestTcp(electrumRequest, host, port); + } else { + return doElectrumRequestSsl(electrumRequest, host, port); + } } else if (card.getBlockchain() == Blockchain.Bitcoin) { BitcoinNode bitcoinNode = BitcoinNode.values()[new Random().nextInt(BitcoinNode.values().length)]; @@ -136,15 +141,12 @@ public class ServerApiElectrum { port = bitcoinNode.getPort(); proto = bitcoinNode.getProto(); - if (proto.equals("tcp")) { - this.host = host; - this.port = port; + this.host = host; + this.port = port; + if (proto.equals("tcp")) { return doElectrumRequestTcp(electrumRequest, host, port); } else { - this.host = host; - this.port = port; - return doElectrumRequestSsl(electrumRequest, host, port); } } diff --git a/app/src/main/java/com/tangem/domain/wallet/BCHUtils.java b/app/src/main/java/com/tangem/domain/wallet/BCHUtils.java new file mode 100644 index 0000000000..91da8e43cf --- /dev/null +++ b/app/src/main/java/com/tangem/domain/wallet/BCHUtils.java @@ -0,0 +1,345 @@ +package com.tangem.domain.wallet; + +/** + * Created by Ilia on 29.09.2017. + */ + +import android.util.Log; + +import com.tangem.domain.wallet.btc.BitcoinException; +import com.tangem.domain.wallet.btc.BitcoinOutputStream; +import com.tangem.domain.wallet.btc.BtcData; +import com.tangem.util.CryptoUtil; +import com.tangem.util.FormatUtil; +import com.tangem.tangemcard.util.Util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@SuppressWarnings({"WeakerAccess", "TryWithIdenticalCatches", "unused"}) +public final class BCHUtils { + static final BigInteger LARGEST_PRIVATE_KEY = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16);//SECP256K1_N + public static final long MIN_FEE_PER_KB = 10000; + public static final long MAX_ALLOWED_FEE = FormatUtil.parseValue("0.1"); + public static final long MIN_PRIORITY_FOR_NO_FEE = 57600000; + public static final long MIN_MIN_OUTPUT_VALUE_FOR_NO_FEE = 10000000L; + public static final int MAX_TX_LEN_FOR_NO_FEE = 10000; + public static final float EXPECTED_BLOCKS_PER_DAY = 144.0f;//(expected confirmations per day) + + public static String toHex(byte[] bytes) { + if (bytes == null) { + return ""; + } + final char[] hexArray = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + char[] hexChars = new char[bytes.length * 2]; + int v; + for (int j = 0; j < bytes.length; j++) { + v = bytes[j] & 0xFF; + hexChars[j * 2] = hexArray[v >>> 4]; + hexChars[j * 2 + 1] = hexArray[v & 0x0F]; + } + return new String(hexChars); + } + + public static byte[] buildTXForSign(String myAddress, String outputAddress, String changeAddress, ArrayList unspentOutputs, int currentInputPos, long amount, long change) throws BitcoinException, IOException { + + int inputPos = currentInputPos; + byte[] tx = buildPreimage(outputAddress, changeAddress, unspentOutputs, inputPos, amount, change); + return tx; + } + + public static byte[] buildTXForSend(String outputAddress, String changeAddress, ArrayList unspentOutputs, long amount, long change) throws BitcoinException, IOException { + + int inputPos = -1; + byte[] tx = buildBodyTX(outputAddress, changeAddress, unspentOutputs, inputPos, amount, change); + return tx; + } + + //BIP 143 as reference + script length added + public static byte[] buildPreimage(String outputAddress, String changeAddress, ArrayList unspentOutputs, int inputPos, long amount, long change) throws BitcoinException, IOException { + + //nVersion of the transaction (4-byte little endian) + BitcoinOutputStream forSign = new BitcoinOutputStream(); + //forSign.writeInt32(0x01); + forSign.write(new byte[]{0x02, 0x00, 0x00, 0x00}); // version + + //inputCount + byte inputCount = (byte) unspentOutputs.size(); + + //hashPrevouts (32-byte hash) + ByteArrayOutputStream prevouts = new ByteArrayOutputStream(); + for (int i = 0; i < inputCount; ++i) { + UnspentOutputInfo outPut = unspentOutputs.get(i); + byte[] txHash = BCHUtils.reverse(Util.hexToBytes(outPut.txHashForBuild));//Little-endian txID + byte[] txIndex = BCHUtils.reverse(Util.intToByteArray4(outPut.outputIndex));//Little-endian outputIndex + prevouts.write(txHash); + prevouts.write(txIndex); + } + byte[] hashPrevouts = CryptoUtil.doubleSha256(prevouts.toByteArray()); + forSign.write(hashPrevouts); + + //hashSequence (32-byte hash), ffffffff only + ByteArrayOutputStream sequences = new ByteArrayOutputStream(); + for (int i = 0; i < inputCount; ++i) { + sequences.write(new byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}); + } + byte[] hashSequence = CryptoUtil.doubleSha256(sequences.toByteArray()); + forSign.write(hashSequence); + + //outpoint (32-byte hash + 4-byte little endian) + UnspentOutputInfo outPut = unspentOutputs.get(inputPos); + byte[] txHash = BCHUtils.reverse(Util.hexToBytes(outPut.txHashForBuild));//Little-endian txID + byte[] txIndex = BCHUtils.reverse(Util.intToByteArray4(outPut.outputIndex));//Little-endian outputIndex + forSign.write(txHash); + forSign.write(txIndex); + + //scriptCode of the input (serialized as scripts inside CTxOuts) + byte[] scriptCode = Transaction.Script.buildOutput(changeAddress).bytes; //build change out + byte[] scriptLength = Util.intToByteArray(scriptCode.length); + forSign.write(scriptLength); + forSign.write(scriptCode); + + //value of the output spent by this input (8-byte little endian) + byte[] outValue = BCHUtils.reverse(Util.longToByteArray8(outPut.value)); + forSign.write(outValue); + + //nSequence of the input (4-byte little endian), ffffffff only + forSign.write(new byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}); + + //hashOutputs (32-byte hash) + ByteArrayOutputStream outputs = new ByteArrayOutputStream(); + byte[] sendAmount = BCHUtils.reverse(Util.longToByteArray8(amount)); + byte[] sendScript = Transaction.Script.buildOutput(outputAddress).bytes; // build out + byte[] sendLength = Util.intToByteArray(sendScript.length); + outputs.write(sendAmount); + outputs.write(sendLength); + outputs.write(sendScript); + //output for change (if any) + if (change != 0) { + byte[] changeAmount = BCHUtils.reverse(Util.longToByteArray8(change)); + byte[] changeScript = Transaction.Script.buildOutput(changeAddress).bytes; //build change out + byte[] changeLength = Util.intToByteArray(changeScript.length); + outputs.write(changeAmount); + outputs.write(changeLength); + outputs.write(changeScript); + } + byte[] hashOutputs = CryptoUtil.doubleSha256(outputs.toByteArray()); + forSign.write(hashOutputs); + + //nLocktime of the transaction (4-byte little endian) + forSign.write(new byte[]{0x00, 0x00, 0x00, 0x00}); + + //sighash type of the signature (4-byte little endian) + forSign.write(new byte[]{0x41, 0x00, 0x00, 0x00}); + + byte[] rawData = forSign.toByteArray(); + + Log.e("Sign_TX_Body", BCHUtils.toHex(rawData)); + + return rawData; + + } + public static byte[] buildBodyTX(String outputAddress, String changeAddress, ArrayList unspentOutputs, int inputPos, long amount, long change) throws BitcoinException, IOException { + + //0200000000 + BitcoinOutputStream forSign = new BitcoinOutputStream(); + //forSign.writeInt32(0x01); + forSign.write(new byte[]{0x02, 0x00, 0x00, 0x00}); // version + + //01 + byte inputCount = (byte) unspentOutputs.size(); + forSign.write(inputCount); // input count + //hex str hash prev btc + + for (int i = 0; i < inputCount; ++i) { + UnspentOutputInfo outPut = unspentOutputs.get(i); + int outputIndex = outPut.outputIndex; + byte[] txHash = BCHUtils.reverse(Util.hexToBytes(outPut.txHashForBuild));//Sha256Hash.hash(rawTxByte); + forSign.write(txHash); + forSign.writeInt32(outputIndex); //output index in prev tx + if (inputPos == -1 || i == inputPos) { + // hex str 1976a914....88ac + forSign.write((byte) outPut.scriptForBuild.length); + forSign.write(outPut.scriptForBuild); + } else { + forSign.write(0x00); + } + //ffffffff + forSign.write(new byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}); // sequence + } + + + //02 + byte outputCount = (byte) ((change == 0) ? 1 : 2); // outputCount + forSign.write(outputCount); + + //8 bytes + + forSign.writeInt64(amount); //amount + byte[] sendScript = Transaction.Script.buildOutput(outputAddress).bytes; // build out + //hex str 1976a914....88ac + forSign.write((byte) sendScript.length); + forSign.write(sendScript); + + if (change != 0) { + //8 bytes + forSign.writeInt64(change); // change + //hex str 1976a914....88ac + byte[] chancheScript = Transaction.Script.buildOutput(changeAddress).bytes; //build out + forSign.write((byte) chancheScript.length); + forSign.write(chancheScript); + + } + + //00000000 + forSign.write(new byte[]{0x00, 0x00, 0x00, 0x00}); + + //forSign.write(new byte[]{0x01, 0x00, 0x00, 0x00}); + + byte[] rawData = forSign.toByteArray(); + + Log.e("Sign_TX_Body", BCHUtils.toHex(rawData)); + + return rawData; + } + + public static byte[] buildBodyTX(String outputAddress, String changeAddress, int outputIndex, String prevID, long amount, long change, byte[] script) throws BitcoinException, IOException { + + //0200000000 + BitcoinOutputStream forSign = new BitcoinOutputStream(); + forSign.writeInt32(0x01);//write(new byte[]{0x02, 0x00, 0x00, 0x00}); // version + + //01 + byte inputCount = 1; + forSign.write(inputCount); // input count + //hex str hash prev btc + byte[] txHash = BCHUtils.reverse(Util.hexToBytes(prevID));//Sha256Hash.hash(rawTxByte); + forSign.write(txHash); //previos tx hash + + //00000000 + //byte indexOutput = outputIndex; + forSign.writeInt32(outputIndex/*indexOutput*/); //output index in prev tx + //forSign.write(0x00); + + // hex str 1976a914....88ac + forSign.write((byte) script.length); + forSign.write(script); + + //ffffffff + forSign.write(new byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}); // sequence + + //02 + byte outputCount = (byte) ((change == 0) ? 1 : 2); // outputCount + forSign.write(outputCount); + + //8 bytes + + forSign.writeInt64(amount); //amount + byte[] sendScript = Transaction.Script.buildOutput(outputAddress).bytes; // build out + //hex str 1976a914....88ac + forSign.write((byte) sendScript.length); + forSign.write(sendScript); + + if (change != 0) { + //8 bytes + forSign.writeInt64(change); // change + //hex str 1976a914....88ac + byte[] chancheScript = Transaction.Script.buildOutput(changeAddress).bytes; //build out + forSign.write((byte) chancheScript.length); + forSign.write(chancheScript); + + } + + //00000000 + forSign.write(new byte[]{0x00, 0x00, 0x00, 0x00}); + + byte[] rawData = forSign.toByteArray(); + + //Log.e("Sign_TX_Body", BCHUtils.toHex(rawData)); + return rawData; + } + + public static ArrayList getOutputs(List rawTxList, byte[] outputScriptWeAreAbleToSpend) throws BitcoinException { + ArrayList unspentOutputs = new ArrayList<>(); + + for (BtcData.UnspentTransaction current : rawTxList) { + byte[] rawTxByte = BCHUtils.fromHex(current.Raw); + if (rawTxByte == null || current.Raw.isEmpty()) { + continue; + } + + Transaction baseTx = new Transaction(rawTxByte); + + if (baseTx.inputs.length == 0 || baseTx.outputs.length == 0) + throw new IllegalArgumentException("Unable to decode given transaction"); + + byte[] txHash = BCHUtils.reverse(CryptoUtil.doubleSha256(rawTxByte)); + String txHashForBuild = current.txID; + byte[] sign = null; + + for (int outputIndex = 0; outputIndex < baseTx.outputs.length; outputIndex++) { + Transaction.Output output = baseTx.outputs[outputIndex]; + + // find outputs + if (Arrays.equals(outputScriptWeAreAbleToSpend, output.script.bytes)) { + unspentOutputs.add(new UnspentOutputInfo(txHash, output.script, output.value, outputIndex, -1, txHashForBuild, sign)); + } + } + + } + + return unspentOutputs; + } + + public static byte[] fromHex(String s) { + if (s != null) { + try { + StringBuilder sb = new StringBuilder(s.length()); + for (int i = 0; i < s.length(); i++) { + char ch = s.charAt(i); + if (!Character.isWhitespace(ch)) { + sb.append(ch); + } + } + s = sb.toString(); + int len = s.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + int hi = (Character.digit(s.charAt(i), 16) << 4); + int low = Character.digit(s.charAt(i + 1), 16); + if (hi >= 256 || low < 0 || low >= 16) { + return null; + } + data[i / 2] = (byte) (hi | low); + } + return data; + } catch (Exception ignored) { + } + } + return null; + } + + public static byte[] reverse(byte[] bytes) { + byte[] result = new byte[bytes.length]; + for (int i = 0; i < bytes.length; i++) { + result[i] = bytes[bytes.length - i - 1]; + } + return result; + } + + public static byte[] reverseInPlace(byte[] bytes) { + int len = bytes.length / 2; + for (int i = 0; i < len; i++) { + byte t = bytes[i]; + bytes[i] = bytes[bytes.length - i - 1]; + bytes[bytes.length - i - 1] = t; + } + return bytes; + } + +} + diff --git a/app/src/main/java/com/tangem/domain/wallet/CoinEngine.java b/app/src/main/java/com/tangem/domain/wallet/CoinEngine.java index f93c438f78..ede4dee25f 100644 --- a/app/src/main/java/com/tangem/domain/wallet/CoinEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/CoinEngine.java @@ -3,6 +3,7 @@ package com.tangem.domain.wallet; import android.net.Uri; import android.text.InputFilter; +import com.tangem.tangemcard.data.Blockchain; import com.tangem.tangemcard.reader.CardProtocol; import com.tangem.tangemcard.tasks.SignTask; @@ -237,7 +238,12 @@ public abstract class CoinEngine { public void defineWallet() throws CardProtocol.TangemException { try { - String wallet = calculateAddress(ctx.getCard().getWalletPublicKey()); + String wallet; + if (ctx.getBlockchain() == Blockchain.BitcoinCash) { + wallet = calculateAddress(ctx.getCard().getWalletPublicKeyRar()); + } else { + wallet = calculateAddress(ctx.getCard().getWalletPublicKey()); + } ctx.getCoinData().setWallet(wallet); } catch (Exception e) diff --git a/app/src/main/java/com/tangem/domain/wallet/bch/BitcoinCashNode.kt b/app/src/main/java/com/tangem/domain/wallet/bch/BitcoinCashNode.kt index 7cd8f18c8c..e08f74eacf 100644 --- a/app/src/main/java/com/tangem/domain/wallet/bch/BitcoinCashNode.kt +++ b/app/src/main/java/com/tangem/domain/wallet/bch/BitcoinCashNode.kt @@ -1,8 +1,24 @@ package com.tangem.domain.wallet.bch -enum class BitcoinCashNode(val host: String, val port: Int) { - n1("electrumx-bch.cryptonermal.net", 50001), - n2("abc1.hsmiths.com", 60001), - n3("electrum.imaginary.cash", 50001), - n4("35.157.238.5", 51001), +enum class BitcoinCashNode(val host: String, val port: Int, val proto: String) { + N_001("electrumx.hillsideinternet.com", 50002, "ssl"), + N_002("bch0.kister.net", 50002, "ssl"), + N_003("abc1.hsmiths.com", 60002, "ssl"), + N_004("bch.curalle.ovh", 50002, "ssl"), + N_005("207.180.215.112", 52002, "ssl"), + N_006("bch.imaginary.cash", 50002, "ssl"), + N_007("dedi.jochen-hoenicke.de", 51002, "ssl"), + N_008("crypto.mldlabs.com", 50002, "ssl"), + N_009("bch.electrumx.cash", 50002, "ssl"), + N_010("electroncash.cascharia.com", 50002, "ssl"), + N_011("bch.crypto.mldlabs.com", 50002, "ssl"), + N_012("electron-cash.dragon.zone", 50002, "ssl"), + N_013("electron.coinucopia.io", 50002, "ssl"), + N_014("blackie.c3-soft.com", 50002, "ssl"), + N_015("electroncash.ueo.ch", 51002, "ssl"), + N_016("electrum.imaginary.cash", 50002, "ssl"), + N_017("35.157.238.5", 51002, "ssl"), + N_018("bitcoincash.quangld.com", 50002, "ssl"), + N_019("bch.stitthappens.com", 50002, "ssl"), + N_020("electroncash.dk", 50002, "ssl"), } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/domain/wallet/bch/BtcCashEngine.java b/app/src/main/java/com/tangem/domain/wallet/bch/BtcCashEngine.java index f615742b96..44f98ae69f 100644 --- a/app/src/main/java/com/tangem/domain/wallet/bch/BtcCashEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/bch/BtcCashEngine.java @@ -3,6 +3,7 @@ package com.tangem.domain.wallet.bch; import android.net.Uri; import android.text.InputFilter; +import com.tangem.domain.wallet.BCHUtils; import com.tangem.tangemcard.data.local.PINStorage; import com.tangem.tangemcard.reader.CardProtocol; import com.tangem.tangemcard.reader.TLV; @@ -16,7 +17,6 @@ import com.tangem.tangemcard.data.TangemCard; import com.tangem.domain.wallet.TangemContext; import com.tangem.domain.wallet.Transaction; import com.tangem.domain.wallet.UnspentOutputInfo; -import com.tangem.domain.wallet.BTCUtils; import com.tangem.tangemcard.tasks.SignTask; import com.tangem.util.CryptoUtil; import com.tangem.util.DecimalDigitsInputFilter; @@ -448,7 +448,7 @@ public class BtcCashEngine extends CoinEngine { byte[] outputScriptWeAreAbleToSpend = Transaction.Script.buildOutput(srcLegacyAddress).bytes; // Collect unspent - ArrayList unspentOutputs = BTCUtils.getOutputs(rawTxList, outputScriptWeAreAbleToSpend); + ArrayList unspentOutputs = BCHUtils.getOutputs(rawTxList, outputScriptWeAreAbleToSpend); long fullAmount = 0; for (int i = 0; i < unspentOutputs.size(); ++i) { @@ -477,7 +477,7 @@ public class BtcCashEngine extends CoinEngine { byte[][] bodyDoubleHash= new byte[unspentOutputs.size()][]; for (int i = 0; i < unspentOutputs.size(); ++i) { - txForSign[i] = BTCUtils.buildTXForSign(srcLegacyAddress, destLegacyAddress, srcLegacyAddress, unspentOutputs, i, amount, change); + txForSign[i] = BCHUtils.buildTXForSign(srcLegacyAddress, destLegacyAddress, srcLegacyAddress, unspentOutputs, i, amount, change); bodyHash[i] = Util.calculateSHA256(txForSign[i]); bodyDoubleHash[i] = Util.calculateSHA256(bodyHash[i]); } @@ -531,94 +531,10 @@ public class BtcCashEngine extends CoinEngine { unspentOutputs.get(i).scriptForBuild = DerEncodingUtil.packSignDerBitcoinCash(r, s, pbKey); } - byte[] txForSend=BTCUtils.buildTXForSend(destLegacyAddress, srcLegacyAddress, unspentOutputs, amountFinal, changeFinal); + byte[] txForSend=BCHUtils.buildTXForSend(destLegacyAddress, srcLegacyAddress, unspentOutputs, amountFinal, changeFinal); notifyOnNeedSendPayment(txForSend); } }; } - -// @Override -// public byte[] sign(Amount feeValue, Amount amountValue, boolean IncFee, String destAddress, CardProtocol protocol) throws Exception { -// -// checkBlockchainDataExists(); -// -// CoinEngine engine = CoinEngineFactory.INSTANCE.create(ctx); -// -// String srcLegacyAddress = ((BtcCashEngine)engine).convertToLegacyAddress(ctx.getCoinData().getWallet()); -// String destLegacyAddress = ((BtcCashEngine)engine).convertToLegacyAddress(destAddress); -// byte[] pbKey = ctx.getCard().getWalletPublicKeyRar(); //ALWAYS USING COMPRESS KEY -// -// // Build script for our address -// List rawTxList = coinData.getUnspentTransactions(); -// byte[] outputScriptWeAreAbleToSpend = Transaction.Script.buildOutput(srcLegacyAddress).bytes; -// -// // Collect unspent -// ArrayList unspentOutputs = BTCUtils.getOutputs(rawTxList, outputScriptWeAreAbleToSpend); -// -// long fullAmount = 0; -// for (int i = 0; i < unspentOutputs.size(); ++i) { -// fullAmount += unspentOutputs.get(i).value; -// } -// -// -// long fees = convertToInternalAmount(feeValue).longValueExact(); -// long amount = convertToInternalAmount(amountValue).longValueExact(); -// long change = fullAmount - amount; -// if (IncFee) { -// amount = amount - fees; -// } else { -// change = change - fees; -// } -// -// if (amount + fees > fullAmount) { -// throw new CardProtocol.TangemException_WrongAmount(String.format("Balance (%d) < change (%d) + amount (%d)", fullAmount, change, amount)); -// } -// -// byte[][] dataForSign = new byte[unspentOutputs.size()][]; -// -// for (int i = 0; i < unspentOutputs.size(); ++i) { -// byte[] newTX = BTCUtils.buildTXForSign(srcLegacyAddress, destLegacyAddress, srcLegacyAddress, unspentOutputs, i, amount, change); -// -// byte[] hashData = Util.calculateSHA256(newTX); -// byte[] doubleHashData = Util.calculateSHA256(hashData); -// -// unspentOutputs.get(i).bodyDoubleHash = doubleHashData; -// unspentOutputs.get(i).bodyHash = hashData; -// -// if (ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Raw || ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Raw_Validated_By_Issuer) { -// dataForSign[i] = newTX; -// } else { -// dataForSign[i] = doubleHashData; -// } -// -// } -// -// byte[] signFromCard; -// if (ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Raw || ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Raw_Validated_By_Issuer) { -// ByteArrayOutputStream bs = new ByteArrayOutputStream(); -// if (dataForSign.length > 10) throw new Exception("To much hashes in one transaction!"); -// for (int i = 0; i < dataForSign.length; i++) { -// if (i != 0 && dataForSign[0].length != dataForSign[i].length) -// throw new Exception("Hashes length must be identical!"); -// bs.write(dataForSign[i]); -// } -// signFromCard = protocol.run_SignRaw(PINStorage.getPIN2(), "sha-256x2", bs.toByteArray(), null, null, null).getTLV(TLV.Tag.TAG_Signature).Value; -// } else { -// //ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer -// //ctx.getCard().getIssuer() -// signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), dataForSign, null, null, null).getTLV(TLV.Tag.TAG_Signature).Value; -// // TODO slice signFromCard to hashes.length parts -// } -// -// for (int i = 0; i < unspentOutputs.size(); ++i) { -// BigInteger r = new BigInteger(1, Arrays.copyOfRange(signFromCard, i * 64, 32 + i * 64)); -// BigInteger s = new BigInteger(1, Arrays.copyOfRange(signFromCard, 32 + i * 64, 64 + i * 64)); -// s = CryptoUtil.toCanonicalised(s); -// -// unspentOutputs.get(i).scriptForBuild = DerEncodingUtil.packSignDerBitcoinCash(r, s, pbKey); -// } -// -// return BTCUtils.buildTXForSend(destLegacyAddress, srcLegacyAddress, unspentOutputs, amount, change); -// } } diff --git a/app/src/main/java/com/tangem/domain/wallet/btc/BitcoinOutputStream.java b/app/src/main/java/com/tangem/domain/wallet/btc/BitcoinOutputStream.java index 243eb7ca10..ced90a20d3 100644 --- a/app/src/main/java/com/tangem/domain/wallet/btc/BitcoinOutputStream.java +++ b/app/src/main/java/com/tangem/domain/wallet/btc/BitcoinOutputStream.java @@ -4,6 +4,8 @@ package com.tangem.domain.wallet.btc; * Created by Ilia on 29.09.2017. */ +import com.tangem.domain.wallet.Transaction; + import java.io.ByteArrayOutputStream; @SuppressWarnings("WeakerAccess") @@ -40,4 +42,7 @@ public final class BitcoinOutputStream extends ByteArrayOutputStream { writeInt64(value); } } + + public void write(Transaction.Script script) { + } } \ No newline at end of file