27
27
28
28
from hathor .conf .settings import HathorSettings
29
29
from hathor .profiler import get_cpu_profiler
30
- from hathor .util import iwindows
30
+ from hathor .types import VertexId
31
+ from hathor .util import iwindows , not_none
31
32
32
33
if TYPE_CHECKING :
33
34
from hathor .transaction import Block , Transaction
35
+ from hathor .transaction .storage .simple_memory_storage import SimpleMemoryStorage
34
36
35
37
logger = get_logger ()
36
38
cpu = get_cpu_profiler ()
@@ -57,17 +59,38 @@ def __init__(self, *, settings: HathorSettings, test_mode: TestMode = TestMode.D
57
59
DifficultyAdjustmentAlgorithm .singleton = self
58
60
59
61
@cpu .profiler (key = lambda _ , block : 'calculate_block_difficulty!{}' .format (block .hash .hex ()))
60
- def calculate_block_difficulty (self , block : 'Block' ) -> float :
61
- """ Calculate block weight according to the ascendents of `block`, using calculate_next_weight."""
62
+ def calculate_block_difficulty (self , block : 'Block' , memory_storage : 'SimpleMemoryStorage' ) -> float :
63
+ """ Calculate block weight according to the ascendants of `block`, using calculate_next_weight."""
62
64
if self .TEST_MODE & TestMode .TEST_BLOCK_WEIGHT :
63
65
return 1.0
64
66
65
67
if block .is_genesis :
66
68
return self .MIN_BLOCK_WEIGHT
67
69
68
- return self . calculate_next_weight (block . get_block_parent (), block . timestamp )
70
+ parent_block = memory_storage . get_parent_block (block )
69
71
70
- def calculate_next_weight (self , parent_block : 'Block' , timestamp : int ) -> float :
72
+ return self .calculate_next_weight (parent_block , block .timestamp , memory_storage )
73
+
74
+ def calculate_N (self , parent_block : 'Block' ) -> int :
75
+ return min (2 * self ._settings .BLOCK_DIFFICULTY_N_BLOCKS , parent_block .get_height () - 1 )
76
+
77
+ def get_block_dependencies (self , block : 'Block' ) -> list [VertexId ]:
78
+ parent_block = block .get_block_parent ()
79
+ N = self .calculate_N (parent_block )
80
+ ids : list [VertexId ] = [not_none (parent_block .hash )]
81
+
82
+ while len (ids ) <= N + 1 :
83
+ parent_block = parent_block .get_block_parent ()
84
+ ids .append (not_none (parent_block .hash ))
85
+
86
+ return ids
87
+
88
+ def calculate_next_weight (
89
+ self ,
90
+ parent_block : 'Block' ,
91
+ timestamp : int ,
92
+ memory_storage : Optional ['SimpleMemoryStorage' ] = None ,
93
+ ) -> float :
71
94
""" Calculate the next block weight, aka DAA/difficulty adjustment algorithm.
72
95
73
96
The algorithm used is described in [RFC 22](https://gitlab.com/HathorNetwork/rfcs/merge_requests/22).
@@ -80,7 +103,7 @@ def calculate_next_weight(self, parent_block: 'Block', timestamp: int) -> float:
80
103
from hathor .transaction import sum_weights
81
104
82
105
root = parent_block
83
- N = min ( 2 * self ._settings . BLOCK_DIFFICULTY_N_BLOCKS , parent_block . get_height () - 1 )
106
+ N = self .calculate_N ( parent_block )
84
107
K = N // 2
85
108
T = self .AVG_TIME_BETWEEN_BLOCKS
86
109
S = 5
@@ -90,7 +113,7 @@ def calculate_next_weight(self, parent_block: 'Block', timestamp: int) -> float:
90
113
blocks : list ['Block' ] = []
91
114
while len (blocks ) < N + 1 :
92
115
blocks .append (root )
93
- root = root .get_block_parent ()
116
+ root = memory_storage . get_parent_block ( root ) if memory_storage else root .get_block_parent ()
94
117
assert root is not None
95
118
96
119
# TODO: revise if this assertion can be safely removed
0 commit comments