package com.google.bitcoin.core; import java.math.BigInteger; import java.util.*; import static com.google.bitcoin.core.Utils.*; public class TransactionStandaloneEncoder { NetworkParameters params; ArrayList<ECKey> in_keys; ArrayList<byte[]> in_hashes; ArrayList<Integer> in_indexes; ArrayList<Address> out_addresses; ArrayList<BigInteger> out_amounts; public TransactionStandaloneEncoder(NetworkParameters params) { this.params = params; this.in_keys = new ArrayList<ECKey>(); this.in_hashes = new ArrayList<byte[]>(); this.in_indexes = new ArrayList<Integer>(); this.out_addresses = new ArrayList<Address>(); this.out_amounts = new ArrayList<BigInteger>(); } public void addInput(ECKey key, int txIndex, String txHashHex) { addInput(key, txIndex, Utils.hexStringToBytes(txHashHex)); } public void addInput(ECKey key, int txIndex, byte[] txHash) { in_keys.add(key); in_hashes.add(txHash); in_indexes.add(txIndex); } public void addOutput(BigInteger amount, String address) throws AddressFormatException { NetworkParameters params = NetworkParameters.prodNet(); out_addresses.add(new Address(params, address)); out_amounts.add(amount); } public Transaction createSignedTransaction() { NetworkParameters params = NetworkParameters.prodNet(); Wallet wallet = new Wallet(params); for (int i = 0; i < in_keys.size(); i++) { wallet.addKey(in_keys.get(i)); } // Prereq transactions ArrayList<TransactionOutput> in_outputs = new ArrayList<TransactionOutput>(); Transaction t; TransactionOutput output; Address whatever = new ECKey().toAddress(params); for (int i = 0; i < in_keys.size(); i++) { t = new Transaction(params); // index (via spacers) int index = in_indexes.get(i).intValue(); for (int j = 0; j < index; j++) { t.addOutput(new TransactionOutput(params, Utils.toNanoCoins(1, 0), whatever, t)); } output = new TransactionOutput(params, Utils.toNanoCoins(1, 0), in_keys.get(i).toAddress(params), t); t.addOutput(output); in_outputs.add(output); // hash t.setFakeHashForTesting(new Sha256Hash(in_hashes.get(i))); try { wallet.receive(t, null, BlockChain.NewBlockType.BEST_CHAIN); } catch (Exception e) { throw new RuntimeException(e); } } Transaction sendTx = new Transaction(params); // Inputs for (int i = 0; i < in_outputs.size(); i++) { sendTx.addInput(in_outputs.get(i)); } // Outputs for (int i = 0; i < out_amounts.size(); i++) { sendTx.addOutput(new TransactionOutput(params, out_amounts.get(i), out_addresses.get(i), sendTx)); } try { sendTx.signInputs(Transaction.SigHash.ALL, wallet); } catch (ScriptException e) { throw new RuntimeException(e); } return sendTx; } }