Пример #1
0
 def _get_deposit(self, deposit_count: int, deposit_index: int) -> Deposit:
     """
     Return `Deposit` according to `deposit_count` and `deposit_index`.
     It should include the deposit data at the `deposit_index`, and the merkle proof of
     the corresponding merkle tree made from deposit data of size `deposit_count`.
     """
     if deposit_index >= deposit_count:
         raise Eth1MonitorValidationError(
             "`deposit_index` should be smaller than `deposit_count`: "
             f"deposit_index={deposit_index}, deposit_count={deposit_count}"
         )
     len_deposit_data = self.total_deposit_count
     if deposit_count <= 0 or deposit_count > len_deposit_data:
         raise Eth1MonitorValidationError(
             f"invalid `deposit_count`: deposit_count={deposit_count}")
     if deposit_index < 0 or deposit_index >= len_deposit_data:
         raise Eth1MonitorValidationError(
             f"invalid `deposit_index`: deposit_index={deposit_index}")
     deposit_data_in_range = self._db.get_deposit_data_range(
         0, deposit_count)
     tree, root = make_deposit_tree_and_root(deposit_data_in_range)
     return Deposit(
         proof=make_deposit_proof(deposit_data_in_range, tree, root,
                                  deposit_index),
         data=self._db.get_deposit_data(deposit_index),
     )
Пример #2
0
    def _get_eth1_data(
            self, distance: BlockNumber,
            eth1_voting_period_start_timestamp: Timestamp) -> Eth1Data:
        """
        Return `Eth1Data` at `distance` relative to the eth1 block earlier and closest to the
        timestamp `eth1_voting_period_start_timestamp`.
        Ref: https://github.com/ethereum/eth2.0-specs/blob/61f2a0662ebcfb4c097360cc1835c5f01872705c/specs/validator/0_beacon-chain-validator.md#eth1-data  # noqa: E501

        First, we find the `eth1_block` whose timestamp is the largest timestamp which is smaller
        than `eth1_voting_period_start_timestamp`. Then, find the block `target_block` at number
        `eth1_block.number - distance`. Therefore, we can return `Eth1Data` according to the
        information of this block.
        """
        eth1_voting_period_start_block_number = self._get_closest_eth1_voting_period_start_block(
            eth1_voting_period_start_timestamp)
        target_block_number = BlockNumber(
            eth1_voting_period_start_block_number - distance)
        if target_block_number < 0:
            raise Eth1MonitorValidationError(
                f"`distance` is larger than `eth1_voting_period_start_block_number`: "
                f"`distance`={distance}, ",
                f"eth1_voting_period_start_block_number={eth1_voting_period_start_block_number}",
            )
        try:
            block = self._eth1_data_provider.get_block(target_block_number)
        except BlockNotFound:
            raise Eth1MonitorValidationError(
                f"Block does not exist for block number={target_block_number}")
        block_hash = block.block_hash
        # `Eth1Data.deposit_count`: get the `deposit_count` corresponding to the block.
        accumulated_deposit_count = self._get_accumulated_deposit_count(
            target_block_number)
        if accumulated_deposit_count == 0:
            raise Eth1MonitorValidationError(
                f"failed to make `Eth1Data`: `deposit_count = 0` at block #{target_block_number}"
            )
        # Verify that the deposit data in db and the deposit data in contract match
        deposit_data_in_range = self._db.get_deposit_data_range(
            0, accumulated_deposit_count)
        _, deposit_root = make_deposit_tree_and_root(deposit_data_in_range)
        contract_deposit_root = self._get_deposit_root_from_contract(
            target_block_number)
        if contract_deposit_root != deposit_root:
            raise DepositDataCorrupted(
                "deposit root built locally mismatches the one in the contract on chain: "
                f"contract_deposit_root={contract_deposit_root.hex()}, "
                f"deposit_root={deposit_root.hex()}")
        return Eth1Data.create(
            deposit_root=deposit_root,
            deposit_count=accumulated_deposit_count,
            block_hash=block_hash,
        )
Пример #3
0
 def get_deposit_root(self, block_number: BlockNumber) -> Hash32:
     # Check and update deposit data when deposit root is requested
     if self.latest_processed_block_number < block_number:
         for blk_number in range(self.latest_processed_block_number + 1, block_number + 1):
             deposit_logs = self.get_logs(BlockNumber(blk_number))
             self.deposits += tuple(
                 convert_deposit_log_to_deposit_data(deposit_log)
                 for deposit_log in deposit_logs
             )
         self.latest_processed_block_number = block_number
     deposit_count_bytes = self.get_deposit_count(block_number)
     deposit_count = int.from_bytes(deposit_count_bytes, byteorder='little')
     deposits = self.deposits[:deposit_count]
     _, deposit_root = make_deposit_tree_and_root(deposits)
     return deposit_root