.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/structures/spv/plot_01_light_clients.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_spv_plot_01_light_clients.py: Simplified payment verification: light clients (Nakamoto 2008) ============================================================== Section 8 of the Bitcoin whitepaper describes a client that never downloads blocks. It keeps only the chain of block headers, checks that they link and carry proof of work, and asks a full node for a Merkle proof that a payment is in one of them. Phones run wallets this way. What to look for ---------------- The client verifies 20 headers and one inclusion proof: a few kilobytes instead of every transaction. What it gives up is visible too: it trusts that the heaviest header chain is valid, without checking the transactions inside. The history behind this experiment: :doc:`/history/structures_breakthroughs`. .. GENERATED FROM PYTHON SOURCE LINES 22-24 A full node mines 20 blocks of payments --------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 24-46 .. code-block:: Python import matplotlib.pyplot as plt import blockchainkit as bk alice_key = 7 alice = bk.crypto.public_key(alice_key) bob = bk.structures.address(bk.crypto.public_key(11)) genesis = bk.consensus.mine(bk.structures.Block(difficulty=6)).block blocks, nonce = [genesis], 0 for height in range(1, 20): payments = [] for _ in range(8): tx = bk.structures.Transaction(alice, bob, 1, nonce) payments.append( tx.signed( alice_key, signing_nonce=bk.crypto.deterministic_nonce(alice_key, tx.payload()) ) ) nonce += 1 block = bk.structures.Block(blocks[-1].hash, tuple(payments), height, height, 6) blocks.append(bk.consensus.mine(block).block) .. GENERATED FROM PYTHON SOURCE LINES 47-49 The light client checks headers and one proof --------------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 49-58 .. code-block:: Python headers = [block.to_header() for block in blocks] work = bk.structures.verify_header_chain(headers) target_block = blocks[13] payment = target_block.transactions[5] tree = bk.structures.MerkleTree(tx.to_bytes() for tx in target_block.transactions) proof = tree.proof(5) assert bk.structures.verify_proof(payment.to_bytes(), proof, headers[13].merkle_root) print(f"verified payment in block 13 under {work} units of work") .. rst-class:: sphx-glr-script-out .. code-block:: none verified payment in block 13 under 1280 units of work .. GENERATED FROM PYTHON SOURCE LINES 59-61 Bytes a light client downloads, against a full node --------------------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 61-73 .. code-block:: Python header_bytes = sum(len(h.encode()) for h in headers) proof_bytes = 32 * sum(s is not None for s in proof.siblings) full_bytes = sum(len(b.header()) + sum(len(tx.to_bytes()) for tx in b.transactions) for b in blocks) fig, ax = plt.subplots(figsize=(7, 3.2)) ax.barh( ["full node", "light client"], [full_bytes, header_bytes + proof_bytes], color=["#64748b", "#2563eb"], ) ax.set(xlabel="bytes downloaded", title="Headers and a Merkle proof instead of every block") fig.tight_layout() .. image-sg:: /api/gallery/structures/spv/images/sphx_glr_plot_01_light_clients_001.png :alt: Headers and a Merkle proof instead of every block :srcset: /api/gallery/structures/spv/images/sphx_glr_plot_01_light_clients_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 74-79 Exercise -------- A light client accepts the heaviest header chain. Describe a block whose header is valid but whose transactions are not. Why can't the client notice, and why does honest-majority mining make that unlikely to last? .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 1.476 seconds) .. _sphx_glr_download_api_gallery_structures_spv_plot_01_light_clients.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/spv/plot_01_light_clients.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_01_light_clients.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_01_light_clients.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_01_light_clients.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_