Skip to content

Commit

Permalink
Fix comments
Browse files Browse the repository at this point in the history
  • Loading branch information
hweawer committed Sep 30, 2024
1 parent 114b884 commit 306e3c5
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 42 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ LIDO_LOCATOR=0x1eDf09b5023DC86737b59dE68a8130De878984f5
# Görli: 0xff50ed3d0ec03aC01D4C79aAd74928BFF48a7b2b
DEPOSIT_CONTRACT=0xff50ed3d0ec03aC01D4C79aAd74928BFF48a7b2b

# rabbit
# rabbit / onchain_transport
MESSAGE_TRANSPORTS=rabbit

# rabbit secrets
Expand Down
77 changes: 59 additions & 18 deletions src/transport/msg_providers/onchain_transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
# address indexed sender,
# bytes data
# ) anonymous;
MESSAGE_EVENT_ABI = {
EVENT_ABI = {
'anonymous': True,
'inputs': [
{'indexed': True, 'name': 'eventId', 'type': 'bytes32'},
Expand All @@ -35,18 +35,49 @@
'type': 'event',
}

UNVET_V1_DATA_SCHEMA = '(uint256,bytes32,uint256,uint256,bytes,bytes,(bytes32,bytes32),(bytes32))'
PING_V1_DATA_SCHEMA = '(uint256,(bytes32))'
DEPOSIT_V1_DATA_SCHEMA = '(uint256,bytes32,bytes32,uint256,uint256,(bytes32,bytes32),(bytes32))'
PAUSE_V2_DATA_SCHEMA = '(uint256,bytes32,(bytes32,bytes32),uint256,(bytes32))'
PAUSE_V3_DATA_SCHEMA = '(uint256,bytes32,(bytes32,bytes32),(bytes32))'


class EventParser(abc.ABC):
"""
Abstract base class for parsing Ethereum event logs.
This class provides a structure for decoding Ethereum logs and transforming the extracted
data into a structured message using the Web3.py library. It abstracts the process of:
- Decoding logs from blockchain events based on a predefined event ABI (Application Binary Interface).
- Extracting relevant data from the decoded log.
- Creating a structured message (usually a dictionary) from the parsed data.
Attributes:
_w3 (Web3): A Web3 instance for interacting with the Ethereum blockchain.
_schema (str): A schema defining the structure for decoding the event data.
_message_abi (dict): The ABI for the 'Message' event used to decode event logs.
Methods:
_create_message(parsed_data: dict, guardian: str) -> dict:
Abstract method to be implemented by subclasses to create a structured message
from the parsed event data.
_decode_event(log: LogReceipt) -> EventData:
Decodes the given log using the provided 'Message' event ABI and returns the decoded event data.
parse(log: LogReceipt) -> Optional[dict]:
Parses the given Ethereum log, decodes the 'Message' event data, and uses the subclass-specific
message creation logic to return a structured message. If parsing fails, it returns None.
Usage:
Subclasses should implement the `_create_message` method, which transforms the parsed
event data and sender (guardian) address into a meaningful structure, such as a dictionary.
Example:
class MyEventParser(EventParser):
def _create_message(self, parsed_data, guardian):
return {"guardian": guardian, "data": parsed_data}
"""

def __init__(self, w3: Web3, schema: str):
self._w3 = w3
self._schema = schema
self._message_abi = w3.eth.contract(abi=[MESSAGE_EVENT_ABI]).events.Message().abi
self._message_abi: dict = w3.eth.contract(abi=[EVENT_ABI]).events.Message().abi

@abc.abstractmethod
def _create_message(self, parsed_data: dict, guardian: str) -> dict:
Expand All @@ -66,8 +97,10 @@ def parse(self, log: LogReceipt) -> Optional[dict]:
# event MessageDepositV1(address indexed guardianAddress, (uint256 blockNumber, bytes32 blockHash, bytes32 depositRoot,
# uint256 stakingModuleId, uint256 nonce, (bytes32 r, bytes32 vs) signature, (bytes32 version) app) data),
class DepositParser(EventParser):
DEPOSIT_V1_DATA_SCHEMA = '(uint256,bytes32,bytes32,uint256,uint256,(bytes32,bytes32),(bytes32))'

def __init__(self, w3: Web3):
super().__init__(w3, DEPOSIT_V1_DATA_SCHEMA)
super().__init__(w3, self.DEPOSIT_V1_DATA_SCHEMA)

def _create_message(self, parsed_data: tuple, guardian: str) -> DepositMessage:
block_number, block_hash, deposit_root, staking_module_id, nonce, (r, vs), app = parsed_data
Expand All @@ -89,8 +122,10 @@ def _create_message(self, parsed_data: tuple, guardian: str) -> DepositMessage:
# event MessageUnvetV1(address indexed guardianAddress, (uint256 blockNumber, bytes32 blockHash, uint256 stakingModuleId, uint256 nonce,
# bytes operatorIds, bytes vettedKeysByOperator, (bytes32 r, bytes32 vs) signature, (bytes32 version) app) data)
class UnvetParser(EventParser):
UNVET_V1_DATA_SCHEMA = '(uint256,bytes32,uint256,uint256,bytes,bytes,(bytes32,bytes32),(bytes32))'

def __init__(self, w3: Web3):
super().__init__(w3, UNVET_V1_DATA_SCHEMA)
super().__init__(w3, self.UNVET_V1_DATA_SCHEMA)

def _create_message(self, parsed_data: tuple, guardian: str) -> UnvetMessage:
block_number, block_hash, staking_module_id, nonce, operator_ids, vetted_keys_by_operator, (r, vs), app = parsed_data
Expand All @@ -111,8 +146,10 @@ def _create_message(self, parsed_data: tuple, guardian: str) -> UnvetMessage:

# event MessagePingV1(address indexed guardianAddress, (uint256 blockNumber, (bytes32 version) app) data)",
class PingParser(EventParser):
PING_V1_DATA_SCHEMA = '(uint256,(bytes32))'

def __init__(self, w3: Web3):
super().__init__(w3, PING_V1_DATA_SCHEMA)
super().__init__(w3, self.PING_V1_DATA_SCHEMA)

def _create_message(self, parsed_data: tuple, guardian: str) -> PingMessage:
block_number, app = parsed_data
Expand All @@ -126,8 +163,10 @@ def _create_message(self, parsed_data: tuple, guardian: str) -> PingMessage:
# event MessagePauseV2(address indexed guardianAddress, (uint256 blockNumber, bytes32 blockHash, (bytes32 r, bytes32 vs) signature,
# uint256 stakingModuleId, (bytes32 version) app) data)
class PauseV2Parser(EventParser):
PAUSE_V2_DATA_SCHEMA = '(uint256,bytes32,(bytes32,bytes32),uint256,(bytes32))'

def __init__(self, w3: Web3):
super().__init__(w3, PAUSE_V2_DATA_SCHEMA)
super().__init__(w3, self.PAUSE_V2_DATA_SCHEMA)

def _create_message(self, parsed_data: tuple, guardian: str) -> dict:
block_number, block_hash, (r, vs), staking_module_id, app = parsed_data
Expand All @@ -146,8 +185,10 @@ def _create_message(self, parsed_data: tuple, guardian: str) -> dict:
# event MessagePauseV3(address indexed guardianAddress, (uint256 blockNumber, bytes32 blockHash, (bytes32 r, bytes32 vs) signature,
# (bytes32 version) app) data)
class PauseV3Parser(EventParser):
PAUSE_V3_DATA_SCHEMA = '(uint256,bytes32,(bytes32,bytes32),(bytes32))'

def __init__(self, w3: Web3):
super().__init__(w3, PAUSE_V3_DATA_SCHEMA)
super().__init__(w3, self.PAUSE_V3_DATA_SCHEMA)

def _create_message(self, parsed_data: tuple, guardian: str) -> dict:
block_number, block_hash, (r, vs), app = parsed_data
Expand All @@ -163,11 +204,11 @@ def _create_message(self, parsed_data: tuple, guardian: str) -> dict:


class OnchainTransportSinks(StrEnum):
DEPOSIT_V1 = f'MessageDepositV1(address,{DEPOSIT_V1_DATA_SCHEMA})'
PAUSE_V2 = f'MessagePauseV2(address,{PAUSE_V2_DATA_SCHEMA})'
PAUSE_V3 = f'MessagePauseV3(address,{PAUSE_V3_DATA_SCHEMA})'
PING_V1 = f'MessagePingV1(address,{PING_V1_DATA_SCHEMA})'
UNVET_V1 = f'MessageUnvetV1(address,{UNVET_V1_DATA_SCHEMA})'
DEPOSIT_V1 = f'MessageDepositV1(address,{DepositParser.DEPOSIT_V1_DATA_SCHEMA})'
PAUSE_V2 = f'MessagePauseV2(address,{PauseV2Parser.PAUSE_V2_DATA_SCHEMA})'
PAUSE_V3 = f'MessagePauseV3(address,{PauseV3Parser.PAUSE_V3_DATA_SCHEMA})'
PING_V1 = f'MessagePingV1(address,{PingParser.PING_V1_DATA_SCHEMA})'
UNVET_V1 = f'MessageUnvetV1(address,{UnvetParser.UNVET_V1_DATA_SCHEMA})'


class OnchainTransportProvider(BaseMessageProvider):
Expand Down
2 changes: 0 additions & 2 deletions src/transport/msg_types/pause.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import logging
from typing import TypedDict

from eth_typing import Hash32
from schema import And, Schema
from transport.msg_types.base import ADDRESS_REGREX, Signature, SignatureSchema

Expand Down Expand Up @@ -39,7 +38,6 @@
class PauseMessage(TypedDict):
type: str
blockNumber: int
blockHash: Hash32
guardianAddress: str
signature: Signature
stakingModuleId: int
3 changes: 2 additions & 1 deletion src/variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
MELLOW_CONTRACT_ADDRESS = Web3.to_checksum_address(MELLOW_CONTRACT_ADDRESS)
VAULT_DIRECT_DEPOSIT_THRESHOLD = Web3.to_wei(*os.getenv('VAULT_DIRECT_DEPOSIT_THRESHOLD', '1 ether').split(' '))

# rabbit
# rabbit / onchain_transport
MESSAGE_TRANSPORTS = os.getenv('MESSAGE_TRANSPORTS', '').split(',')

# rabbit secrets
Expand All @@ -59,6 +59,7 @@
ONCHAIN_TRANSPORT_ADDRESS = os.getenv('ONCHAIN_TRANSPORT_ADDRESS', None)
if ONCHAIN_TRANSPORT_ADDRESS:
# bot will throw exception if there is unexpected str and it's ok
# Expecting onchain databus contract address
ONCHAIN_TRANSPORT_ADDRESS = Web3.to_checksum_address(ONCHAIN_TRANSPORT_ADDRESS)

# Transactions settings
Expand Down
30 changes: 16 additions & 14 deletions tests/transport/onchain_sender.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from blockchain.contracts.data_bus import DataBusContract
from transport.msg_providers.onchain_transport import (
DEPOSIT_V1_DATA_SCHEMA,
PAUSE_V2_DATA_SCHEMA,
PAUSE_V3_DATA_SCHEMA,
PING_V1_DATA_SCHEMA,
UNVET_V1_DATA_SCHEMA,
DepositParser,
OnchainTransportSinks,
PauseV2Parser,
PauseV3Parser,
PingParser,
UnvetParser,
)
from transport.msg_types.deposit import DepositMessage
from transport.msg_types.pause import PauseMessage
Expand All @@ -20,6 +20,7 @@ class OnchainTransportSender:
"""

_DEFAULT_SIGNATURE = ((0).to_bytes(32), (0).to_bytes(32))
_DEFAULT_BLOCK_HASH = '0x42eef33d13c4440627c3fab6e3abee85af796ae6f77dcade628b183640b519d0'

def __init__(self, w3: Web3, data_bus_contract: DataBusContract):
self._w3 = w3
Expand All @@ -36,31 +37,32 @@ def send_deposit(self, deposit_mes: DepositMessage):
((1).to_bytes(32),),
)
mes = self._w3.codec.encode(
types=[DEPOSIT_V1_DATA_SCHEMA],
types=[DepositParser.DEPOSIT_V1_DATA_SCHEMA],
args=[(block_number, block_hash, deposit_root, staking_module_id, nonce, self._DEFAULT_SIGNATURE, app)],
)
tx = self._data_bus.functions.sendMessage(deposit_topic, mes)
return tx.transact()

def send_pause_v2(self, pause_mes: PauseMessage):
pause_topic = self._w3.keccak(text=OnchainTransportSinks.PAUSE_V2)
block_number, block_hash, staking_module_id, app = (
block_number, staking_module_id, app = (
pause_mes['blockNumber'],
pause_mes['blockHash'],
pause_mes['stakingModuleId'],
((1).to_bytes(32),),
)
mes = self._w3.codec.encode(
types=[PAUSE_V2_DATA_SCHEMA],
args=[(block_number, block_hash, self._DEFAULT_SIGNATURE, staking_module_id, app)],
types=[PauseV2Parser.PAUSE_V2_DATA_SCHEMA],
args=[(block_number, self._DEFAULT_BLOCK_HASH, self._DEFAULT_SIGNATURE, staking_module_id, app)],
)
tx = self._data_bus.functions.sendMessage(pause_topic, mes)
return tx.transact()

def send_pause_v3(self, pause_mes: PauseMessage):
pause_topic = self._w3.keccak(text=OnchainTransportSinks.PAUSE_V3)
block_number, block_hash, version = pause_mes['blockNumber'], pause_mes['blockHash'], (1).to_bytes(32)
mes = self._w3.codec.encode(types=[PAUSE_V3_DATA_SCHEMA], args=[(block_number, block_hash, self._DEFAULT_SIGNATURE, (version,))])
block_number, version = pause_mes['blockNumber'], (1).to_bytes(32)
mes = self._w3.codec.encode(
types=[PauseV3Parser.PAUSE_V3_DATA_SCHEMA], args=[(block_number, self._DEFAULT_BLOCK_HASH, self._DEFAULT_SIGNATURE, (version,))]
)
tx = self._data_bus.functions.sendMessage(pause_topic, mes)
return tx.transact()

Expand All @@ -76,7 +78,7 @@ def send_unvet(self, unvet_mes: UnvetMessage):
(1).to_bytes(32),
)
mes = self._w3.codec.encode(
types=[UNVET_V1_DATA_SCHEMA],
types=[UnvetParser.UNVET_V1_DATA_SCHEMA],
args=[(block_number, block_hash, staking_module_id, nonce, operator_ids, vetted_keys, self._DEFAULT_SIGNATURE, (version,))],
)
tx = self._data_bus.functions.sendMessage(unvet_topic, mes)
Expand All @@ -85,6 +87,6 @@ def send_unvet(self, unvet_mes: UnvetMessage):
def send_ping(self, ping_mes: PingMessage):
ping_topic = self._w3.keccak(text=OnchainTransportSinks.PING_V1)
block_number, version = ping_mes['blockNumber'], (1).to_bytes(32)
mes = self._w3.codec.encode(types=[PING_V1_DATA_SCHEMA], args=[(block_number, (version,))])
mes = self._w3.codec.encode(types=[PingParser.PING_V1_DATA_SCHEMA], args=[(block_number, (version,))])
tx = self._data_bus.functions.sendMessage(ping_topic, mes)
return tx.transact()
15 changes: 9 additions & 6 deletions tests/transport/test_data_bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
from eth_typing import ChecksumAddress, HexAddress, HexStr
from schema import Or, Schema
from transport.msg_providers.onchain_transport import (
DEPOSIT_V1_DATA_SCHEMA,
PING_V1_DATA_SCHEMA,
DepositParser,
OnchainTransportProvider,
OnchainTransportSinks,
PingParser,
)
from transport.msg_types.deposit import DepositMessage, DepositMessageSchema
from transport.msg_types.ping import PingMessage, PingMessageSchema
Expand Down Expand Up @@ -123,15 +123,16 @@ def mock_receipts(w3: Web3) -> list[EventData]:
args={
'sender': _DEFAULT_GUARDIAN,
'data': w3.codec.encode(
types=[PING_V1_DATA_SCHEMA], args=[(1, ('0x0000000000000000000000000000000000000000000000000000000000000000',))]
types=[PingParser.PING_V1_DATA_SCHEMA],
args=[(1, ('0x0000000000000000000000000000000000000000000000000000000000000000',))],
),
},
),
EventData(
args={
'sender': _DEFAULT_GUARDIAN,
'data': w3.codec.encode(
types=[DEPOSIT_V1_DATA_SCHEMA],
types=[DepositParser.DEPOSIT_V1_DATA_SCHEMA],
args=[
(
2,
Expand All @@ -150,15 +151,17 @@ def mock_receipts(w3: Web3) -> list[EventData]:
args={
'sender': _DEFAULT_GUARDIAN,
'data': w3.codec.encode(
types=[PING_V1_DATA_SCHEMA], args=[(3, ('0x0000000000000000000000000000000000000000000000000000000000000000',))]
types=[PingParser.PING_V1_DATA_SCHEMA],
args=[(3, ('0x0000000000000000000000000000000000000000000000000000000000000000',))],
),
},
),
EventData(
args={
'sender': _DEFAULT_GUARDIAN,
'data': w3.codec.encode(
types=[PING_V1_DATA_SCHEMA], args=[(4, ('0x0000000000000000000000000000000000000000000000000000000000000000',))]
types=[PingParser.PING_V1_DATA_SCHEMA],
args=[(4, ('0x0000000000000000000000000000000000000000000000000000000000000000',))],
),
},
),
Expand Down

0 comments on commit 306e3c5

Please sign in to comment.