Пример #1
0
def get_eth2_details(
        beaconchain: 'BeaconChain',
        addresses: List[ChecksumEthAddress],
) -> List[ValidatorDetails]:
    """Go through the list of eth1 addresses and find all eth2 validators associated
    with them along with their details. Also returns the daily stats for each validator.

    May raise RemoteError due to beaconcha.in API"""
    indices = []
    index_to_address = {}
    index_to_pubkey = {}
    assert beaconchain.db is not None, 'Beaconchain db should be populated'
    # and for each address get the validator info (to get the index) -- this could be avoided
    for address in addresses:
        validators = beaconchain.get_eth1_address_validators(address)
        for validator in validators:
            index_to_address[validator.validator_index] = address
            index_to_pubkey[validator.validator_index] = validator.public_key
            indices.append(validator.validator_index)

    # Get current balance of all validator indices
    result = []
    performance_result = beaconchain.get_performance(list(indices))
    for validator_index, entry in performance_result.items():
        stats = get_validator_daily_stats(
            db=beaconchain.db,
            validator_index=validator_index,
            msg_aggregator=beaconchain.msg_aggregator,
        )
        result.append(ValidatorDetails(
            validator_index=validator_index,
            public_key=index_to_pubkey[validator_index],
            eth1_depositor=index_to_address[validator_index],
            performance=entry,
            daily_stats=stats,
        ))

    # The performance call does not return validators that are not active and are still depositing
    depositing_indices = set(index_to_address.keys()) - set(performance_result.keys())
    for index in depositing_indices:
        stats = get_validator_daily_stats(
            db=beaconchain.db,
            validator_index=index,
            msg_aggregator=beaconchain.msg_aggregator,
        )
        result.append(ValidatorDetails(
            validator_index=index,
            public_key=index_to_pubkey[index],
            eth1_depositor=index_to_address[index],
            performance=DEPOSITING_VALIDATOR_PERFORMANCE,
            daily_stats=stats,
        ))

    return result
Пример #2
0
def test_get_eth2_details_validator_not_yet_active(beaconchain, inquirer,
                                                   price_historian):  # pylint: disable=unused-argument  # noqa: E501
    """Test that if a validator is detected but is not yet active the balance is shown properly

    Test for: https://github.com/rotki/rotki/issues/1888
    """
    with _create_beacon_mock(beaconchain):
        details = get_eth2_details(beaconchain=beaconchain, addresses=[ADDR1])

    for idx in range(0, 2):
        # basic check about daily stats but then delete since this is not what this test checks
        assert len(details[idx].daily_stats) > 0
        assert details[idx].daily_stats[0].timestamp < details[
            idx].daily_stats[-1].timestamp
        details[idx] = details[idx]._replace(daily_stats=[])

    expected_details = [
        ValidatorDetails(
            validator_index=9,
            public_key=
            '0xb016e31f633a21fbe42a015152399361184f1e2c0803d89823c224994af74a561c4ad8cfc94b18781d589d03e952cd5b',  # noqa: E501
            eth1_depositor=ADDR1,
            performance=ValidatorPerformance(
                balance=32143716247,
                performance_1d=14437802,
                performance_1w=105960750,
                performance_1m=143716247,
                performance_1y=143716247,
            ),
            daily_stats=[],
        ),
        ValidatorDetails(
            validator_index=1507,
            public_key=
            '0x8b242e5cdb0a7740a605f3c39262253eb2b5e7ee514a544e823f996e8de9961db7d5264d08c5ce13a65efa82b868accc',  # noqa: E501
            eth1_depositor=ADDR1,
            performance=DEPOSITING_VALIDATOR_PERFORMANCE,
            daily_stats=[],
        ),
    ]
    assert details == expected_details
Пример #3
0
    def get_details(
        self,
        addresses: List[ChecksumEthAddress],
    ) -> List[ValidatorDetails]:
        """Go through the list of eth1 addresses and find all eth2 validators associated
        with them along with their details. Also returns the daily stats for each validator.

        May raise RemoteError due to beaconcha.in API"""
        indices = []
        index_to_address = {}
        index_to_pubkey = {}
        result = []
        assert self.beaconchain.db is not None, 'Beaconchain db should be populated'

        for address in addresses:
            validators = self.beaconchain.get_eth1_address_validators(address)
            for validator in validators:
                if validator.validator_index is None:
                    # for validators that are so early in the depositing queue that no
                    # validator index is confirmed yet let's return only the most basic info
                    result.append(
                        ValidatorDetails(
                            validator_index=None,
                            public_key=validator.public_key,
                            eth1_depositor=address,
                            performance=DEPOSITING_VALIDATOR_PERFORMANCE,
                            daily_stats=[],
                        ))
                    continue

                index_to_address[validator.validator_index] = address
                index_to_pubkey[
                    validator.validator_index] = validator.public_key
                indices.append(validator.validator_index)

        # Get current balance of all validator indices
        performance_result = self.beaconchain.get_performance(list(indices))
        for validator_index, entry in performance_result.items():
            stats = self.get_validator_daily_stats(
                validator_index=validator_index,
                msg_aggregator=self.msg_aggregator,
            )
            result.append(
                ValidatorDetails(
                    validator_index=validator_index,
                    public_key=index_to_pubkey[validator_index],
                    eth1_depositor=index_to_address[validator_index],
                    performance=entry,
                    daily_stats=stats,
                ))

        # Performance call does not return validators that are not active and are still depositing
        depositing_indices = set(index_to_address.keys()) - set(
            performance_result.keys())
        for index in depositing_indices:
            stats = self.get_validator_daily_stats(
                validator_index=index,
                msg_aggregator=self.msg_aggregator,
            )
            result.append(
                ValidatorDetails(
                    validator_index=index,
                    public_key=index_to_pubkey[index],
                    eth1_depositor=index_to_address[index],
                    performance=DEPOSITING_VALIDATOR_PERFORMANCE,
                    daily_stats=stats,
                ))

        return result
Пример #4
0
    def get_details(
        self,
        addresses: List[ChecksumEthAddress],
    ) -> List[ValidatorDetails]:
        """Go through the list of eth1 addresses and find all eth2 validators associated
        with them along with their details.



        May raise RemoteError due to beaconcha.in API"""
        indices = []
        index_to_address = {}
        index_to_pubkey = {}
        pubkey_to_index = {}
        result = []
        assert self.beaconchain.db is not None, 'Beaconchain db should be populated'
        address_validators = []

        for address in addresses:
            validators = self.beaconchain.get_eth1_address_validators(address)
            for validator in validators:
                if validator.index is None:
                    # for validators that are so early in the depositing queue that no
                    # validator index is confirmed yet let's return only the most basic info
                    result.append(
                        ValidatorDetails(
                            validator_index=None,
                            public_key=validator.public_key,
                            eth1_depositor=address,
                            performance=DEPOSITING_VALIDATOR_PERFORMANCE,
                        ))
                    continue

                index_to_address[validator.index] = address
                address_validators.append(
                    Eth2Validator(index=validator.index,
                                  public_key=validator.public_key,
                                  ownership_proportion=ONE))  # noqa: E501

        # make sure all validators we deal with are saved in the DB
        dbeth2 = DBEth2(self.database)
        dbeth2.add_validators(address_validators)

        # Also get all manually input validators
        all_validators = dbeth2.get_validators()
        saved_deposits = dbeth2.get_eth2_deposits()
        pubkey_to_deposit = {x.pubkey: x for x in saved_deposits}
        validators_to_query_for_deposits = []
        for v in all_validators:
            index_to_pubkey[v.index] = v.public_key
            pubkey_to_index[v.public_key] = v.index
            indices.append(v.index)
            depositor = index_to_address.get(v.index)
            if depositor is None:
                if v.public_key not in pubkey_to_deposit:
                    validators_to_query_for_deposits.append(v.public_key)

        # Get new deposits if needed, and populate index_to_address
        new_deposits = self._query_and_save_deposits(
            dbeth2, validators_to_query_for_deposits)
        for deposit in saved_deposits + new_deposits:
            index = pubkey_to_index.get(Eth2PubKey(deposit.pubkey))
            if index is None:  # should never happen, unless returned data is off
                log.error(
                    f'At eth2 staking details could not find index for pubkey '
                    f'{deposit.pubkey} at deposit {deposit}.', )
                continue

            index_to_address[index] = deposit.from_address

        # Get current balance of all validator indices
        performance_result = self.beaconchain.get_performance(indices)
        for validator_index, entry in performance_result.items():
            depositor = index_to_address.get(validator_index)
            if depositor is None:  # should never happen, unless returned data is off
                log.error(
                    f'At eth2 staking details could not find depositor for index '
                    f'{validator_index} at index_to_address', )
                continue

            result.append(
                ValidatorDetails(
                    validator_index=validator_index,
                    public_key=index_to_pubkey[validator_index],
                    eth1_depositor=depositor,
                    performance=entry,
                ))

        # Performance call does not return validators that are not active and are still depositing
        depositing_indices = set(index_to_address.keys()) - set(
            performance_result.keys())
        for index in depositing_indices:
            depositor = index_to_address.get(index)
            if depositor is None:  # should never happen, unless returned data is off
                log.error(
                    f'At eth2 staking details could not find depositor for index '
                    f'{index} at index_to_address for depositing indices', )
                continue

            result.append(
                ValidatorDetails(
                    validator_index=index,
                    public_key=index_to_pubkey[index],
                    eth1_depositor=depositor,
                    performance=DEPOSITING_VALIDATOR_PERFORMANCE,
                ))

        return result