In a proof of stake blockchain, validators need to split the rewards gained from transaction fees each block. Furthermore, these fees must be fairly distributed to each of a validator's constituent delegators. They accrue this reward throughout the entire time they are delegated, and they have a special operation to withdraw accrued rewards.
The F1 fee distribution scheme works for any algorithm to split funds between validators each block, with minimal iteration, and the only approximations being due to finite decimal precision. Per block there is a single iteration over the validator set, to enable reward algorithms that differ by validator. No iteration is required to delegate, or withdraw. The state usage is one state update per validator per block, and one state entry per active delegation. It can optionally handle arbitrary inflation schemes, and auto-bonding of rewards.
In a proof of stake blockchain, each validator has an associated stake.
Transaction fees get rewarded to validators based on the incentive scheme of the underlying proof of stake model.
The fee distribution problem occurs in proof of stake blockchains supporting delegation, as there is a need to distribute a validator's fee rewards to its delegators.
The trivial solution of just giving the rewards to each delegator every block is too expensive to perform on-chain.
So instead fee distribution algorithms have delegators perform a withdraw action, which when performed yields the same total amount of fees as if they had received them at every block.
This details F1, an approximation-free, slash-tolerant fee distribution algorithm which allows validator commission-rates, inflation rates, and fee proportions, which can all efficiently change per validator, every block.
The key point of how F1 works is that it tracks how much rewards a delegator with 1 stake for a given validator would be entitled to if it had bonded at block 0 until the latest block.
When a delegator bonds at block $b$, the amount of rewards a delegator with 1 stake would have if bonded at block 0 until block $b$ is also persisted to state.
When the delegator withdraws, they receive the difference of these two values.
Since rewards are distributed according to stake-weighting, this amount of rewards can be scaled by the amount of stake a delegator had.
Section 1.2 describes this in more detail, with an argument for it being approximation free.
Section 2 details how to adapt this algorithm to handle commission rates, slashing, and inflation.
\subsection{Base algorithm}
In this section, we show that the F1 base algorithm gives each delegator rewards identical to that which they'd receive in the naive and correct fee distribution algorithm that iterated over all delegators every block.
Even distribution of a validators rewards amongst its validators weighted by stake means the following:
Suppose a delegator delegates $x$ stake to a validator $v$ at block $h$.
It is clear from the equations that this payout mechanism maintains correctness, and requires no iterations. It just needed the two state reads for these entries.
Commission rates are the idea that a validator can take a fixed $x\%$ cut of all of their received fees, before redistributing evenly to the constituent delegators.
This can easily be done as follows:
In block $h$ a validator receives $f_h$ fees.
Instead of incrementing that validators ``total accrued fees this period variable" by $f_h$, it is instead incremented by $(1- commission\_rate)* f_p$.
Then $commission\_rate * f_p$ is deposited directly to the validator's account.
This allows for efficient updates to a validator's commission rate every block if desired.
More generally, each validator could have a function which takes their fees as input, and outputs a set of outputs to pay these fees too. (i.e. x\% going to themselves, y\% to delegators, z\% burnt)
In practice this will not really be an efficiency hit, as the number of slashes is expected to be 0 or 1 for most validators.
Validators that get slashed more will naturally lose their delegators.
A malicious validator that gets itself slashed many times would increase the gas to withdraw linearly, but the economic loss of funds due to the slashes is expected to far out-weigh the extra overhead the honest withdrawer must pay for due to the gas.
(TODO: frame that above sentence in terms of griefing factors, as thats more correct)
Inflation is the idea that we want every staked coin to create more staking tokens as time progresses.
The purpose being to drive down the relative worth of unstaked tokens.
Each block, every staked token should produce $x$ staking tokens as inflation, where $x$ is calculated from a function $inflation$ which takes state and the block information as input.
Let $x_i$ represent the evaluation of $inflation$ in the $i$th block.
The goal of this section is to auto-bond inflation in the fee distribution model without iteration.
This is done by preserving the invariant that every state entry contains the rewards one would have if they had bonded one stake at genesis until that corresponding block.
In state a variable should be kept for the number of tokens one would have now due to inflation,
given that they bonded one token at genesis.
This is $\prod_{0}^{now}(1+ x_i)$.
Each period now stores this total inflation product along with what it already stores per-period.
Let $R_i$ be the fee rewards in block $i$, and $n_i$ be the total amount bonded to that validator in that block.
The correct amount of rewards which 1 token at genesis should have now is:
The term in the sum is the amount of stake one stake becomes due to inflation, multiplied by the amount of fees per stake.
Now we cast this into the period frame of view.
Recall that we build the rewards by creating a state entry for the rewards of the previous period, and keeping track of the rewards within this period.
Thus we first define the correct amount of rewards for each successive period, proving correctness of this via induction.
We then show that the state entry that gets efficiently built up block by block is equal to this value for the latest period.
Let $start, end$ denote the start/end of a period.
Suppose that $\forall f > 0$, $Reward(end(f))$ is correctly constructed as
(With period 1 being defined as the period that has the first bond into it)
It must be shown that assuming the supposition $\forall f \leq f_0$, $$Reward(end(f_0+1))= Reward(end(f_0))+\sum_{i = start(f_0+1)}^{end(f_0+1)}\left(\prod_{j =0}^{i}1+ x_j \right)\frac{R_i}{n_i}$$
Using the definition of $Reward$, it follows that:
When withdrawing, you take the difference as before,
which yields the amount of rewards you would have obtained with $(\prod_0^{begin\ bonding\ period}1+ x)$ stake from the block you began bonding at until now.
$(\prod_0^{begin\ bonding\ period}1+ x)$ is known, since its included in the state entry for when you bonded.
You then divide the entitled fees by $(\prod_0^{begin\ bonding\ period}1+ x)$ to normalize it to being the amount of rewards you're entitled to from 1 stake at that block to now.
Then as before, you multiply by the amount of stake you had initially bonded.
Notice that a slash is the same as a negative inflation rate for a validator in one block.
For example a $20\%$ slash is equivalent to a $-20\%$ inflation for a validator in a block.
Given correctness of auto-bonding inflation with different inflation rates per-validator,
it follows that handling slashes can be correctly done by simply subtracting the validators inflation factor in that block to be the negative of the slash factor.
This significantly simplifies the withdrawal procedure.
This can be easily adapted to the case where there are multiple delegations / withdrawals per block, by maintaining a reference count in each period starting state entry.
This is an extremely simple scheme with many nice benefits.
\begin{itemize}
\item The overhead per block is a simple iteration over the bonded validator set, which occurs anyway. (Thus it can be implemented ``for-free" with an optimized code-base)
\item Withdrawing earned fees only requires iterating over slashes since when you bonded. (Which is a negligible iteration)
\item There are no approximations in any of the calculations. (modulo minor errata resulting from fixed precision decimals used in divisions)
\item Supports arbitrary inflation models. (Thus could even vary upon block signers)
\item Supports arbitrary fee distribution amongst the validator set. (Thus can account for things like only online validators get fees, which has important incentivization impacts)
\item The above two can change on a live chain with no issues.
\item Validator commission rates can be changed every block
\item The simplicity of this scheme lends itself well to implementation
\end{itemize}
Thus this scheme has efficiency improvements, simplicity improvements, and expressiveness improvements over the currently proposed schemes. With a correct fee distribution amongst the validator set, this solves the existing problem where one could withhold their signature for risk-free gain.
\item Section on decimal precision considerations (would unums help?), and mitigating errors in calculation with floats and decimals. -- This probably belongs in a corrollary markdown file in the implementation
\item Consider indicating that the withdraw action need not be a tx type and could instead happen 'transparently' when more coins are needed, if a chain desired this for UX / p2p efficiency.