Skip to content

node: proposer for limiting blocks #156

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Cargo.lock

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

6 changes: 6 additions & 0 deletions sugondat-chain/node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down Expand Up @@ -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" }
Expand All @@ -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" }

Expand Down
1 change: 1 addition & 0 deletions sugondat-chain/node/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ mod chain_spec;
mod service;
mod cli;
mod command;
mod proposer;
mod rpc;

fn main() -> sc_cli::Result<()> {
Expand Down
89 changes: 89 additions & 0 deletions sugondat-chain/node/src/proposer.rs
Original file line number Diff line number Diff line change
@@ -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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like we might need to think to extract this. (Well, I guess by we I mean cumulus devs)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extract in what sense?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, sorry, I meant that RelayChainStateProof seems like a generally useful primitive and as such probably would be better placed in a primitives crate. That crate would be dependent upon by places such as this one and the cumulus_pallet_parachain_system.

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<P> {
inner: P,
para_id: ParaId,
transaction_pool: Arc<sc_transaction_pool::FullPool<Block, ParachainClient>>,
}

#[async_trait::async_trait]
impl<P: ProposerInterface<Block> + Send> ProposerInterface<Block> for BlockLimitingProposer<P> {
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<usize>,
) -> Result<Proposal<Block, StorageProof>, 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"
)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hopefully, this isn't going to be printed all the time, or is it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is. Needs an upstream fix.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
}
}
2 changes: 1 addition & 1 deletion sugondat-chain/node/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ type HostFunctions = (
frame_benchmarking::benchmarking::HostFunctions,
);

type ParachainClient = TFullClient<Block, RuntimeApi, WasmExecutor<HostFunctions>>;
pub(crate) type ParachainClient = TFullClient<Block, RuntimeApi, WasmExecutor<HostFunctions>>;

type ParachainBackend = TFullBackend<Block>;

Expand Down