Once an epoch completes, the operator client takes a snapshot of the Bank from the last existing block of the previous epoch.
Using the Bank, the client constructs the StakeMetaCollection, which includes details about each validator, their tip distribution account, and the active delegations (stake accounts) on that validator.
Based on the StakeMetaCollection, the client generates Merkle trees for each validator, resulting in the GeneratedMerkleTreeCollection. Each tree contains a set of "claimants," which include all the validator's stake accounts, an additional claimant representing the validator’s share of tips (calculated using their mev_commission_bps from the tip distribution account), and a claimant for the fee allocated to the TipRouter.
Details about the TipRouter
claimant:
StakeMetaCollection
and GeneratedMerkleTreeCollection
compared to the prior approach in jito-solana/tip-distributor
.TipRouter
claimant is calculated by multiplying the validator's total tips by the TipRouter
's NcnConfig.fees_config.total_fees_bps()
, which aggregates the BaseFees and NcnFees.TipRouter
fee represents a percentage of fees assessed on each validator's tips. The program only holds the complete fee once all validators’ TipRouter
claimants have been claimed.BaseRewardReceiver
.Finally, a MetaMerkleTree is created from the GeneratedMerkleTreeCollection
.
Once the meta_merkle_root
is created, the operator submits their vote by calling the cast_vote instruction, provided the BallotBox, EpochSnapshot, and OperatorSnapshot accounts have already been initialized.