bitcoin-s/docs/core/txbuilder.md
Nadav Kohen 4eb9980d6b InputInfo Refactor (#1400)
Added OutputReference and introduced public key computation on SPKs

Made InputInfo into an ADT

Made UTXOSpendingInfo use InputInfo

Replaced UTXOSpendingInfo with NewSpendingInfo and got non-test things compiling

Made aliases for (NewSpendingInfo/NewSpendingInfoFull/NewSpendingInfoSingle)[InputInfo]

Got rid of source code mention of UTXOSpendingInfo

sbt compile passes

tests compile

Fixed all coreTest tests

Renamed to UTXOInfo

Some cleanup

Moved redeem script and script witness accessors to companion object

Responded to code review

Added OutputReference and scaladocs

Moved p2pkhPreImageOpt downstream and generalized to hashPreImages

Fixed adding-spks.md

Fixed psbts.md and txbuilder.md

Renamed UTXOInfo

Apply renaming to docs
2020-05-15 11:14:15 -05:00

139 lines
4.7 KiB
Markdown

---
id: txbuilder
title: TxBuilder Example
---
Bitcoin-S features a transaction builder that constructs and signs Bitcoin
transactions. Here's an example of how to use it
```scala mdoc:invisible
import scala.concurrent._
import scala.concurrent.duration._
import org.bitcoins.core._
import number._
import config._
import currency._
import org.bitcoins.crypto._
import script.crypto._
import protocol.transaction._
import protocol.script._
import wallet.builder._
import wallet.fee._
import wallet.utxo._
```
```scala mdoc:to-string
implicit val ec: ExecutionContext = ExecutionContext.Implicits.global
// generate a fresh private key that we are going to use in the scriptpubkey
val privKey = ECPrivateKey.freshPrivateKey
val pubKey = privKey.publicKey
// this is the script that the TxBuilder is going to create a
// script signature that validly spends this scriptPubKey
val creditingSpk = P2PKHScriptPubKey(pubKey = privKey.publicKey)
val amount = 10000.satoshis
// this is the UTXO we are going to be spending
val utxo =
TransactionOutput(value = amount, scriptPubKey = creditingSpk)
// the private key that locks the funds for the script we are spending too
val destinationPrivKey = ECPrivateKey.freshPrivateKey
// the amount we are sending -- 5000 satoshis -- to the destinationSPK
val destinationAmount = 5000.satoshis
// the script that corresponds to destination private key, this is what is protecting the money
val destinationSPK =
P2PKHScriptPubKey(pubKey = destinationPrivKey.publicKey)
// this is where we are sending money too
// we could add more destinations here if we
// wanted to batch transactions
val destinations = {
val destination1 = TransactionOutput(value = destinationAmount,
scriptPubKey = destinationSPK)
Vector(destination1)
}
// we have to fabricate a transaction that contains the
// UTXO we are trying to spend. If this were a real blockchain
// we would need to reference the UTXO set
val creditingTx = BaseTransaction(version = Int32.one,
inputs = Vector.empty,
outputs = Vector(utxo),
lockTime = UInt32.zero)
// this is the information we need from the crediting TX
// to properly "link" it in the transaction we are creating
val outPoint = TransactionOutPoint(creditingTx.txId, UInt32.zero)
// this contains all the information we need to
// validly sign the UTXO above
val utxoInfo = ScriptSignatureParams(inputInfo = InputInfo(outPoint = outPoint,
output = utxo,
redeemScriptOpt = None,
scriptWitnessOpt = None,
conditionalPath =
ConditionalPath.NoCondition,
hashPreImages = Vector(privKey.publicKey)),
signers = Vector(privKey),
hashType =
HashType.sigHashAll)
// all of the UTXO spending information, since we are only
//spending one UTXO, this is just one element
val utxos: Vector[ScriptSignatureParams[InputInfo]] = Vector(utxoInfo)
// this is how much we are going to pay as a fee to the network
// for this example, we are going to pay 1 satoshi per byte
val feeRate = SatoshisPerByte(1.satoshi)
val changePrivKey = ECPrivateKey.freshPrivateKey
val changeSPK = P2PKHScriptPubKey(pubKey = changePrivKey.publicKey)
// the network we are on, for this example we are using
// the regression test network. This is a network you control
// on your own machine
val networkParams = RegTest
// Yay! Now we have a TxBuilder object that we can use
// to sign the TX.
val txBuilder: BitcoinTxBuilder = {
val builderF = BitcoinTxBuilder(
destinations = destinations,
utxos = utxos,
feeRate = feeRate,
changeSPK = changeSPK,
network = networkParams)
Await.result(builderF, 30.seconds)
}
// Let's finally produce a validly signed tx!
// The 'sign' method is going produce a validly signed transaction
// This is going to iterate through each of the UTXOs and use
// the corresponding ScriptSignatureParams to produce a validly
// signed input. This UTXO has:
// 1: one input
// 2: outputs (destination and change outputs)
// 3: a fee rate of 1 satoshi/byte
val signedTx: Transaction = {
val signF = txBuilder.sign
Await.result(signF, 30.seconds)
}
```
```scala mdoc:to-string
signedTx.inputs.length
signedTx.outputs.length
//remember, you can call .hex on any bitcoin-s data structure to get the hex representation!
signedTx.hex
```