.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/privacy/mixing/plot_01_coinjoin.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_mixing_plot_01_coinjoin.py: CoinJoin: many payers, one transaction (2013) ============================================= Gregory Maxwell observed that the inputs of a Bitcoin transaction need not belong to one person. In a CoinJoin, several users each contribute an input and name an output; each checks the joint transaction and signs only its own input. If the mixed outputs all have one *denomination* :math:`d`, an observer cannot tell whose is whose, and the common-input heuristic now merges strangers. Change is the weak point. Each change output is an input minus :math:`d`, .. math:: \text{change}_i = a_i - d , which usually points straight back at its input. Only the equal outputs are anonymous: :math:`n` of them hide each participant among :math:`n`. .. GENERATED FROM PYTHON SOURCE LINES 23-29 .. code-block:: Python from random import Random import matplotlib.pyplot as plt import blockchainkit as bk .. GENERATED FROM PYTHON SOURCE LINES 30-32 One round --------- .. GENERATED FROM PYTHON SOURCE LINES 32-47 .. code-block:: Python participants = [("ann", "a1", 10), ("bob", "b1", 13), ("cat", "c1", 17), ("dan", "d1", 10)] round_ = bk.privacy.coinjoin(participants, 10, seed=1) for address, amount in round_.transaction.outputs: print(f"{address} {amount:>3}") print("anonymity set of the 10-coin outputs:", round_.anonymity_set) links = bk.privacy.link_change(round_.transaction, 10) assert all(round_.owners[c] == round_.owners[i] for c, i in links.items()) print("change linked to its input:", {round_.owners[c] for c in links}) clusters = bk.privacy.cluster_addresses([round_.transaction]) score = bk.privacy.score_clusters(clusters, round_.owners) assert score.false_merges == 1 print("the input heuristic merges", len(clusters[0]), "addresses of 4 users into one cluster") .. rst-class:: sphx-glr-script-out .. code-block:: none b42728bfaea822ae 3 5007614821705756 10 84a78c39bf93a468 10 a9a04e1352d51aff 10 17663be6439ae9c6 7 9f853c0b158c51b3 10 anonymity set of the 10-coin outputs: 4 change linked to its input: {'bob', 'cat'} the input heuristic merges 4 addresses of 4 users into one cluster .. GENERATED FROM PYTHON SOURCE LINES 48-51 Larger rounds ------------- Inputs between 10 and 30 coins, denomination 10. .. GENERATED FROM PYTHON SOURCE LINES 51-71 .. code-block:: Python rng = Random(4) sizes = [2, 5, 10, 20, 50] anonymous, linked = [], [] for n in sizes: people = [(f"u{i}", f"in{i}", rng.randrange(10, 31)) for i in range(n)] r = bk.privacy.coinjoin(people, 10, seed=n) anonymous.append(r.anonymity_set) linked.append(len(bk.privacy.link_change(r.transaction, 10)) / n) # A change output that happens to equal the denomination joins the set too. assert all(a >= n for a, n in zip(anonymous, sizes, strict=True)) fig, ax = plt.subplots(figsize=(6, 4)) ax.plot(sizes, linked, marker="o", color="#dc2626") ax.set(xlabel="participants", ylabel="fraction of change outputs linked", ylim=(0, 1.05)) ax.set_title("Equal outputs hide among n; change points back to its input") fig.tight_layout() plt.show() .. image-sg:: /api/gallery/privacy/mixing/images/sphx_glr_plot_01_coinjoin_001.png :alt: Equal outputs hide among n; change points back to its input :srcset: /api/gallery/privacy/mixing/images/sphx_glr_plot_01_coinjoin_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 72-78 Exercise -------- In a round of three with inputs 15, 15 and 25 and denomination 10, which change outputs can :func:`~blockchainkit.privacy.systems.coinjoin.link_change` link? What does that suggest about choosing inputs? A worked solution is in :doc:`/exercises/privacy`. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.055 seconds) .. _sphx_glr_download_api_gallery_privacy_mixing_plot_01_coinjoin.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/mixing/plot_01_coinjoin.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_01_coinjoin.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_01_coinjoin.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_01_coinjoin.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_