From a290f2e3109b9f0d62928277b6f216d2487a8174 Mon Sep 17 00:00:00 2001 From: "Andres D. Molins" Date: Thu, 31 Oct 2024 21:46:27 +0100 Subject: [PATCH] Fix: Added EVMVerifier class that is used on all EVM chains. Also added that chains to the SignatureVerifier as EVM chains. --- pyproject.toml | 4 ++- src/aleph/chains/ethereum.py | 41 +++------------------- src/aleph/chains/evm.py | 48 ++++++++++++++++++++++++++ src/aleph/chains/signature_verifier.py | 15 ++++++++ 4 files changed, 70 insertions(+), 38 deletions(-) create mode 100644 src/aleph/chains/evm.py diff --git a/pyproject.toml b/pyproject.toml index 898e24b66..84c87ecbc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,8 @@ classifiers = [ "Development Status :: 4 - Beta", "Programming Language :: Python", "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", ] dynamic = [ "version" ] @@ -32,7 +34,7 @@ dependencies = [ "aleph-nuls2==0.1", "aleph-p2p-client @ git+https://github.com/aleph-im/p2p-service-client-python@2c04af39c566217f629fd89505ffc3270fba8676", "aleph-pytezos==3.13.4", - "asyncpg==0.30.0", + "asyncpg==0.30", "base58>=1.0.3", "coincurve==20", "configmanager==1.35.1", diff --git a/src/aleph/chains/ethereum.py b/src/aleph/chains/ethereum.py index 1036166a8..db83aec07 100644 --- a/src/aleph/chains/ethereum.py +++ b/src/aleph/chains/ethereum.py @@ -1,5 +1,4 @@ import asyncio -import functools import importlib.resources import json import logging @@ -8,7 +7,6 @@ from aleph_message.models import Chain from configmanager import Config from eth_account import Account -from eth_account.messages import encode_defunct from hexbytes import HexBytes from web3 import Web3 from web3._utils.events import get_event_data @@ -17,21 +15,20 @@ from web3.middleware.filter import local_filter_middleware from web3.middleware.geth_poa import geth_poa_middleware -from aleph.chains.common import get_verification_buffer from aleph.db.accessors.chains import get_last_height, upsert_chain_sync_status from aleph.db.accessors.messages import get_unconfirmed_messages from aleph.db.accessors.pending_messages import count_pending_messages from aleph.db.accessors.pending_txs import count_pending_txs from aleph.db.models.chains import ChainTxDb from aleph.schemas.chains.tx_context import TxContext -from aleph.schemas.pending_messages import BasePendingMessage from aleph.toolkit.timestamp import utc_now from aleph.types.chain_sync import ChainEventType from aleph.types.db_session import DbSessionFactory from aleph.utils import run_in_executor -from .abc import ChainWriter, Verifier +from .abc import ChainWriter from .chain_data_service import ChainDataService, PendingTxPublisher +from .evm import EVMVerifier from .indexer_reader import AlephIndexerReader LOGGER = logging.getLogger("chains.ethereum") @@ -68,38 +65,8 @@ def get_logs_query(web3: Web3, contract, start_height, end_height): ) -class EthereumVerifier(Verifier): - async def verify_signature(self, message: BasePendingMessage) -> bool: - """Verifies a signature of a message, return True if verified, false if not""" - - verification = get_verification_buffer(message) - - message_hash = await run_in_executor( - None, functools.partial(encode_defunct, text=verification.decode("utf-8")) - ) - - verified = False - try: - # we assume the signature is a valid string - address = await run_in_executor( - None, - functools.partial( - Account.recover_message, message_hash, signature=message.signature - ), - ) - if address == message.sender: - verified = True - else: - LOGGER.warning( - "Received bad signature from %s for %s" % (address, message.sender) - ) - return False - - except Exception: - LOGGER.exception("Error processing signature for %s" % message.sender) - verified = False - - return verified +class EthereumVerifier(EVMVerifier): + pass class EthereumConnector(ChainWriter): diff --git a/src/aleph/chains/evm.py b/src/aleph/chains/evm.py new file mode 100644 index 000000000..abdaf4195 --- /dev/null +++ b/src/aleph/chains/evm.py @@ -0,0 +1,48 @@ +import functools +import logging + +from eth_account import Account +from eth_account.messages import encode_defunct + +from aleph.chains.common import get_verification_buffer +from aleph.schemas.pending_messages import BasePendingMessage +from aleph.utils import run_in_executor + +from .abc import Verifier + +LOGGER = logging.getLogger("chains.evm") +CHAIN_NAME = "ETH" + + +class EVMVerifier(Verifier): + async def verify_signature(self, message: BasePendingMessage) -> bool: + """Verifies a signature of a message, return True if verified, false if not""" + + verification = get_verification_buffer(message) + + message_hash = await run_in_executor( + None, functools.partial(encode_defunct, text=verification.decode("utf-8")) + ) + + verified = False + try: + # we assume the signature is a valid string + address = await run_in_executor( + None, + functools.partial( + Account.recover_message, message_hash, signature=message.signature + ), + ) + if address == message.sender: + verified = True + else: + LOGGER.warning( + "Received bad signature from %s for %s" % (address, message.sender) + ) + return False + + except Exception: + LOGGER.exception("Error processing signature for %s" % message.sender) + verified = False + + return verified diff --git a/src/aleph/chains/signature_verifier.py b/src/aleph/chains/signature_verifier.py index 02da09d79..b87921487 100644 --- a/src/aleph/chains/signature_verifier.py +++ b/src/aleph/chains/signature_verifier.py @@ -5,6 +5,7 @@ from aleph.chains.abc import Verifier from aleph.chains.avalanche import AvalancheConnector from aleph.chains.ethereum import EthereumVerifier +from aleph.chains.evm import EVMVerifier from aleph.chains.nuls import NulsConnector from aleph.chains.nuls2 import Nuls2Verifier from aleph.chains.solana import SolanaConnector @@ -19,13 +20,27 @@ class SignatureVerifier: def __init__(self): self.verifiers = { + Chain.ARBITRUM: EVMVerifier(), Chain.AVAX: AvalancheConnector(), + Chain.BLAST: EVMVerifier(), + Chain.BOB: EVMVerifier(), + Chain.CYBER: EVMVerifier(), Chain.DOT: SubstrateConnector(), Chain.ETH: EthereumVerifier(), + Chain.FRAXTAL: EVMVerifier(), + Chain.INK: EVMVerifier(), + Chain.METIS: EVMVerifier(), + Chain.MODE: EVMVerifier(), Chain.NULS: NulsConnector(), Chain.NULS2: Nuls2Verifier(), + Chain.LINEA: EVMVerifier(), + Chain.LISK: EVMVerifier(), + Chain.OPTIMISM: EVMVerifier(), + Chain.POL: EVMVerifier(), Chain.SOL: SolanaConnector(), Chain.TEZOS: TezosVerifier(), + Chain.WORLDCHAIN: EVMVerifier(), + Chain.ZORA: EVMVerifier(), } async def verify_signature(self, message: BasePendingMessage) -> None: