As I mentioned in the Accounting section of eODS design notes, beacon chain accounting already exists under the current protocol, in the form of beacon chain operations, or beacon state mutators, e.g. process_deposit, increase_balance, etc.
Since Accounting is an important part of eODS model, it proved useful to group these functions in a virtual group based on functionality (i.e. accounting) rather than beacon-chain specification appartenance. This document is a study I made on beacon chain accounting under the current Ethereum protocol.
The following is a design validation document (pseudocode), with a python project and pytests attached, in order to prove the beacon-chain accounting model I proposed for the eODS feature.
We can add delegated boolean entry in the records:
Validators' actual balance is stored in the BeaconState records, as a registry of validators and their balances.
We can add a fee List structure, mapping each Validator in the registry with its fee rate (NULL if delegated entry defined in class Validator is False):
validators: List[Validator, VALIDATOR_REGISTRY_LIMIT]
balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT]
fees: List[Fee, VALIDATOR_REGISTRY_LIMIT]
We can add beacon chain class Delegator:
Delegator balances are to be stored in the BeaconState records, as a registry of delegators and their balances:
We can add delegators registry inside BeaconState, similar to validator registry
I went for a Test-driven Development approach for writing the model validation project. The minimal requirements of functionality proven by tests:
test_initiate_Delegator
- Add a delegator to registry and set its balance (deposit).
test_add_multiple_Delegators
- Add multiple delegators to delegators' registry and set their balance (deposit).
test_delegate
- Delegate to delegated validators and update:
amount
)amount
)test_adjust_accounting
- Adjust the validator's balance (due to profit / loss) and have the delegators' balances updated.
test_adjust_accounting_keep_quota
- Adjust the validator's balance (due to profit / loss) and have the delegators' quota unchanged.
test_withdraw
- Withdraw a specified amount from a delegator's balance in a particular validator, and update:
amount
)amount
)For the python project purposes, I wrote toy classValidator and classDelegator and imported them in the code file. The validator and the delegator IDs are stored as string, i.e. Validator_no1, Validator_no2, and Delegator_no1, Delegator_no2 respectively, instead of delegator pubkeys, as in the beacon-chain specification.
The code file stores validators' and delegators' data as a list of Validator
and Delegator
class instances. Looking deeper into the implementation, we can observe that the following functions perform balance sheet operations, as follows:
register_delegator
- Registers a delegator if not already registered and returns the delegator index
deposit
- Adds an amount to the balance of an existing or newly registered delegator
delegate
- Delegates capital to a d elegated validator, updates validator's and delegator's balance, and recalculates delegators' quotas.
withdraw
- Withdraws a specified amount from a delegator's balance in this validator, returning it to the delegator's available balance, updating delegators' quotas.
adjust_DelegatedValidator_balance
- Adjusts the total DelegatedValidator value (due to profit/loss) without changing individual delegators' quotas.
*calculate_quotas
- Calculate and return the quota for each delegator in this validator.
Helper functions:
get_all_quotas_by_delegator
- Returns a list of delegators with their quotas across all validators. Each entry contains the delegator ID and a list of their quotas across validators.
get_validator_index
- Get a validator's index in List[Validator]
, based on its given ID