Skip to content
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

Fixes #75 #78

Merged
merged 3 commits into from
Oct 10, 2023
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
4 changes: 2 additions & 2 deletions eth_validator_watcher/entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
LimitedDict,
Slack,
convert_seconds_to_dhms,
eth1_address_0x_prefixed,
eth1_address_lower_0x_prefixed,
get_our_pubkeys,
slots,
write_liveness_file,
Expand Down Expand Up @@ -203,7 +203,7 @@ def _handler(

if fee_recipient is not None:
try:
fee_recipient = eth1_address_0x_prefixed(fee_recipient)
fee_recipient = eth1_address_lower_0x_prefixed(fee_recipient)
except ValueError:
raise typer.BadParameter("`fee-recipient` should be a valid ETH1 address")

Expand Down
13 changes: 10 additions & 3 deletions eth_validator_watcher/fee_recipient.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,17 @@ def process_fee_recipient(
epoch = slot // NB_SLOT_PER_EPOCH

# First, we check if the beacon block fee recipient is the one expected
actual_fee_recipient = block.data.message.body.execution_payload.fee_recipient
# `.lower()` is here just in case the execution client returns a fee recipient in
# checksum casing
actual_fee_recipient = (
block.data.message.body.execution_payload.fee_recipient.lower()
)

if actual_fee_recipient == expected_fee_recipient:
# Allright, we're good
return

# If not, it may be because the block was builded by an external builder that
# If not, it may be because the block was built by an external builder that
# set its own fee recipient. In this case, we need to check if the last transaction
# in the execution block is a transaction to the expected fee recipient.

Expand All @@ -65,9 +69,12 @@ def process_fee_recipient(
try:
*_, last_transaction = transactions

# `.lower()` is here just in case the execution client returns transacion "to"
# in checksum casing

if (
last_transaction.to is not None
and expected_fee_recipient == last_transaction.to
and expected_fee_recipient == last_transaction.to.lower()
):
# The last transaction is to the expected fee recipient
return
Expand Down
28 changes: 17 additions & 11 deletions eth_validator_watcher/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,9 @@ def load_pubkeys_from_file(path: Path) -> set[str]:
Returns the corresponding set of public keys.
"""
with path.open() as file_descriptor:
return set((eth2_address_0x_prefixed(line.strip()) for line in file_descriptor))
return set(
(eth2_address_lower_0x_prefixed(line.strip()) for line in file_descriptor)
)


def get_our_pubkeys(
Expand Down Expand Up @@ -254,24 +256,28 @@ def convert_seconds_to_dhms(seconds: int) -> tuple[int, int, int, int]:
return days, hours, minutes, seconds


def eth1_address_0x_prefixed(address: str) -> str:
if not re.match(f"^(0x)?[0-9a-fA-F]{{{ETH1_ADDRESS_LEN}}}$", address):
raise ValueError(f"Invalid ETH1 address: {address}")
def eth1_address_lower_0x_prefixed(address: str) -> str:
address_lower = address.lower()

if not re.match(f"^(0x)?[0-9a-f]{{{ETH1_ADDRESS_LEN}}}$", address_lower):
raise ValueError(f"Invalid ETH1 address: {address_lower}")

if len(address) == ETH1_ADDRESS_LEN:
return f"0x{address}"
return f"0x{address_lower}"

return address_lower

return address

def eth2_address_lower_0x_prefixed(address: str) -> str:
address_lower = address.lower()

def eth2_address_0x_prefixed(address: str) -> str:
if not re.match(f"^(0x)?[0-9a-fA-F]{{{ETH2_ADDRESS_LEN}}}$", address):
raise ValueError(f"Invalid ETH2 address: {address}")
if not re.match(f"^(0x)?[0-9a-f]{{{ETH2_ADDRESS_LEN}}}$", address_lower):
raise ValueError(f"Invalid ETH2 address: {address_lower}")

if len(address) == ETH2_ADDRESS_LEN:
return f"0x{address}"
return f"0x{address_lower}"

return address
return address_lower


class LimitedDict:
Expand Down
2 changes: 1 addition & 1 deletion tests/fee_recipient/assets/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
],
"execution_payload": {
"parent_hash": "0x4b7de5b987b9bfc9aa2e7e58cf25515950c8f0b7da00366ecd5ae8cfd8e05fa3",
"fee_recipient": "0xebec795c9c8bbd61ffc14a6662944748f299cacf",
"fee_recipient": "0xEbeC795c9C8bbd61ffc14a6662944748f299cacf",
"state_root": "0x1e21e560eb6ba930006c3dad4d1b301f74ab324711931a0a5e8632f1ee3c2de2",
"receipts_root": "0x102f655d8a01fc5484b259c4067fa560796ae22ca5d67364b94e217e3f3f8029",
"logs_bloom": "0x46a5913764080408104db1108133191d16e4cc411f45c59a0103580f570e915451a55b82c752a92107a0961404d11161165584b699427a00230e21f111eca4828cc160bae709da2ce9436609cb388529b2f6522915f7e8a8f8ad5769d8f62810132ef61aa61384c711c00508b02868cfcc15483ee01a8d18e28805d1ca580744a0e232d6ff040c0810cc04404346d03e569024a1a99c10d9453439685832c08c1e1e25455c9a6e835d5949d677298c2d87108a012082440514364c051106304157fe1a47b4010b49f800cc540055f00484444a26545810540b1d45220ae4e088383aa80ad05007340915a0aa1403f0e58039161019a81c4608df0912008a950a",
Expand Down
2 changes: 1 addition & 1 deletion tests/fee_recipient/assets/execution_block.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"hash": "0xdedc7e577b6e84727edd683a447c8a9b684bfd0ddaaf3110050f37c750ee44cd",
"input": "0x",
"nonce": "0xfb30",
"to": "0x760a6314a1d207377271917075f88e520141d55f",
"to": "0x760A6314a1D207377271917075f88e520141D55F",
"transactionIndex": "0x6b",
"value": "0x13274cb7135e000",
"type": "0x2",
Expand Down
19 changes: 10 additions & 9 deletions tests/utils/test_eth1_address_0x_prefixed.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
from pytest import raises

from eth_validator_watcher.utils import eth1_address_0x_prefixed
from eth_validator_watcher.utils import eth1_address_lower_0x_prefixed


def test_eth1_address_0x_prefixed_invalid() -> None:
# Too short
with raises(ValueError):
eth1_address_0x_prefixed("0x123")
eth1_address_lower_0x_prefixed("0x123")

# Too long
with raises(ValueError):
eth1_address_0x_prefixed(
eth1_address_lower_0x_prefixed(
"0x123456789012345678901234567890123456789012345678901234567890123"
)

# Invalid character
with raises(ValueError):
eth1_address_0x_prefixed("0x8d8b1b85d02d05ad3a14e2e9cc7b458d5invalid")
eth1_address_lower_0x_prefixed("0x8d8b1b85d02d05ad3a14e2e9cc7b458d5invalid")


def test_eth1_address_0x_prefixed_valid_already_prefixed() -> None:
address = "0x8d8b1b85d02d05ad3a14e2e9cc7b458d5c7d8f8c"
assert eth1_address_0x_prefixed(address) == address
input = "0x8D8B1b85D02d05Ad3a14E2e9cC7b458d5c7d8f8c"
expected_output = "0x8d8b1b85d02d05ad3a14e2e9cc7b458d5c7d8f8c"
assert eth1_address_lower_0x_prefixed(input) == expected_output


def test_eth1_address_0x_prefixed_valid_not_already_prefixed() -> None:
address_without_prefix = "8d8b1b85d02d05ad3a14e2e9cc7b458d5c7d8f8c"
address_with_prefix = "0x8d8b1b85d02d05ad3a14e2e9cc7b458d5c7d8f8c"
assert eth1_address_0x_prefixed(address_without_prefix) == address_with_prefix
input = "8D8B1b85D02d05Ad3a14E2e9cC7b458d5c7d8f8c"
expected_output = "0x8d8b1b85d02d05ad3a14e2e9cc7b458d5c7d8f8c"
assert eth1_address_lower_0x_prefixed(input) == expected_output
19 changes: 10 additions & 9 deletions tests/utils/test_eth2_address_0x_prefixed.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
from pytest import raises

from eth_validator_watcher.utils import eth2_address_0x_prefixed
from eth_validator_watcher.utils import eth2_address_lower_0x_prefixed


def test_eth2_address_0x_prefixed_invalid() -> None:
# Too short
with raises(ValueError):
eth2_address_0x_prefixed("0x123")
eth2_address_lower_0x_prefixed("0x123")

# Too long
with raises(ValueError):
eth2_address_0x_prefixed(
eth2_address_lower_0x_prefixed(
"0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
)

# Invalid character
with raises(ValueError):
eth2_address_0x_prefixed("0x8d8b1b85d02d05ad3a14e2e9cc7b458d5invalid")
eth2_address_lower_0x_prefixed("0x8d8b1b85d02d05ad3a14e2e9cc7b458d5invalid")


def test_eth2_address_0x_prefixed_valid_already_prefixed() -> None:
address = "0xb2ddae7e32fd8257c2dd468ca16dc86d310cab218f9a41ed6fabea525a9620d46955350776e8496553138c8a291a365b"
assert eth2_address_0x_prefixed(address) == address
input = "0xB2dDae7E32fd8257c2dd468ca16dc86d310cab218f9a41ed6fabea525a9620d46955350776e8496553138c8a291a365b"
expected_output = "0xb2ddae7e32fd8257c2dd468ca16dc86d310cab218f9a41ed6fabea525a9620d46955350776e8496553138c8a291a365b"
assert eth2_address_lower_0x_prefixed(input) == expected_output


def test_eth2_address_0x_prefixed_valid_not_already_prefixed() -> None:
address_without_prefix = "b2ddae7e32fd8257c2dd468ca16dc86d310cab218f9a41ed6fabea525a9620d46955350776e8496553138c8a291a365b"
address_with_prefix = "0xb2ddae7e32fd8257c2dd468ca16dc86d310cab218f9a41ed6fabea525a9620d46955350776e8496553138c8a291a365b"
assert eth2_address_0x_prefixed(address_without_prefix) == address_with_prefix
input = "B2Ddae7e32fd8257C2dd468ca16dc86d310cab218f9a41ed6fabea525a9620d46955350776e8496553138c8a291a365b"
expected_output = "0xb2ddae7e32fd8257c2dd468ca16dc86d310cab218f9a41ed6fabea525a9620d46955350776e8496553138c8a291a365b"
assert eth2_address_lower_0x_prefixed(input) == expected_output