@Nullable @Override public VerificationException call() throws Exception { try { ListIterator<Script> prevOutIt = prevOutScripts.listIterator(); for (int index = 0; index < tx.getInputs().size(); index++) { Coin value = tx.getInput(index).getConnectedOutput() != null ? tx.getInput(index).getConnectedOutput().getValue() : Coin.ZERO; tx.getInputs().get(index).getScriptSig().correctlySpends(tx, index, prevOutIt.next(), value, verifyFlags); } } catch (VerificationException e) { return e; } return null; } }
/** * Calculates the sum of the inputs that are spending coins with keys in the wallet. This requires the * transactions sending coins to those keys to be in the wallet. This method will not attempt to download the * blocks containing the input transactions if the key is in the wallet but the transactions are not. * * @return sum of the inputs that are spending coins with keys in the wallet */ public Coin getValueSentFromMe(TransactionBag wallet) throws ScriptException { // This is tested in WalletTest. Coin v = Coin.ZERO; for (TransactionInput input : inputs) { // This input is taking value from a transaction in our wallet. To discover the value, // we must find the connected transaction. TransactionOutput connected = input.getConnectedOutput(wallet.getTransactionPool(Pool.UNSPENT)); if (connected == null) connected = input.getConnectedOutput(wallet.getTransactionPool(Pool.SPENT)); if (connected == null) connected = input.getConnectedOutput(wallet.getTransactionPool(Pool.PENDING)); if (connected == null) continue; // The connected output may be the change to the sender of a previous input sent to this wallet. In this // case we ignore it. if (!connected.isMineOrWatched(wallet)) continue; v = v.add(connected.getValue()); } return v; }
/** * Calculates the sum of the inputs that are spending coins with keys in the wallet. This requires the * transactions sending coins to those keys to be in the wallet. This method will not attempt to download the * blocks containing the input transactions if the key is in the wallet but the transactions are not. * * @return sum of the inputs that are spending coins with keys in the wallet */ public Coin getValueSentFromMe(TransactionBag wallet) throws ScriptException { // This is tested in WalletTest. Coin v = Coin.ZERO; for (TransactionInput input : inputs) { // This input is taking value from a transaction in our wallet. To discover the value, // we must find the connected transaction. TransactionOutput connected = input.getConnectedOutput(wallet.getTransactionPool(Pool.UNSPENT)); if (connected == null) connected = input.getConnectedOutput(wallet.getTransactionPool(Pool.SPENT)); if (connected == null) connected = input.getConnectedOutput(wallet.getTransactionPool(Pool.PENDING)); if (connected == null) continue; // The connected output may be the change to the sender of a previous input sent to this wallet. In this // case we ignore it. if (!connected.isMineOrWatched(wallet)) continue; v = v.add(connected.getValue()); } return v; }
/** * Calculates the sum of the inputs that are spending coins with keys in the wallet. This requires the * transactions sending coins to those keys to be in the wallet. This method will not attempt to download the * blocks containing the input transactions if the key is in the wallet but the transactions are not. * * @return sum of the inputs that are spending coins with keys in the wallet */ public Coin getValueSentFromMe(TransactionBag wallet) throws ScriptException { // This is tested in WalletTest. Coin v = Coin.ZERO; for (TransactionInput input : inputs) { // This input is taking value from a transaction in our wallet. To discover the value, // we must find the connected transaction. TransactionOutput connected = input.getConnectedOutput(wallet.getTransactionPool(Pool.UNSPENT)); if (connected == null) connected = input.getConnectedOutput(wallet.getTransactionPool(Pool.SPENT)); if (connected == null) connected = input.getConnectedOutput(wallet.getTransactionPool(Pool.PENDING)); if (connected == null) continue; // The connected output may be the change to the sender of a previous input sent to this wallet. In this // case we ignore it. if (!connected.isMineOrWatched(wallet)) continue; v = v.add(connected.getValue()); } return v; }
/** * Calculates the sum of the inputs that are spending coins with keys in the wallet. This requires the * transactions sending coins to those keys to be in the wallet. This method will not attempt to download the * blocks containing the input transactions if the key is in the wallet but the transactions are not. * * @return sum of the inputs that are spending coins with keys in the wallet */ public Coin getValueSentFromMe(TransactionBag wallet) throws ScriptException { // This is tested in WalletTest. Coin v = Coin.ZERO; for (TransactionInput input : inputs) { // This input is taking value from a transaction in our wallet. To discover the value, // we must find the connected transaction. TransactionOutput connected = input.getConnectedOutput(wallet.getTransactionPool(Pool.UNSPENT)); if (connected == null) connected = input.getConnectedOutput(wallet.getTransactionPool(Pool.SPENT)); if (connected == null) connected = input.getConnectedOutput(wallet.getTransactionPool(Pool.PENDING)); if (connected == null) continue; // The connected output may be the change to the sender of a previous input sent to this wallet. In this // case we ignore it. if (!connected.isMineOrWatched(wallet)) continue; v = v.add(connected.getValue()); } return v; }
@Override public boolean isValid() { for (TransactionInput input : this.bitcoinj.getInputs()) { TransactionOutput output = input.getConnectedOutput(); if (input.getScriptSig() == null) { return false; } try { input.verify(output); } catch (VerificationException e) { return false; } } return true; }
/** * @param unsignedTx The unsigned transaction (expect OP_0 in place of signatures) * @param wallet The wallet * * @return The receiving address path map linking the tx input index to a deterministic path */ private Map<Integer, ImmutableList<ChildNumber>> buildReceivingAddressPathMap(Transaction unsignedTx, Wallet wallet) { log.debug("Building Receiving address path map for transaction {}", unsignedTx); Map<Integer, ImmutableList<ChildNumber>> receivingAddressPathMap = Maps.newHashMap(); // Examine the Tx inputs to determine receiving addresses in use for (int i = 0; i < unsignedTx.getInputs().size(); i++) { TransactionInput input = unsignedTx.getInput(i); // Get input script from the connected transaction output script Script script = input.getScriptSig(); TransactionOutput connectedTransactionOutput = input.getConnectedOutput(); log.debug("Connected transaction output {}", connectedTransactionOutput); if (connectedTransactionOutput != null) { byte[] pubKeyHash = connectedTransactionOutput.getScriptPubKey().getPubKeyHash(); log.debug("Connected transaction pubKeyHash {}", Utils.HEX.encode(pubKeyHash)); DeterministicKey keyFromPubKey = wallet.getActiveKeychain().findKeyFromPubHash(pubKeyHash); Preconditions.checkNotNull(keyFromPubKey, "Could not find deterministic key from given pubKeyHash. Input script index: " + i); receivingAddressPathMap.put(i, keyFromPubKey.getPath()); } else { log.debug("Could not parse tx input script '{}'", script.toString()); } } return receivingAddressPathMap; }
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)); } }
if (input.getConnectedOutput().isMine(this)) { candidates.remove(input.getConnectedOutput());
@Override public boolean signInputs(ProposedTransaction propTx, KeyBag keyBag) { assertEquals(propTx.partialTx.getInputs().size(), propTx.keyPaths.size()); List<ChildNumber> externalZeroLeaf = ImmutableList.<ChildNumber>builder() .addAll(DeterministicKeyChain.ACCOUNT_ZERO_PATH) .addAll(DeterministicKeyChain.EXTERNAL_SUBPATH).add(ChildNumber.ZERO).build(); for (TransactionInput input : propTx.partialTx.getInputs()) { List<ChildNumber> keypath = propTx.keyPaths.get(input.getConnectedOutput().getScriptPubKey()); assertNotNull(keypath); assertEquals(externalZeroLeaf, keypath); } return true; } };
TransactionOutput prevOut = in.getConnectedOutput(); if (prevOut != null && prevOut.isMine(this)) { txOwnedInputsTotal = txOwnedInputsTotal.add(prevOut.getValue());
public org.bitcoinj.core.Transaction signTransaction(org.bitcoinj.core.Transaction signTx, List<Bytestring> programSignatures) { List<Script> inputScripts = new LinkedList<>(); for (Bytestring programs : programSignatures) { if (!inputScripts.add(bytestringToInputScript(programs))) { return null; } } for (Script inScript : inputScripts) { for (int i = 0; i < signTx.getInputs().size(); i++) { TransactionInput input = signTx.getInput(i); TransactionOutput connectedOutput = input.getConnectedOutput(); byte[] originalScript = input.getScriptBytes().clone(); input.setScriptSig(inScript); try { input.verify(connectedOutput); break; } catch (VerificationException e) { input.setScriptSig(this.bytestringToInputScript(new Bytestring(originalScript))); if (i == signTx.getInputs().size() - 1) { return null; } } } } return signTx; }
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); }
/** * Returns the amount of bitcoin ever received via output. <b>This is not the balance!</b> If an output spends from a * transaction whose inputs are also to our wallet, the input amounts are deducted from the outputs contribution, with a minimum of zero * contribution. The idea behind this is we avoid double counting money sent to us. * @return the total amount of satoshis received, regardless of whether it was spent or not. */ public Coin getTotalReceived() { Coin total = Coin.ZERO; // Include outputs to us if they were not just change outputs, ie the inputs to us summed to less // than the outputs to us. for (Transaction tx: transactions.values()) { Coin txTotal = Coin.ZERO; for (TransactionOutput output : tx.getOutputs()) { if (output.isMine(this)) { txTotal = txTotal.add(output.getValue()); } } for (TransactionInput in : tx.getInputs()) { TransactionOutput prevOut = in.getConnectedOutput(); if (prevOut != null && prevOut.isMine(this)) { txTotal = txTotal.subtract(prevOut.getValue()); } } if (txTotal.isPositive()) { total = total.add(txTotal); } } return total; }
/** * Returns the amount of bitcoin ever received via output. <b>This is not the balance!</b> If an output spends from a * transaction whose inputs are also to our wallet, the input amounts are deducted from the outputs contribution, with a minimum of zero * contribution. The idea behind this is we avoid double counting money sent to us. * @return the total amount of satoshis received, regardless of whether it was spent or not. */ public Coin getTotalReceived() { Coin total = Coin.ZERO; // Include outputs to us if they were not just change outputs, ie the inputs to us summed to less // than the outputs to us. for (Transaction tx: transactions.values()) { Coin txTotal = Coin.ZERO; for (TransactionOutput output : tx.getOutputs()) { if (output.isMine(this)) { txTotal = txTotal.add(output.getValue()); } } for (TransactionInput in : tx.getInputs()) { TransactionOutput prevOut = in.getConnectedOutput(); if (prevOut != null && prevOut.isMine(this)) { txTotal = txTotal.subtract(prevOut.getValue()); } } if (txTotal.isPositive()) { total = total.add(txTotal); } } return total; }
/** * Returns the amount of bitcoin ever received via output. <b>This is not the balance!</b> If an output spends from a * transaction whose inputs are also to our wallet, the input amounts are deducted from the outputs contribution, with a minimum of zero * contribution. The idea behind this is we avoid double counting money sent to us. * @return the total amount of satoshis received, regardless of whether it was spent or not. */ public Coin getTotalReceived() { Coin total = Coin.ZERO; // Include outputs to us if they were not just change outputs, ie the inputs to us summed to less // than the outputs to us. for (Transaction tx: transactions.values()) { Coin txTotal = Coin.ZERO; for (TransactionOutput output : tx.getOutputs()) { if (output.isMine(this)) { txTotal = txTotal.add(output.getValue()); } } for (TransactionInput in : tx.getInputs()) { TransactionOutput prevOut = in.getConnectedOutput(); if (prevOut != null && prevOut.isMine(this)) { txTotal = txTotal.subtract(prevOut.getValue()); } } if (txTotal.isPositive()) { total = total.add(txTotal); } } return total; }
/** * Returns the amount of bitcoin ever received via output. <b>This is not the balance!</b> If an output spends from a * transaction whose inputs are also to our wallet, the input amounts are deducted from the outputs contribution, with a minimum of zero * contribution. The idea behind this is we avoid double counting money sent to us. * @return the total amount of satoshis received, regardless of whether it was spent or not. */ public Coin getTotalReceived() { Coin total = Coin.ZERO; // Include outputs to us if they were not just change outputs, ie the inputs to us summed to less // than the outputs to us. for (Transaction tx: transactions.values()) { Coin txTotal = Coin.ZERO; for (TransactionOutput output : tx.getOutputs()) { if (output.isMine(this)) { txTotal = txTotal.add(output.getValue()); } } for (TransactionInput in : tx.getInputs()) { TransactionOutput prevOut = in.getConnectedOutput(); if (prevOut != null && prevOut.isMine(this)) { txTotal = txTotal.subtract(prevOut.getValue()); } } if (txTotal.isPositive()) { total = total.add(txTotal); } } return total; }
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); }
/** * 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; }
@SuppressWarnings("ConstantConditions") public void completeTxPartiallySigned(Wallet.MissingSigsMode missSigMode, byte[] expectedSig) throws Exception { // Check the wallet will write dummy scriptSigs for inputs that we have only pubkeys for without the privkey. ECKey priv = new ECKey(); ECKey pub = ECKey.fromPublicOnly(priv.getPubKeyPoint()); wallet.importKey(pub); ECKey priv2 = wallet.freshReceiveKey(); // Send three transactions, with one being an address type and the other being a raw CHECKSIG type pubkey only, // and the final one being a key we do have. We expect the first two inputs to be dummy values and the last // to be signed correctly. Transaction t1 = sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, CENT, pub.toAddress(PARAMS)); Transaction t2 = sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, CENT, pub); Transaction t3 = sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, CENT, priv2); SendRequest req = SendRequest.emptyWallet(OTHER_ADDRESS); req.missingSigsMode = missSigMode; wallet.completeTx(req); byte[] dummySig = TransactionSignature.dummy().encodeToBitcoin(); // Selected inputs can be in any order. for (int i = 0; i < req.tx.getInputs().size(); i++) { TransactionInput input = req.tx.getInput(i); if (input.getConnectedOutput().getParentTransaction().equals(t1)) { assertArrayEquals(expectedSig, input.getScriptSig().getChunks().get(0).data); } else if (input.getConnectedOutput().getParentTransaction().equals(t2)) { assertArrayEquals(expectedSig, input.getScriptSig().getChunks().get(0).data); } else if (input.getConnectedOutput().getParentTransaction().equals(t3)) { input.getScriptSig().correctlySpends(req.tx, i, t3.getOutput(0).getScriptPubKey()); } } assertTrue(TransactionSignature.isEncodingCanonical(dummySig)); }