.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/structures/transactions/plot_01_malleability.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_transactions_plot_01_malleability.py: Transaction malleability and segregated witness (2014-2017) =========================================================== Bitcoin's transaction id hashed the whole transaction, signatures included. Anyone relaying a transaction could alter its signature encoding without invalidating it, changing the id. In 2014 the Mt. Gox exchange blamed malleability for lost withdrawals; Decker and Wattenhofer found it explained only a small fraction. Segregated witness (2017) moved signatures out of the id, which also made payment channels such as Lightning safe to build. What to look for ---------------- The same payment, signed twice, has two txids: a child transaction that named the first id would point at nothing. The unsigned id, like SegWit's txid, is the same for every valid signature. The history behind this experiment: :doc:`/history/structures_breakthroughs`. .. GENERATED FROM PYTHON SOURCE LINES 23-25 One payment, two signatures, two txids -------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 25-41 .. code-block:: Python import matplotlib.pyplot as plt import blockchainkit as bk alice_key = 7 payment = bk.structures.Transaction( bk.crypto.public_key(alice_key), bk.structures.address(bk.crypto.public_key(11)), 25, 0 ) first = payment.signed(alice_key, signing_nonce=1001) second = payment.signed(alice_key, signing_nonce=2002) # Same payment, re-signed. assert first.is_valid() and second.is_valid() assert first.txid != second.txid assert first.unsigned_id == second.unsigned_id print("txid: ", first.txid.hex()[:16], "vs", second.txid.hex()[:16]) print("unsigned id:", first.unsigned_id.hex()[:16], "for both") .. rst-class:: sphx-glr-script-out .. code-block:: none txid: fa96fe8ee56adcbe vs df5d5b6e70155532 unsigned id: bf31ad29acf982f8 for both .. GENERATED FROM PYTHON SOURCE LINES 42-44 A child that names its parent by txid breaks -------------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 44-49 .. code-block:: Python child_refers_to = first.txid confirmed = second # A miner confirmed the re-signed version. assert child_refers_to != confirmed.txid assert first.unsigned_id == confirmed.unsigned_id # A SegWit-style reference still works. .. GENERATED FROM PYTHON SOURCE LINES 50-63 .. code-block:: Python ids = {f"signature {n}": payment.signed(alice_key, signing_nonce=n) for n in (11, 22, 33, 44)} fig, ax = plt.subplots(figsize=(8, 3)) for row, (label, tx) in enumerate(ids.items()): ax.text(0.02, row, label, va="center") ax.text(0.30, row, tx.txid.hex()[:20], va="center", family="monospace", color="#dc2626") ax.text(0.68, row, tx.unsigned_id.hex()[:20], va="center", family="monospace", color="#16a34a") ax.text(0.30, len(ids), "txid (covers signature)", weight="bold") ax.text(0.68, len(ids), "unsigned id (SegWit)", weight="bold") ax.set(xlim=(0, 1), ylim=(-0.7, len(ids) + 0.5), title="Re-signing changes one id, not the other") ax.axis("off") ax.invert_yaxis() fig.tight_layout() .. image-sg:: /api/gallery/structures/transactions/images/sphx_glr_plot_01_malleability_001.png :alt: Re-signing changes one id, not the other :srcset: /api/gallery/structures/transactions/images/sphx_glr_plot_01_malleability_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 64-69 Exercise -------- In Lightning, two parties pre-sign a refund transaction that spends a funding transaction before it is broadcast. Explain why the refund needs an id for its parent that cannot change. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.159 seconds) .. _sphx_glr_download_api_gallery_structures_transactions_plot_01_malleability.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/transactions/plot_01_malleability.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_01_malleability.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_01_malleability.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_01_malleability.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_