How to pay the block author/validator on a Proof-of-Authority (PoA) consensus in Substrate.

If you are starting your own blockchain and you don’t want the complexity of a large chain, you need  start with a new and controlled community which later on be converted into Parachains, a large shared chain that can connect to a relay chain in the Polkadot eco-system.

For me, starting with Proof-of-Aurthority (PoA) is the most suitable consensus mechanism for small and controlled community while having the flexibility to scale to Nominated Proof-of-Stake (nPoS). 

The current PoA of Substrate using Aura and Grandpa does not incentivize the block authors nor validators, making it hard for you to grow your network because you have to pay for all servers and infrastructures on your own. 

To solve this issue we need to activated the fees and rewards of the author of the blocks.  In this way other people are more committed to join the network because they will be incentivize for the infrastructure without having to stake or be nominated like in a typical nPoS network.

Here is how we do it:

Install pallet_authorship (runtime/Cargo.toml)

pallet-authorship = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.23" }

Configure the pallet to get the current author of the block (runtime/src/lib.rs)

You need to implement the FindAuthor trait in the AuraAccountAdaptor and use it to feed the FindAuthor type enum in the pallet_authorship.

pub struct AuraAccountAdapter;
impl frame_support::traits::FindAuthor<AccountId> for AuraAccountAdapter {
	fn find_author<'a, I>(digests: I) -> Option<AccountId>
		where I: 'a + IntoIterator<Item=(frame_support::ConsensusEngineId, &'a [u8])>
	{
		pallet_aura::AuraAuthorId::<Runtime>::find_author(digests).and_then(|k| {
			AccountId::try_from(k.as_ref()).ok()
		})
	}
}

impl pallet_authorship::Config for Runtime {
	type FindAuthor = AuraAccountAdapter;
	type UncleGenerations = ();
	type FilterUncle = ();
	type EventHandler =  ();
}

Create OnUnbalanced implementation of Author and DealWithFees (runtime/src/impls.rs)

This is a separate rust (rs) file. You need to include it in the lib.rs by adding a line mod impls. I commented the Treasury share since we haven’t implemented the treasury pallet yet.

use crate::{Authorship, Balances};
use frame_support::traits::{Imbalance, OnUnbalanced};
use crate::sp_api_hidden_includes_construct_runtime::hidden_include::traits::Currency;
use crate::AccountId;

type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;

pub struct Author;
impl OnUnbalanced<NegativeImbalance> for Author {
	fn on_nonzero_unbalanced(amount: NegativeImbalance) {
		if let Some(author) = Authorship::author() {
			Balances::resolve_creating(&author, amount);
		}
	}
}

pub struct DealWithFees;
impl OnUnbalanced<NegativeImbalance> for DealWithFees {
	fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {
		if let Some(fees) = fees_then_tips.next() {
			let mut split = fees.ration(80, 20);
			if let Some(tips) = fees_then_tips.next() {
				// for tips, if any, 80% to treasury, 20% to block author (though this can be anything)
				tips.ration_merge_into(80, 20, &mut split);
			}
			//Treasury::on_unbalanced(split.0);
			Author::on_unbalanced(split.1);
		}
	}
} 

Call the implementation in the pallet_transaction_payment tuple OnChargeTransaction (runtime/src/lib.rs)

The substrate-node-template repository already has pallet_transaction_payment pallet, just replace the tupple parameter in OnChargeTransaction by calling the DealWithFees implementation.

impl pallet_transaction_payment::Config for Runtime {
	type OnChargeTransaction = CurrencyAdapter<Balances, crate::impls::DealWithFees>;
	type OperationalFeeMultiplier = ConstU8<5>;
	type WeightToFee = IdentityFee<Balance>;
	type LengthToFee = IdentityFee<Balance>;
	type FeeMultiplierUpdate = ();
}

That’s it. Have fun with your own chain. Please don’t forget to donate if your find this blog helpful.

Leave a comment

Blog at WordPress.com.