.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/structures/ledger/plot_02_account_nonces.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_ledger_plot_02_account_nonces.py: The account model and nonces (Ethereum 2014) ============================================ Ethereum replaced Bitcoin's coins with accounts: a balance per address, and a *nonce* counting the transactions each account has sent. A transaction must carry the next expected nonce, so it can be applied once and only in order. Without it, anyone could replay a signed payment again and again. What to look for ---------------- The same signed transfer is accepted once and rejected on replay. A transfer with a skipped nonce waits until the gap is filled. Account balances make wallets simple, at the cost of this global ordering per sender. The history behind this experiment: :doc:`/history/structures_breakthroughs`. .. GENERATED FROM PYTHON SOURCE LINES 21-23 Replay is rejected by the nonce ------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 23-49 .. code-block:: Python import matplotlib.pyplot as plt import blockchainkit as bk alice_key = 7 alice_pub = bk.crypto.public_key(alice_key) alice = bk.structures.address(alice_pub) bob = bk.structures.address(bk.crypto.public_key(11)) ledger = bk.structures.Ledger({alice: 100}) def pay(amount, nonce): tx = bk.structures.Transaction(alice_pub, bob, amount, nonce) return tx.signed( alice_key, signing_nonce=bk.crypto.deterministic_nonce(alice_key, tx.payload()) ) first = pay(10, 0) ledger = ledger.apply([first]) try: ledger.apply([first]) except ValueError as error: print("Replay rejected:", error) assert ledger.balances[bob] == 10 and ledger.nonces[alice] == 1 .. rst-class:: sphx-glr-script-out .. code-block:: none Replay rejected: unexpected account nonce (replay or out-of-order transfer) .. GENERATED FROM PYTHON SOURCE LINES 50-52 Out-of-order transactions wait for the gap ------------------------------------------ .. GENERATED FROM PYTHON SOURCE LINES 52-60 .. code-block:: Python later = pay(5, 2) try: ledger.apply([later]) except ValueError: print("Nonce 2 cannot run before nonce 1") ledger = ledger.apply([pay(3, 1), later]) assert ledger.nonces[alice] == 3 and ledger.balances[bob] == 18 .. rst-class:: sphx-glr-script-out .. code-block:: none Nonce 2 cannot run before nonce 1 .. GENERATED FROM PYTHON SOURCE LINES 61-63 Nonce and balance after each transfer ------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 63-75 .. code-block:: Python history = [(0, 100)] state = bk.structures.Ledger({alice: 100}) for nonce, amount in enumerate([10, 3, 5, 20, 7]): state = state.apply([pay(amount, nonce)]) history.append((state.nonces[alice], state.balances[alice])) fig, ax = plt.subplots(figsize=(7, 3.5)) ax.step(*zip(*history, strict=True), where="post", marker="o") ax.set( xlabel="Alice's account nonce", ylabel="Alice's balance", title="One nonce per transaction sent" ) fig.tight_layout() .. image-sg:: /api/gallery/structures/ledger/images/sphx_glr_plot_02_account_nonces_001.png :alt: One nonce per transaction sent :srcset: /api/gallery/structures/ledger/images/sphx_glr_plot_02_account_nonces_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 76-81 Exercise -------- The account nonce and the signing nonce are different ideas sharing a name. Which one is public and sequential, which one secret and random, and what goes wrong when each is reused? .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.377 seconds) .. _sphx_glr_download_api_gallery_structures_ledger_plot_02_account_nonces.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/ledger/plot_02_account_nonces.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_02_account_nonces.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_02_account_nonces.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_02_account_nonces.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_