From 56de3b38463a612c59b7ba9f0a12443d9b847eac Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Wed, 27 Dec 2023 12:55:12 -0800 Subject: [PATCH] node: proposer for limiting blocks --- Cargo.lock | 5 ++ sugondat-chain/node/Cargo.toml | 6 ++ sugondat-chain/node/src/main.rs | 1 + sugondat-chain/node/src/proposer.rs | 89 +++++++++++++++++++++++++++++ sugondat-chain/node/src/service.rs | 2 +- 5 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 sugondat-chain/node/src/proposer.rs diff --git a/Cargo.lock b/Cargo.lock index be335ea6..5f4c103f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13833,6 +13833,8 @@ dependencies = [ name = "sugondat-node" version = "0.1.0" dependencies = [ + "anyhow", + "async-trait", "clap", "color-print", "cumulus-client-cli", @@ -13841,6 +13843,7 @@ dependencies = [ "cumulus-client-consensus-common", "cumulus-client-consensus-proposer", "cumulus-client-service", + "cumulus-pallet-parachain-system", "cumulus-primitives-core", "cumulus-primitives-parachain-inherent", "cumulus-relay-chain-interface", @@ -13874,8 +13877,10 @@ dependencies = [ "sp-api", "sp-block-builder", "sp-blockchain", + "sp-consensus", "sp-consensus-aura", "sp-core", + "sp-inherents", "sp-io", "sp-keystore", "sp-runtime", diff --git a/sugondat-chain/node/Cargo.toml b/sugondat-chain/node/Cargo.toml index 96c4245a..0dc9daa8 100644 --- a/sugondat-chain/node/Cargo.toml +++ b/sugondat-chain/node/Cargo.toml @@ -10,6 +10,8 @@ build = "build.rs" license = "MIT OR Apache-2.0" [dependencies] +anyhow = "1.0" +async-trait = "0.1.73" clap = { version = "4.4.6", features = ["derive"] } log = "0.4.17" codec = { package = "parity-scale-codec", version = "3.0.0" } @@ -46,10 +48,12 @@ sc-transaction-pool-api = { git = "https://github.com/paritytech/polkadot-sdk", sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.4.0" } sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.4.0" } sp-blockchain = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.4.0" } +sp-consensus = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.4.0" } sp-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.4.0" } sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.4.0" } sp-keystore = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.4.0" } sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.4.0" } +sp-inherents = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.4.0" } sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.4.0" } sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.4.0" } sp-timestamp = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.4.0" } @@ -75,6 +79,8 @@ cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/p cumulus-relay-chain-interface = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.4.0" } color-print = "0.3.4" +cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.4.0" } + [build-dependencies] substrate-build-script-utils = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.4.0" } diff --git a/sugondat-chain/node/src/main.rs b/sugondat-chain/node/src/main.rs index fd65f2ca..96f7007c 100644 --- a/sugondat-chain/node/src/main.rs +++ b/sugondat-chain/node/src/main.rs @@ -7,6 +7,7 @@ mod chain_spec; mod service; mod cli; mod command; +mod proposer; mod rpc; fn main() -> sc_cli::Result<()> { diff --git a/sugondat-chain/node/src/proposer.rs b/sugondat-chain/node/src/proposer.rs new file mode 100644 index 00000000..0244ffd9 --- /dev/null +++ b/sugondat-chain/node/src/proposer.rs @@ -0,0 +1,89 @@ +//! Wrapper around a proposer which only authors blocks when certain conditions are met. +//! +//! These conditions are: +//! 1. There is at least one transaction ready to post. This is used to determine that there were +//! non-inherent extrinsics and avoid authoring empty blocks. +//! 2. There is an incoming downward message from the relay chain. +//! 3. There is a go-ahead signal for a parachain code upgrade. +//! +//! If any of these conditions are met, then the block is authored. + +use anyhow::anyhow; + +use sc_transaction_pool_api::TransactionPool; +use sp_api::StorageProof; +use sp_consensus::Proposal; +use sp_inherents::InherentData; +use sp_runtime::generic::Digest; + +use cumulus_client_consensus_proposer::{Error as ProposerError, ProposerInterface}; +use cumulus_pallet_parachain_system::relay_state_snapshot::RelayChainStateProof; +use cumulus_primitives_core::ParaId; +use cumulus_primitives_parachain_inherent::ParachainInherentData; + +use sugondat_primitives::opaque::{Block, Header}; + +use std::sync::Arc; +use std::time::Duration; + +use crate::service::ParachainClient; + +/// Proposes blocks, but only under certain conditions. See module docs. +pub struct BlockLimitingProposer

{ + inner: P, + para_id: ParaId, + transaction_pool: Arc>, +} + +#[async_trait::async_trait] +impl + Send> ProposerInterface for BlockLimitingProposer

{ + async fn propose( + &mut self, + parent_header: &Header, + paras_inherent_data: &ParachainInherentData, + other_inherent_data: InherentData, + inherent_digests: Digest, + max_duration: Duration, + block_size_limit: Option, + ) -> Result, ProposerError> { + let has_downward_message = !paras_inherent_data.downward_messages.is_empty(); + let has_transactions = self.transaction_pool.status().ready > 0; + let has_go_ahead = { + let maybe_go_ahead = RelayChainStateProof::new( + self.para_id, + paras_inherent_data + .validation_data + .relay_parent_storage_root, + paras_inherent_data.relay_chain_state.clone(), + ) + .and_then(|p| p.read_upgrade_go_ahead_signal()); + + // when we encounter errors reading the go ahead signal, + // we pessimistically opt to create a block as such errors indicate + // changes in the relay chain protocol and would likely persist + // until something is fixed here. + match maybe_go_ahead { + Err(_) => true, + Ok(Some(_)) => true, + Ok(None) => false, + } + }; + + if has_downward_message || has_go_ahead || has_transactions { + self.inner + .propose( + parent_header, + paras_inherent_data, + other_inherent_data, + inherent_digests, + max_duration, + block_size_limit, + ) + .await + } else { + Err(ProposerError::proposing(anyhow!( + "no need to create a block" + ))) + } + } +} diff --git a/sugondat-chain/node/src/service.rs b/sugondat-chain/node/src/service.rs index 4a630a08..e2277740 100644 --- a/sugondat-chain/node/src/service.rs +++ b/sugondat-chain/node/src/service.rs @@ -52,7 +52,7 @@ type HostFunctions = ( frame_benchmarking::benchmarking::HostFunctions, ); -type ParachainClient = TFullClient>; +pub(crate) type ParachainClient = TFullClient>; type ParachainBackend = TFullBackend;