private void signMultisigInput(Transaction tx, Transaction.SigHash hashType, boolean anyoneCanPay, @Nullable KeyParameter userKey) { TransactionSignature signature = tx.calculateSignature(0, serverKey, userKey, getContractScript(), hashType, anyoneCanPay); byte[] mySig = signature.encodeToBitcoin(); Script scriptSig = ScriptBuilder.createMultiSigInputScriptBytes(ImmutableList.of(bestValueSignature, mySig)); tx.getInput(0).setScriptSig(scriptSig); }
private void signMultisigInput(Transaction tx, Transaction.SigHash hashType, boolean anyoneCanPay, @Nullable KeyParameter userKey) { TransactionSignature signature = tx.calculateSignature(0, serverKey, userKey, getContractScript(), hashType, anyoneCanPay); byte[] mySig = signature.encodeToBitcoin(); Script scriptSig = ScriptBuilder.createMultiSigInputScriptBytes(ImmutableList.of(bestValueSignature, mySig)); tx.getInput(0).setScriptSig(scriptSig); }
private void signMultisigInput(Transaction tx, Transaction.SigHash hashType, boolean anyoneCanPay) { TransactionSignature signature = tx.calculateSignature(0, serverKey, getContractScript(), hashType, anyoneCanPay); byte[] mySig = signature.encodeToBitcoin(); Script scriptSig = ScriptBuilder.createMultiSigInputScriptBytes(ImmutableList.of(bestValueSignature, mySig)); tx.getInput(0).setScriptSig(scriptSig); }
private static void addOutputs(final Transaction outputTransaction, final KeyBag bag) throws ScriptException { int numInputs = outputTransaction.getInputs().size(); for (int i = 0; i < numInputs; i++) { TransactionInput txIn = outputTransaction.getInput(i); Script scriptPubKey = txIn.getConnectedOutput().getScriptPubKey(); RedeemData redeemData = txIn.getConnectedRedeemData(bag); checkNotNull(redeemData, "Transaction exists in wallet that we cannot redeem: %s", txIn.getOutpoint().getHash()); txIn.setScriptSig(scriptPubKey.createEmptyInputScript(redeemData.keys.get(0), redeemData.redeemScript)); } }
private void signP2SHInput(Transaction tx, Transaction.SigHash hashType, boolean anyoneCanPay, @Nullable KeyParameter userKey) { TransactionSignature signature = tx.calculateSignature(0, serverKey, userKey, createP2SHRedeemScript(), hashType, anyoneCanPay); byte[] mySig = signature.encodeToBitcoin(); Script scriptSig = ScriptBuilder.createCLTVPaymentChannelP2SHInput(bestValueSignature, mySig, createP2SHRedeemScript()); tx.getInput(0).setScriptSig(scriptSig); }
private void signP2SHInput(Transaction tx, Transaction.SigHash hashType, boolean anyoneCanPay, @Nullable KeyParameter userKey) { TransactionSignature signature = tx.calculateSignature(0, serverKey, userKey, createP2SHRedeemScript(), hashType, anyoneCanPay); byte[] mySig = signature.encodeToBitcoin(); Script scriptSig = ScriptBuilder.createCLTVPaymentChannelP2SHInput(bestValueSignature, mySig, createP2SHRedeemScript()); tx.getInput(0).setScriptSig(scriptSig); }
/** * Adds a new and fully signed input for the given parameters. Note that this method is <b>not</b> thread safe * and requires external synchronization. Please refer to general documentation on Bitcoin scripting and contracts * to understand the values of sigHash and anyoneCanPay: otherwise you can use the other form of this method * that sets them to typical defaults. * * @throws ScriptException if the scriptPubKey is not a pay to address or pay to pubkey script. */ public TransactionInput addSignedInput(TransactionOutPoint prevOut, Script scriptPubKey, ECKey sigKey, SigHash sigHash, boolean anyoneCanPay) throws ScriptException { // Verify the API user didn't try to do operations out of order. checkState(!outputs.isEmpty(), "Attempting to sign tx without outputs."); TransactionInput input = new TransactionInput(params, this, new byte[]{}, prevOut); addInput(input); Sha256Hash hash = hashForSignature(inputs.size() - 1, scriptPubKey, sigHash, anyoneCanPay); ECKey.ECDSASignature ecSig = sigKey.sign(hash); TransactionSignature txSig = new TransactionSignature(ecSig, sigHash, anyoneCanPay, false); if (scriptPubKey.isSentToRawPubKey()) input.setScriptSig(ScriptBuilder.createInputScript(txSig)); else if (scriptPubKey.isSentToAddress()) input.setScriptSig(ScriptBuilder.createInputScript(txSig, sigKey)); else throw new ScriptException("Don't know how to sign for this kind of scriptPubKey: " + scriptPubKey); return input; } /**
/** * Adds a new and fully signed input for the given parameters. Note that this method is <b>not</b> thread safe * and requires external synchronization. Please refer to general documentation on Bitcoin scripting and contracts * to understand the values of sigHash and anyoneCanPay: otherwise you can use the other form of this method * that sets them to typical defaults. * * @throws ScriptException if the scriptPubKey is not a pay to address or pay to pubkey script. */ public TransactionInput addSignedInput(TransactionOutPoint prevOut, Script scriptPubKey, ECKey sigKey, SigHash sigHash, boolean anyoneCanPay, boolean forkId) throws ScriptException { // Verify the API user didn't try to do operations out of order. checkState(!outputs.isEmpty(), "Attempting to sign tx without outputs."); TransactionInput input = new TransactionInput(params, this, new byte[]{}, prevOut); addInput(input); Sha256Hash hash = forkId ? hashForSignatureWitness(inputs.size() -1, scriptPubKey, prevOut.getConnectedOutput().getValue(), sigHash, anyoneCanPay) : hashForSignature(inputs.size() - 1, scriptPubKey, sigHash, anyoneCanPay); ECKey.ECDSASignature ecSig = sigKey.sign(hash); TransactionSignature txSig = new TransactionSignature(ecSig, sigHash, anyoneCanPay, forkId); if (scriptPubKey.isSentToRawPubKey()) input.setScriptSig(ScriptBuilder.createInputScript(txSig)); else if (scriptPubKey.isSentToAddress()) input.setScriptSig(ScriptBuilder.createInputScript(txSig, sigKey)); else throw new ScriptException("Don't know how to sign for this kind of scriptPubKey: " + scriptPubKey); return input; }
boolean addSig(final TransactionInput vin) { for(DarkSendEntryVin s : sev) { if(s.vin.getOutpoint().equals(vin.getOutpoint()) && s.vin.getSequenceNumber() == vin.getSequenceNumber()){ if(s.isSigSet){return false;} s.vin.setScriptSig(vin.getScriptSig()); //TODO: ???? s.vin.prevPubKey = vin.prevPubKey; s.isSigSet = true; return true; } } return false; }
private void signP2SHInput(Transaction tx, Transaction.SigHash hashType, boolean anyoneCanPay) { TransactionSignature signature = tx.calculateSignature(0, serverKey, createP2SHRedeemScript(), hashType, anyoneCanPay); byte[] mySig = signature.encodeToBitcoin(); Script scriptSig = ScriptBuilder.createCLTVPaymentChannelP2SHInput(bestValueSignature, mySig, createP2SHRedeemScript()); tx.getInput(0).setScriptSig(scriptSig); }
private static Transaction signTransaction (Transaction transaction, Wallet wallet) { //TODO: Currently only working if we have P2PKH outputs in our wallet int j = 0; for (int i = 0; i < transaction.getInputs().size(); ++i) { TransactionInput input = transaction.getInput(i); Optional<TransactionOutput> optional = wallet.calculateAllSpendCandidates().stream().filter(out -> input.getOutpoint().equals(out.getOutPointFor())).findAny(); if (optional.isPresent()) { TransactionOutput output = optional.get(); Address address = output.getAddressFromP2PKHScript(Constants.getNetwork()); //Only sign P2PKH and only those that we possess the key for.. if (address != null) { ECKey key = wallet.findKeyFromPubHash(address.getHash160()); if (key != null) { TransactionSignature sig = Tools.getSignature(transaction, i, output, key); byte[] s = sig.encodeToBitcoin(); ScriptBuilder builder = new ScriptBuilder(); builder.data(s); builder.data(key.getPubKey()); transaction.getInput(i).setScriptSig(builder.build()); } } } } return transaction; }
private void signMultisigInput(Transaction tx, Transaction.SigHash hashType, boolean anyoneCanPay) { //TransactionSignature signature = tx.calculateSignature(0, serverKey, getContractScript(), hashType, anyoneCanPay, true); TransactionSignature signature = tx.getVersion() >= Transaction.FORKID_VERSION ? tx.calculateWitnessSignature(0, serverKey, getContractScript(), tx.getInput(0).getConnectedOutput().getValue(), Transaction.SigHash.NONE, true): tx.calculateSignature(0, serverKey, getContractScript(), hashType, true); byte[] mySig = signature.encodeToBitcoin(); Script scriptSig = ScriptBuilder.createMultiSigInputScriptBytes(ImmutableList.of(bestValueSignature, mySig)); tx.getInput(0).setScriptSig(scriptSig); }
/** * These constants are a part of a scriptSig signature on the inputs. They define the details of how a * transaction can be redeemed, specifically, they control how the hash of the transaction is calculated. */ public enum SigHash { ALL(1), NONE(2), SINGLE(3), ANYONECANPAY(0x80), // Caution: Using this type in isolation is non-standard. Treated similar to ANYONECANPAY_ALL. ANYONECANPAY_ALL(0x81), ANYONECANPAY_NONE(0x82), ANYONECANPAY_SINGLE(0x83), UNSET(0); // Caution: Using this type in isolation is non-standard. Treated similar to ALL. public final int value; /** * @param value */ private SigHash(final int value) { this.value = value; } /** * @return the value as a byte */ public byte byteValue() { return (byte) this.value; } }
private void processChannelClose (LNCloseAMessage message) { checkClosingMessage(message); Transaction transaction = getClosingTransaction(channel.channelStatus, message.feePerByte); List<TransactionSignature> signatures = getTransactionSignatures(transaction); isBlocked = true; Channel channel = getChannel(); channel.isReady = false; channel.closingSignatures = message.getSignatureList(); dbHandler.updateChannel(channel); if (channel.phase != CLOSE_REQUESTED_SERVER) { channel.phase = CLOSE_REQUESTED_CLIENT; sendCloseMessage(signatures); //Okay, so the other party sent us correct signatures to close down the channel.. } Script inputScript = ScriptTools.getCommitInputScript( message.getSignatureList().get(0).encodeToBitcoin(), signatures.get(0).encodeToBitcoin(), channel.keyClient, channel.keyServer); transaction.getInput(0).setScriptSig(inputScript); blockchainHelper.broadcastTransaction(transaction); onChannelClose(); }
/** * Takes in a transaction and a private key and returns a signature (if possible) * as a Bytestring object. */ public Bytestring getSignature(org.bitcoinj.core.Transaction signTx, ECKey privKey) { org.bitcoinj.core.Transaction copyTx = signTx; for (int i = 0; i < copyTx.getInputs().size(); i++) { TransactionInput input = copyTx.getInput(i); TransactionOutput connectedOutput = input.getConnectedOutput(); Sha256Hash hash = copyTx.hashForSignature(i, connectedOutput.getScriptPubKey(), org.bitcoinj.core.Transaction.SigHash.ALL, false); ECKey.ECDSASignature ecSig = privKey.sign(hash); TransactionSignature txSig = new TransactionSignature(ecSig, org.bitcoinj.core.Transaction.SigHash.ALL, false); byte[] originalScript = input.getScriptBytes().clone(); Script inputScript = ScriptBuilder.createInputScript(txSig, ECKey.fromPublicOnly(privKey.getPubKey())); input.setScriptSig(inputScript); try { input.verify(connectedOutput); return new Bytestring(inputScript.getProgram()); } catch (VerificationException e) { input.setScriptSig(this.bytestringToInputScript(new Bytestring(originalScript))); } } return null; }
private void addOnlyInputToTransaction(Transaction t, TransactionOutPointWithValue prevOut, long sequence) throws ScriptException { TransactionInput input = new TransactionInput(params, t, new byte[]{}, prevOut.outpoint); input.setSequenceNumber(sequence); t.addInput(input); if (prevOut.scriptPubKey.getChunks().get(0).equalsOpCode(OP_TRUE)) { input.setScriptSig(new ScriptBuilder().op(OP_1).build()); } else { // Sign input checkState(prevOut.scriptPubKey.isSentToRawPubKey()); Sha256Hash hash = t.hashForSignature(0, prevOut.scriptPubKey, SigHash.ALL, false); input.setScriptSig(ScriptBuilder.createInputScript( new TransactionSignature(coinbaseOutKey.sign(hash), SigHash.ALL, false)) ); } }
private void signP2SHInput(Transaction tx, Transaction.SigHash hashType, boolean anyoneCanPay) { TransactionSignature signature = tx.getVersion() >= Transaction.FORKID_VERSION ? tx.calculateWitnessSignature(0, serverKey, createP2SHRedeemScript(), tx.getInput(0).getConnectedOutput().getValue(), hashType, anyoneCanPay): tx.calculateSignature(0, serverKey, createP2SHRedeemScript(), hashType, anyoneCanPay); byte[] mySig = signature.encodeToBitcoin(); Script scriptSig = ScriptBuilder.createCLTVPaymentChannelP2SHInput(bestValueSignature, mySig, createP2SHRedeemScript()); tx.getInput(0).setScriptSig(scriptSig); }
@Test public void testPrioSizeCalc() throws Exception { Transaction tx1 = FakeTxBuilder.createFakeTx(PARAMS, Coin.COIN, ADDRESS); int size1 = tx1.getMessageSize(); int size2 = tx1.getMessageSizeForPriorityCalc(); assertEquals(113, size1 - size2); tx1.getInput(0).setScriptSig(new Script(new byte[109])); assertEquals(78, tx1.getMessageSizeForPriorityCalc()); tx1.getInput(0).setScriptSig(new Script(new byte[110])); assertEquals(78, tx1.getMessageSizeForPriorityCalc()); tx1.getInput(0).setScriptSig(new Script(new byte[111])); assertEquals(79, tx1.getMessageSizeForPriorityCalc()); }
@Test public void testSigning() throws AddressFormatException { NetworkParameters netParams = TestNet3Params.get(); HexBinaryAdapter adapter = new HexBinaryAdapter(); Context context = Context.getOrCreate(netParams); byte[] bx = adapter.unmarshal("0100000001bd5ee90ffe5eedd67c09c3bb348dd7dc1308800eb221b1c92dda651010519ba3010000006a4730440220467868c0b2ed001a915cca5269b928698bee8aba4fe454e1d775070d9e4041cb02205d1c979dbc75e5dc656c4e9d5969d716a383797bd5ad5df79a13d0d6e3f51ccb012102403adb7674f25212bc8cf4a97797154a4980c60e9f328c90300b71a8a04389c7ffffffff024088db60000000001976a914990628d3670f439a5f9e0dfa6492b8bbf3b3fa1b88ac76cf6edd050000001976a914b679378d01ee7203a454bca2ad25698ef23a056388ac00000000"); org.bitcoinj.core.Transaction testbx = new org.bitcoinj.core.Transaction(netParams, bx); org.bitcoinj.core.Transaction tx = new org.bitcoinj.core.Transaction(netParams); tx.addOutput(org.bitcoinj.core.Coin.SATOSHI.multiply(testbx.getOutput(0).getValue().value - 50000l), new Address(netParams, "mobDb19geJ66kkQnsSYvN9PNEKNDiNBHEp")); System.out.println(testbx.getOutput(0)); tx.addInput(testbx.getOutput(0)); String seckey = "3EC95EBFEDCF77373BABA0DE345A0962E51344CD2D0C8DBDF93AEFD0B66BE240"; byte[] privkey = Hex.decode(seckey); ECKey ecPriv = ECKey.fromPrivate(privkey); Sha256Hash hash2 = tx.hashForSignature(0, testbx.getOutput(0).getScriptPubKey().getProgram(), Transaction.SigHash.ALL, false); ECKey.ECDSASignature ecSig = ecPriv.sign(hash2); TransactionSignature txSig = new TransactionSignature(ecSig, Transaction.SigHash.ALL, false); Script inputScript = ScriptBuilder.createInputScript(txSig, ECKey.fromPublicOnly(ecPriv.getPubKey())); tx.getInput(0).setScriptSig(inputScript); String hexBin = DatatypeConverter.printHexBinary(tx.bitcoinSerialize()); System.out.println(hexBin); tx.getInput(0).verify(testbx.getOutput(0)); // SUCCESSFULLY BROADCAST WOO! }
/** * Create a fake TX of sufficient realism to exercise the unit tests. Two outputs, one to us, one to somewhere * else to simulate change. There is one random input. */ public static Transaction createFakeTxWithChangeAddress(NetworkParameters params, Coin value, Address to, Address changeOutput) { Transaction t = new Transaction(params); TransactionOutput outputToMe = new TransactionOutput(params, t, value, to); t.addOutput(outputToMe); TransactionOutput change = new TransactionOutput(params, t, valueOf(1, 11), changeOutput); t.addOutput(change); // Make a previous tx simply to send us sufficient coins. This prev tx is not really valid but it doesn't // matter for our purposes. Transaction prevTx = new Transaction(params); TransactionOutput prevOut = new TransactionOutput(params, prevTx, value, to); prevTx.addOutput(prevOut); // Connect it. t.addInput(prevOut).setScriptSig(ScriptBuilder.createInputScript(TransactionSignature.dummy())); // Fake signature. // Serialize/deserialize to ensure internal state is stripped, as if it had been read from the wire. return roundTripTransaction(params, t); }