Skip to content

Commit

Permalink
refactor(verification): create vertex verifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
glevco committed Sep 29, 2023
1 parent 96b93db commit 8f2d608
Show file tree
Hide file tree
Showing 10 changed files with 227 additions and 122 deletions.
18 changes: 16 additions & 2 deletions hathor/builder/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
TransactionStorage,
)
from hathor.util import Random, Reactor, get_environment_info
from hathor.verification.verification_service import VerificationService
from hathor.verification.verification_service import VerificationService, VertexVerifiers
from hathor.wallet import BaseWallet, Wallet

logger = get_logger()
Expand Down Expand Up @@ -102,6 +102,7 @@ def __init__(self) -> None:
self._feature_service: Optional[FeatureService] = None
self._bit_signaling_service: Optional[BitSignalingService] = None

self._vertex_verifiers: Optional[VertexVerifiers] = None
self._verification_service: Optional[VerificationService] = None

self._rocksdb_path: Optional[str] = None
Expand Down Expand Up @@ -432,10 +433,18 @@ def _get_or_create_bit_signaling_service(self, tx_storage: TransactionStorage) -

def _get_or_create_verification_service(self) -> VerificationService:
if self._verification_service is None:
self._verification_service = VerificationService()
verifiers = self._get_or_create_vertex_verifiers()
self._verification_service = VerificationService(verifiers=verifiers)

return self._verification_service

def _get_or_create_vertex_verifiers(self) -> VertexVerifiers:
if self._vertex_verifiers is None:
settings = self._get_or_create_settings()
self._vertex_verifiers = VertexVerifiers.create(settings=settings)

return self._vertex_verifiers

def use_memory(self) -> 'Builder':
self.check_if_can_modify()
self._storage_type = StorageType.MEMORY
Expand Down Expand Up @@ -533,6 +542,11 @@ def set_verification_service(self, verification_service: VerificationService) ->
self._verification_service = verification_service
return self

def set_vertex_verifiers(self, vertex_verifiers: VertexVerifiers) -> 'Builder':
self.check_if_can_modify()
self._vertex_verifiers = vertex_verifiers
return self

def set_reactor(self, reactor: Reactor) -> 'Builder':
self.check_if_can_modify()
self._reactor = reactor
Expand Down
5 changes: 3 additions & 2 deletions hathor/builder/cli_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
from hathor.pubsub import PubSubManager
from hathor.stratum import StratumFactory
from hathor.util import Random, Reactor
from hathor.verification.verification_service import VerificationService
from hathor.verification.verification_service import VerificationService, VertexVerifiers
from hathor.wallet import BaseWallet, HDWallet, Wallet

logger = get_logger()
Expand Down Expand Up @@ -202,7 +202,8 @@ def create_manager(self, reactor: Reactor) -> HathorManager:
not_support_features=self._args.signal_not_support
)

verification_service = VerificationService()
vertex_verifiers = VertexVerifiers.create(settings=settings)
verification_service = VerificationService(verifiers=vertex_verifiers)

p2p_manager = ConnectionsManager(
reactor,
Expand Down
47 changes: 0 additions & 47 deletions hathor/verification/block_verification.py

This file was deleted.

50 changes: 50 additions & 0 deletions hathor/verification/block_verifier.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Copyright 2023 Hathor Labs
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from hathor.profiler import get_cpu_profiler
from hathor.transaction import Block
from hathor.verification.vertex_verifier import VertexVerifier

cpu = get_cpu_profiler()


class BlockVerifier(VertexVerifier):
__slots__ = ()

def verify_basic(self, block: Block, *, skip_block_weight_verification: bool = False) -> None:
"""Partially run validations, the ones that need parents/inputs are skipped."""
if not skip_block_weight_verification:
block.verify_weight()
block.verify_reward()

@cpu.profiler(key=lambda _, block: 'block-verify!{}'.format(block.hash.hex()))
def verify(self, block: Block) -> None:
"""
(1) confirms at least two pending transactions and references last block
(2) solves the pow with the correct weight (done in HathorManager)
(3) creates the correct amount of tokens in the output (done in HathorManager)
(4) all parents must exist and have timestamp smaller than ours
(5) data field must contain at most BLOCK_DATA_MAX_SIZE bytes
"""
# TODO Should we validate a limit of outputs?
if block.is_genesis:
# TODO do genesis validation
return

block.verify_without_storage()

# (1) and (4)
block.verify_parents()

block.verify_height()
19 changes: 19 additions & 0 deletions hathor/verification/merge_mined_block_verifier.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright 2023 Hathor Labs
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from hathor.verification.block_verifier import BlockVerifier


class MergeMinedBlockVerifier(BlockVerifier):
__slots__ = ()
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@
# limitations under the License.

from hathor.transaction.token_creation_tx import TokenCreationTransaction
from hathor.verification import transaction_verification
from hathor.verification.transaction_verifier import TransactionVerifier


def verify(tx: TokenCreationTransaction, *, reject_locked_reward: bool = True) -> None:
""" Run all validations as regular transactions plus validation on token info.
class TokenCreationTransactionVerifier(TransactionVerifier):
__slots__ = ()

We also overload verify_sum to make some different checks
"""
transaction_verification.verify(tx, reject_locked_reward=reject_locked_reward)
tx.verify_token_info()
def verify(self, tx: TokenCreationTransaction, *, reject_locked_reward: bool = True) -> None:
""" Run all validations as regular transactions plus validation on token info.
We also overload verify_sum to make some different checks
"""
super().verify(tx, reject_locked_reward=reject_locked_reward)
tx.verify_token_info()
53 changes: 0 additions & 53 deletions hathor/verification/transaction_verification.py

This file was deleted.

56 changes: 56 additions & 0 deletions hathor/verification/transaction_verifier.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Copyright 2023 Hathor Labs
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from hathor.profiler import get_cpu_profiler
from hathor.transaction import Transaction
from hathor.verification.vertex_verifier import VertexVerifier

cpu = get_cpu_profiler()


class TransactionVerifier(VertexVerifier):
__slots__ = ()

def verify_basic(self, tx: Transaction) -> None:
"""Partially run validations, the ones that need parents/inputs are skipped."""
if tx.is_genesis:
# TODO do genesis validation?
return
tx.verify_parents_basic()
tx.verify_weight()
tx.verify_without_storage()

@cpu.profiler(key=lambda _, tx: 'tx-verify!{}'.format(tx.hash.hex()))
def verify(self, tx: Transaction, *, reject_locked_reward: bool = True) -> None:
""" Common verification for all transactions:
(i) number of inputs is at most 256
(ii) number of outputs is at most 256
(iii) confirms at least two pending transactions
(iv) solves the pow (we verify weight is correct in HathorManager)
(v) validates signature of inputs
(vi) validates public key and output (of the inputs) addresses
(vii) validate that both parents are valid
(viii) validate input's timestamps
(ix) validate inputs and outputs sum
"""
if tx.is_genesis:
# TODO do genesis validation
return
tx.verify_without_storage()
tx.verify_sigops_input()
tx.verify_inputs() # need to run verify_inputs first to check if all inputs exist
tx.verify_parents()
tx.verify_sum()
if reject_locked_reward:
tx.verify_reward_locked()
Loading

0 comments on commit 8f2d608

Please sign in to comment.