Skip to content

Commit

Permalink
change: Feed block production log from session validator management p…
Browse files Browse the repository at this point in the history
…allet

Signed-off-by: Nikolaos Dymitriadis <[email protected]>
  • Loading branch information
AmbientTea committed Feb 24, 2025
1 parent e7a9c57 commit eb2c8cd
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 72 deletions.
3 changes: 2 additions & 1 deletion Cargo.lock

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

10 changes: 6 additions & 4 deletions node/node/src/inherent_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ use sidechain_domain::{McBlockHash, ScEpochNumber};
use sidechain_mc_hash::McHashDataSource;
use sidechain_mc_hash::McHashInherentDataProvider as McHashIDP;
use sidechain_runtime::opaque::SessionKeys;
use sidechain_runtime::CrossChainPublic;
use sidechain_runtime::{opaque::Block, BeneficiaryId};
use sidechain_runtime::{BlockAuthor, CrossChainPublic};
use sidechain_slots::ScSlotConfig;
use sp_api::ProvideRuntimeApi;
use sp_block_production_log::BlockProducerIdInherentProvider;
use sp_block_production_log::BlockAuthorInherentProvider;
use sp_block_production_log::BlockProductionLogApi;
use sp_block_rewards::BlockBeneficiaryInherentProvider;
use sp_blockchain::HeaderBackend;
use sp_consensus_aura::{
Expand Down Expand Up @@ -56,13 +57,14 @@ where
ScEpochNumber,
>,
T::Api: NativeTokenManagementApi<Block>,
T::Api: BlockProductionLogApi<Block, CommitteeMember<CrossChainPublic, SessionKeys>>,
{
type InherentDataProviders = (
AuraIDP,
TimestampIDP,
McHashIDP,
AriadneIDP,
BlockProducerIdInherentProvider<BeneficiaryId>,
BlockAuthorInherentProvider<BlockAuthor>,
BlockBeneficiaryInherentProvider<BeneficiaryId>,
NativeTokenIDP,
);
Expand Down Expand Up @@ -101,7 +103,7 @@ where
)
.await?;
let block_producer_id_provider =
BlockProducerIdInherentProvider::from_env("SIDECHAIN_BLOCK_BENEFICIARY")?;
BlockAuthorInherentProvider::new(client.as_ref(), parent_hash)?;
let block_beneficiary_provider =
BlockBeneficiaryInherentProvider::<BeneficiaryId>::from_env(
"SIDECHAIN_BLOCK_BENEFICIARY",
Expand Down
15 changes: 9 additions & 6 deletions node/node/src/tests/inherent_data_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ use authority_selection_inherents::{
authority_selection_inputs::AuthoritySelectionInputs, mock::MockAuthoritySelectionDataSource,
};
use hex_literal::hex;
use sidechain_domain::byte_string::SizedByteString;
use sidechain_domain::{
MainchainBlock, McBlockHash, McBlockNumber, McEpochNumber, McSlotNumber, NativeTokenAmount,
ScEpochNumber,
};
use sidechain_mc_hash::mock::MockMcHashDataSource;
use sidechain_runtime::BlockAuthor;
use sp_consensus_aura::Slot;
use sp_core::H256;
use sp_core::{ecdsa, H256};
use sp_inherents::CreateInherentDataProviders;
use sp_inherents::{InherentData, InherentDataProvider};
use sp_native_token_management::mock::MockNativeTokenDataSource;
Expand Down Expand Up @@ -97,11 +97,14 @@ async fn block_proposal_cidp_should_be_created_correctly() {
.is_some());
assert_eq!(
inherent_data
.get_data::<SizedByteString::<32>>(&sp_block_production_log::INHERENT_IDENTIFIER)
.get_data::<BlockAuthor>(&sp_block_production_log::INHERENT_IDENTIFIER)
.unwrap(),
Some(SizedByteString::<32>(hex!(
"0000000000000000000000000000000000000000000000000000000000000001"
)))
Some(BlockAuthor::ProBono(
ecdsa::Public::from_raw(hex!(
"000000000000000000000000000000000000000000000000000000000000000001"
))
.into()
))
);
}

Expand Down
14 changes: 14 additions & 0 deletions node/node/src/tests/runtime_api_mock.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use super::mock::mock_genesis_utxo;
use authority_selection_inherents::authority_selection_inputs::AuthoritySelectionInputs;
use authority_selection_inherents::CommitteeMember;
use hex_literal::hex;
use sidechain_domain::*;
use sidechain_mc_hash::McHashInherentDigest;
use sidechain_runtime::opaque::SessionKeys;
use sidechain_runtime::CrossChainPublic;
use sp_api::{ApiRef, ProvideRuntimeApi};
use sp_blockchain::HeaderBackend;
use sp_core::ecdsa;
use sp_core::{ed25519, sr25519};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero};
use sp_runtime::Digest;
use sp_sidechain::GetGenesisUtxo;
Expand Down Expand Up @@ -107,6 +109,18 @@ sp_api::mock_impl_runtime_apis! {
true
}
}

impl sp_block_production_log::BlockProductionLogApi<Block, CommitteeMember<CrossChainPublic, SessionKeys>> for TestApi {
fn get_current_author() -> CommitteeMember<CrossChainPublic, SessionKeys> {
CommitteeMember::permissioned(
ecdsa::Public::from_raw(hex!("000000000000000000000000000000000000000000000000000000000000000001")).into(),
SessionKeys {
aura: sr25519::Public::default().into(),
grandpa: ed25519::Public::default().into()
}
)
}
}
}

impl HeaderBackend<Block> for TestApi {
Expand Down
2 changes: 2 additions & 0 deletions node/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ frame-system-benchmarking = { workspace = true, optional = true }

# Local Dependencies
sp-block-rewards = { workspace = true }
sp-block-production-log = { workspace = true }
pallet-block-production-log = { workspace = true }
pallet-block-rewards = { workspace = true }
sp-sidechain = { workspace = true }
Expand Down Expand Up @@ -153,6 +154,7 @@ std = [
"pallet-native-token-management/std",
"sp-native-token-management/std",
"pallet-session-runtime-stub/std",
"sp-block-production-log/std",
]

runtime-benchmarks = [
Expand Down
44 changes: 40 additions & 4 deletions node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,17 @@ use opaque::SessionKeys;
use pallet_grandpa::AuthorityId as GrandpaId;
use pallet_session_validator_management;
use pallet_transaction_payment::{ConstFeeMultiplier, FungibleAdapter, Multiplier};
use parity_scale_codec::MaxEncodedLen;
use parity_scale_codec::{Decode, Encode};
use scale_info::TypeInfo;
use session_manager::ValidatorManagementSessionManager;
use sidechain_domain::{
NativeTokenAmount, PermissionedCandidateData, RegistrationData, ScEpochNumber, ScSlotNumber,
StakeDelegation, StakePoolPublicKey, UtxoId,
};
use sp_api::impl_runtime_apis;
use sp_consensus_aura::sr25519::AuthorityId as AuraId;
use sp_core::{crypto::KeyTypeId, hexdisplay::HexDisplay, OpaqueMetadata};
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::{
generic, impl_opaque_keys,
traits::{
Expand Down Expand Up @@ -431,10 +434,10 @@ impl sp_sidechain::OnNewEpoch for LogBeneficiaries {
let slot = pallet_aura::CurrentSlot::<Runtime>::get();
let block_production_log = BlockProductionLog::take_prefix(&slot);
if let Some((s, b)) = block_production_log.first() {
log::info!("Block production log head: {} -> {}", **s, HexDisplay::from(&b.0))
log::info!("Block production log head: {} -> {:?}", **s, b)
};
if let Some((s, b)) = block_production_log.last() {
log::info!("Block production log tail: {} -> {}", **s, HexDisplay::from(&b.0))
log::info!("Block production log tail: {} -> {:?}", **s, b)
};
RuntimeDbWeight::get().reads_writes(1, 1)
}
Expand All @@ -455,8 +458,32 @@ impl pallet_block_rewards::Config for Runtime {
type GetBlockRewardPoints = sp_block_rewards::SimpleBlockCount;
}

#[derive(MaxEncodedLen, Encode, Decode, Clone, TypeInfo, PartialEq, Eq, Debug)]
pub enum BlockAuthor {
Incentivized(CrossChainPublic, StakePoolPublicKey),
ProBono(CrossChainPublic),
}
impl BlockAuthor {
pub fn id(&self) -> &CrossChainPublic {
match self {
Self::Incentivized(id, _ ) => id,
Self::ProBono(id) => id
}
}
}
impl From<CommitteeMember<CrossChainPublic, SessionKeys>> for BlockAuthor {
fn from(value: CommitteeMember<CrossChainPublic, SessionKeys>) -> Self {
match value {
CommitteeMember::Permissioned { id, .. } => BlockAuthor::ProBono(id),
CommitteeMember::Registered { id, stake_pool_pub_key, .. } => {
BlockAuthor::Incentivized(id, stake_pool_pub_key)
},
}
}
}

impl pallet_block_production_log::Config for Runtime {
type BlockProducerId = BeneficiaryId;
type BlockProducerId = BlockAuthor;
type WeightInfo = pallet_block_production_log::weights::SubstrateWeight<Runtime>;

fn current_slot() -> sp_consensus_slots::Slot {
Expand Down Expand Up @@ -871,6 +898,15 @@ impl_runtime_apis! {
NativeTokenManagement::initialized()
}
}

impl sp_block_production_log::BlockProductionLogApi<Block, CommitteeMember<CrossChainPublic, SessionKeys>> for Runtime {
fn get_current_author() -> CommitteeMember<CrossChainPublic, SessionKeys> {
let mut committee = SessionCommitteeManagement::get_current_committee().1;
let slot = pallet_aura::CurrentSlot::<Runtime>::get();
// this implementation is compatible with round-robin employed by Aura
committee.remove(*slot as usize % committee.len())
}
}
}

#[cfg(test)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
use crate::authority_selection_inputs::AuthoritySelectionDataSource;
use crate::authority_selection_inputs::AuthoritySelectionInputs;
use parity_scale_codec::{Decode, Encode};
use sp_session_validator_management::CommitteeMember as CommitteeMemberT;
#[cfg(feature = "std")]
use {
crate::authority_selection_inputs::AuthoritySelectionInputsCreationError,
Expand All @@ -13,6 +12,7 @@ use {
sp_consensus_slots::Slot,
sp_inherents::{InherentData, InherentIdentifier},
sp_runtime::traits::Block as BlockT,
sp_session_validator_management::CommitteeMember as CommitteeMemberT,
sp_session_validator_management::{
InherentError, MainChainScripts, SessionValidatorManagementApi, INHERENT_IDENTIFIER,
},
Expand Down
3 changes: 2 additions & 1 deletion toolkit/primitives/block-production-log/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ license = "Apache-2.0"
[dependencies]
async-trait = { workspace = true }
parity-scale-codec = { workspace = true }
sp-api = { workspace = true }
sp-core = { workspace = true, optional = true }
sp-inherents = { workspace = true }
sp-runtime = { workspace = true }
thiserror = { workspace = true }

[dev-dependencies]
hex = { workspace = true }
sealed_test = { workspace = true }

[features]
default = ["std"]
Expand All @@ -26,4 +26,5 @@ std = [
"sp-core/std",
"sp-inherents/std",
"sp-runtime/std",
"sp-api/std",
]
58 changes: 35 additions & 23 deletions toolkit/primitives/block-production-log/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
#![cfg_attr(not(feature = "std"), no_std)]

extern crate alloc;

#[cfg(test)]
mod test;

use parity_scale_codec::Encode;
use core::error::Error;
use parity_scale_codec::{Decode, Encode};
use sp_inherents::{InherentIdentifier, IsFatalError};
use sp_runtime::traits::Block as BlockT;
#[cfg(feature = "std")]
use {parity_scale_codec::Decode, sp_inherents::InherentData};
use {sp_api::ProvideRuntimeApi, sp_inherents::InherentData};

pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"blprdlog";

#[derive(Encode, PartialEq)]
#[cfg_attr(not(feature = "std"), derive(Debug))]
#[cfg_attr(feature = "std", derive(Decode, thiserror::Error, sp_runtime::RuntimeDebug))]
pub enum InherentError {
#[cfg_attr(feature = "std", error("Block Producer Id inherent must be provided every block"))]
#[cfg_attr(feature = "std", error("Block Author inherent must be provided every block"))]
InherentRequired,
}
impl IsFatalError for InherentError {
Expand All @@ -25,41 +29,40 @@ impl IsFatalError for InherentError {

#[cfg(feature = "std")]
#[derive(Debug)]
pub struct BlockProducerIdInherentProvider<T> {
pub id: T,
pub struct BlockAuthorInherentProvider<Author> {
pub author: Author,
}

#[cfg(feature = "std")]
impl<T> BlockProducerIdInherentProvider<T>
where
T: TryFrom<Vec<u8>> + Send + Sync + Encode,
<T as TryFrom<Vec<u8>>>::Error: std::fmt::Debug,
{
pub fn from_env(env_var: &str) -> Result<Self, String> {
let env_var_value = std::env::var(env_var).map_err(|_| {
format!("Block Producer Id environment variable '{env_var}' is not set")
})?;
let bytes = sp_core::bytes::from_hex(&env_var_value)
.map_err(|_| format!("Block Producer Id environment variable '{env_var}' value '{env_var_value}' is not a valid hex string"))?;
let id = T::try_from(bytes.clone()).map_err(|e| {
format!("Could not convert '{env_var_value}' into Block Producer Id. Cause: {e:#?}")
})?;
impl<Author> BlockAuthorInherentProvider<Author> {
pub fn new<C, Member, Block>(
client: &C,
parent_hash: Block::Hash,
) -> Result<Self, Box<dyn Error + Send + Sync>>
where
Member: Decode,
Block: BlockT,
C: ProvideRuntimeApi<Block>,
C::Api: BlockProductionLogApi<Block, Member>,
Author: From<Member>,
{
let author: Author = client.runtime_api().get_current_author(parent_hash)?.into();

Ok(BlockProducerIdInherentProvider { id })
Ok(BlockAuthorInherentProvider { author })
}
}

#[cfg(feature = "std")]
#[async_trait::async_trait]
impl<T> sp_inherents::InherentDataProvider for BlockProducerIdInherentProvider<T>
impl<T> sp_inherents::InherentDataProvider for BlockAuthorInherentProvider<T>
where
T: TryFrom<Vec<u8>> + Send + Sync + Encode,
T: Send + Sync + Encode + Decode,
{
async fn provide_inherent_data(
&self,
inherent_data: &mut InherentData,
) -> Result<(), sp_inherents::Error> {
inherent_data.put_data(INHERENT_IDENTIFIER, &self.id)
inherent_data.put_data(INHERENT_IDENTIFIER, &self.author)
}

async fn try_handle_error(
Expand All @@ -75,3 +78,12 @@ where
}
}
}

sp_api::decl_runtime_apis! {
pub trait BlockProductionLogApi<Member>
where
Member: Decode
{
fn get_current_author() -> Member;
}
}
Loading

0 comments on commit eb2c8cd

Please sign in to comment.