.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/contracts/foundations/plot_01_ricardian_contracts.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_contracts_foundations_plot_01_ricardian_contracts.py: Grigg's Ricardian contracts: a bond whose terms are its name (1996) =================================================================== Ian Grigg designed the Ricardian contract to issue bonds and currencies on the Ricardo payment system. One document is both a legal contract a person can read and a set of parameters a program can parse. The issuer signs it, and its hash becomes the instrument's identifier: .. math:: \mathrm{id} = H(\mathrm{prose} \,\|\, \mathrm{parameters}). Every payment cites the identifier, so there is never a question which terms a payment was made under. Change one word of the prose and the hash, and so the instrument, changes. Here a token is issued under a signed bond: the supply comes from the same document the holder reads, payments citing the terms go through, and payments citing an edited version are refused. .. GENERATED FROM PYTHON SOURCE LINES 22-26 .. code-block:: Python import matplotlib.pyplot as plt import blockchainkit as bk .. GENERATED FROM PYTHON SOURCE LINES 27-29 Write, sign and issue --------------------- .. GENERATED FROM PYTHON SOURCE LINES 29-50 .. code-block:: Python ISSUER_KEY = 7 # A fixed teaching key: never use such a key for real money. terms = ( "The issuer will pay the holder of each of the {supply} units a coupon of " "{coupon}% a year until {maturity}, then redeem it at par." ) bond = bk.contracts.ricardian_contract( terms, {"supply": 1_000, "coupon": 5, "maturity": "2030-12-31"}, ISSUER_KEY ) print(bond.rendered) print("identifier", bond.identifier[:16], "...", "signed:", bk.contracts.verify_ricardian(bond)) assert bk.contracts.verify_ricardian(bond) world = bk.contracts.World() token = world.deploy( "issuer", bk.contracts.RicardianToken, bond.identifier, bond.parameters["supply"] ) assert world.view(token, "total_supply") == 1_000 paid = world.transact("issuer", token, "transfer_under", bond.identifier, "holder", 10) assert paid.success .. rst-class:: sphx-glr-script-out .. code-block:: none The issuer will pay the holder of each of the 1000 units a coupon of 5% a year until 2030-12-31, then redeem it at par. identifier 9ed66d014ecbcc43 ... signed: True .. GENERATED FROM PYTHON SOURCE LINES 51-53 One word changes the instrument ------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 53-86 .. code-block:: Python edited = terms.replace("will pay", "may pay") edited_id = bk.contracts.ricardian_digest(edited, bond.parameters).hex() refused = world.transact("issuer", token, "transfer_under", edited_id, "holder", 10) print("payment under edited terms:", refused.error) assert refused.error == "payment cites different terms" assert world.view(token, "balance_of", "holder") == 10 # A digest that does not match its prose fails verification. tampered = type(bond)(edited, bond.parameters, bond.issuer, bond.signature, bond.digest) assert not bk.contracts.verify_ricardian(tampered) words = terms.split() changed_bits = [] for index in range(len(words)): variant = " ".join(words[:index] + [words[index] + "s"] + words[index + 1 :]) digest = bk.contracts.ricardian_digest(variant, bond.parameters) changed_bits.append(bk.crypto.hamming_distance(digest, bond.digest)) assert min(changed_bits) > 90 fig, ax = plt.subplots(figsize=(8, 3.5)) ax.bar(range(len(words)), changed_bits, color="#2563eb") ax.axhline(128, color="#dc2626", linestyle="--", label="half of 256 bits") ax.set( xlabel="word edited (an 's' appended)", ylabel="identifier bits changed", title="Any edit to the prose renames the instrument", ) ax.legend() fig.tight_layout() plt.show() .. image-sg:: /api/gallery/contracts/foundations/images/sphx_glr_plot_01_ricardian_contracts_001.png :alt: Any edit to the prose renames the instrument :srcset: /api/gallery/contracts/foundations/images/sphx_glr_plot_01_ricardian_contracts_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none payment under edited terms: payment cites different terms .. GENERATED FROM PYTHON SOURCE LINES 87-93 Exercise -------- The parameters are hashed with the prose. Show that changing only the coupon, without touching the text, also changes the identifier. Why must the parameters be inside the signed document rather than stored only in the token contract? .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.061 seconds) .. _sphx_glr_download_api_gallery_contracts_foundations_plot_01_ricardian_contracts.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/contracts/foundations/plot_01_ricardian_contracts.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_01_ricardian_contracts.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_01_ricardian_contracts.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_01_ricardian_contracts.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_