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

Cache validator registration request while deposit root not changed #149

Merged
merged 5 commits into from
Aug 24, 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
13 changes: 8 additions & 5 deletions src/validators/execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
get_eth1_withdrawal_credentials,
is_valid_deposit_data_signature,
)
from sw_utils.typings import Bytes32
from web3 import Web3
from web3.types import EventData, Wei

Expand Down Expand Up @@ -225,6 +226,7 @@ async def register_single_validator(
validator: Validator,
approval: OraclesApproval,
update_state_call: HexStr | None,
validators_registry_root: Bytes32,
) -> None:
"""Registers single validator."""
if settings.network not in ETH_NETWORKS:
Expand All @@ -237,7 +239,7 @@ async def register_single_validator(
logger.info('Submitting registration transaction')
register_call_args = [
(
approval.validators_registry_root,
validators_registry_root,
tx_validator,
approval.signatures,
approval.ipfs_hash,
Expand All @@ -262,7 +264,8 @@ async def register_multiple_validator(
tree: StandardMerkleTree,
validators: list[Validator],
approval: OraclesApproval,
update_call: HexStr | None,
update_state_call: HexStr | None,
validators_registry_root: Bytes32,
) -> None:
"""Registers multiple validators."""
if settings.network not in ETH_NETWORKS:
Expand All @@ -283,7 +286,7 @@ async def register_multiple_validator(
logger.info('Submitting registration transaction')
register_call_args = [
(
approval.validators_registry_root,
validators_registry_root,
b''.join(tx_validators),
approval.signatures,
approval.ipfs_hash,
Expand All @@ -292,12 +295,12 @@ async def register_multiple_validator(
multi_proof.proof_flags,
multi_proof.proof,
]
if update_call is not None:
if update_state_call is not None:
register_call = vault_contract.encodeABI(
fn_name='registerValidators',
args=register_call_args,
)
tx = await vault_contract.functions.multicall([update_call, register_call]).transact()
tx = await vault_contract.functions.multicall([update_state_call, register_call]).transact()
else:
tx = await vault_contract.functions.registerValidators(*register_call_args).transact()

Expand Down
52 changes: 38 additions & 14 deletions src/validators/tasks.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import logging

from sw_utils.typings import Bytes32
from web3 import Web3
from web3.types import BlockNumber, Wei

Expand Down Expand Up @@ -70,7 +71,27 @@ async def register_validators(keystores: Keystores, deposit_data: DepositData) -
)
return

oracles_approval = await get_oracles_approval(oracles, keystores, validators)
registry_root = None

while True:
latest_registry_root = await validators_registry_contract.get_registry_root()

if not registry_root or registry_root != latest_registry_root:
registry_root = latest_registry_root
logger.debug('Fetched latest validators registry root: %s', registry_root)

oracles_request = await create_approval_request(
registry_root=registry_root,
oracles=oracles,
keystores=keystores,
validators=validators,
)

try:
oracles_approval = await get_oracles_approval(oracles=oracles, request=oracles_request)
break
except Exception as e:
logger.exception(e)

if len(validators) == 1:
validator = validators[0]
Expand All @@ -79,30 +100,30 @@ async def register_validators(keystores: Keystores, deposit_data: DepositData) -
validator=validator,
approval=oracles_approval,
update_state_call=update_state_call,
validators_registry_root=registry_root,
)
logger.info('Successfully registered validator with public key %s', validator.public_key)

if len(validators) > 1:
await register_multiple_validator(
deposit_data.tree, validators, oracles_approval, update_state_call
tree=deposit_data.tree,
validators=validators,
approval=oracles_approval,
update_state_call=update_state_call,
validators_registry_root=registry_root,
)
pub_keys = ', '.join([val.public_key for val in validators])
logger.info('Successfully registered validators with public keys %s', pub_keys)


async def get_oracles_approval(
oracles: Oracles, keystores: Keystores, validators: list[Validator]
) -> OraclesApproval:
"""Fetches approval from oracles."""

# get latest registry root
registry_root = await validators_registry_contract.get_registry_root()
logger.debug('Fetched latest validators registry root: %s', registry_root)
async def create_approval_request(
oracles: Oracles, keystores: Keystores, validators: list[Validator], registry_root: Bytes32
) -> ApprovalRequest:
"""Generate validator registration request data"""

# get next validator index for exit signature
latest_public_keys = await get_latest_network_validator_public_keys()
validator_index = NetworkValidatorCrud().get_next_validator_index(list(latest_public_keys))
start_validator_index = validator_index
logger.debug('Next validator index for exit signature: %d', validator_index)

# fetch current fork data
Expand Down Expand Up @@ -138,18 +159,21 @@ async def get_oracles_approval(
request.exit_signature_shards.append(shards.exit_signatures)

validator_index += 1
return request


async def get_oracles_approval(oracles: Oracles, request: ApprovalRequest) -> OraclesApproval:
"""Fetches approval from oracles."""
# send approval request to oracles
signatures, ipfs_hash = await send_approval_requests(oracles, request)
logger.info(
'Fetched oracles approval for validators: count=%d, start index=%d',
len(validators),
start_validator_index,
len(request.public_keys),
request.validator_index,
)
return OraclesApproval(
signatures=signatures,
ipfs_hash=ipfs_hash,
validators_registry_root=registry_root,
)


Expand Down
2 changes: 1 addition & 1 deletion src/validators/typings.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ class ExitSignatureShards:

@dataclass
class OraclesApproval:
validators_registry_root: Bytes32
signatures: bytes
ipfs_hash: str


@dataclass
# pylint: disable-next=too-many-instance-attributes
cyc60 marked this conversation as resolved.
Show resolved Hide resolved
class ApprovalRequest:
validator_index: int
vault_address: ChecksumAddress
Expand Down
2 changes: 1 addition & 1 deletion src/validators/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ async def send_approval_requests(oracles: Oracles, request: ApprovalRequest) ->
raise RuntimeError('Not enough oracles to get approval from')

if len(set(ipfs_hashes)) != 1:
raise ValueError('Different oracles IPFS hashes for approval request')
raise ValueError('Different oracles IPFS hashes for approval request.')

signatures = b''
for address in sorted(responses.keys())[: oracles.validators_threshold]:
Expand Down