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; }
DarkSendEntryVin(NetworkParameters params) { isSigSet = false; vin = new TransactionInput(params, null, null); //need to set later } }
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)); } }
@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; }
/** * For a connected transaction, runs the script against the connected pubkey and verifies they are correct. * @throws ScriptException if the script did not verify. * @throws VerificationException If the outpoint doesn't match the given output. */ public void verify() throws VerificationException { final Transaction fromTx = getOutpoint().fromTx; long spendingIndex = getOutpoint().getIndex(); checkNotNull(fromTx, "Not connected"); final TransactionOutput output = fromTx.getOutput((int) spendingIndex); verify(output); }
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; }
/** * Returns the connected transaction, assuming the input was connected with * {@link TransactionInput#connect(TransactionOutput)} or variants at some point. If it wasn't connected, then * this method returns null. */ @Nullable public Transaction getConnectedTransaction() { return getOutpoint().fromTx; }
String toStringCpp() { String str; str = "CTxIn("; str = str + getOutpoint().toStringCpp(); if (isCoinBase()) str = str + ", coinbase " + scriptSig.toString(); else str = str + ", scriptSig="+ (getScriptSig().getChunks().size() != 0 ? getScriptSig().toString().substring(0,24) : ""); if (this.sequence != 4294967295L) str = str + ", nSequence=" + sequence; str = str + ")"; return str; }
/** * Construct from a bitcoinj transaction * @param transaction A bitcoinj confirmed or unconfirmed transaction */ public RawTransactionInfo(Transaction transaction) { this.hex = TransactionHexSerializer.bytesToHexString(transaction.bitcoinSerialize()); this.txid = transaction.getHash(); this.version = transaction.getVersion(); this.locktime = transaction.getLockTime(); this.blockhash = null; // For now this.confirmations = transaction.getConfidence().getDepthInBlocks(); this.time = 0; // TODO: block header time of block including transaction this.blocktime = this.time; // same as time (see API doc) vin = new VinList(); for (TransactionInput input : transaction.getInputs()) { vin.add(new Vin(txid, input.getOutpoint().getIndex(), input.getScriptSig().toString(), input.getSequenceNumber())); } vout = new VoutList(); for (TransactionOutput output : transaction.getOutputs()) { vout.add(new Vout(output.getValue(), output.getIndex(), output.getScriptPubKey().toString())); } }
/** * Convenience method that returns the from address of this input by parsing the scriptSig. The concept of a * "from address" is not well defined in Bitcoin and you should not assume that senders of a transaction can * actually receive coins on the same address they used to sign (e.g. this is not true for shared wallets). */ @Deprecated public Address getFromAddress() throws ScriptException { if (isCoinBase()) { throw new ScriptException( "This is a coinbase transaction which generates new coins. It does not have a from address."); } return getScriptSig().getFromAddress(params); }
@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; } }
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 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, 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); }
@Nullable @Override public VerificationException call() throws Exception { try { ListIterator<Script> prevOutIt = prevOutScripts.listIterator(); for (int index = 0; index < tx.getInputs().size(); index++) { tx.getInputs().get(index).getScriptSig().correctlySpends(tx, index, prevOutIt.next(), verifyFlags); } } catch (VerificationException e) { return e; } return null; } }
/** * Transactions can have an associated lock time, specified either as a block height or in seconds since the * UNIX epoch. A transaction is not allowed to be confirmed by miners until the lock time is reached, and * since Bitcoin 0.8+ a transaction that did not end its lock period (non final) is considered to be non * standard and won't be relayed or included in the memory pool either. */ public void setLockTime(long lockTime) { unCache(); boolean seqNumSet = false; for (TransactionInput input : inputs) { if (input.getSequenceNumber() != TransactionInput.NO_SEQUENCE) { seqNumSet = true; break; } } if (lockTime != 0 && (!seqNumSet || inputs.isEmpty())) { // At least one input must have a non-default sequence number for lock times to have any effect. // For instance one of them can be set to zero to make this feature work. log.warn("You are setting the lock time on a transaction but none of the inputs have non-default sequence numbers. This will not do what you expect!"); } this.lockTime = lockTime; }
public int calculateMessageSizeInBytes() { int cursor = 0; //vin cursor += 36; long scriptLen = vin.getScriptBytes().length; // 4 = length of sequence field (unint32) cursor += scriptLen + 4 + VarInt.sizeOf(scriptLen); //blockHash cursor += 32; //sigTime cursor += 8; //vchSig cursor += vchSig.calculateMessageSizeInBytes(); return cursor; }
/** * Connects this input to the relevant output of the referenced transaction. * Connecting means updating the internal pointers and spent flags. If the mode is to ABORT_ON_CONFLICT then * the spent output won't be changed, but the outpoint.fromTx pointer will still be updated. * * @param transaction The transaction to try. * @param mode Whether to abort if there's a pre-existing connection or not. * @return NO_SUCH_TX if transaction is not the prevtx, ALREADY_SPENT if there was a conflict, SUCCESS if not. */ public ConnectionResult connect(Transaction transaction, ConnectMode mode) { if (!transaction.getHash().equals(outpoint.getHash())) return ConnectionResult.NO_SUCH_TX; checkElementIndex((int) outpoint.getIndex(), transaction.getOutputs().size(), "Corrupt transaction"); TransactionOutput out = transaction.getOutput((int) outpoint.getIndex()); if (!out.isAvailableForSpending()) { if (getParentTransaction().equals(outpoint.fromTx)) { // Already connected. return ConnectionResult.SUCCESS; } else if (mode == ConnectMode.DISCONNECT_ON_CONFLICT) { out.markAsUnspent(); } else if (mode == ConnectMode.ABORT_ON_CONFLICT) { outpoint.fromTx = out.getParentTransaction(); return TransactionInput.ConnectionResult.ALREADY_SPENT; } } connect(out); return TransactionInput.ConnectionResult.SUCCESS; }
/** * Sets the transaction lock time. * * @param transaction the transaction * @param locktime the locktime * @return the transaction */ public static Transaction setTransactionLockTime (Transaction transaction, int locktime) { transaction.setLockTime(locktime); for (TransactionInput input : transaction.getInputs()) { input.setSequenceNumber(0); } return transaction; }
/** * Verifies that this input can spend the given output. Note that this input must be a part of a transaction. * Also note that the consistency of the outpoint will be checked, even if this input has not been connected. * * @param output the output that this input is supposed to spend. * @throws ScriptException If the script doesn't verify. * @throws VerificationException If the outpoint doesn't match the given output. */ public void verify(TransactionOutput output) throws VerificationException { verify(output, Script.ALL_VERIFY_FLAGS); }