Skip to content

Commit

Permalink
doc: Document block rewards feature (#421)
Browse files Browse the repository at this point in the history
  • Loading branch information
AmbientTea authored Feb 5, 2025
1 parent 7ff19f1 commit 31fc129
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 0 deletions.
52 changes: 52 additions & 0 deletions toolkit/pallets/block-rewards/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Block Rewards Pallet

This crate implements the runtime component of the block rewards whose task is to track
allocation of rewards for block production and allow processing of this information for
reward payouts.

This crate works together with the `sp-block-rewards` crate to implement this functionality.

## Usage

*Note*: Some type names used below refer to type fields in the `Config` trait of the pallet.
For clarity, these are prefixed with `T::` similarly to how they're used in the code (where
`T` stands for the runtime generic type).

### Block beneficiary

Rewards for block production are credited to a `beneficiary`, identified by a `T::BeneficiaryId`,
which is a chain-specific type that needs to be provided by the developer.
When each block is produced, the `beneficiary` is determined by the inherent data provided by the
`BlockBeneficiaryInherentProvider`. This inherent data provider can be construed in an arbitrary
way, but `BlockBeneficiaryInherentProvider::from_env` helper method on the type is provided to fetch
the ID from the node's local environment.

The value of the beneficiary ID is chosen at the sole discretion of each particular
block producing node's operator and is not subject to any checks beyond simple format validation
(in particular, it is not checked whether the node operator controls any keys related to the ID).

### Block value

Rewards credited for each block's production can be calculated arbitrarily, by providing the
`T::BlockRewardPoints` type representing the rewards and `T::GetBlockRewardPoints: GetBlockRewardPoints` type
implementing the logic determining current block value.

For simple cases, type `SimpleBlockCount: GetBlockRewardPoints` is provided that assigns a constant
value of 1 to every block, for any `T::BlockRewardPoints` implementing the `One` trait.

### Pallet operation

The pallet ingests the inherent data and keeps a tally of beneficiaries and their accumulated
rewards in its on-chain storage. The rewards are only credited for blocks whose production
was successfuly finalized.

### Processing the rewards

To make the reward information available for processing, the pallet exposes the `get_rewards_and_clear`
function, which returns all accumulated reward data and resets the pallet storage. This function
should be called from the chain-specific runtime code that implements the payout mechanism, and it is
the calling logic's responsibility to process all returned reward entries.

`get_rewards_and_clear` can be called with any frequency, depending on how often reward payouts are to
be performed. For Partner Chains using `pallet-sidechain`, it's convenient to put the payouts logic
in the `OnNewEpoch` handler defined in the Sidechain pallet's `Config`.
6 changes: 6 additions & 0 deletions toolkit/pallets/block-rewards/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ pub mod pallet {

#[pallet::config]
pub trait Config: frame_system::Config {
/// Beneficiary ID. This can be an arbitrary type, depending on what entities are block
/// beneficiaries on a specific chain.
type BeneficiaryId: Member + Parameter + MaxEncodedLen;

/// Type of accumulated "reward" value
Expand All @@ -31,6 +33,7 @@ pub mod pallet {
+ MaxEncodedLen
+ Add<Self::BlockRewardPoints, Output = Self::BlockRewardPoints>;

/// Reward calculator, run each block to determine its worth in [BlockRewardPoints]
type GetBlockRewardPoints: GetBlockRewardPoints<Self::BlockRewardPoints>;
}

Expand Down Expand Up @@ -69,6 +72,7 @@ pub mod pallet {
}

impl<T: Config> Pallet<T> {
/// Inherent setting the current block beneficiary, so it can be processed when the block is finalized
fn get_beneficiary_from_inherent_data(
data: &InherentData,
) -> Result<T::BeneficiaryId, InherentError> {
Expand Down Expand Up @@ -113,6 +117,8 @@ pub mod pallet {
}

impl<T: Config> Pallet<T> {
/// Returns the current beneficiary-accumulated blocks rewards mapping and cleans internal storage.
/// The caller must process all entries returned by this function.
pub fn get_rewards_and_clear() -> Vec<(T::BeneficiaryId, T::BlockRewardPoints)> {
PendingRewards::<T>::drain().collect()
}
Expand Down
5 changes: 5 additions & 0 deletions toolkit/primitives/block-rewards/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Block Rewards Primitives

This crate implements the primitives and inherent data provider for the block producer
rewards feature. See the corresponding pallet's (`pallet-block-rewards`) documentation
for more information.
1 change: 1 addition & 0 deletions toolkit/primitives/block-rewards/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ where
BeneficiaryId: TryFrom<Vec<u8>> + Send + Sync + Encode,
<BeneficiaryId as TryFrom<Vec<u8>>>::Error: std::fmt::Debug,
{
/// Read and decode beneficiary ID from the specified environment variable
pub fn from_env(env_var: &str) -> Result<Self, InherentProviderCreationError> {
let beneficiary_string = std::env::var(env_var)
.map_err(|_| InherentProviderCreationError::NotSet(env_var.into()))?;
Expand Down

0 comments on commit 31fc129

Please sign in to comment.