.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/consensus/pow/plot_03_difficulty_retargeting.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_consensus_pow_plot_03_difficulty_retargeting.py: Difficulty retargeting: keeping ten-minute blocks (Bitcoin 2009) ================================================================ Proof of work is only a clock if its speed is controlled. Bitcoin adjusts its target every 2016 blocks by the ratio of the actual to the expected time, clamped to a factor of four, so blocks return to ten minutes after hashrate rises or falls. What to look for ---------------- When the hashrate quadruples, blocks come every 2.5 minutes until the next retarget, which lowers the target and restores the interval. The clamp limits how far one adjustment can go. The history behind this experiment: :doc:`/history/consensus_breakthroughs`. See :doc:`/exercises/consensus` for a worked solution to the exercise. .. GENERATED FROM PYTHON SOURCE LINES 22-24 A hashrate jump --------------- .. GENERATED FROM PYTHON SOURCE LINES 24-35 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np import blockchainkit as bk hashrates = [1.0] * 3000 + [4.0] * 5000 + [2.0] * 4000 run = bk.consensus.simulate_difficulty(hashrates, interval=600, window=500, seed=2009) late = run.block_times[-1000:] assert abs(np.mean(late) - 600) < 60 assert bk.consensus.retarget(1000, actual_time=10, expected_time=1000) == 250 # Clamped. .. GENERATED FROM PYTHON SOURCE LINES 36-51 .. code-block:: Python blocks = np.arange(len(hashrates)) # Average over 250-block windows, plotted at each window's last block (no edge padding). window_means = np.convolve(run.block_times, np.ones(250) / 250, mode="valid") fig, (top, bottom) = plt.subplots(2, 1, figsize=(8, 5), sharex=True) top.plot(blocks[249:], window_means / 60, color="#2563eb") top.axhline(10, color="black", linestyle="--") top.set(ylabel="minutes per block\n(moving average)", title="Retargeting every 500 blocks") bottom.plot(blocks, hashrates, color="#ea580c", label="hashrate") bottom.plot( blocks, np.array(run.targets) / run.targets[0], color="#16a34a", label="target (relative)" ) bottom.set(xlabel="block height", ylabel="relative value") bottom.legend() fig.tight_layout() .. image-sg:: /api/gallery/consensus/pow/images/sphx_glr_plot_03_difficulty_retargeting_001.png :alt: Retargeting every 500 blocks :srcset: /api/gallery/consensus/pow/images/sphx_glr_plot_03_difficulty_retargeting_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 52-56 Exercise -------- Bitcoin's original code measured 2015 intervals for 2016 blocks, an off-by-one. Estimate the effect on the long-run average block time. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.212 seconds) .. _sphx_glr_download_api_gallery_consensus_pow_plot_03_difficulty_retargeting.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/consensus/pow/plot_03_difficulty_retargeting.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_03_difficulty_retargeting.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_03_difficulty_retargeting.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_03_difficulty_retargeting.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_