Chapter 6 Exercises

Conceptual Exercises

Exercise 6.1: UTXO Tracing

Alice has the following UTXOs in her wallet: - UTXO-1: 0.4 BTC (from tx_aaa, output 0) - UTXO-2: 0.25 BTC (from tx_bbb, output 1) - UTXO-3: 0.1 BTC (from tx_ccc, output 0) - UTXO-4: 0.05 BTC (from tx_ddd, output 2)

Alice wants to send exactly 0.6 BTC to Bob. The current fee rate is approximately 0.0005 BTC for a transaction of this complexity.

a) Which UTXOs should Alice's wallet select to minimize the number of inputs (and thus minimize the transaction fee)?

b) What will the outputs of this transaction be? Include the exact amounts.

c) After this transaction confirms, how many UTXOs does Alice have? What are their values?

d) What happens to the UTXOs Alice spent? Where do they "go"?

Exercise 6.2: The Dust Problem

A user made hundreds of small Bitcoin transactions over several years and now has a wallet with the following UTXO distribution: - 5 UTXOs of 0.01 BTC each - 50 UTXOs of 0.0001 BTC each - 200 UTXOs of 0.000005 BTC each (500 satoshis each)

a) Calculate the total "balance" shown in the wallet.

b) At a fee rate of 50 sat/vB, and assuming each additional input adds approximately 68 vbytes to the transaction, how much would it cost (in BTC) to consolidate all 255 UTXOs into a single UTXO?

c) Are any of these UTXOs below the dust threshold (546 satoshis for P2PKH, 294 satoshis for P2WPKH)? What does this mean practically?

d) What is the user's effectively spendable balance? Explain the difference between nominal balance and effective balance.

Exercise 6.3: Block Header Analysis

Given the following block header fields (all in hexadecimal, little-endian):

Version:        20000000
Previous Hash:  00000000000000000002a7c4c1e48d76c5a37902165a270156b7a8d72014f600
Merkle Root:    7f3a4b5c6d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a
Timestamp:      a4d36765
Bits:           1703a30c
Nonce:          b9f50518

a) What is the block version number? What does this version indicate?

b) Convert the timestamp from hexadecimal (little-endian) to a human-readable date and time (UTC).

c) Explain why the previous block hash field creates an immutable chain. What would an attacker need to do to alter a transaction in this block?

d) If a miner changes the order of two transactions in the block body, which header field changes? Would the existing nonce still produce a valid proof of work?

Exercise 6.4: Script Execution

Trace the execution of the following P2PKH script validation. Assume the signature and public key are valid, and that the public key's HASH160 matches the hash in the locking script.

Unlocking Script (ScriptSig):

<sig_Alice> <pubKey_Alice>

Locking Script (ScriptPubKey):

OP_DUP OP_HASH160 <hash_of_pubKey_Alice> OP_EQUALVERIFY OP_CHECKSIG

a) Draw the stack state after each operation. Start with an empty stack.

b) What would happen if someone tried to spend this UTXO with Bob's signature and Bob's public key instead?

c) At which step would the validation fail in scenario (b)?

d) Why does the script use OP_HASH160 on the public key instead of directly comparing the full public key? What are the security implications?

Exercise 6.5: Coinbase Transaction Properties

Consider a block at height 850,000 that contains 2,500 transactions with a total fee of 0.875 BTC.

a) What is the maximum value the coinbase transaction's outputs can total? Show your calculation, including the current block reward at this height.

b) Can the coinbase outputs total less than this maximum? If so, what happens to the "unclaimed" value?

c) Why must coinbase outputs wait 100 blocks before being spent? Provide a concrete scenario where this rule prevents a problem.

d) The coinbase transaction's ScriptSig must begin with the block height (BIP 34). Express the block height 850,000 as it would appear in the coinbase ScriptSig (little-endian hex encoding of the integer).

Programming Exercises

Exercise 6.6: UTXO Set Implementation

Extend the UTXOSet class from this chapter's code files to include the following features:

a) A method get_balance(address) that returns the total balance for a given address by summing all UTXOs locked to that address.

b) A method find_utxos_for_amount(address, amount) that implements a simple coin selection algorithm: returns the smallest set of UTXOs that covers the requested amount, preferring to use the fewest UTXOs possible.

c) A method get_utxo_count() that returns the total number of UTXOs in the set.

d) Test your implementation by creating a scenario where Alice receives five transactions, spends from three of them, and verify the balance and UTXO count at each step.

Exercise 6.7: Transaction Serialization

Write a Python function serialize_transaction(version, inputs, outputs, locktime) that takes structured transaction data and produces the raw hexadecimal serialization (legacy format, not SegWit).

Requirements: - Correctly encode all integers as little-endian - Implement VarInt encoding for counts and script lengths - Handle the full inputs and outputs arrays - Test by serializing a known transaction and comparing against the expected hex

Exercise 6.8: Merkle Proof Verification

Implement a function verify_merkle_proof(tx_hash, proof, merkle_root) that verifies a Merkle inclusion proof.

a) The proof should be a list of (hash, direction) pairs, where direction is "left" or "right," indicating which side of the concatenation the proof hash goes on.

b) Verify your implementation against a hand-computed example with 8 transactions.

c) What is the length of the proof for a block with 4,096 transactions? How does this compare to the size of downloading all 4,096 transaction hashes?

Exercise 6.9: Raw Transaction Parser

Using the transaction_parser.py from this chapter's code files as a starting point, extend the parser to handle:

a) SegWit transactions (detect the marker/flag bytes and parse witness data)

b) Multi-input and multi-output transactions (not just one input, one output)

c) Display the total input value, total output value, and implied fee (you will need to look up the input UTXOs, which in a real implementation would require querying the UTXO set or a block explorer API)

Exercise 6.10: Blockchain Tamper Detection

Using the Blockchain class from the progressive project code:

a) Create a blockchain with at least 5 blocks, each containing 2-3 transactions.

b) Verify the chain is valid using validate_chain().

c) Now tamper with the blockchain: modify a transaction amount in block 2. Run validate_chain() again and observe which check fails.

d) Try to "fix" the tampering by recomputing block 2's hash. What happens to block 3's validation? Explain why fixing one block is not sufficient.

e) How many blocks would you need to recompute to successfully tamper with block 2 in a chain of 100 blocks? What makes this practically infeasible in the real Bitcoin network?

Challenge Exercises

Exercise 6.11: Fee Estimation

Write a Python program that simulates fee estimation for a Bitcoin transaction. Given: - A set of available UTXOs (various amounts) - A desired payment amount - A fee rate in sat/vB

Your program should: a) Select UTXOs using a simple heuristic (e.g., largest-first, or branch-and-bound approximation) b) Calculate the transaction size based on the number of inputs and outputs (use approximate sizes: 148 vbytes per P2PKH input, 34 vbytes per output, 10 vbytes overhead) c) Calculate the total fee d) Determine if the transaction is economically viable (fee not exceeding some percentage of the payment amount)

Test with at least three different scenarios: a large payment with few UTXOs, a small payment with many UTXOs, and a case where the fee makes the transaction uneconomical.

Exercise 6.12: Multi-Signature Script Construction

Write a Python function that constructs a 2-of-3 multi-signature redeem script given three public keys (as hex strings). Your function should:

a) Produce the correct Script bytecode for a 2-of-3 multisig (OP_2 OP_3 OP_CHECKMULTISIG)

b) Compute the HASH160 of the redeem script (this becomes the P2SH address)

c) Construct the P2SH ScriptPubKey that locks funds to this multisig

d) Explain why P2SH was necessary for practical multisig — what would the locking script look like without P2SH, and why is that problematic?

Exercise 6.13: SegWit Weight Calculation

For each of the following transaction types, calculate the transaction weight and virtual size:

a) A legacy P2PKH transaction with 2 inputs and 2 outputs (total serialized size: 374 bytes, all bytes are non-witness)

b) A native SegWit P2WPKH transaction with 2 inputs and 2 outputs (non-witness: 164 bytes, witness: 214 bytes)

c) A mixed transaction with 1 legacy input and 1 SegWit input, 2 outputs (non-witness: 222 bytes, witness: 107 bytes)

For each, calculate: total weight in WU, virtual size in vbytes, and the fee at 20 sat/vB. Which format is cheapest? By what percentage?