Transactions
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[0]
(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())