Skip to content

refactor(verification): remove VertexVerifier inheritance [part 6/9] #835

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion hathor/builder/cli_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
from hathor.pubsub import PubSubManager
from hathor.stratum import StratumFactory
from hathor.util import Random, Reactor, not_none
from hathor.verification.verification_service import VerificationService, VertexVerifiers
from hathor.verification.verification_service import VerificationService
from hathor.verification.vertex_verifiers import VertexVerifiers
from hathor.wallet import BaseWallet, HDWallet, Wallet

logger = get_logger()
Expand Down
33 changes: 4 additions & 29 deletions hathor/simulator/patches.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,41 +18,16 @@

from hathor.mining.cpu_mining_service import CpuMiningService
from hathor.transaction import BaseTransaction
from hathor.verification.block_verifier import BlockVerifier
from hathor.verification.merge_mined_block_verifier import MergeMinedBlockVerifier
from hathor.verification.token_creation_transaction_verifier import TokenCreationTransactionVerifier
from hathor.verification.transaction_verifier import TransactionVerifier
from hathor.verification.vertex_verifier import VertexVerifier

logger = get_logger()


def _verify_pow(vertex: BaseTransaction) -> None:
assert vertex.hash is not None
logger.new().debug('Skipping VertexVerifier.verify_pow() for simulator')


class SimulatorBlockVerifier(BlockVerifier):
@classmethod
def verify_pow(cls, vertex: BaseTransaction, *, override_weight: Optional[float] = None) -> None:
_verify_pow(vertex)


class SimulatorMergeMinedBlockVerifier(MergeMinedBlockVerifier):
@classmethod
def verify_pow(cls, vertex: BaseTransaction, *, override_weight: Optional[float] = None) -> None:
_verify_pow(vertex)


class SimulatorTransactionVerifier(TransactionVerifier):
@classmethod
def verify_pow(cls, vertex: BaseTransaction, *, override_weight: Optional[float] = None) -> None:
_verify_pow(vertex)


class SimulatorTokenCreationTransactionVerifier(TokenCreationTransactionVerifier):
class SimulatorVertexVerifier(VertexVerifier):
@classmethod
def verify_pow(cls, vertex: BaseTransaction, *, override_weight: Optional[float] = None) -> None:
_verify_pow(vertex)
assert vertex.hash is not None
logger.new().debug('Skipping VertexVerifier.verify_pow() for simulator')


class SimulatorCpuMiningService(CpuMiningService):
Expand Down
20 changes: 7 additions & 13 deletions hathor/simulator/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,10 @@
from hathor.p2p.peer_id import PeerId
from hathor.simulator.clock import HeapClock, MemoryReactorHeapClock
from hathor.simulator.miner.geometric_miner import GeometricMiner
from hathor.simulator.patches import (
SimulatorBlockVerifier,
SimulatorCpuMiningService,
SimulatorMergeMinedBlockVerifier,
SimulatorTokenCreationTransactionVerifier,
SimulatorTransactionVerifier,
)
from hathor.simulator.patches import SimulatorCpuMiningService, SimulatorVertexVerifier
from hathor.simulator.tx_generator import RandomTransactionGenerator
from hathor.util import Random
from hathor.verification.verification_service import VertexVerifiers
from hathor.verification.vertex_verifiers import VertexVerifiers
from hathor.wallet import HDWallet

if TYPE_CHECKING:
Expand Down Expand Up @@ -257,9 +251,9 @@ def _build_vertex_verifiers(
"""
A custom VertexVerifiers builder to be used by the simulator.
"""
return VertexVerifiers(
block=SimulatorBlockVerifier(settings=settings, daa=daa, feature_service=feature_service),
merge_mined_block=SimulatorMergeMinedBlockVerifier(),
tx=SimulatorTransactionVerifier(settings=settings, daa=daa),
token_creation_tx=SimulatorTokenCreationTransactionVerifier(settings=settings),
return VertexVerifiers.create(
settings=settings,
vertex_verifier=SimulatorVertexVerifier(settings=settings, daa=daa),
daa=daa,
feature_service=feature_service,
)
22 changes: 12 additions & 10 deletions hathor/transaction/resources/create_tx.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from hathor.cli.openapi_files.register import register_resource
from hathor.crypto.util import decode_address
from hathor.exception import InvalidNewTransaction
from hathor.manager import HathorManager
from hathor.transaction import Transaction, TxInput, TxOutput
from hathor.transaction.scripts import create_output_script
from hathor.util import api_catch_exceptions, json_dumpb, json_loadb
Expand Down Expand Up @@ -49,7 +50,7 @@ class CreateTxResource(Resource):
"""
isLeaf = True

def __init__(self, manager):
def __init__(self, manager: HathorManager) -> None:
# Important to have the manager so we can know the tx_storage
self.manager = manager

Expand Down Expand Up @@ -107,15 +108,16 @@ def render_POST(self, request):
def _verify_unsigned_skip_pow(self, tx: Transaction) -> None:
""" Same as .verify but skipping pow and signature verification."""
assert type(tx) is Transaction
verifier = self.manager.verification_service.verifiers.tx
verifier.verify_number_of_inputs(tx)
verifier.verify_number_of_outputs(tx)
verifier.verify_outputs(tx)
verifier.verify_sigops_output(tx)
verifier.verify_sigops_input(tx)
verifier.verify_inputs(tx, skip_script=True) # need to run verify_inputs first to check if all inputs exist
verifier.verify_parents(tx)
verifier.verify_sum(tx)
verifiers = self.manager.verification_service.verifiers
verifiers.tx.verify_number_of_inputs(tx)
verifiers.vertex.verify_number_of_outputs(tx)
verifiers.tx.verify_outputs(tx)
verifiers.vertex.verify_sigops_output(tx)
verifiers.tx.verify_sigops_input(tx)
# need to run verify_inputs first to check if all inputs exist
verifiers.tx.verify_inputs(tx, skip_script=True)
verifiers.vertex.verify_parents(tx)
verifiers.tx.verify_sum(tx)


CreateTxResource.openapi = {
Expand Down
16 changes: 9 additions & 7 deletions hathor/verification/block_verifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from hathor.conf.settings import HathorSettings
from hathor.daa import DifficultyAdjustmentAlgorithm
from hathor.feature_activation.feature_service import BlockIsMissingSignal, BlockIsSignaling, FeatureService
from hathor.transaction import BaseTransaction, Block
from hathor.transaction import Block
from hathor.transaction.exceptions import (
BlockMustSignalError,
BlockWithInputs,
Expand All @@ -28,17 +28,20 @@
from hathor.verification.vertex_verifier import VertexVerifier


class BlockVerifier(VertexVerifier):
__slots__ = ('_feature_service', )
class BlockVerifier:
__slots__ = ('_settings', '_vertex_verifier', '_daa', '_feature_service')

def __init__(
self,
*,
settings: HathorSettings,
vertex_verifier: VertexVerifier,
daa: DifficultyAdjustmentAlgorithm,
feature_service: FeatureService | None = None
) -> None:
super().__init__(settings=settings, daa=daa)
self._settings = settings
self._vertex_verifier = vertex_verifier
self._daa = daa
self._feature_service = feature_service

def verify_height(self, block: Block) -> None:
Expand Down Expand Up @@ -71,9 +74,8 @@ def verify_no_inputs(self, block: Block) -> None:
if inputs:
raise BlockWithInputs('number of inputs {}'.format(len(inputs)))

def verify_outputs(self, block: BaseTransaction) -> None:
assert isinstance(block, Block)
super().verify_outputs(block)
def verify_outputs(self, block: Block) -> None:
self._vertex_verifier.verify_outputs(block)
for output in block.outputs:
if output.get_token_index() > 0:
raise BlockWithTokensError('in output: {}'.format(output.to_human_readable()))
Expand Down
22 changes: 17 additions & 5 deletions hathor/verification/transaction_verifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from hathor.conf.settings import HathorSettings
from hathor.daa import DifficultyAdjustmentAlgorithm
from hathor.profiler import get_cpu_profiler
from hathor.transaction import BaseTransaction, Transaction, TxInput
from hathor.transaction.exceptions import (
Expand Down Expand Up @@ -39,8 +41,19 @@
cpu = get_cpu_profiler()


class TransactionVerifier(VertexVerifier):
__slots__ = ()
class TransactionVerifier:
__slots__ = ('_settings', '_vertex_verifier', '_daa')

def __init__(
self,
*,
settings: HathorSettings,
vertex_verifier: VertexVerifier,
daa: DifficultyAdjustmentAlgorithm,
) -> None:
self._settings = settings
self._vertex_verifier = vertex_verifier
self._daa = daa

def verify_parents_basic(self, tx: Transaction) -> None:
"""Verify number and non-duplicity of parents."""
Expand Down Expand Up @@ -164,13 +177,12 @@ def verify_number_of_inputs(self, tx: Transaction) -> None:
if not tx.is_genesis:
raise NoInputError('Transaction must have at least one input')

def verify_outputs(self, tx: BaseTransaction) -> None:
def verify_outputs(self, tx: Transaction) -> None:
"""Verify outputs reference an existing token uid in the tokens list

:raises InvalidToken: output references non existent token uid
"""
assert isinstance(tx, Transaction)
super().verify_outputs(tx)
self._vertex_verifier.verify_outputs(tx)
for output in tx.outputs:
# check index is valid
if output.get_token_index() > len(tx.tokens):
Expand Down
49 changes: 7 additions & 42 deletions hathor/verification/verification_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,52 +12,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import NamedTuple

from typing_extensions import assert_never

from hathor.conf.settings import HathorSettings
from hathor.daa import DifficultyAdjustmentAlgorithm
from hathor.feature_activation.feature_service import FeatureService
from hathor.profiler import get_cpu_profiler
from hathor.transaction import BaseTransaction, Block, MergeMinedBlock, Transaction, TxVersion
from hathor.transaction.token_creation_tx import TokenCreationTransaction
from hathor.transaction.validation_state import ValidationState
from hathor.verification.block_verifier import BlockVerifier
from hathor.verification.merge_mined_block_verifier import MergeMinedBlockVerifier
from hathor.verification.token_creation_transaction_verifier import TokenCreationTransactionVerifier
from hathor.verification.transaction_verifier import TransactionVerifier
from hathor.verification.vertex_verifiers import VertexVerifiers

cpu = get_cpu_profiler()


class VertexVerifiers(NamedTuple):
"""A group of verifier instances, one for each vertex type."""
block: BlockVerifier
merge_mined_block: MergeMinedBlockVerifier
tx: TransactionVerifier
token_creation_tx: TokenCreationTransactionVerifier

@classmethod
def create_defaults(
cls,
*,
settings: HathorSettings,
daa: DifficultyAdjustmentAlgorithm,
feature_service: FeatureService | None = None,
) -> 'VertexVerifiers':
"""
Create a VertexVerifiers instance using the default verifier for each vertex type,
from all required dependencies.
"""
return VertexVerifiers(
block=BlockVerifier(settings=settings, daa=daa, feature_service=feature_service),
merge_mined_block=MergeMinedBlockVerifier(),
tx=TransactionVerifier(settings=settings, daa=daa),
token_creation_tx=TokenCreationTransactionVerifier(settings=settings),
)


class VerificationService:
__slots__ = ('verifiers', )

Expand Down Expand Up @@ -192,7 +157,7 @@ def _verify_block(self, block: Block) -> None:
self.verify_without_storage(block)

# (1) and (4)
self.verifiers.block.verify_parents(block)
self.verifiers.vertex.verify_parents(block)

self.verifiers.block.verify_height(block)

Expand Down Expand Up @@ -220,7 +185,7 @@ def _verify_tx(self, tx: Transaction, *, reject_locked_reward: bool) -> None:
self.verify_without_storage(tx)
self.verifiers.tx.verify_sigops_input(tx)
self.verifiers.tx.verify_inputs(tx) # need to run verify_inputs first to check if all inputs exist
self.verifiers.tx.verify_parents(tx)
self.verifiers.vertex.verify_parents(tx)
self.verifiers.tx.verify_sum(tx)
if reject_locked_reward:
self.verifiers.tx.verify_reward_locked(tx)
Expand Down Expand Up @@ -255,11 +220,11 @@ def verify_without_storage(self, vertex: BaseTransaction) -> None:
def _verify_without_storage_block(self, block: Block) -> None:
""" Run all verifications that do not need a storage.
"""
self.verifiers.block.verify_pow(block)
self.verifiers.vertex.verify_pow(block)
self.verifiers.block.verify_no_inputs(block)
self.verifiers.block.verify_outputs(block)
self.verifiers.block.verify_data(block)
self.verifiers.block.verify_sigops_output(block)
self.verifiers.vertex.verify_sigops_output(block)

def _verify_without_storage_merge_mined_block(self, block: MergeMinedBlock) -> None:
self.verifiers.merge_mined_block.verify_aux_pow(block)
Expand All @@ -268,10 +233,10 @@ def _verify_without_storage_merge_mined_block(self, block: MergeMinedBlock) -> N
def _verify_without_storage_tx(self, tx: Transaction) -> None:
""" Run all verifications that do not need a storage.
"""
self.verifiers.tx.verify_pow(tx)
self.verifiers.vertex.verify_pow(tx)
self.verifiers.tx.verify_number_of_inputs(tx)
self.verifiers.tx.verify_outputs(tx)
self.verifiers.tx.verify_sigops_output(tx)
self.verifiers.vertex.verify_sigops_output(tx)

def _verify_without_storage_token_creation_tx(self, tx: TokenCreationTransaction) -> None:
self._verify_without_storage_tx(tx)
Loading