19
19
from hathor .conf .settings import HathorSettings
20
20
from hathor .daa import DifficultyAdjustmentAlgorithm
21
21
from hathor .feature_activation .feature_service import FeatureService
22
+ from hathor .profiler import get_cpu_profiler
22
23
from hathor .transaction import BaseTransaction , Block , MergeMinedBlock , Transaction , TxVersion
23
24
from hathor .transaction .token_creation_tx import TokenCreationTransaction
24
25
from hathor .transaction .validation_state import ValidationState
27
28
from hathor .verification .token_creation_transaction_verifier import TokenCreationTransactionVerifier
28
29
from hathor .verification .transaction_verifier import TransactionVerifier
29
30
31
+ cpu = get_cpu_profiler ()
32
+
30
33
31
34
class VertexVerifiers (NamedTuple ):
32
35
"""A group of verifier instances, one for each vertex type."""
@@ -49,7 +52,7 @@ def create_defaults(
49
52
"""
50
53
return VertexVerifiers (
51
54
block = BlockVerifier (settings = settings , daa = daa , feature_service = feature_service ),
52
- merge_mined_block = MergeMinedBlockVerifier (settings = settings , daa = daa , feature_service = feature_service ),
55
+ merge_mined_block = MergeMinedBlockVerifier (),
53
56
tx = TransactionVerifier (settings = settings , daa = daa ),
54
57
token_creation_tx = TokenCreationTransactionVerifier (settings = settings , daa = daa ),
55
58
)
@@ -116,16 +119,10 @@ def verify_basic(self, vertex: BaseTransaction, *, skip_block_weight_verificatio
116
119
match vertex .version :
117
120
case TxVersion .REGULAR_BLOCK :
118
121
assert type (vertex ) is Block
119
- self .verifiers .block .verify_basic (
120
- vertex ,
121
- skip_block_weight_verification = skip_block_weight_verification
122
- )
122
+ self ._verify_basic_block (vertex , skip_weight_verification = skip_block_weight_verification )
123
123
case TxVersion .MERGE_MINED_BLOCK :
124
124
assert type (vertex ) is MergeMinedBlock
125
- self .verifiers .merge_mined_block .verify_basic (
126
- vertex ,
127
- skip_block_weight_verification = skip_block_weight_verification
128
- )
125
+ self ._verify_basic_merge_mined_block (vertex , skip_weight_verification = skip_block_weight_verification )
129
126
case TxVersion .REGULAR_TRANSACTION :
130
127
assert type (vertex ) is Transaction
131
128
self .verifiers .tx .verify_basic (vertex )
@@ -135,6 +132,15 @@ def verify_basic(self, vertex: BaseTransaction, *, skip_block_weight_verificatio
135
132
case _:
136
133
assert_never (vertex .version )
137
134
135
+ def _verify_basic_block (self , block : Block , * , skip_weight_verification : bool ) -> None :
136
+ """Partially run validations, the ones that need parents/inputs are skipped."""
137
+ if not skip_weight_verification :
138
+ self .verifiers .block .verify_weight (block )
139
+ self .verifiers .block .verify_reward (block )
140
+
141
+ def _verify_basic_merge_mined_block (self , block : MergeMinedBlock , * , skip_weight_verification : bool ) -> None :
142
+ self ._verify_basic_block (block , skip_weight_verification = skip_weight_verification )
143
+
138
144
def verify (self , vertex : BaseTransaction , * , reject_locked_reward : bool = True ) -> None :
139
145
"""Run all verifications. Raises on error.
140
146
@@ -143,10 +149,10 @@ def verify(self, vertex: BaseTransaction, *, reject_locked_reward: bool = True)
143
149
match vertex .version :
144
150
case TxVersion .REGULAR_BLOCK :
145
151
assert type (vertex ) is Block
146
- self .verifiers . block . verify (vertex )
152
+ self ._verify_block (vertex )
147
153
case TxVersion .MERGE_MINED_BLOCK :
148
154
assert type (vertex ) is MergeMinedBlock
149
- self .verifiers . merge_mined_block . verify (vertex )
155
+ self ._verify_merge_mined_block (vertex )
150
156
case TxVersion .REGULAR_TRANSACTION :
151
157
assert type (vertex ) is Transaction
152
158
self .verifiers .tx .verify (vertex , reject_locked_reward = reject_locked_reward )
@@ -156,15 +162,42 @@ def verify(self, vertex: BaseTransaction, *, reject_locked_reward: bool = True)
156
162
case _:
157
163
assert_never (vertex .version )
158
164
165
+ @cpu .profiler (key = lambda _ , block : 'block-verify!{}' .format (block .hash .hex ()))
166
+ def _verify_block (self , block : Block ) -> None :
167
+ """
168
+ (1) confirms at least two pending transactions and references last block
169
+ (2) solves the pow with the correct weight (done in HathorManager)
170
+ (3) creates the correct amount of tokens in the output (done in HathorManager)
171
+ (4) all parents must exist and have timestamp smaller than ours
172
+ (5) data field must contain at most BLOCK_DATA_MAX_SIZE bytes
173
+ (6) whether this block must signal feature support
174
+ """
175
+ # TODO Should we validate a limit of outputs?
176
+ if block .is_genesis :
177
+ # TODO do genesis validation
178
+ return
179
+
180
+ self .verify_without_storage (block )
181
+
182
+ # (1) and (4)
183
+ self .verifiers .block .verify_parents (block )
184
+
185
+ self .verifiers .block .verify_height (block )
186
+
187
+ self .verifiers .block .verify_mandatory_signaling (block )
188
+
189
+ def _verify_merge_mined_block (self , block : MergeMinedBlock ) -> None :
190
+ self ._verify_block (block )
191
+
159
192
def verify_without_storage (self , vertex : BaseTransaction ) -> None :
160
193
# We assert with type() instead of isinstance() because each subclass has a specific branch.
161
194
match vertex .version :
162
195
case TxVersion .REGULAR_BLOCK :
163
196
assert type (vertex ) is Block
164
- self .verifiers . block . verify_without_storage (vertex )
197
+ self ._verify_without_storage_block (vertex )
165
198
case TxVersion .MERGE_MINED_BLOCK :
166
199
assert type (vertex ) is MergeMinedBlock
167
- self .verifiers . merge_mined_block . verify_without_storage (vertex )
200
+ self ._verify_without_storage_merge_mined_block (vertex )
168
201
case TxVersion .REGULAR_TRANSACTION :
169
202
assert type (vertex ) is Transaction
170
203
self .verifiers .tx .verify_without_storage (vertex )
@@ -173,3 +206,16 @@ def verify_without_storage(self, vertex: BaseTransaction) -> None:
173
206
self .verifiers .token_creation_tx .verify_without_storage (vertex )
174
207
case _:
175
208
assert_never (vertex .version )
209
+
210
+ def _verify_without_storage_block (self , block : Block ) -> None :
211
+ """ Run all verifications that do not need a storage.
212
+ """
213
+ self .verifiers .block .verify_pow (block )
214
+ self .verifiers .block .verify_no_inputs (block )
215
+ self .verifiers .block .verify_outputs (block )
216
+ self .verifiers .block .verify_data (block )
217
+ self .verifiers .block .verify_sigops_output (block )
218
+
219
+ def _verify_without_storage_merge_mined_block (self , block : MergeMinedBlock ) -> None :
220
+ self .verifiers .merge_mined_block .verify_aux_pow (block )
221
+ self ._verify_without_storage_block (block )
0 commit comments