<p>6 blocks per second can be sustained.</p>
<h3>Satisfying the MTP rule</h3>
<p>The timestamp of each block must be strictly larger than the median of the timetamps of the 11 blocks before it.</p>
<p>This can be satisfied using a pattern consisting of repeating the same timestamp 6 times, then incrementing by one second, and repeat again.</p>
<p>So the series would be:</p>
<pre><code>... 0 0 0 0 0 0 1 1 1 1 1 1 2 2 2 2 2 2 3 3 3 3 3 3 3 ...
</code></pre>
<p>We can abstract over the actual values. With that, there are just 6 distinct &quot;blocks&quot;, based on what the 11 timestamps before it were:</p>
<ul>
<li><code>T+0 T+0 T+0 T+0 T+0 T+1 T+1 T+1 T+1 T+1 T+1</code>: MTP=<code>T+2</code></li>
<li><code>T+0 T+0 T+0 T+0 T+1 T+1 T+1 T+1 T+1 T+1 T+2</code>: MTP=<code>T+2</code></li>
<li><code>T+0 T+0 T+0 T+1 T+1 T+1 T+1 T+1 T+1 T+2 T+2</code>: MTP=<code>T+2</code></li>
<li><code>T+0 T+0 T+1 T+1 T+1 T+1 T+1 T+1 T+2 T+2 T+2</code>: MTP=<code>T+2</code></li>
<li><code>T+0 T+1 T+1 T+1 T+1 T+1 T+1 T+2 T+2 T+2 T+2</code>: MTP=<code>T+2</code></li>
<li><code>T+1 T+1 T+1 T+1 T+1 T+1 T+2 T+2 T+2 T+2 T+2</code>: MTP=<code>T+2</code></li>
</ul>
<p>Which in each case continues the pattern.</p>
<h3>Keeping the difficulty low</h3>
<p>Using the pattern above naively would result in the difficulty adjustment period quadrupling the difficulty every period (the maximum allowed).</p>
<p>To prevent it from doing so, it is necessary to exploit the timewarp bug.</p>
<p>The winning strategy involves setting the timestamp of every block exactly 2 weeks in the past, except those blocks whose height modulo 2016 equals 2015; those are given the current time (or up to two hours in the future). This will make the adjustment algorithm see every period as having taken 2 weeks, and thus not cause any adjustment.</p>

CC BY-SA 4.0
2024-07-19T16:02:57.413Z
2024-07-22T11:50:58.113Z
2024-07-22T11:50:58.113Z
Pieter Wuille
<p>An attacker would be able to sustain a cadence of 6 blocks per second without increasing the difficulty.</p>
<p>The attacker would start by holding the timestamps back by more than 14 days to erode the difficulty. Once the difficulty was reduced to the minimum, they would be able to increase the timestamp only every sixth block, keeping all blocks’ timestamps at least two weeks in the past except for the timestamp of each last block per difficulty period, which they would timestamp with the present time or up to 2h into the future at least 14 days ahead of the first block in the same period.</p>
<p>While the timestamps eventually settle on a series of the same value repeating six times before incrementing it, there is a quirk in how the timestamps sort to find the median when timestamps are first shifted to increasing minimally.</p>
<p>Assuming we start with 11 blocks spaced at 10 minutes, the subsequent minimum timestamps would be as follows:</p>
<div class="s-table-container"><table class="s-table">
<thead>
<tr>
<th style="text-align: center;">Block height</th>
<th style="text-align: center;">Timestamp [s]</th>
<th style="text-align: center;">Timestamps of prior 11 blocks (median bold)</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;">1</td>
<td style="text-align: center;">0</td>
<td style="text-align: center;">-</td>
</tr>
<tr>
<td style="text-align: center;">2</td>
<td style="text-align: center;">600</td>
<td style="text-align: center;">-</td>
</tr>
<tr>
<td style="text-align: center;">3</td>
<td style="text-align: center;">1200</td>
<td style="text-align: center;">-</td>
</tr>
<tr>
<td style="text-align: center;">4</td>
<td style="text-align: center;">1800</td>
<td style="text-align: center;">-</td>
</tr>
<tr>
<td style="text-align: center;">5</td>
<td style="text-align: center;">2400</td>
<td style="text-align: center;">-</td>
</tr>
<tr>
<td style="text-align: center;">6</td>
<td style="text-align: center;">3000</td>
<td style="text-align: center;">-</td>
</tr>
<tr>
<td style="text-align: center;">7</td>
<td style="text-align: center;">3600</td>
<td style="text-align: center;">-</td>
</tr>
<tr>
<td style="text-align: center;">8</td>
<td style="text-align: center;">4200</td>
<td style="text-align: center;">-</td>
</tr>
<tr>
<td style="text-align: center;">9</td>
<td style="text-align: center;">4800</td>
<td style="text-align: center;">-</td>
</tr>
<tr>
<td style="text-align: center;">10</td>
<td style="text-align: center;">5400</td>
<td style="text-align: center;">-</td>
</tr>
<tr>
<td style="text-align: center;">11</td>
<td style="text-align: center;">6000</td>
<td style="text-align: center;">-</td>
</tr>
<tr>
<td style="text-align: center;">12</td>
<td style="text-align: center;">3001</td>
<td style="text-align: center;">0, 600, 1200, 1800, 2400, <strong>3000</strong>, 3600, 4200, 4800, 5400, 6000</td>
</tr>
<tr>
<td style="text-align: center;">13</td>
<td style="text-align: center;">3002</td>
<td style="text-align: center;">600, 1200, 1800, 2400, 3000, 3600, 4200, 4800, 5400, 6000, <strong>3001</strong></td>
</tr>
<tr>
<td style="text-align: center;">14</td>
<td style="text-align: center;">3003</td>
<td style="text-align: center;">1200, 1800, 2400, 3000, 3600, 4200, 4800, 5400, 6000, 3001, <strong>3002</strong></td>
</tr>
<tr>
<td style="text-align: center;">15</td>
<td style="text-align: center;">3004</td>
<td style="text-align: center;">1800, 2400, 3000, 3600, 4200, 4800, 5400, 6000, 3001, 3002, <strong>3003</strong></td>
</tr>
<tr>
<td style="text-align: center;">16</td>
<td style="text-align: center;">3005</td>
<td style="text-align: center;">2400, 3000, 3600, 4200, 4800, 5400, 6000, 3001, 3002, 3003, <strong>3004</strong></td>
</tr>
<tr>
<td style="text-align: center;">17</td>
<td style="text-align: center;">3006</td>
<td style="text-align: center;">3000, 3600, 4200, 4800, 5400, 6000, 3001, 3002, 3003, 3004, <strong>3005</strong></td>
</tr>
<tr>
<td style="text-align: center;">18</td>
<td style="text-align: center;">3007</td>
<td style="text-align: center;">3600, 4200, 4800, 5400, 6000, 3001, 3002, 3003, 3004, 3005, <strong>3006</strong></td>
</tr>
<tr>
<td style="text-align: center;">19</td>
<td style="text-align: center;">3007</td>
<td style="text-align: center;">4200, 4800, 5400, 6000, 3001, 3002, 3003, 3004, 3005, <strong>3006</strong>, 3007</td>
</tr>
<tr>
<td style="text-align: center;">20</td>
<td style="text-align: center;">3007</td>
<td style="text-align: center;">4800, 5400, 6000, 3001, 3002, 3003, 3004, 3005, <strong>3006</strong>, 3007, 3007</td>
</tr>
<tr>
<td style="text-align: center;">21</td>
<td style="text-align: center;">3007</td>
<td style="text-align: center;">5400, 6000, 3001, 3002, 3003, 3004, 3005, <strong>3006</strong>, 3007, 3007, 3007</td>
</tr>
<tr>
<td style="text-align: center;">22</td>
<td style="text-align: center;">3007</td>
<td style="text-align: center;">6000, 3001, 3002, 3003, 3004, 3005, <strong>3006</strong>, 3007, 3007, 3007, 3007</td>
</tr>
<tr>
<td style="text-align: center;">23</td>
<td style="text-align: center;">3007</td>
<td style="text-align: center;">3001, 3002, 3003, 3004, 3005, <strong>3006</strong>, 3007, 3007, 3007, 3007, 3007</td>
</tr>
<tr>
<td style="text-align: center;">24</td>
<td style="text-align: center;">3008</td>
<td style="text-align: center;">3002, 3003, 3004, 3005, 3006, <strong>3007</strong>, 3007, 3007, 3007, 3007, 3007</td>
</tr>
<tr>
<td style="text-align: center;">25</td>
<td style="text-align: center;">3008</td>
<td style="text-align: center;">3003, 3004, 3005, 3006, 3007, <strong>3007</strong>, 3007, 3007, 3007, 3007, 3008</td>
</tr>
<tr>
<td style="text-align: center;">26</td>
<td style="text-align: center;">3008</td>
<td style="text-align: center;">3004, 3005, 3006, 3007, 3007, <strong>3007</strong>,  3007, 3007, 3007, 3008, 3008</td>
</tr>
<tr>
<td style="text-align: center;">27</td>
<td style="text-align: center;">3008</td>
<td style="text-align: center;">3005, 3006, 3007, 3007, 3007, <strong>3007</strong>, 3007, 3007, 3008, 3008, 3008</td>
</tr>
<tr>
<td style="text-align: center;">28</td>
<td style="text-align: center;">3008</td>
<td style="text-align: center;">3006, 3007, 3007, 3007,  3007, <strong>3007</strong>, 3007, 3008, 3008, 3008, 3008</td>
</tr>
<tr>
<td style="text-align: center;">29</td>
<td style="text-align: center;">3008</td>
<td style="text-align: center;">3007, 3007,  3007, 3007, 3007, <strong>3007</strong>, 3008, 3008, 3008, 3008, 3008</td>
</tr>
<tr>
<td style="text-align: center;">30</td>
<td style="text-align: center;">3009</td>
<td style="text-align: center;">3007, 3007, 3007, 3007, 3007, <strong>3008</strong>, 3008, 3008, 3008, 3008, 3008</td>
</tr>
</tbody>
</table></div>
<p>this causes the minimum timestamp to increment one second each block at first before it settles to incrementing only after repeating six times.</p>

CC BY-SA 4.0
2024-07-19T16:24:59.483Z
2024-07-19T17:30:39.087Z
2024-07-19T17:30:39.087Z
Murch
<p>In a time warp attack, an attacker can reduce proof of work difficulty to its minimum, which allows even a single piece of modern mining equipment to create large numbers of blocks per second.  However, these blocks must follow the median time past consensus rule of each block having a block header time greater than the median of the previous 11 blocks' header times.  The blocks also can't use a header time more than two hours in the future if they want to be accepted immediately by full nodes.</p>
<p>The block header time field is an integer representing seconds since the Unix epoch.</p>
<p>Given those constraints, what is the greatest number of blocks per second that an attacker can produce?  It's clearly possible for them average one block per second, but I've heard that they may be able to produce more than that.</p>

<consensus><timestamp><block-interval><time-warp-attack>
How many blocks per second can sustainably be created using a time warp attack?
David A. Harding
# How many blocks per second can sustainably be created using a time warp attack?

(Asked by: username_0 on 2024-07-19)

In a time warp attack, an attacker can reduce proof of work difficulty to its minimum, which allows even a single piece of modern mining equipment to create large numbers of blocks per second. However, these blocks must follow the median time past consensus rule of each block having a block header time greater than the median of the previous 11 blocks' header times. The blocks also can't use a header time more than two hours in the future if they want to be accepted immediately by full nodes.

The block header time field is an integer representing seconds since the Unix epoch.

Given those constraints, what is the greatest number of blocks per second that an attacker can produce? It's clearly possible for them average one block per second, but I've heard that they may be able to produce more than that.

**Tags:** consensus, timestamp, block-interval, time-warp-attack


---

## 2 answers

### Answer by username_2 on 2024-07-19. Score: 7 | Accepted answer

An attacker would be able to sustain a cadence of 6 blocks per second without increasing the difficulty.

The attacker would start by holding the timestamps back by more than 14 days to erode the difficulty. Once the difficulty was reduced to the minimum, they would be able to increase the timestamp only every sixth block, keeping all blocks’ timestamps at least two weeks in the past except for the timestamp of each last block per difficulty period, which they would timestamp with the present time or up to 2h into the future at least 14 days ahead of the first block in the same period.

While the timestamps eventually settle on a series of the same value repeating six times before incrementing it, there is a quirk in how the timestamps sort to find the median when timestamps are first shifted to increasing minimally.

Assuming we start with 11 blocks spaced at 10 minutes, the subsequent minimum timestamps would be as follows:

| Block height | Timestamp [s] | Timestamps of prior 11 blocks (median bold) |
| --- | --- | --- |
| 1 | 0 | - |
| 2 | 600 | - |
| 3 | 1200 | - |
| 4 | 1800 | - |
| 5 | 2400 | - |
| 6 | 3000 | - |
| 7 | 3600 | - |
| 8 | 4200 | - |
| 9 | 4800 | - |
| 10 | 5400 | - |
| 11 | 6000 | - |
| 12 | 3001 | 0, 600, 1200, 1800, 2400, **3000**, 3600, 4200, 4800, 5400, 6000 |
| 13 | 3002 | 600, 1200, 1800, 2400, 3000, 3600, 4200, 4800, 5400, 6000, **3001** |
| 14 | 3003 | 1200, 1800, 2400, 3000, 3600, 4200, 4800, 5400, 6000, 3001, **3002** |
| 15 | 3004 | 1800, 2400, 3000, 3600, 4200, 4800, 5400, 6000, 3001, 3002, **3003** |
| 16 | 3005 | 2400, 3000, 3600, 4200, 4800, 5400, 6000, 3001, 3002, 3003, **3004** |
| 17 | 3006 | 3000, 3600, 4200, 4800, 5400, 6000, 3001, 3002, 3003, 3004, **3005** |
| 18 | 3007 | 3600, 4200, 4800, 5400, 6000, 3001, 3002, 3003, 3004, 3005, **3006** |
| 19 | 3007 | 4200, 4800, 5400, 6000, 3001, 3002, 3003, 3004, 3005, **3006**, 3007 |
| 20 | 3007 | 4800, 5400, 6000, 3001, 3002, 3003, 3004, 3005, **3006**, 3007, 3007 |
| 21 | 3007 | 5400, 6000, 3001, 3002, 3003, 3004, 3005, **3006**, 3007, 3007, 3007 |
| 22 | 3007 | 6000, 3001, 3002, 3003, 3004, 3005, **3006**, 3007, 3007, 3007, 3007 |
| 23 | 3007 | 3001, 3002, 3003, 3004, 3005, **3006**, 3007, 3007, 3007, 3007, 3007 |
| 24 | 3008 | 3002, 3003, 3004, 3005, 3006, **3007**, 3007, 3007, 3007, 3007, 3007 |
| 25 | 3008 | 3003, 3004, 3005, 3006, 3007, **3007**, 3007, 3007, 3007, 3007, 3008 |
| 26 | 3008 | 3004, 3005, 3006, 3007, 3007, **3007**, 3007, 3007, 3007, 3008, 3008 |
| 27 | 3008 | 3005, 3006, 3007, 3007, 3007, **3007**, 3007, 3007, 3008, 3008, 3008 |
| 28 | 3008 | 3006, 3007, 3007, 3007, 3007, **3007**, 3007, 3008, 3008, 3008, 3008 |
| 29 | 3008 | 3007, 3007, 3007, 3007, 3007, **3007**, 3008, 3008, 3008, 3008, 3008 |
| 30 | 3009 | 3007, 3007, 3007, 3007, 3007, **3008**, 3008, 3008, 3008, 3008, 3008 |

this causes the minimum timestamp to increment one second each block at first before it settles to incrementing only after repeating six times.


---

### Answer by username_1 on 2024-07-19. Score: 7

6 blocks per second can be sustained.

### Satisfying the MTP rule

The timestamp of each block must be strictly larger than the median of the timetamps of the 11 blocks before it.

This can be satisfied using a pattern consisting of repeating the same timestamp 6 times, then incrementing by one second, and repeat again.

So the series would be:

```
... 0 0 0 0 0 0 1 1 1 1 1 1 2 2 2 2 2 2 3 3 3 3 3 3 3 ...

```

We can abstract over the actual values. With that, there are just 6 distinct "blocks", based on what the 11 timestamps before it were:

* `T+0 T+0 T+0 T+0 T+0 T+1 T+1 T+1 T+1 T+1 T+1`: MTP=`T+2`
* `T+0 T+0 T+0 T+0 T+1 T+1 T+1 T+1 T+1 T+1 T+2`: MTP=`T+2`
* `T+0 T+0 T+0 T+1 T+1 T+1 T+1 T+1 T+1 T+2 T+2`: MTP=`T+2`
* `T+0 T+0 T+1 T+1 T+1 T+1 T+1 T+1 T+2 T+2 T+2`: MTP=`T+2`
* `T+0 T+1 T+1 T+1 T+1 T+1 T+1 T+2 T+2 T+2 T+2`: MTP=`T+2`
* `T+1 T+1 T+1 T+1 T+1 T+1 T+2 T+2 T+2 T+2 T+2`: MTP=`T+2`

Which in each case continues the pattern.

### Keeping the difficulty low

Using the pattern above naively would result in the difficulty adjustment period quadrupling the difficulty every period (the maximum allowed).

To prevent it from doing so, it is necessary to exploit the timewarp bug.

The winning strategy involves setting the timestamp of every block exactly 2 weeks in the past, except those blocks whose height modulo 2016 equals 2015; those are given the current time (or up to two hours in the future). This will make the adjustment algorithm see every period as having taken 2 weeks, and thus not cause any adjustment.


---

