-
Notifications
You must be signed in to change notification settings - Fork 44
Vaults Release #815
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
base: master
Are you sure you want to change the base?
Vaults Release #815
Conversation
…le into feat/vaults-pectra
| """ | ||
| Returns the Vaults | ||
| """ | ||
| response = self.functions.batchVaultsInfo(offset, limit).call(block_identifier=block_identifier) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| response = self.functions.batchVaultsInfo(offset, limit).call(block_identifier=block_identifier) | |
| response = self.functions().batchVaultsInfo(offset, limit).call(block_identifier=block_identifier) |
| CACHE_PATH: Final = Path(os.getenv("CACHE_PATH", ".")) | ||
|
|
||
| VAULT_PAGINATION_LIMIT: Final = int(os.getenv("VAULT_PAGINATION_LIMIT", 1_000)) | ||
| VAULT_VALIDATOR_STAGES_BATCH_SIZE: Final = int(os.getenv("VAULT_VALIDATOR_STAGES_BATCH_SIZE", 1_00)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tamtamchik you've not renamed this variable stages -> statuses
also formatting suggestion (just in case is it supposed to be 100 or 1_000?)
| VAULT_VALIDATOR_STAGES_BATCH_SIZE: Final = int(os.getenv("VAULT_VALIDATOR_STAGES_BATCH_SIZE", 1_00)) | |
| VAULT_VALIDATOR_STAGES_BATCH_SIZE: Final = int(os.getenv("VAULT_VALIDATOR_STAGES_BATCH_SIZE", 100)) |
|
|
||
| CACHE_PATH: Final = Path(os.getenv("CACHE_PATH", ".")) | ||
|
|
||
| VAULT_PAGINATION_LIMIT: Final = int(os.getenv("VAULT_PAGINATION_LIMIT", 1_000)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Too high. Estimated gas consumtion > 80kk. I propose to set it in 100.
| CACHE_PATH: Final = Path(os.getenv("CACHE_PATH", ".")) | ||
|
|
||
| VAULT_PAGINATION_LIMIT: Final = int(os.getenv("VAULT_PAGINATION_LIMIT", 1_000)) | ||
| VAULT_VALIDATOR_STAGES_BATCH_SIZE: Final = int(os.getenv("VAULT_VALIDATOR_STAGES_BATCH_SIZE", 1_00)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| VAULT_VALIDATOR_STAGES_BATCH_SIZE: Final = int(os.getenv("VAULT_VALIDATOR_STAGES_BATCH_SIZE", 1_00)) | |
| VAULT_VALIDATOR_STAGES_BATCH_SIZE: Final = int(os.getenv("VAULT_VALIDATOR_STAGES_BATCH_SIZE", 100)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be increased to 1_000
| def get_validator_statuses( | ||
| self, | ||
| pubkeys: list[str], | ||
| batch_size: int = variables.VAULT_VALIDATOR_STAGES_BATCH_SIZE, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better provide this variable from staking vault service. Do not use as default, like this
| out: dict[str, ValidatorStatus] = {} | ||
|
|
||
| for i in range(0, len(pubkeys), batch_size): | ||
| batch = list(map(HexBytes, pubkeys[i : i + batch_size])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we applying HexBytes here? Let's remove it
| for pk, status in zip(batch, response) | ||
| }) | ||
|
|
||
| return out |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add info log after all responses were received
| batch = self.get_vaults( | ||
| block_identifier=block_identifier, offset=offset, limit=variables.VAULT_PAGINATION_LIMIT | ||
| ) | ||
| if not batch: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a case when we can receive empty response here?
|
|
||
| return out | ||
|
|
||
| def get_all_vaults(self, block_identifier: BlockIdentifier = 'latest') -> list[VaultInfo]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need tests for pagination in get_all_vaults and for get_validator_statuses
|
|
||
| logger.info( | ||
| { | ||
| 'msg': 'Call `simulateOracleReport({}, {}, {}, {}, {}, {}, {}, {}, {})`.'.format( # pylint: disable=consider-using-f-string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 'msg': 'Call `simulateOracleReport({}, {}, {}, {}, {}, {}, {}, {}, {})`.'.format( # pylint: disable=consider-using-f-string | |
| 'msg': 'Call `simulateOracleReport({}, {}, {}, {}, {}, {}, {}, {}, {})`.'.format(*payload.as_tuple()) |
|
|
||
| response = self.functions.simulateOracleReport(payload.as_tuple()).call(block_identifier=block_identifier) | ||
|
|
||
| response = ReportSimulationResults(*response) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better assign field by field:
eg balance=balance
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or use named_tuple_to_dataclass
|
|
||
| out: list[VaultInfo] = [] | ||
| for vault in response: | ||
| out.append(VaultInfo( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we use named_tuple_to_dataclass here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or just
@list_of_dataclasses(VaultInfo)
| ) -> list[MintedSharesOnVaultEvent]: | ||
| logs = get_events_in_range(self.events.MintedSharesOnVault(), from_block_number, to_block_number) | ||
|
|
||
| return [MintedSharesOnVaultEvent.from_log(log) for log in logs] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need some tests on all from_log methods
| BRIDGE_URL = 'https://up.storacha.network/bridge' | ||
| GATEWAY_URL = 'https://storacha.link/ipfs/' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe move this to variables?
| API_GET_VALIDATORS = 'eth/v1/beacon/states/{}/validators' | ||
| API_GET_SPEC = 'eth/v1/config/spec' | ||
| API_GET_GENESIS = 'eth/v1/beacon/genesis' | ||
| API_GET_VALIDATOR = 'eth/v1/beacon/states/{}/validators/{}' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add additional check with this api to checks module
| 'simulate_oracle_report', | ||
| ( | ||
| ReportSimulationPayload( | ||
| timestamp=0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we write a test with non zero vaules?
| """ | ||
| validators_by_vault = self._get_validators_by_vault(validators, vaults) | ||
| total_pending_amount_by_pubkey = self._get_total_pending_amount_by_pubkey(pending_deposits) | ||
| inactive_validator_statuses = self._get_non_activated_validator_stages(validators, vaults, block_identifier) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_get_non_activated_validator_stages -> _get_non_activated_validator_statuses
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe get_non_aligable_to_activate_validators?
| and v.validator.withdrawal_credentials in vault_wcs | ||
| ] | ||
|
|
||
| return self.w3.lido_contracts.lazy_oracle.get_validator_statuses( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I propose to filter all not found keys here
| return {pubkey: Gwei(deposits[pubkey]) for pubkey in deposits} | ||
|
|
||
| @staticmethod | ||
| def _get_validators_by_vault(validators: list[Validator], vaults: VaultsMap) -> VaultToValidators: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add unit tests for this func
|
|
||
|
|
||
| def calculate_gross_core_apr( | ||
| post_internal_ether: int, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think here should be weis and shares everywhere
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: check why typecheking not working
| from src.modules.accounting.types import SECONDS_IN_YEAR, Shares | ||
|
|
||
|
|
||
| def calculate_gross_core_apr( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it's net apr since we're removing fees from calculations?
| rate_diff: Decimal = post_share_rate_no_fees - pre_share_rate | ||
|
|
||
| if rate_diff < 0: | ||
| return Decimal(0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why it can't be negative?
| time_elapsed_seconds=self._get_time_elapsed_seconds_from_prev_report(blockstamp), | ||
| ) | ||
|
|
||
| latest_onchain_ipfs_report_data = self.staking_vaults.get_latest_onchain_ipfs_report_data(blockstamp.block_hash) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe call self.w3.lido_contracts.lazy_oracle.get_latest_report_data(blockstamp.block_hash) directly here. Function with one call is redundant
| latest_onchain_ipfs_report_data: OnChainIpfsVaultReportData, | ||
| core_apr_ratio: Decimal, | ||
| pre_total_pooled_ether: int, | ||
| pre_total_shares: int, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| pre_total_shares: int, | |
| pre_total_shares: Shares, |
| bb = self.w3.ipfs.fetch(CID(tree_cid), current_frame) | ||
| return StakingVaultIpfsReport.parse_merkle_tree_data(bb) | ||
|
|
||
| def get_latest_onchain_ipfs_report_data(self, block_identifier: BlockIdentifier) -> OnChainIpfsVaultReportData: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets remove this function. Since and replace with direct contract call. Also report is not from IPFS, so the name confuses a little bit
| chain_config: ChainConfig, | ||
| current_frame: FrameNumber, | ||
| ) -> tuple[Optional[StakingVaultIpfsReport], BlockNumber]: | ||
| slots_per_frame = frame_config.epochs_per_frame * chain_config.slots_per_epoch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Web3Converter can be reused to calculate slots and other staff
| accounting_oracle = self.w3.lido_contracts.accounting_oracle | ||
|
|
||
| if latest_onchain_ipfs_report_data.report_cid != "": | ||
| prev_ipfs_report = self.get_ipfs_report(latest_onchain_ipfs_report_data.report_cid, current_frame) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we remove part with current frame from ipfs methods?
| prev_ipfs_report = self.get_ipfs_report(latest_onchain_ipfs_report_data.report_cid, current_frame) | ||
| tree_root_hex = Web3.to_hex(latest_onchain_ipfs_report_data.tree_root) | ||
|
|
||
| if not self.is_tree_root_valid(tree_root_hex, prev_ipfs_report): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we validate data in ipfs provider, so we can correctly use fallbacks in case in one of provider got broken
| return output | ||
|
|
||
| def get_ipfs_report(self, ipfs_report_cid: str, current_frame: FrameNumber) -> StakingVaultIpfsReport: | ||
| if ipfs_report_cid == "": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we already called this method in function below.
I propose to remove this function and call self.get_vault_report directly from _get_start_point_for_fee_calculations
| current_frame: FrameNumber, | ||
| ) -> tuple[Optional[StakingVaultIpfsReport], BlockNumber]: | ||
| slots_per_frame = frame_config.epochs_per_frame * chain_config.slots_per_epoch | ||
| accounting_oracle = self.w3.lido_contracts.accounting_oracle |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's inline this line into line 511
Description
Describe what this pull request does. Explain the purpose of the changes and the problem they solve.
Related Issue/Task
How Has This Been Tested?
Describe how you tested the changes:
pytest)Checklist
CSM_STATE_VERSIONis bumped (if the new version affects data in the cache)