owned this note
owned this note
Published
Linked with GitHub
# aleo-consensus fees, validator rewards and staking proposal
2022-12-27 NOTE: this was a design proposal which has already been implemented. Refer to the aleo-consensus README for up to date documentation.
## Current status / assumptions
* We currently use the SnarkVM built-in credits program to create and transfer credits
* The initial credits distribution is done at genesis. We already implemented support to set a list of initial records in the tendermint genesis file, which is loaded into the record store when a testnet is first started.
* Further credits can be minted by nodes when blocks are proposed (see below)
* An execution consists of a list of transitions. A transition is essentially a function calls with inputs, outputs and a proof.
* In our current implementation, executions are a single function call and thus generate a single transition. There could be more if the function had nested functions or called imported programs, which we don't support right at the moment.
* Part of execution generation in SnarkVM is to [calculate the transition fee](https://github.com/Entropy1729/snarkVM/blob/6f601cb1458b65e035f6d9043475cc543c8acfb1/vm/compiler/src/process/stack/execute.rs#L373) (inputs - outputs).
* Part of execution validation in SnarkVM includes [verifying that executions don't mint new tokens](https://github.com/Entropy1729/snarkVM/blob/6f601cb1458b65e035f6d9043475cc543c8acfb1/vm/compiler/src/process/stack/execute.rs#L346) (inputs - outputs is non-negative)
* We assume that when we switch from SnarkVM to EntropyVM, the credits and execution validations will continue to work with similar behavior
## Fees and validator rewards
* Transaction fees are the sum of the fees of its transitions.
* For executions, there will be an implicit fee in the difference of input and output credits. This difference will typically be zero, so a secondary transition can be included to force a difference to be payed as the fee.
* For deployments there are no function calls, so fees need to be payed as well by including a separate credit-consuming transition.
* The `credits` program in SnarkVM [already includes a 'fee' function](https://github.com/Entropy1729/aleo-consensus/blob/62c89cfa0b434018079d07b23711312910441dbb/aleo/credits.aleo#L45-L50) for this purpose. The function takes a record and subtracts credits from it.
* In addition credits from transaction fees, a baseline amount of credits could be minted with each block.
* The sum of the fees payed by all transactions and the baseline credits will be distributed among the validators according to some rule, for example: 50% for the block proposer and 50% for the subset of validators that voted for it, weighted by their voting power.
* NOTE: the fees associated with each transition and with each block are public. This seems to be the same model as the current SnarkVM/SnarkOS implementation. In the future we could look into how zcash handles this in case we can make it privacy preserving.
### Implementation details
* On our blockchain application, we will track a mapping between tendermint validator addresses and their aleo account addresses.
* The `BeginBlock` tendermint hook includes the current block proposer address and the list of votes from the previous block (validator addresses and their voting power). We can use this to decide how to distribute the next round of rewards.
* NOTE: with this approach we'd be rewarding voters from block H and proposer of block H+1 with the fees from H+1. We could workaround this if it becomes a problem.
* Each time the `DeliverTx` hook is run for a transaction we calculate the fee as described above and add it to the current block rewards.
* In the `Commit` hook we add the baseline credits to the collected fees and distribute the credits as described above, by generating new records owned by the validator aleo addresses. The records are then added as unspent in the record store.
* **NOTE: this requires some way of producing the exact same record in all blockchain nodes (because all need to reach consensus about the reward records without explicit synchronization). To do this we need to figure out how to deterministically generate the same record nonce in all nodes using pseudo-randomness (sharing a seed at genesis, tracking a counter, deriving it from the block height, etc.). This pseudo-randomness would be exclusive to the records generated on-chain for rewards, the rest of the execution output records can still use proper randomness.**
* NOTE: by default, fees won't affect transaction prioritization (they will run in the order they arrive regarldess of the fee). Different versions of tendermint have different features that can enable this feature. We started a discussion about this [in the tendermint repo](https://github.com/tendermint/tendermint/discussions/9772). Depending on what we find out we may just use an available feature or need to upgrade to a different tendermint version or implement the feature on our own.
* We can update the `deploy` and `execute` functions in the CLI to accept a `--fee <gates>` argument. This could lookup available records owned by the current account, and call `credits/fee` as necessary to ensure the transaction pays the desired amount of credits to the blockchain.
## Staking
* Tendermint has a voting power attribute that affects the weight of a validator's vote in the conensus algorithm.
* Above we used this to weight the rewards assigned to each validator.
* To implement staking we need some way of translating staked credits to tendermint voting power. Tendermint tracks the total voting power so we can just increase it proportionally to the staked credits.
* By default, just as we distribute a default amount of credits at genesis, we can set a default validator power.
* We can add `stake` an `unstake` functions to the credits program
* The `stake` function consume credits from an input record and outputs staked voting power.
* The `unstake` function consumes voting power and outputs records with credits.
* Changes resulting from executions of these functions will be passed to tendermint to adjust the voting power of validators used in consensus.
* These functions would executed directly by the validator account. A future improvement would be to allow other accounts to delegate stake to the validator.
* For a second iteration we could consider setting up the validators to automatically stake their rewards.
* NOTE: the voting power (and thus, the amount of credits staked/unstaked by an account) will be public. We could improve this in future versions for example by delegating/pooling staked credits (such that the total amount of staked credits is public but not the individual account contributions).
### Implementation details
* These functions will need special treatment (like other functions of the credits program): unstake is allowed to execute even though it creates credits, but nodes will need to validate that the account has the amount of voting power used as input.
* The blockchain application tracks voting power changes by stake/unstake executions in the `DeliverTx` hook, and applies them as `validator_updates` in the `EndBlock` hook.
* By default, voting power updates in tendermint at hieght H will become effective in H+2. If we wanted, we could add some extra delay (e.g. need to stake for N blocks before voting power changes take effect).