Be sure to review the section on Bitcoin Script from the Developer Guide.
Creating a Transaction
Transactions never stand in isolation. Every new transaction we create must “spend from” another, existing transaction. Referring to the above diagram:
In order to construct a Transaction [c1], we need to do the following:
- Obtain a copy of Transaction [b1]
- Obtain the Output Script (aka scriptPubKey) in the Output of Transaction [b1] (marked in orange)
- Create an Input Script (aka scriptSig) in the Input of Transaction [c1] (marked in blue)
(1) Obtaining a Transaction to spend from
One can obtain the Transaction to spend from in any of a number of ways. These include:
- Quering the Merchant API of a service provider (e.g. WhatsOnchain)
- Have it passed directly to you by a counter party
For our purposes, we will assume that we have the following Transaction, serialised in hexadecimal to act as our Transaction [b1]
val b1Hex = "01000000015884e5db9de218238671572340b207ee85b628074e7e467096c267266baf77a4000000006a473044022013fa3089327b50263029265572ae1b022a91d10ac80eb4f32f291c914533670b02200d8a5ed5f62634a7e1a0dc9188a3cc460a986267ae4d58faf50c79105431327501210223078d2942df62c45621d209fab84ea9a7a23346201b7727b9b45a29c4e76f5effffffff0150690f00000000001976a9147821c0a3768aa9d1a37e16cf76002aef5373f1a888ac00000000"
(2) Obtain the Output to spend from
val fundingTx = Transaction.fromHex(b1Hex) //let's assume we are spending the first output in the list val utxo: TransactionOutput = fundingTx.outputs
(3) Create the spending Transaction
We now use a TransactionBuilder to construct the spending transaction.
/* our new transaction [c1] will contain an Output Script. The coins in that script will be locked using an address of our choosing. We use a P2PKHLockBuilder to help us construct a canonical P2PKH locking script. */ //assume we have a wif private key to import val pkOne = PrivateKey.fromWIF("L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m") //In order to create our spending Input Script in Transaction *[c1]* we use //another utility (P2PKHUnlockBuilder), to help us construct the unlocking/spending script. val unlocker = P2PKHUnlockBuilder(pkOne.publicKey) //create a recipient to send the money to val recipientAddress = Address.fromKey(NetworkAddressType.MAIN_PKH, pkOne.publicKey) //construct a LockingScriptBuilder that will generate the P2PKH locking script val locker = P2PKHLockBuilder(recipientAddress) //create a TransactionSigner that will be invoked to sign our spending transaction val txSigner = TransactionSigner(SigHashType.ALL.value or SigHashType.FORKID.value, pkOne) val txBuilder = TransactionBuilder() .spendFromTransaction(txSigner, fundingTx, 0, TransactionInput.MAX_SEQ_NUMBER, unlocker) .spendTo(locker, BigInteger.valueOf(200000)) .sendChangeTo(recipientAddress) //send change to recipient too ! .withFeePerKb(512) //Build the transaction, which will invoke signing operations automatically val broadcastTx: Transaction = txBuilder.build(true) //serialise our tx ready for network broadcast val txHex = HEX.encode(broadcastTx.serialize())