Skip to content
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

Support instant sealing #170

Merged
merged 7 commits into from
Oct 21, 2020
Merged
Show file tree
Hide file tree
Changes from 4 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
18 changes: 15 additions & 3 deletions template/node/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use structopt::StructOpt;
use structopt::{StructOpt, clap::arg_enum};

arg_enum! {
/// Available Sealing methods.
#[allow(missing_docs)]
#[derive(Debug, Copy, Clone, StructOpt)]
pub enum Sealing {
// Seal using rpc method.
Manual,
// Seal when transaction is executed.
Instant,
}
}

#[allow(missing_docs)]
#[derive(Debug, StructOpt)]
Expand All @@ -25,8 +37,8 @@ pub struct RunCmd {
pub base: sc_cli::RunCmd,

/// Force using Kusama native runtime.
#[structopt(long = "manual-seal")]
pub manual_seal: bool,
#[structopt(long = "sealing")]
pub sealing: Option<Sealing>,
}

#[derive(Debug, StructOpt)]
Expand Down
12 changes: 6 additions & 6 deletions template/node/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,31 +75,31 @@ pub fn run() -> sc_cli::Result<()> {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { client, task_manager, import_queue, ..}
= new_partial(&config, cli.run.manual_seal)?;
= new_partial(&config, cli.run.sealing)?;
Ok((cmd.run(client, import_queue), task_manager))
})
},
Some(Subcommand::ExportBlocks(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { client, task_manager, ..}
= new_partial(&config, cli.run.manual_seal)?;
= new_partial(&config, cli.run.sealing)?;
Ok((cmd.run(client, config.database), task_manager))
})
},
Some(Subcommand::ExportState(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { client, task_manager, ..}
= new_partial(&config, cli.run.manual_seal)?;
= new_partial(&config, cli.run.sealing)?;
Ok((cmd.run(client, config.chain_spec), task_manager))
})
},
Some(Subcommand::ImportBlocks(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { client, task_manager, import_queue, ..}
= new_partial(&config, cli.run.manual_seal)?;
= new_partial(&config, cli.run.sealing)?;
Ok((cmd.run(client, import_queue), task_manager))
})
},
Expand All @@ -111,15 +111,15 @@ pub fn run() -> sc_cli::Result<()> {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { client, task_manager, backend, ..}
= new_partial(&config, cli.run.manual_seal)?;
= new_partial(&config, cli.run.sealing)?;
Ok((cmd.run(client, backend), task_manager))
})
},
None => {
let runner = cli.create_runner(&cli.run.base)?;
runner.run_node_until_exit(|config| match config.role {
Role::Light => service::new_light(config),
_ => service::new_full(config, cli.run.manual_seal),
_ => service::new_full(config, cli.run.sealing),
})
}
}
Expand Down
98 changes: 74 additions & 24 deletions template/node/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@ use std::time::Duration;
use sc_client_api::{ExecutorProvider, RemoteBackend};
use sc_consensus_manual_seal::{self as manual_seal};
use frontier_consensus::FrontierBlockImport;
use frontier_template_runtime::{self, opaque::Block, RuntimeApi};
use frontier_template_runtime::{self, opaque::Block, RuntimeApi, SLOT_DURATION};
use sc_service::{error::Error as ServiceError, Configuration, TaskManager};
use sp_inherents::InherentDataProviders;
use sp_inherents::{InherentDataProviders, ProvideInherentData, InherentIdentifier, InherentData};
use sc_executor::native_executor_instance;
pub use sc_executor::NativeExecutor;
use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair};
use sc_finality_grandpa::{
FinalityProofProvider as GrandpaFinalityProofProvider, SharedVoterState,
};
use sp_timestamp::InherentError;
use crate::cli::Sealing;

// Our native executor instance.
native_executor_instance!(
Expand All @@ -40,10 +42,39 @@ pub enum ConsensusResult {
>,
sc_finality_grandpa::LinkHalf<Block, FullClient, FullSelectChain>
),
ManualSeal(FrontierBlockImport<Block, Arc<FullClient>, FullClient>)
ManualSeal(FrontierBlockImport<Block, Arc<FullClient>, FullClient>, Sealing)
}

pub fn new_partial(config: &Configuration, manual_seal: bool) -> Result<
pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"timstap0";

/// Provide a mock duration since unix epoch in millisecond for timestamp inherent.
/// First call will return current timestamp and others calls with increment
/// it by slot_duration to make Aura think time has passed
pub struct MockInherentDataProvider;
ermalkaleci marked this conversation as resolved.
Show resolved Hide resolved

static mut CURRENT_TIMESTAMP: u64 = 0;

impl ProvideInherentData for MockInherentDataProvider {
fn inherent_identifier(&self) -> &'static InherentIdentifier {
&INHERENT_IDENTIFIER
}

fn provide_inherent_data(
&self,
inherent_data: &mut InherentData,
) -> Result<(), sp_inherents::Error> {
unsafe {
CURRENT_TIMESTAMP += SLOT_DURATION;
inherent_data.put_data(INHERENT_IDENTIFIER, &CURRENT_TIMESTAMP)
}
}

fn error_to_string(&self, error: &[u8]) -> Option<String> {
InherentError::try_from(&INHERENT_IDENTIFIER, error).map(|e| format!("{:?}", e))
}
}

pub fn new_partial(config: &Configuration, sealing: Option<Sealing>) -> Result<
sc_service::PartialComponents<
FullClient, FullBackend, FullSelectChain,
sp_consensus::import_queue::BasicQueue<Block, sp_api::TransactionFor<FullClient, Block>>,
Expand All @@ -65,9 +96,9 @@ pub fn new_partial(config: &Configuration, manual_seal: bool) -> Result<
client.clone(),
);

if manual_seal {
if sealing.is_some() {
ermalkaleci marked this conversation as resolved.
Show resolved Hide resolved
inherent_data_providers
.register_provider(sp_timestamp::InherentDataProvider)
.register_provider(MockInherentDataProvider)
.map_err(Into::into)
.map_err(sp_consensus::error::Error::InherentData)?;

Expand All @@ -86,7 +117,7 @@ pub fn new_partial(config: &Configuration, manual_seal: bool) -> Result<
return Ok(sc_service::PartialComponents {
client, backend, task_manager, import_queue, keystore, select_chain, transaction_pool,
inherent_data_providers,
other: ConsensusResult::ManualSeal(frontier_block_import)
other: ConsensusResult::ManualSeal(frontier_block_import, sealing.expect("already checked above"))
})
}

Expand Down Expand Up @@ -124,15 +155,15 @@ pub fn new_partial(config: &Configuration, manual_seal: bool) -> Result<
}

/// Builds a new service for a full client.
pub fn new_full(config: Configuration, manual_seal: bool) -> Result<TaskManager, ServiceError> {
pub fn new_full(config: Configuration, sealing: Option<Sealing>) -> Result<TaskManager, ServiceError> {
let sc_service::PartialComponents {
client, backend, mut task_manager, import_queue, keystore, select_chain, transaction_pool,
inherent_data_providers,
other: consensus_result
} = new_partial(&config, manual_seal)?;
} = new_partial(&config, sealing)?;

let (network, network_status_sinks, system_rpc_tx, network_starter) = match consensus_result {
ConsensusResult::ManualSeal(_) => {
ConsensusResult::ManualSeal(_, _) => {
sc_service::build_network(sc_service::BuildNetworkParams {
config: &config,
client: client.clone(),
Expand Down Expand Up @@ -213,7 +244,7 @@ pub fn new_full(config: Configuration, manual_seal: bool) -> Result<TaskManager,
})?;

match consensus_result {
ConsensusResult::ManualSeal(block_import) => {
ConsensusResult::ManualSeal(block_import, sealing) => {
if role.is_authority() {
let env = sc_basic_authorship::ProposerFactory::new(
client.clone(),
Expand All @@ -222,21 +253,40 @@ pub fn new_full(config: Configuration, manual_seal: bool) -> Result<TaskManager,
);

// Background authorship future
let authorship_future = manual_seal::run_manual_seal(
manual_seal::ManualSealParams {
block_import,
env,
client: client.clone(),
pool: transaction_pool.pool().clone(),
commands_stream,
select_chain,
consensus_data_provider: None,
inherent_data_providers,
match sealing {
Sealing::Manual => {
let authorship_future = manual_seal::run_manual_seal(
manual_seal::ManualSealParams {
block_import,
env,
client,
pool: transaction_pool.pool().clone(),
commands_stream,
select_chain,
consensus_data_provider: None,
inherent_data_providers,
}
);
// we spawn the future on a background thread managed by service.
task_manager.spawn_essential_handle().spawn_blocking("manual-seal", authorship_future);
},
Sealing::Instant => {
let authorship_future = manual_seal::run_instant_seal(
manual_seal::InstantSealParams {
block_import,
env,
client: client.clone(),
pool: transaction_pool.pool().clone(),
select_chain,
consensus_data_provider: None,
inherent_data_providers,
}
);
// we spawn the future on a background thread managed by service.
task_manager.spawn_essential_handle().spawn_blocking("instant-seal", authorship_future);
}
);
};

// we spawn the future on a background thread managed by service.
task_manager.spawn_essential_handle().spawn_blocking("manual-seal", authorship_future);
}
log::info!("Manual Seal Ready");
},
Expand Down
11 changes: 4 additions & 7 deletions ts-tests/tests/test-block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describeWithFrontier("Frontier RPC (Block)", `simple-specs.json`, (context) => {
receiptsRoot: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
size: 533,
stateRoot: "0x0000000000000000000000000000000000000000000000000000000000000000",
//timestamp: 1595012243836,
timestamp: 0,
totalDifficulty: null,
//transactions: [],
transactionsRoot: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
Expand Down Expand Up @@ -60,10 +60,7 @@ describeWithFrontier("Frontier RPC (Block)", `simple-specs.json`, (context) => {

step("should have valid timestamp after block production", async function () {
const block = await context.web3.eth.getBlock("latest");
const last5Minutes = (Date.now() / 1000) - 300;
const next5Minutes = (Date.now() / 1000) + 300;
expect(block.timestamp).to.be.least(last5Minutes);
expect(block.timestamp).to.be.below(next5Minutes);
expect(block.timestamp).to.be.eq(6);
});

step("retrieve block information", async function () {
Expand All @@ -83,9 +80,9 @@ describeWithFrontier("Frontier RPC (Block)", `simple-specs.json`, (context) => {
number: 1,
//parentHash: "0x04540257811b46d103d9896e7807040e7de5080e285841c5430d1a81588a0ce4",
receiptsRoot: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
size: 539,
size: 535,
stateRoot: "0x0000000000000000000000000000000000000000000000000000000000000000",
//timestamp: 1595012243836,
timestamp: 6,
totalDifficulty: null,
//transactions: [],
transactionsRoot: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
Expand Down
2 changes: 1 addition & 1 deletion ts-tests/tests/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export async function startFrontierNode(specFilename: string): Promise<{ web3: W
`--execution=Native`, // Faster execution using native
`--no-telemetry`,
`--no-prometheus`,
`--manual-seal`,
`--sealing=Manual`,
`--no-grandpa`,
`--force-authoring`,
`-l${FRONTIER_LOG}`,
Expand Down