.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/privacy/amounts/plot_04_mimblewimble.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_privacy_amounts_plot_04_mimblewimble.py: Mimblewimble: transactions with no addresses, and cut-through (2016) ==================================================================== A pseudonymous author, "Tom Elvis Jedusor", noticed that in confidential transactions the blinding factor can be the key. An output is just :math:`C = g^v h^r`, owned by whoever knows :math:`r`. When a transaction balances, outputs over inputs leave :math:`h^{k}`, and a Schnorr signature under this *excess* :math:`E = h^k`, kept in a *kernel*, proves it is :math:`h` to a known power and not hidden coins. Since only products matter, transactions merge into one, and an output spent within the merged set cancels with its input. Nodes can drop it and still check the whole chain with .. math:: \frac{\prod \text{outputs}}{\prod \text{inputs}} \, g^{\text{fees} - \text{minted}} = \Big(\prod_k E_k\Big) h^{\text{offset}} . .. GENERATED FROM PYTHON SOURCE LINES 23-27 .. code-block:: Python import matplotlib.pyplot as plt import blockchainkit as bk .. GENERATED FROM PYTHON SOURCE LINES 28-30 A short chain ------------- .. GENERATED FROM PYTHON SOURCE LINES 30-47 .. code-block:: Python coinbase = bk.privacy.mimblewimble_transaction([], [(60, 101)], minted=60, seed=1) pay = bk.privacy.mimblewimble_transaction([(60, 101)], [(35, 202), (24, 303)], fee=1, seed=2) onward = bk.privacy.mimblewimble_transaction([(35, 202)], [(20, 404), (15, 505)], seed=3) back = bk.privacy.mimblewimble_transaction([(24, 303), (20, 404)], [(44, 606)], seed=4) chain = [coinbase, pay, onward, back] assert all(bk.privacy.verify_mimblewimble(tx) for tx in chain) block = bk.privacy.aggregate(chain) compact = bk.privacy.cut_through(block) assert bk.privacy.verify_mimblewimble(block) and bk.privacy.verify_mimblewimble(compact) print(f"merged: {len(block.inputs)} inputs, {len(block.outputs)} outputs") print( f"after cut-through: {len(compact.inputs)} inputs, {len(compact.outputs)} outputs, " f"{len(compact.kernels)} kernels" ) .. rst-class:: sphx-glr-script-out .. code-block:: none merged: 4 inputs, 6 outputs after cut-through: 0 inputs, 2 outputs, 4 kernels .. GENERATED FROM PYTHON SOURCE LINES 48-50 Forged coins do not balance --------------------------- .. GENERATED FROM PYTHON SOURCE LINES 50-60 .. code-block:: Python forged = bk.privacy.MimblewimbleTransaction( compact.inputs, (*compact.outputs, bk.crypto.pedersen_commit(1, 7)), compact.kernels, compact.offset, compact.minted, ) assert not bk.privacy.verify_mimblewimble(forged) .. GENERATED FROM PYTHON SOURCE LINES 61-64 Growth with and without cut-through ----------------------------------- A coin passed hand to hand: each payment spends the last output. .. GENERATED FROM PYTHON SOURCE LINES 64-88 .. code-block:: Python lengths = range(1, 41) history = [coinbase] kept_all, kept_cut = [], [] for n in lengths: history.append( bk.privacy.mimblewimble_transaction([(60, 101 + n - 1)], [(60, 101 + n)], seed=n) ) merged = bk.privacy.aggregate(history) kept_all.append(len(merged.inputs) + len(merged.outputs)) cut = bk.privacy.cut_through(merged) kept_cut.append(len(cut.inputs) + len(cut.outputs)) assert kept_cut[-1] == 1 fig, ax = plt.subplots(figsize=(6, 4)) ax.plot(lengths, kept_all, label="every input and output") ax.plot(lengths, kept_cut, label="after cut-through") ax.set(xlabel="payments", ylabel="commitments stored") ax.set_title("Spent outputs vanish; only kernels grow") ax.legend() fig.tight_layout() plt.show() .. image-sg:: /api/gallery/privacy/amounts/images/sphx_glr_plot_04_mimblewimble_001.png :alt: Spent outputs vanish; only kernels grow :srcset: /api/gallery/privacy/amounts/images/sphx_glr_plot_04_mimblewimble_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 89-94 Exercise -------- Without the offset, how could an observer split a merged block back into its transactions? Try it on two of the transactions above. A worked solution is in :doc:`/exercises/privacy`. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.071 seconds) .. _sphx_glr_download_api_gallery_privacy_amounts_plot_04_mimblewimble.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/privacy/amounts/plot_04_mimblewimble.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_04_mimblewimble.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_04_mimblewimble.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_04_mimblewimble.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_