Figure 1: Transaction Inputs and Outputs

Figure 1: Transaction Inputs and Outputs

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:

  1. Obtain a copy of Transaction [b1]
  2. Obtain the Output Script (aka scriptPubKey) in the Output of Transaction [b1] (marked in orange)
  3. 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]

var b1Hex = '01000000015884e5db9de218238671572340b207ee85b628074e7e467096c267266baf77a4000000006a473044022013fa3089327b50263029265572ae1b022a91d10ac80eb4f32f291c914533670b02200d8a5ed5f62634a7e1a0dc9188a3cc460a986267ae4d58faf50c79105431327501210223078d2942df62c45621d209fab84ea9a7a23346201b7727b9b45a29c4e76f5effffffff0150690f00000000001976a9147821c0a3768aa9d1a37e16cf76002aef5373f1a888ac00000000';

(2) Obtain the Output to spend from

List<TransactionOutput> outputList =  Transaction.fromHex(b1Hex).outputs;

//let's assume we are spending the first output in the list
var utxo = outputList[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.
var locker = P2PKHLockBuilder(recipientAddress);

//In order to create our spending Input Script in Transaction *[c1]* we use
//another utility (P2PKHUnlockBuilder), to help us construct the unlocking/spending script.
var unlocker = P2PKHUnlockBuilder(privateKey.publicKey);

//Transaction() employs the builder pattern for convenience.
var txn = Transaction()
    .spendFromOutput(utxo, Transaction.NLOCKTIME_MAX_VALUE, scriptBuilder: unlocker)
    .spendTo(recipientAddress, BigInt.from(50000000),scriptBuilder: locker)
    .sendChangeTo(changeAddress, scriptBuilder: locker)
    .withFeePerKb(1024); //set a one satoshi per byte fee

Signing a Transaction

We still have to sign the Transaction [c1] using a private key. This assumes that the output we are spending from was locked using a public key (pubKeyHash) corresponding to our private key.

It is important to note that when signing transactions for broadcast on the BitcoinSV network, we must always include the SIGHASH_FORKID value. See Signature Schemes section.

txn.signInput(0, privateKey, sighashType: SighashType.SIGHASH_ALL | SighashType.SIGHASH_FORKID);

//obtain a hexadecimal version (raw transaction) which is
//ready for broadcast using something like the Merchant API

var txHex = txn.serialize();