.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/wallets/addresses/plot_03_bech32m_checksum_flaw.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_wallets_addresses_plot_03_bech32m_checksum_flaw.py: Bech32m and the insertion flaw in Bech32 (BIP350, 2020) ======================================================= In 2019 it was found that Bech32 has a blind spot: when a string ends in ``p``, inserting or deleting ``q`` characters just before that ``p`` leaves the checksum valid. ``q`` is the value 0, and ``p`` is 1, the constant the checksum must leave, so the extra zeros multiply the polynomial by powers of x without changing its remainder. Witness version 0 survives, because its programs must be 20 or 32 bytes, but Taproot's version 1 and later allow other lengths. Pieter Wuille's Bech32m changes only the constant, .. math:: \mathrm{polymod}(\dots) = \texttt{0x2bc830a3}, and is required from witness version 1 on. .. GENERATED FROM PYTHON SOURCE LINES 21-25 .. code-block:: Python import matplotlib.pyplot as plt import blockchainkit as bk .. GENERATED FROM PYTHON SOURCE LINES 26-28 A string ending in p -------------------- .. GENERATED FROM PYTHON SOURCE LINES 28-56 .. code-block:: Python def ending_in_p(encoding): for n in range(1_000): data = [n % 32, n // 32 % 32, 7, 3, 1] text = bk.wallets.bech32_encode("bc", data, encoding) if text.endswith("p"): return text raise ValueError("no string found") def accepts(text): try: bk.wallets.bech32_decode(text) except ValueError: return False return True original = ending_in_p("bech32") print("original:", original) inserted = {} for encoding in ("bech32", "bech32m"): text = ending_in_p(encoding) inserted[encoding] = [accepts(text[:-1] + "q" * k + "p") for k in range(1, 9)] print(f"{encoding:8} with 1..8 q's inserted:", inserted[encoding]) assert all(inserted["bech32"]) and not any(inserted["bech32m"]) .. rst-class:: sphx-glr-script-out .. code-block:: none original: bc1sq8rpprd0lp bech32 with 1..8 q's inserted: [True, True, True, True, True, True, True, True] bech32m with 1..8 q's inserted: [False, False, False, False, False, False, False, False] .. GENERATED FROM PYTHON SOURCE LINES 57-59 Why version 0 was safe ---------------------- .. GENERATED FROM PYTHON SOURCE LINES 59-82 .. code-block:: Python program = bytes(20) v0 = bk.wallets.segwit_encode("bc", 0, program) assert bk.wallets.segwit_decode("bc", v0).program == program taproot = bk.wallets.segwit_encode("bc", 1, bytes(32)) print("version 0:", v0) print("version 1:", taproot, bk.wallets.bech32_decode(taproot).encoding) fig, ax = plt.subplots(figsize=(6, 4)) k = list(range(1, 9)) ax.plot(k, inserted["bech32"], "o-", color="#dc2626", label="Bech32") ax.plot(k, inserted["bech32m"], "o-", color="#2563eb", label="Bech32m") ax.set( xlabel="q characters inserted before the final p", ylabel="accepted", yticks=[0, 1], yticklabels=["no", "yes"], ) ax.set_title("A new constant closes the insertion hole") ax.legend() fig.tight_layout() plt.show() .. image-sg:: /api/gallery/wallets/addresses/images/sphx_glr_plot_03_bech32m_checksum_flaw_001.png :alt: A new constant closes the insertion hole :srcset: /api/gallery/wallets/addresses/images/sphx_glr_plot_03_bech32m_checksum_flaw_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none version 0: bc1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq9e75rs version 1: bc1pqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpqqenm bech32m .. GENERATED FROM PYTHON SOURCE LINES 83-88 Exercise -------- Does deleting a ``q`` before a final ``p`` fool Bech32 too? Find a string ending in ``qp`` and try. A worked solution is in :doc:`/exercises/wallets`. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.049 seconds) .. _sphx_glr_download_api_gallery_wallets_addresses_plot_03_bech32m_checksum_flaw.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/wallets/addresses/plot_03_bech32m_checksum_flaw.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_03_bech32m_checksum_flaw.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_03_bech32m_checksum_flaw.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_03_bech32m_checksum_flaw.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_