public Address getAddressForInput(TransactionInput in, boolean confirmed) { if (in.isCoinBase()) return null; try { Address a = in.getFromAddress(); return a; } catch (ScriptException e) { // Lets try this the other way try { TransactionOutPoint out_p = in.getOutpoint(); Transaction src_tx = null; while (src_tx == null) { src_tx = getTransaction(out_p.getHash()); if (src_tx == null) { if (!confirmed) { return null; } System.out.println("Unable to get source transaction: " + out_p.getHash()); try { Thread.sleep(500); } catch (Exception e7) { } } } TransactionOutput out = src_tx.getOutput((int) out_p.getIndex()); Address a = getAddressForOutput(out); return a; } catch (ScriptException e2) { return null; } } }
/** * When the servers signature for the refund transaction is received, call this to verify it and * sign the complete refund ourselves. * * <p>If this does not throw an exception, we are secure against the loss of funds and can safely * provide the server with the multi-sig contract to lock in the agreement. In this case, both the * multisig contract and the refund transaction are automatically committed to wallet so that it * can handle broadcasting the refund transaction at the appropriate time if necessary. */ public synchronized void provideRefundSignature(byte[] theirSignature) throws VerificationException { checkNotNull(theirSignature); checkState(state == State.WAITING_FOR_SIGNED_REFUND); TransactionSignature theirSig = TransactionSignature.decodeFromBitcoin(theirSignature, true); if (theirSig.sigHashMode() != Transaction.SigHash.NONE || !theirSig.anyoneCanPay()) throw new VerificationException("Refund signature was not SIGHASH_NONE|SIGHASH_ANYONECANPAY"); // Sign the refund transaction ourselves. final TransactionOutput multisigContractOutput = multisigContract.getOutput(0); try { multisigScript = multisigContractOutput.getScriptPubKey(); } catch (ScriptException e) { throw new RuntimeException(e); // Cannot happen: we built this ourselves. } TransactionSignature ourSignature = refundTx.calculateSignature(0, myKey, multisigScript, Transaction.SigHash.ALL, false); // Insert the signatures. Script scriptSig = ScriptBuilder.createMultiSigInputScript(ourSignature, theirSig); log.info("Refund scriptSig: {}", scriptSig); log.info("Multi-sig contract scriptPubKey: {}", multisigScript); TransactionInput refundInput = refundTx.getInput(0); refundInput.setScriptSig(scriptSig); refundInput.verify(multisigContractOutput); state = State.SAVE_STATE_IN_WALLET; }
public void putTxOutSpents(Transaction tx) { LinkedList<String> tx_outs = new LinkedList<String>(); for (TransactionInput in : tx.getInputs()) { if (!in.isCoinBase()) { TransactionOutPoint out = in.getOutpoint(); String key = out.getHash().toString() + ":" + out.getIndex(); // file_db.addTxOutSpentByMap(key, tx.getHash()); tx_outs.add(key); } } }
private void readTransaction(Protos.Transaction txProto, NetworkParameters params) { Transaction tx = new Transaction(params); if (txProto.hasUpdatedAt()) { tx.setUpdateTime(new Date(txProto.getUpdatedAt())); } for (Protos.TransactionOutput outputProto : txProto.getTransactionOutputList()) { BigInteger value = BigInteger.valueOf(outputProto.getValue()); byte[] scriptBytes = outputProto.getScriptBytes().toByteArray(); TransactionOutput output = new TransactionOutput(params, tx, value, scriptBytes); tx.addOutput(output); } for (Protos.TransactionInput transactionInput : txProto.getTransactionInputList()) { byte[] scriptBytes = transactionInput.getScriptBytes().toByteArray(); TransactionOutPoint outpoint = new TransactionOutPoint( params, transactionInput.getTransactionOutPointIndex(), byteStringToHash(transactionInput.getTransactionOutPointHash())); TransactionInput input = new TransactionInput(params, tx, scriptBytes, outpoint); if (transactionInput.hasSequence()) { input.setSequenceNumber(transactionInput.getSequence()); } tx.addInput(input); } for (ByteString blockHash : txProto.getBlockHashList()) { tx.addBlockAppearance(byteStringToHash(blockHash)); } if (txProto.hasLockTime()) { tx.setLockTime(0xffffffffL & txProto.getLockTime()); } // Transaction should now be complete. Sha256Hash protoHash = byteStringToHash(txProto.getHash()); Preconditions.checkState( tx.getHash().equals(protoHash), "Transaction did not deserialize completely: %s vs %s", tx.getHash(), protoHash); Preconditions.checkState( !txMap.containsKey(txProto.getHash()), "Wallet contained duplicate transaction %s", byteStringToHash(txProto.getHash())); txMap.put(txProto.getHash(), tx); }
public static void signTransaction(Transaction tx, String qrCodeContent) throws ScriptException { String[] stringArray = qrCodeContent.split(StringUtil.QR_CODE_SPLIT); List<String> hashList = new ArrayList<String>(); for (String str : stringArray) { if (!StringUtil.isEmpty(str)) { hashList.add(str); LogUtil.d("sign", str); } } for (int i = 0; i < tx.getInputs().size(); i++) { TransactionInput input = tx.getInputs().get(i); String str = hashList.get(i); input.setScriptSig(new Script(StringUtil.hexStringToByteArray(str))); input .getScriptSig() .correctlySpends(tx, i, input.getOutpoint().getConnectedOutput().getScriptPubKey(), true); } }
private WalletTransaction connectTransactionOutputs( org.bitcoinj.wallet.Protos.Transaction txProto) { Transaction tx = txMap.get(txProto.getHash()); WalletTransaction.Pool pool = WalletTransaction.Pool.valueOf(txProto.getPool().getNumber()); if (pool == WalletTransaction.Pool.INACTIVE || pool == WalletTransaction.Pool.PENDING_INACTIVE) { // Upgrade old wallets: inactive pool has been merged with the pending pool. // Remove this some time after 0.9 is old and everyone has upgraded. // There should not be any spent outputs in this tx as old wallets would not allow them to be // spent // in this state. pool = WalletTransaction.Pool.PENDING; } for (int i = 0; i < tx.getOutputs().size(); i++) { TransactionOutput output = tx.getOutputs().get(i); final Protos.TransactionOutput transactionOutput = txProto.getTransactionOutput(i); if (transactionOutput.hasSpentByTransactionHash()) { final ByteString spentByTransactionHash = transactionOutput.getSpentByTransactionHash(); Transaction spendingTx = txMap.get(spentByTransactionHash); if (spendingTx == null) throw new IllegalArgumentException( String.format( "Could not connect %s to %s", tx.getHashAsString(), byteStringToHash(spentByTransactionHash))); final int spendingIndex = transactionOutput.getSpentByTransactionIndex(); TransactionInput input = checkNotNull(spendingTx.getInput(spendingIndex)); input.connect(output); } } if (txProto.hasConfidence()) { Protos.TransactionConfidence confidenceProto = txProto.getConfidence(); TransactionConfidence confidence = tx.getConfidence(); readConfidence(tx, confidenceProto, confidence); } return new WalletTransaction(pool, tx); }
@Test public void dataDrivenInvalidTransactions() throws Exception { BufferedReader in = new BufferedReader( new InputStreamReader( getClass().getResourceAsStream("tx_invalid.json"), Charset.forName("UTF-8"))); NetworkParameters params = TestNet3Params.get(); // Poor man's (aka. really, really poor) JSON parser (because pulling in a lib for this is // probably overkill) List<JSONObject> tx = new ArrayList<JSONObject>(1); in.read(); // remove first [ StringBuffer buffer = new StringBuffer(1000); while (in.ready()) { String line = in.readLine(); if (line == null || line.equals("")) continue; buffer.append(line); if (line.equals("]") && buffer.toString().equals("]") && !in.ready()) break; // ignore last ] boolean isFinished = appendToList(tx, buffer); while (tx.size() > 0 && tx.get(0).isList() && tx.get(0).list.size() == 1 && tx.get(0).list.get(0).isString()) tx.remove(0); if (isFinished && tx.size() == 1 && tx.get(0).list.size() == 3) { HashMap<TransactionOutPoint, Script> scriptPubKeys = new HashMap<TransactionOutPoint, Script>(); for (JSONObject input : tx.get(0).list.get(0).list) { String hash = input.list.get(0).string; int index = input.list.get(1).integer; String script = input.list.get(2).string; Sha256Hash sha256Hash = new Sha256Hash(Hex.decode(hash.getBytes(Charset.forName("UTF-8")))); scriptPubKeys.put( new TransactionOutPoint(params, index, sha256Hash), parseScriptString(script)); } byte[] bytes = tx.get(0).list.get(1).string.getBytes(Charset.forName("UTF-8")); Transaction transaction = new Transaction(params, Hex.decode(bytes)); boolean enforceP2SH = tx.get(0).list.get(2).booleanValue; assertTrue(tx.get(0).list.get(2).isBoolean()); boolean valid = true; try { transaction.verify(); } catch (VerificationException e) { valid = false; } // The reference client checks this case in CheckTransaction, but we leave it to // later where we will see an attempt to double-spend, so we explicitly check here HashSet<TransactionOutPoint> set = new HashSet<TransactionOutPoint>(); for (TransactionInput input : transaction.getInputs()) { if (set.contains(input.getOutpoint())) valid = false; set.add(input.getOutpoint()); } for (int i = 0; i < transaction.getInputs().size() && valid; i++) { TransactionInput input = transaction.getInputs().get(i); assertTrue(scriptPubKeys.containsKey(input.getOutpoint())); try { input .getScriptSig() .correctlySpends( transaction, i, scriptPubKeys.get(input.getOutpoint()), enforceP2SH); } catch (VerificationException e) { valid = false; } } if (valid) fail(); tx.clear(); } } in.close(); }
@Test public void dataDrivenValidTransactions() throws Exception { BufferedReader in = new BufferedReader( new InputStreamReader( getClass().getResourceAsStream("tx_valid.json"), Charset.forName("UTF-8"))); NetworkParameters params = TestNet3Params.get(); // Poor man's (aka. really, really poor) JSON parser (because pulling in a lib for this is // probably not overkill) int lineNum = -1; List<JSONObject> tx = new ArrayList<JSONObject>(3); in.read(); // remove first [ StringBuffer buffer = new StringBuffer(1000); while (in.ready()) { lineNum++; String line = in.readLine(); if (line == null || line.equals("")) continue; buffer.append(line); if (line.equals("]") && buffer.toString().equals("]") && !in.ready()) break; boolean isFinished = appendToList(tx, buffer); while (tx.size() > 0 && tx.get(0).isList() && tx.get(0).list.size() == 1 && tx.get(0).list.get(0).isString()) tx.remove(0); // ignore last ] if (isFinished && tx.size() == 1 && tx.get(0).list.size() == 3) { Transaction transaction = null; try { HashMap<TransactionOutPoint, Script> scriptPubKeys = new HashMap<TransactionOutPoint, Script>(); for (JSONObject input : tx.get(0).list.get(0).list) { String hash = input.list.get(0).string; int index = input.list.get(1).integer; String script = input.list.get(2).string; Sha256Hash sha256Hash = new Sha256Hash(Hex.decode(hash.getBytes(Charset.forName("UTF-8")))); scriptPubKeys.put( new TransactionOutPoint(params, index, sha256Hash), parseScriptString(script)); } byte[] bytes = tx.get(0).list.get(1).string.getBytes(Charset.forName("UTF-8")); transaction = new Transaction(params, Hex.decode(bytes)); boolean enforceP2SH = tx.get(0).list.get(2).booleanValue; assertTrue(tx.get(0).list.get(2).isBoolean()); transaction.verify(); for (int i = 0; i < transaction.getInputs().size(); i++) { TransactionInput input = transaction.getInputs().get(i); if (input.getOutpoint().getIndex() == 0xffffffffL) input.getOutpoint().setIndex(-1); assertTrue(scriptPubKeys.containsKey(input.getOutpoint())); input .getScriptSig() .correctlySpends( transaction, i, scriptPubKeys.get(input.getOutpoint()), enforceP2SH); } tx.clear(); } catch (Exception e) { System.err.println("Exception processing line " + lineNum + ": " + line); if (transaction != null) System.err.println(transaction); throw e; } } } in.close(); }
private static Protos.Transaction makeTxProto(WalletTransaction wtx) { Transaction tx = wtx.getTransaction(); Protos.Transaction.Builder txBuilder = Protos.Transaction.newBuilder(); txBuilder .setPool(Protos.Transaction.Pool.valueOf(wtx.getPool().getValue())) .setHash(hashToByteString(tx.getHash())) .setVersion((int) tx.getVersion()); if (tx.getUpdateTime() != null) { txBuilder.setUpdatedAt(tx.getUpdateTime().getTime()); } if (tx.getLockTime() > 0) { txBuilder.setLockTime((int) tx.getLockTime()); } // Handle inputs. for (TransactionInput input : tx.getInputs()) { Protos.TransactionInput.Builder inputBuilder = Protos.TransactionInput.newBuilder() .setScriptBytes(ByteString.copyFrom(input.getScriptBytes())) .setTransactionOutPointHash(hashToByteString(input.getOutpoint().getHash())) .setTransactionOutPointIndex((int) input.getOutpoint().getIndex()); if (input.hasSequence()) { inputBuilder.setSequence((int) input.getSequenceNumber()); } txBuilder.addTransactionInput(inputBuilder); } // Handle outputs. for (TransactionOutput output : tx.getOutputs()) { Protos.TransactionOutput.Builder outputBuilder = Protos.TransactionOutput.newBuilder() .setScriptBytes(ByteString.copyFrom(output.getScriptBytes())) .setValue(output.getValue().longValue()); final TransactionInput spentBy = output.getSpentBy(); if (spentBy != null) { Sha256Hash spendingHash = spentBy.getParentTransaction().getHash(); int spentByTransactionIndex = spentBy.getParentTransaction().getInputs().indexOf(spentBy); outputBuilder .setSpentByTransactionHash(hashToByteString(spendingHash)) .setSpentByTransactionIndex(spentByTransactionIndex); } txBuilder.addTransactionOutput(outputBuilder); } // Handle which blocks tx was seen in. if (tx.getAppearsInHashes() != null) { for (Sha256Hash hash : tx.getAppearsInHashes()) { txBuilder.addBlockHash(hashToByteString(hash)); } } if (tx.hasConfidence()) { TransactionConfidence confidence = tx.getConfidence(); Protos.TransactionConfidence.Builder confidenceBuilder = Protos.TransactionConfidence.newBuilder(); writeConfidence(txBuilder, confidence, confidenceBuilder); } return txBuilder.build(); }