TeachMeBitcoin

Custom Python UTXO Tracker

From TeachMeBitcoin, the free encyclopedia Reading time: 2 min

Custom Python UTXO Tracker

In this final simulation, we will build a Python script that mimics a Bitcoin node's Chainstate. The script will maintain a database of UTXOs and process "transactions" by verifying that inputs exist and updating the set with new outputs.

The Python Chainstate Simulator

class Chainstate:
    def __init__(self):
        # Dictionary acting as our LevelDB
        # Key: "TXID:VOUT", Value: Amount in satoshis
        self.utxo_set = {
            "genesis_tx:0": 5000000000, # 50 BTC
            "alpha_tx:0": 2500000000,   # 25 BTC
        }

    def process_transaction(self, txid, inputs, outputs):
        print(f"\n--- Processing Transaction: {txid} ---")

        # 1. Verify Inputs exist in UTXO set
        for outpoint in inputs:
            if outpoint not in self.utxo_set:
                print(f"[REJECTED] Input {outpoint} does not exist or was already spent!")
                return False

        # 2. Calculate input sum and REMOVE spent UTXOs
        total_in = 0
        for outpoint in inputs:
            total_in += self.utxo_set.pop(outpoint)
            print(f"[*] Consumed: {outpoint}")

        # 3. ADD new UTXOs from outputs
        total_out = 0
        for i, amount in enumerate(outputs):
            new_outpoint = f"{txid}:{i}"
            self.utxo_set[new_outpoint] = amount
            total_out += amount
            print(f"[*] Created:  {new_outpoint} ({amount:,} sats)")

        # 4. Calculate Fee (Implicit)
        fee = total_in - total_out
        print(f"[*] Total Fee collected by miner: {fee:,} sats")
        return True

    def show_status(self):
        print(f"\n--- Current UTXO Set Status ---")
        print(f"Total Entries: {len(self.utxo_set)}")
        for key, val in self.utxo_set.items():
            print(f" - {key}: {val:,} sats")

# --- Simulation ---
node = Chainstate()
node.show_status()

# Spend the genesis coin
node.process_transaction("payment_1", ["genesis_tx:0"], [1000000000, 3999900000])

# Spend a coin that was just created
node.process_transaction("payment_2", ["payment_1:0"], [500000000, 499900000])

node.show_status()

How to Run the Tracker

  1. Ensure you have Python 3 installed.

  2. Copy the code into a file named utxo_tracker.py.

  3. Run it using python3 utxo_tracker.py.

Technical Takeaways

  1. Implicit Removal: Spending isn't "moving" money; it's the destruction of an old record and the creation of new ones.

  2. Constraint Check: In a real node, the total_out must never exceed total_in. If it does, the money is being "printed," and the node will reject the block.

  3. Database Efficiency: By using a dictionary (Key-Value), the node can check if a coin is valid in O(1) time, which is extremely fast regardless of how many billions of transactions have happened.

Congratulations! You have completed the UTXO Model module. You now understand the true state of the Bitcoin network.

☕ Help support TeachMeBitcoin

TeachMeBitcoin is an ad-free, open-source educational repository curated by a passionate team of Bitcoin researchers and educators for public benefit. If you found our articles helpful, please consider supporting our hosting and ongoing content updates with a clean donation:

Ethereum: 0x578417C51783663D8A6A811B3544E1f779D39A85
Bitcoin: bc1q77k9e95rn669kpzyjr8ke9w95zhk7pa5s63qzz
Solana: 4ycT2ayqeMucixj3wS8Ay8Tq9NRDYRPKYbj3UGESyQ4J
Address copied to clipboard!