Skip to content

Commit 8b6322a

Browse files
committed
fix(mining): Fix block template not checking for MAX_FUTURE_TIMESTAMP_ALLOWED
1 parent dbfb9ec commit 8b6322a

File tree

4 files changed

+46
-9
lines changed

4 files changed

+46
-9
lines changed

hathor/exception.py

+10
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ class BuilderError(Exception):
2323
pass
2424

2525

26+
class BlockTemplateError(Exception):
27+
"""Base class for exceptions generating block template."""
28+
pass
29+
30+
31+
class BlockTemplateTimestampError(BlockTemplateError):
32+
"""Raised when there is no timestamp available to prepare a block template."""
33+
pass
34+
35+
2636
class InvalidNewTransaction(HathorError):
2737
"""Raised when a new received tx/block is not valid.
2838
"""

hathor/manager.py

+8
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from hathor.consensus import ConsensusAlgorithm
3232
from hathor.event.event_manager import EventManager
3333
from hathor.exception import (
34+
BlockTemplateTimestampError,
3435
DoubleSpendingError,
3536
HathorError,
3637
InitializationError,
@@ -807,6 +808,13 @@ def _make_block_template(self, parent_block: Block, parent_txs: 'ParentTxs', cur
807808
timestamp_max = min(timestamp_abs_max, timestamp_max_decay)
808809
else:
809810
timestamp_max = timestamp_abs_max
811+
timestamp_max = min(timestamp_max, int(current_timestamp + self._settings.MAX_FUTURE_TIMESTAMP_ALLOWED))
812+
if timestamp_max < timestamp_min:
813+
raise BlockTemplateTimestampError(
814+
f'Unable to create a block template because there is no timestamp available. '
815+
f'(min={timestamp_min}, max={timestamp_max}) '
816+
f'(current_timestamp={current_timestamp})'
817+
)
810818
timestamp = min(max(current_timestamp, timestamp_min), timestamp_max)
811819
parent_block_metadata = parent_block.get_metadata()
812820
# this is the min weight to cause an increase of twice the WEIGHT_TOL, we make sure to generate a template with

hathor/simulator/miner/geometric_miner.py

+14-7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from typing import TYPE_CHECKING, Optional
1717

1818
from hathor.conf.get_settings import get_settings
19+
from hathor.exception import BlockTemplateTimestampError
1920
from hathor.manager import HathorEvents
2021
from hathor.simulator.miner.abstract_miner import AbstractMiner
2122
from hathor.util import Random
@@ -96,13 +97,19 @@ def _schedule_next_block(self):
9697
self._block = None
9798

9899
if self._manager.can_start_mining():
99-
block = self._generate_mining_block()
100-
geometric_p = 2**(-block.weight)
101-
trials = self._rng.geometric(geometric_p)
102-
dt = 1.0 * trials / self._hashpower
103-
self._block = block
104-
self.log.debug('randomized step: start mining new block', dt=dt, parents=[h.hex() for h in block.parents],
105-
block_timestamp=block.timestamp)
100+
try:
101+
block = self._generate_mining_block()
102+
except BlockTemplateTimestampError:
103+
dt = 5 # Try again in 5 seconds.
104+
else:
105+
geometric_p = 2**(-block.weight)
106+
trials = self._rng.geometric(geometric_p)
107+
dt = 1.0 * trials / self._hashpower
108+
self._block = block
109+
self.log.debug('randomized step: start mining new block',
110+
dt=dt,
111+
parents=[h.hex() for h in block.parents],
112+
block_timestamp=block.timestamp)
106113
else:
107114
dt = 60
108115

tests/tx/test_mining.py

+14-2
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,19 @@ def test_block_template_after_genesis(self) -> None:
3737

3838
block_templates = manager.get_block_templates()
3939
self.assertEqual(len(block_templates), 1)
40+
41+
timestamp_max = min(
42+
0xffffffff,
43+
int(manager.reactor.seconds()) + self._settings.MAX_FUTURE_TIMESTAMP_ALLOWED
44+
)
45+
4046
self.assertEqual(block_templates[0], BlockTemplate(
4147
versions={0, 3},
4248
reward=settings.INITIAL_TOKEN_UNITS_PER_BLOCK * 100,
4349
weight=1.0,
4450
timestamp_now=int(manager.reactor.seconds()),
4551
timestamp_min=settings.GENESIS_BLOCK_TIMESTAMP + 3,
46-
timestamp_max=0xffffffff, # no limit for next block after genesis
52+
timestamp_max=timestamp_max, # no limit for next block after genesis
4753
# parents=[tx.hash for tx in self.genesis_blocks + self.genesis_txs],
4854
parents=block_templates[0].parents,
4955
parents_any=[],
@@ -60,13 +66,19 @@ def test_regular_block_template(self) -> None:
6066

6167
block_templates = manager.get_block_templates()
6268
self.assertEqual(len(block_templates), 1)
69+
70+
timestamp_max = min(
71+
blocks[-1].timestamp + settings.MAX_DISTANCE_BETWEEN_BLOCKS - 1,
72+
int(manager.reactor.seconds()) + self._settings.MAX_FUTURE_TIMESTAMP_ALLOWED
73+
)
74+
6375
self.assertEqual(block_templates[0], BlockTemplate(
6476
versions={0, 3},
6577
reward=settings.INITIAL_TOKEN_UNITS_PER_BLOCK * 100,
6678
weight=1.0,
6779
timestamp_now=int(manager.reactor.seconds()),
6880
timestamp_min=blocks[-1].timestamp + 1,
69-
timestamp_max=blocks[-1].timestamp + settings.MAX_DISTANCE_BETWEEN_BLOCKS - 1,
81+
timestamp_max=timestamp_max,
7082
# parents=[blocks[-1].hash, self.genesis_txs[-1].hash, self.genesis_txs[-2].hash],
7183
parents=block_templates[0].parents,
7284
parents_any=[],

0 commit comments

Comments
 (0)