MASTERING-BITCOIN ยท Unit 3 ยท Video 5 ยท Interactive Practice

Commanding Bitcoin Core with Code

IKey Reference

Pattern Structure Purpose
JSON-RPC Request {"jsonrpc":"1.0", "id":1, "method":"...", "params":[...]} Call any Bitcoin Core RPC method
RPC Connection URL http://user:pass@127.0.0.1:8332 Authenticate and connect to your node
Verbose Transaction rpc.getrawtransaction(txid, 1) Get decoded JSON instead of raw hex
Block Scan Pattern for txid in block["tx"]: tx = rpc.getrawtransaction(txid, 1) Iterate all transactions in a block

IIVisualization 1: JSON-RPC Request Builder

How does the structure of a JSON-RPC request change depending on which method you call?

Every RPC call follows the same JSON format โ€” only the method and params fields change. Select different methods below to see how the request payload and response differ.

โš™ interactive visualization โ€” coming to this page format soon

๐Ÿ’ก Notice: Every method uses the exact same JSON envelope โ€” only method and params change. This is why bitcoin-cli is just a thin wrapper: it constructs this same JSON payload, sends it via HTTP POST to port 8332, and prints the result. Your Python script does the identical thing.

IIIVisualization 2: Block Scanning โ€” How BTC Accumulates

How does total BTC accumulate as we scan every transaction in a block, and how many RPC calls does it take?

The video showed a script scanning block 840,000 (~2,500 transactions) and finding over 10,000 BTC moved. Adjust the sliders below to simulate scanning blocks of different sizes and see the cumulative effect.

โš™ interactive visualization โ€” coming to this page format soon

๐Ÿ’ก Notice how RPC calls scale linearly with the number of transactions. A block with 2,500 transactions needs 2,501 calls (1 getblock + 2,500 getrawtransaction). Each call is a separate HTTP round-trip โ€” that's why the scan takes a few seconds. Try increasing the transaction count and see how the total climbs.

IVVisualization 3: Trust Model โ€” Who Do You Depend On?

How does running your own node compare to third-party services in terms of external trust?

The video's key argument is that querying your own node eliminates all external dependencies. Explore below to see how dependencies multiply as you rely on more external sources.

โš™ interactive visualization โ€” coming to this page format soon

๐Ÿ’ก Key Insight: Your node's dependencies stay at zero no matter how many queries you make or how many sources you'd otherwise need. Meanwhile, external dependencies multiply with each additional service. This is the foundation of financial sovereignty โ€” your hardware stores the blockchain, your node validates every block, your code extracts the data.

VQuiz Questions

Question 1

When you type bitcoin-cli getblockchaininfo in the terminal, what actually happens behind the scenes?

โœ… Correct! bitcoin-cli is just a convenience wrapper around JSON-RPC. Your Python code uses the identical protocol underneath.

โŒ Not quite. Think about the protocol that connects bitcoin-cli to the Bitcoin Core daemon running in the background.

Show solution

Solution:

bitcoin-cli is a thin wrapper around JSON-RPC. When you run a command:

  1. It reads the .cookie file for authentication credentials
  2. It formats a JSON-RPC request: {"method": "getblockchaininfo", "params": [], ...}
  3. It sends an HTTP POST to 127.0.0.1:8332 (localhost)
  4. Bitcoin Core daemon processes the request and returns JSON
  5. bitcoin-cli prints the result

This is the exact same protocol your Python scripts use โ€” bitcoin-cli just provides a convenient command-line interface for it.

Question 2

In the Python call rpc.getrawtransaction(txid, 1), what does the second argument 1 do?

โœ… Correct! The verbose flag (1) returns a rich JSON dictionary you can navigate with Python, instead of an opaque hex string.

โŒ Not quite. This argument controls the format of the response โ€” how the data comes back to you.

Show solution

Solution:

The second argument is the verbose flag:

  • rpc.getrawtransaction(txid) or rpc.getrawtransaction(txid, 0) โ†’ returns a raw hex string
  • rpc.getrawtransaction(txid, 1) โ†’ returns a decoded JSON dictionary with all transaction fields

With verbose mode (1), the response includes structured data you can navigate:

  • tx["vin"] โ€” list of inputs
  • tx["vout"] โ€” list of outputs, each with value (BTC amount) and scriptPubKey (containing address)
  • tx["size"], tx["locktime"], etc.

Without it, you'd get an unreadable hex string requiring a separate decode step.

Question 3

True or False: The .cookie authentication file is generated once when Bitcoin Core is first installed and remains the same across all restarts.

โœ… Correct! The .cookie file regenerates on every restart. For long-running scripts, static credentials in bitcoin.conf are more reliable.

โŒ Not quite. Think about what happens to the cookie file each time the Bitcoin Core daemon restarts.

Show solution

Solution: False

The .cookie file is regenerated every time Bitcoin Core starts. Each restart produces a new, randomly generated credential pair.

This has practical implications:

  • Short scripts: Reading the .cookie file works fine โ€” credentials are valid for the current session
  • Long-running scripts: If your node restarts, the cookie changes and your script's connection breaks
  • Better for production: Set static credentials in bitcoin.conf using rpcuser and rpcpassword โ€” these persist across restarts

Both methods use the same JSON-RPC protocol; only the authentication credentials differ.

Question 4

A Python script scans all outputs in block 840,000, which contains approximately 2,500 transactions. It calls getblock once to get the list of transaction IDs, then calls getrawtransaction(txid, 1) for each transaction, and loops through the vout list in each decoded transaction. How many total RPC calls does this require?

โœ… Correct! One getblock for the transaction ID list, then one getrawtransaction per transaction. The inner output loop needs no additional calls since the data is already decoded.

โŒ Not quite. Remember: getblock returns only transaction IDs (not full data), and getrawtransaction with verbose flag 1 already returns decoded JSON (no separate decode step needed).

Show solution

Solution: ~2,501 calls

Here's the script pattern from the video:

block = rpc.getblock(block_hash)        # 1 RPC call
total = 0
for txid in block["tx"]:               # ~2,500 iterations
    tx = rpc.getrawtransaction(txid, 1) # 1 RPC call each
    for out in tx["vout"]:              # inner loop โ€” NO extra RPC calls
        total += out["value"]
print(total)                            # "10,247 BTC"

Why ~2,501:

  • 1 call for getblock โ†’ returns a list of transaction IDs (not full data)
  • ~2,500 calls for getrawtransaction โ†’ one per transaction
  • 0 extra calls for the inner vout loop โ†’ outputs are already inside the decoded transaction JSON

The verbose flag (1) means getrawtransaction returns already decoded JSON โ€” no separate decoderawtransaction call is needed.

Solved: 0 / 4