.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/structures/utxo/plot_01_utxo.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code or to run this example in your browser via JupyterLite. .. rst-class:: sphx-glr-example-title .. _sphx_glr_api_gallery_structures_utxo_plot_01_utxo.py: Coins, not accounts: the unspent-output model (Nakamoto 2008) ============================================================= Bitcoin keeps no balances. Value lives in coins, the outputs of earlier transactions, each locked to an owner. A payment consumes whole coins as inputs and creates new outputs: one to the payee, usually one back to the payer as change. Whatever is not assigned to an output goes to the miner as a fee. A coin can be spent once; a double spend is two transactions consuming the same coin. What to look for ---------------- Alice pays Bob 30 from a 50 coin: she gets 18 back as change and 2 goes to fees. Spending the same coin again is rejected, because it is no longer in the unspent set. The history behind this experiment: :doc:`/history/structures_breakthroughs`. .. GENERATED FROM PYTHON SOURCE LINES 23-25 Spend a coin, receive change ---------------------------- .. GENERATED FROM PYTHON SOURCE LINES 25-39 .. code-block:: Python import matplotlib.pyplot as plt import blockchainkit as bk alice_key, bob_key = 7, 11 alice = bk.structures.address(bk.crypto.public_key(alice_key)) bob = bk.structures.address(bk.crypto.public_key(bob_key)) utxos = bk.structures.UTXOSet.genesis({alice: 50}) (coin,) = utxos.coins_of(alice) payment = bk.structures.UTXOTransaction((coin,), ((bob, 30), (alice, 18))).signed([alice_key]) after = utxos.apply(payment) print(f"Bob {after.balance(bob)}, Alice {after.balance(alice)}, fee {payment.fee(utxos)}") assert (after.balance(bob), after.balance(alice), payment.fee(utxos)) == (30, 18, 2) .. rst-class:: sphx-glr-script-out .. code-block:: none Bob 30, Alice 18, fee 2 .. GENERATED FROM PYTHON SOURCE LINES 40-42 A coin cannot be spent twice ---------------------------- .. GENERATED FROM PYTHON SOURCE LINES 42-48 .. code-block:: Python double_spend = bk.structures.UTXOTransaction((coin,), ((alice, 50),)).signed([alice_key]) try: after.apply(double_spend) except ValueError as error: print("Rejected:", error) .. rst-class:: sphx-glr-script-out .. code-block:: none Rejected: OutPoint(aeebad4a796f..., 0) is not an unspent output .. GENERATED FROM PYTHON SOURCE LINES 49-51 Bob combines coins ------------------ .. GENERATED FROM PYTHON SOURCE LINES 51-79 .. code-block:: Python second = bk.structures.UTXOTransaction((after.coins_of(alice)[0],), ((bob, 18),)).signed( [alice_key] ) after2 = after.apply(second) merge = bk.structures.UTXOTransaction(after2.coins_of(bob), ((alice, 48),)).signed( [bob_key, bob_key] ) final = after2.apply(merge) assert final.balance(alice) == 48 and len(final) == 1 stages = {"genesis": utxos, "pay Bob": after, "change to Bob": after2, "Bob merges": final} fig, ax = plt.subplots(figsize=(8, 3.5)) for row, state in enumerate(stages.values()): left = 0 for outpoint in sorted(state.coins_of(alice) + state.coins_of(bob)): coin_ = state[outpoint] color = "#2563eb" if coin_.owner == alice else "#ea580c" ax.barh(row, coin_.amount, left=left, color=color, edgecolor="white") left += coin_.amount ax.set( yticks=range(len(stages)), yticklabels=list(stages), xlabel="value (blue: Alice, orange: Bob)", title="Unspent coins after each transaction", ) ax.invert_yaxis() fig.tight_layout() .. image-sg:: /api/gallery/structures/utxo/images/sphx_glr_plot_01_utxo_001.png :alt: Unspent coins after each transaction :srcset: /api/gallery/structures/utxo/images/sphx_glr_plot_01_utxo_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 80-85 Exercise -------- In the UTXO model, how does a wallet compute "its balance"? Why can two transactions that spend different coins of the same owner be validated in parallel, while two account-model transfers from one sender cannot? .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.221 seconds) .. _sphx_glr_download_api_gallery_structures_utxo_plot_01_utxo.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: lite-badge .. image:: images/jupyterlite_badge_logo.svg :target: ../../../../lite/lab/index.html?path=api/gallery/structures/utxo/plot_01_utxo.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_01_utxo.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_01_utxo.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_01_utxo.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_