Scenario 1: Fund and spend¶
Goal: Do the smallest loop from start to end. Mine to Alice, pay Bob, confirm the payment and read the state.
#lang bitcoin/model
;; Scenario 1: fund and spend on one chain.
(require rackunit)
(chain mainnet #:rules bitcoin)
(keys alice bob)
(define cb (first (mine 1 #:on mainnet #:to alice))) ; mine returns a list of coinbase coins
(mine 100 #:on mainnet) ; mature it
(define-tx pay
#:inputs ([cb #:sign alice])
#:outputs ([to-bob (wpkh bob) (btc 49.99)]
[change (wpkh alice) (btc 0.009)]))
(check-pred accepted? (broadcast pay))
(mine 1 #:on mainnet)
(check-true (confirmed? pay))
(check-equal? (utxos #:spendable-by bob) (list to-bob))
(check-equal? (fee pay) (btc 0.001))
(check-equal? to-bob (out pay 'to-bob))
(check-equal? change (output-of pay 1))
What occurs¶
(chain mainnet #:rules bitcoin)makes a chain at height 0.(keys alice bob)binds two keys.minereturns the list of coinbase coins. Thus(first …)is the 50 BTC coin of Alice. A coinbase output matures after 100 blocks, thus the scenario mines 100 more blocks.define-txbuilds and signs the payment, and bindspay,to-bobandchange.(broadcast pay)returns(accepted …). The next block confirms the payment.- The queries return values.
(confirmed? pay)is#t. The only coin that Bob can spend isto-bob. The fee is(btc 0.001). The block that confirmedpaypaid 50.001 BTC to its miner.
A spend that is too early gives an explained rejection:
(rejected #:chain mainnet #:rule coinbase-maturity #:input 0 #:need 100 #:have 1 #:step 3 #:trace 1)
Against a real node¶
tests/replay-1.rkt runs the same code in #lang bitcoin/conform. It replays the code against a regtest Bitcoin Core node. Each step is confirmed, which includes the real ECDSA signature of Alice and the block reward of 50.001 BTC.
Forms in this scenario: chain, keys, mine, define-tx, output-of, out, broadcast, confirmed?, utxos, fee, wpkh.