Requirements: Rewards Requirements
Contents |
Espresso incentivizes validators who act honestly and help secure the network through rewards distributed as Espresso tokens (ESP). Validators stake tokens in the form of Espresso tokens in the stake table contract. They earn rewards by proposing new blocks. In the case of dishonest behavior, their staked capital can be penalized. Validators can miss the rewards if they fail to propose a block when they are selected as the leader. Validators list is basically the stake table which is constructed from the permissionless stake table contract every epoch.
Hotshot executes add_epoch_root(decided_header: Header) to construct the stake table based on contract data and update the in-memory state. This function processes all stake table contract events and selects validators that meet the specified criteria. Only the top 100 validators with stakes above a minimum threshold are included. Leaders are selected using a Distributed Randomness Beacon (DRB). The leader proposing a block receives a commission reward, and the remaining reward is distributed among delegators based on their stakes. The stake table from the contract is only populated third epoch onwards (root is e -2 ) Therefore, reward distribution starts from the third epoch onwards.
Each validator has a commission rate and a set of delegators contributing to their total stake.
The Validator type has the following fields:
account: Ethereum account address.
stake_table_key: The peer’s public key used in the stake table.
state_ver_key: The state verification key for the peer.
stake: The sum of all delegators’ stakes.
commission: Validator commission rate in basis points (1 basis point = 0.01%). Range: 0–10,000.
delegators: A map of Ethereum addresses to stake amounts.
If a validator wants to stake tokens, it must delegate tokens to itself. Thus, the validator’s account address will also appear in the delegators list. This relaxes the requirement for node operators to possess the tokens themselves. The Espresso Foundation can delegate tokens to the node operator, allowing them to remain an active node, provided they meet the criteria.
The ComputedRewards type represents the calculated rewards for a validator and its delegators after processing a block reward. It includes:
leader_address: The validator’s Ethereum account address.
leader_commission: The validator’s commission reward amount.
delegators: A list of tuples pairing each delegator’s Ethereum address with their individual reward amount.
The reward distribution is computed by the validator’s compute_rewards method, which allocates the total block reward between delegators (proportional to their stake) and the validator’s commission (based on the commission rate). Any rounding discrepancies are adjusted in the validator’s commission to ensure the total reward matches the block reward.
Rewards are applied to the in-memory state, reward merkle tree in this case, via the apply_rewards method, which updates the persistent reward balances for each delegator and the validator.
Rewards are tracked using a Universal Merkle Tree data structure called the RewardMerkleTree. It uses the SHA3 hashing algorithm and has an arity of 256 (28), meaning each node has 256 children. Since an Ethereum address is 160 bits (or 20 bytes) long, each byte can correspond to one level of the tree, resulting in a fixed depth of 20. This structure allows efficient lookups, as each byte determines which child to traverse at each level. It also eliminates the need for deeper trees, making proof verification faster because the number of hash computations required to generate or verify a proof is significantly reduced. The tree stores reward amounts as 256-bit unsigned integers (U256).
Each reward distribution updates an account’s balance by adding the new reward to the previous balance. Thus, an account’s total reward balance in the RewardMerkleTree is the cumulative sum of all rewards received over time.
Updating the reward Merkle tree requires each node to have the existing reward account entries for which rewards need to be distributed. Since each reward entry represents a cumulative sum, the node must know the previous account balance to correctly apply the new reward. If it does not, the node needs to catch up. Each query node stores the reward Merklized state in its own database. During catchup, the node can directly query the database for the exact snapshot it needs. If the exact snapshot is not available, it can rebuild the state using an older snapshot and by applying the undecided proposals stored in consensus storage. If that still doesn’t work, the node can request the missing reward accounts from other peers. This can be done using the catchup API or the peer-to-peer (P2P) catchup, which uses a simple request-response protocol. This catchup process ensures consistency and must occur whenever a node proposes a block or validates a proposal.
During proposal validation, the node recalculates the rewards and verifies that the computed reward Merkle tree commitment matches the one included in the proposal. Hence, the node must first catch up on the reward accounts and reconstruct the corresponding state.
Latest reward balance:
Path: /reward-balance/latest/:address
Parameter: :address (Ethereum address in hex format)
Reward balance at specific block height:
Path: /reward-balance/:height/:address
Parameters: :height (block height as an integer), :address (Ethereum address in hex format)
The leader selection process in a randomized committee is based on a pseudo-random breakpoint.
This breakpoint is derived by hashing together the DRB (Distributed Randomness Beacon) result, the current view number, and a hash of the stake table using the SHA-512 hashing algorithm. The resulting hash output is then reduced modulo the total cumulative stake, producing a breakpoint value within the range of possible cumulative stakes.
Nodes in the stake table are ordered by xor(public key, DRB result), with the DRB result cyclically repeated to match the number of bytes in the public key. The leader for a given view is the first node whose cumulative total stake is strictly greater than the breakpoint. The leader selection process is deterministic, and all nodes will independently select the same leader for the same view. The time required to produce the DRB result makes it practically impossible to bias.
Note: This section requires further discussion and has not been implemented yet.