Skip to content

Commit

Permalink
Cache validator registration request while deposit root not changed
Browse files Browse the repository at this point in the history
Signed-off-by: cyc60 <[email protected]>
  • Loading branch information
cyc60 committed Aug 22, 2023
1 parent 3d27c3b commit 0a7f9bb
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 21 deletions.
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
53 changes: 39 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)
# get latest registry root
latest_registry_root = await validators_registry_contract.get_registry_root()
logger.debug('Fetched latest validators registry root: %s', latest_registry_root)
registry_root = None

while True:
if not registry_root or registry_root != latest_registry_root:
registry_root = latest_registry_root
oracles_request = await get_oracles_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)
latest_registry_root = await validators_registry_contract.get_registry_root()

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 get_oracles_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 All @@ -118,6 +139,7 @@ async def get_oracles_approval(
deposit_signatures=[],
public_key_shards=[],
exit_signature_shards=[],
proof=Bytes32(b''),
)
for validator in validators:
shards = get_exit_signature_shards(
Expand All @@ -138,18 +160,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
3 changes: 2 additions & 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
class ApprovalRequest:
validator_index: int
vault_address: ChecksumAddress
Expand All @@ -50,6 +50,7 @@ class ApprovalRequest:
deposit_signatures: list[HexStr]
public_key_shards: list[list[HexStr]]
exit_signature_shards: list[list[HexStr]]
proof: Bytes32


@dataclass
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

0 comments on commit 0a7f9bb

Please sign in to comment.