Skip to content

Commit

Permalink
Add pallet reward inflation (#277)
Browse files Browse the repository at this point in the history
* reward trait

* reward distribution code

* tests (wip)

* reward distribution tests

* fix test + remove warning

* chore: create pallet inflation-rewards and primitive tp-maths

* chore: move trait DistributeRewards in tp-traits

* ref: move AuthorNotingHook in tp-traits

* ref: pooled-staking: use Credit for rewards

* reword pallet inflation rewards

* ref: use bounded vec for container chains

* fix existing rust tests compilation

* reward orchestrator chain

* add rust tests for pallet inflation-rewards

* fmt

* remove dead code

Co-authored-by: tmpolaczyk <[email protected]>

* note container author only if block increase

* fmt

* cleanup merge

* reward author if it increases

* Re-design on-container-author-noted to simplify it for now

* adapt to 1.1.0

* fmt

* fix merge mistakes and benchmarking

* types and unitest error

* take invulnerables into account

* fmt

* let's use collatorAssignment to fethc the author account

* hack around how to get the collator account to be rewarded

* fix rust tests

* TODO: important!

* events for inflation rewards and benchmark for rewards

* add runtime event to mock

* substitute extractFee for extractFeeAuthor

* fix ts-tests and local interfaceS

* fix linting and fmt

* first ts-tests dedicated to inflation

* add new parafchain bond account

* add more test

* fmt lint

* wire in container rewarding

* fmt

* add more test, including container-chain reward

* try-runtime

* staking rewards tests, not through invlunerables

* test fixed

* a couple of tests for staking

* make distribute_rewards transactional (#299)

* make distribute_rewards transactional

* fmt

---------

Co-authored-by: girazoki <[email protected]>

* reward the author of the first container block

* PR feedback

* compile

* Inflation rewards integration tests (#295)

* test reward distribution

* ensure it still works even with key change

* find_map + fmt

* fmt

* remove dbg!

* a few todos added and cleaning the remaining feedback

---------

Co-authored-by: nanocryk <[email protected]>
Co-authored-by: tmpolaczyk <[email protected]>
Co-authored-by: girazoki <[email protected]>
  • Loading branch information
4 people authored Oct 31, 2023
1 parent 8f95799 commit 84d3d97
Show file tree
Hide file tree
Showing 57 changed files with 2,873 additions and 622 deletions.
38 changes: 38 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ authors = [ "Moondance Labs" ]
repository = "https://github.com/moondance-labs/tanssi"

[workspace.dependencies]

# Members
pallet-author-noting = { path = "pallets/author-noting", default-features = false }
pallet-author-noting-runtime-api = { path = "pallets/author-noting/rpc/runtime-api", default-features = false }
Expand All @@ -28,6 +29,7 @@ pallet-authority-mapping = { path = "pallets/authority-mapping", default-feature
pallet-collator-assignment = { path = "pallets/collator-assignment", default-features = false }
pallet-collator-assignment-runtime-api = { path = "pallets/collator-assignment/rpc/runtime-api", default-features = false }
pallet-configuration = { path = "pallets/configuration", default-features = false }
pallet-inflation-rewards = { path = "pallets/inflation-rewards", default-features = false }
pallet-initializer = { path = "pallets/initializer", default-features = false }
pallet-invulnerables = { path = "pallets/invulnerables", default-features = false }
pallet-pooled-staking = { path = "pallets/pooled-staking", default-features = false }
Expand All @@ -52,6 +54,7 @@ tp-collator-assignment = { path = "primitives/collator-assignment", default-feat
tp-consensus = { path = "primitives/consensus", default-features = false }
tp-container-chain-genesis-data = { path = "primitives/container-chain-genesis-data", default-features = false }
tp-core = { path = "primitives/core", default-features = false }
tp-maths = { path = "primitives/maths", default-features = false }
tp-traits = { path = "primitives/traits", default-features = false }

# Moonkit (wasm)
Expand Down Expand Up @@ -217,6 +220,7 @@ fc-rpc-core = { git = "https://github.com/moondance-labs/frontier", branch = "ta
fc-storage = { git = "https://github.com/moondance-labs/frontier", branch = "tanssi-polkadot-v1.1.0", default-features = false }

# General (wasm)
bounded-collections = { version = "0.1.8", default-features = false }
hex-literal = { version = "0.3.4" }
log = { version = "0.4.17", default-features = false }
serde = { version = "1.0.152", default-features = false }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,17 @@ use {
super::*,
crate::ContainerChainAuthoritiesInherentData,
async_trait::async_trait,
cumulus_primitives_core::relay_chain::BlockId,
cumulus_primitives_core::{
relay_chain::{
CommittedCandidateReceipt, HeadData, OccupiedCoreAssumption, SessionIndex, ValidatorId,
BlockId, CommittedCandidateReceipt, HeadData, OccupiedCoreAssumption, SessionIndex,
ValidatorId,
},
InboundDownwardMessage, InboundHrmpMessage, ParaId, PersistedValidationData,
},
cumulus_relay_chain_interface::{PHash, PHeader, RelayChainInterface, RelayChainResult},
futures::Stream,
polkadot_overseer::Handle,
sc_client_api::HeaderBackend,
sc_client_api::{StorageKey, StorageProvider},
sc_client_api::{HeaderBackend, StorageKey, StorageProvider},
sp_inherents::{InherentData, InherentDataProvider},
sp_state_machine::{prove_read, StorageValue},
std::{collections::BTreeMap, pin::Pin, sync::Arc},
Expand Down
16 changes: 8 additions & 8 deletions container-chains/templates/frontier/node/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,23 @@ use {
sc_network::config::FullNetworkConfiguration,
};
// std
use futures::FutureExt;
use sc_client_api::Backend;
use sc_transaction_pool_api::OffchainTransactionPoolFactory;
use std::{
collections::BTreeMap,
sync::{Arc, Mutex},
time::Duration,
};
use {
cumulus_client_cli::CollatorOptions,
cumulus_primitives_parachain_inherent::{
MockValidationDataInherentDataProvider, MockXcmConfig,
},
fc_consensus::FrontierBlockImport,
futures::FutureExt,
nimbus_primitives::NimbusId,
sc_client_api::Backend,
sc_transaction_pool_api::OffchainTransactionPoolFactory,
sp_consensus_aura::SlotDuration,
sp_core::Pair,
std::{
collections::BTreeMap,
sync::{Arc, Mutex},
time::Duration,
},
};
// Local Runtime Types
use {
Expand Down
2 changes: 1 addition & 1 deletion container-chains/templates/simple/node/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ use {
};

// Substrate Imports
use futures::FutureExt;
use {
futures::FutureExt,
sc_client_api::Backend,
sc_consensus::ImportQueue,
sc_executor::NativeElseWasmExecutor,
Expand Down
3 changes: 1 addition & 2 deletions node/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@

//! Service and ServiceFactory implementation. Specialized wrapper over substrate service.

use futures::FutureExt;
use sc_transaction_pool_api::OffchainTransactionPoolFactory;
#[allow(deprecated)]
use {
crate::{
Expand Down Expand Up @@ -82,6 +80,7 @@ use {
},
tokio::sync::mpsc::{unbounded_channel, UnboundedSender},
};
use {futures::FutureExt, sc_transaction_pool_api::OffchainTransactionPoolFactory};

type FullBackend = TFullBackend<Block>;
type MaybeSelectChain = Option<sc_consensus::LongestChain<FullBackend, Block>>;
Expand Down
1 change: 1 addition & 0 deletions pallets/author-noting/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ tp-core = { workspace = true }
tp-traits = { workspace = true }

[dev-dependencies]
bounded-collections = { workspace = true }
hex-literal = { workspace = true }
polkadot-parachain-primitives = { workspace = true }
polkadot-primitives = { workspace = true }
Expand Down
49 changes: 44 additions & 5 deletions pallets/author-noting/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ use {
sp_runtime::{traits::Header, DispatchResult, RuntimeString},
tp_author_noting_inherent::INHERENT_IDENTIFIER,
tp_core::well_known_keys::PARAS_HEADS_INDEX,
tp_traits::{GetContainerChainAuthor, GetCurrentContainerChains},
tp_traits::{AuthorNotingHook, GetContainerChainAuthor, GetCurrentContainerChains},
};

#[cfg(test)]
Expand Down Expand Up @@ -81,6 +81,11 @@ pub mod pallet {

type RelayChainStateProvider: cumulus_pallet_parachain_system::RelaychainStateProvider;

/// An entry-point for higher-level logic to react to containers chains authoring.
///
/// Typically, this can be a hook to reward block authors.
type AuthorNotingHook: AuthorNotingHook<Self::AccountId>;

/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;
}
Expand Down Expand Up @@ -140,7 +145,7 @@ pub mod pallet {
);

let registered_para_ids = T::ContainerChains::current_container_chains();
let total_weight =
let mut total_weight =
T::WeightInfo::set_latest_author_data(registered_para_ids.len() as u32);

// We do this first to make sure we dont do 2 reads (parachains and relay state)
Expand All @@ -151,15 +156,49 @@ pub mod pallet {
relay_storage_proof,
} = data;

let relay_storage_root =
T::RelayChainStateProvider::current_relay_chain_state().state_root;
let relay_chain_state = T::RelayChainStateProvider::current_relay_chain_state();
let relay_storage_root = relay_chain_state.state_root;
let relay_storage_rooted_proof =
GenericStateProof::new(relay_storage_root, relay_storage_proof)
.expect("Invalid relay chain state proof");

// TODO: we should probably fetch all authors-containers first
// then pass the vector to the hook, this would allow for a better estimation
for para_id in registered_para_ids {
match Self::fetch_block_info_from_proof(&relay_storage_rooted_proof, para_id) {
Ok(block_info) => LatestAuthor::<T>::insert(para_id, block_info),
Ok(block_info) => {
LatestAuthor::<T>::mutate(
para_id,
|maybe_old_block_info: &mut Option<ContainerChainBlockInfo<T>>| {
if let Some(ref mut old_block_info) = maybe_old_block_info {
if block_info.block_number > old_block_info.block_number {
// We only reward author if the block increases
total_weight = total_weight.saturating_add(
T::AuthorNotingHook::on_container_author_noted(
&block_info.author,
block_info.block_number,
para_id,
),
);
let _ = core::mem::replace(old_block_info, block_info);
}
} else {
// If there is no previous block, we should reward the author of the first block
total_weight = total_weight.saturating_add(
T::AuthorNotingHook::on_container_author_noted(
&block_info.author,
block_info.block_number,
para_id,
),
);
let _ = core::mem::replace(
maybe_old_block_info,
Some(block_info),
);
}
},
);
}
Err(e) => log::warn!(
"Author-noting error {:?} found in para {:?}",
e,
Expand Down
19 changes: 12 additions & 7 deletions pallets/author-noting/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

use {
crate::{self as author_noting_pallet, Config},
bounded_collections::bounded_vec,
cumulus_pallet_parachain_system::{RelayChainState, RelaychainStateProvider},
cumulus_primitives_core::ParaId,
frame_support::{
Expand All @@ -25,14 +26,15 @@ use {
ConstU32, ConstU64, Everything, OnFinalize, OnInitialize, UnfilteredDispatchable,
},
},
frame_system::pallet_prelude::BlockNumberFor,
frame_system::RawOrigin,
frame_system::{pallet_prelude::BlockNumberFor, RawOrigin},
parity_scale_codec::{Decode, Encode},
polkadot_parachain_primitives::primitives::RelayChainBlockNumber,
polkadot_primitives::Slot,
sp_core::H256,
sp_runtime::traits::{BlakeTwo256, IdentityLookup},
sp_runtime::BuildStorage,
sp_runtime::{
traits::{BlakeTwo256, IdentityLookup},
BoundedVec, BuildStorage,
},
sp_state_machine::StorageProof,
test_relay_sproof_builder::ParaHeaderSproofBuilder,
};
Expand Down Expand Up @@ -116,13 +118,13 @@ impl mock_data::Config for Test {}
#[derive(Clone, Encode, Decode, PartialEq, sp_core::RuntimeDebug, scale_info::TypeInfo)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub struct Mocks {
pub container_chains: Vec<ParaId>,
pub container_chains: BoundedVec<ParaId, ConstU32<5>>,
}

impl Default for Mocks {
fn default() -> Self {
Self {
container_chains: vec![1001.into()],
container_chains: bounded_vec![1001.into()],
}
}
}
Expand All @@ -141,7 +143,9 @@ impl tp_traits::GetContainerChainAuthor<AccountId> for MockAuthorFetcher {
pub struct MockContainerChainGetter;

impl tp_traits::GetCurrentContainerChains for MockContainerChainGetter {
fn current_container_chains() -> Vec<ParaId> {
type MaxContainerChains = ConstU32<5>;

fn current_container_chains() -> BoundedVec<ParaId, Self::MaxContainerChains> {
MockData::mock().container_chains
}

Expand Down Expand Up @@ -181,6 +185,7 @@ impl Config for Test {
type ContainerChainAuthor = MockAuthorFetcher;
type SelfParaId = ParachainId;
type ContainerChains = MockContainerChainGetter;
type AuthorNotingHook = ();
type RelayChainStateProvider = MockRelayStateProvider;
}

Expand Down
3 changes: 2 additions & 1 deletion pallets/author-noting/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

use {
crate::{mock::*, ContainerChainBlockInfo, Event},
bounded_collections::bounded_vec,
cumulus_primitives_core::ParaId,
frame_support::{
assert_ok,
Expand Down Expand Up @@ -166,7 +167,7 @@ fn test_author_id_insertion_many_paras() {
// Writing to this pallet storage will only change the sproofs of the next block,
// not the ones of the current block
MockData::mutate(|m| {
m.container_chains = vec![1001.into(), 1002.into()];
m.container_chains = bounded_vec![1001.into(), 1002.into()];
});
assert_eq!(
AuthorNoting::latest_author(ParaId::from(1001)),
Expand Down
9 changes: 8 additions & 1 deletion pallets/collator-assignment/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ pub mod pallet {
// which guarantees that at least one full session has passed before any changes are applied.
type HostConfiguration: GetHostConfiguration<Self::SessionIndex>;
type ContainerChains: GetSessionContainerChains<Self::SessionIndex>;
type SelfParaId: Get<ParaId>;
type ShouldRotateAllCollators: ShouldRotateAllCollators<Self::SessionIndex>;
type GetRandomnessForNextBlock: GetRandomnessForNextBlock<BlockNumberFor<Self>>;
type RemoveInvulnerables: RemoveInvulnerables<Self::AccountId>;
Expand Down Expand Up @@ -411,9 +412,15 @@ pub mod pallet {
}

impl<T: Config> GetContainerChainAuthor<T::AccountId> for Pallet<T> {
// TODO: pending collator container chain if the block is a session change!
fn author_for_slot(slot: Slot, para_id: ParaId) -> Option<T::AccountId> {
let assigned_collators = Pallet::<T>::collator_container_chain();
let collators = assigned_collators.container_chains.get(&para_id)?;
let collators = if para_id == T::SelfParaId::get() {
Some(&assigned_collators.orchestrator_chain)
} else {
assigned_collators.container_chains.get(&para_id)
}?;

if collators.is_empty() {
// Avoid division by zero below
return None;
Expand Down
Loading

0 comments on commit 84d3d97

Please sign in to comment.