.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/vm/contracts/plot_01_vending_machine.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_vm_contracts_plot_01_vending_machine.py: Smart contracts: the vending machine (Szabo 1994) ================================================= Nick Szabo coined *smart contract* for terms of an agreement enforced by a mechanism rather than by courts, and gave the vending machine as the primordial example: anyone who inserts enough money gets the item and the change, and nobody can take the goods without paying. A blockchain contract is such a machine whose code and state every node can check. What to look for ---------------- Every outcome follows from the code: a sale moves exactly one item and the price, underpaying or buying from an empty machine changes nothing, and the machine's books always balance: revenue equals price times items sold. The history behind this experiment: :doc:`/history/vm_breakthroughs`. .. GENERATED FROM PYTHON SOURCE LINES 22-24 Run a day of customers ---------------------- .. GENERATED FROM PYTHON SOURCE LINES 24-59 .. code-block:: Python from random import Random import matplotlib.pyplot as plt import blockchainkit as bk machine = bk.vm.vending_machine() STOCK, PRICE, REVENUE = 0, 1, 2 storage = {STOCK: 10, PRICE: 3, REVENUE: 0} rng = Random(4) history = [] for _ in range(25): payment = rng.randint(0, 6) try: result = bk.vm.execute(machine, arguments=(payment,), storage=storage) storage = dict(result.storage) history.append(("sale", payment, result.stack[0])) except bk.vm.VMError: history.append(("refused", payment, payment)) # Nothing happened; money returned. sold = 10 - storage[STOCK] assert storage.get(REVENUE, 0) == sold * storage[PRICE] sales = [h for h in history if h[0] == "sale"] print(len(sales), "sales;", storage) assert all(change == paid - 3 for _, paid, change in sales) assert storage[STOCK] == 0 or all(h[1] < 3 for h in history if h[0] == "refused") fig, ax = plt.subplots(figsize=(8, 3.5)) colors = {"sale": "#16a34a", "refused": "#dc2626"} for i, (kind, paid, _) in enumerate(history): ax.bar(i, paid, color=colors[kind]) ax.axhline(3, color="black", linestyle="--", label="price") ax.set(xlabel="customer", ylabel="payment", title="Green: sale, red: refused (nothing changes)") ax.legend() fig.tight_layout() .. image-sg:: /api/gallery/vm/contracts/images/sphx_glr_plot_01_vending_machine_001.png :alt: Green: sale, red: refused (nothing changes) :srcset: /api/gallery/vm/contracts/images/sphx_glr_plot_01_vending_machine_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none 10 sales; {0: 0, 1: 3, 2: 30} .. GENERATED FROM PYTHON SOURCE LINES 60-65 Exercise -------- Add an owner withdrawal: a second program that moves the revenue out and resets it to zero. What stops a customer from running it? (This machine has no notion of a caller; what would the contract need to know?) .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.134 seconds) .. _sphx_glr_download_api_gallery_vm_contracts_plot_01_vending_machine.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/vm/contracts/plot_01_vending_machine.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_01_vending_machine.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_01_vending_machine.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_01_vending_machine.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_