Compare commits

...

18 Commits

Author SHA1 Message Date
df85600159
generate chain spec for the latest ghost-node
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2025-07-29 16:03:34 +03:00
141f05ddab
finalize hard reset for starter script
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2025-07-29 16:00:58 +03:00
6ae3fd6291
rustfmt ghost cli and fix typos
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2025-07-29 15:03:44 +03:00
767161ac9c
rustfmt ghost client cli and fix typos
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2025-07-29 15:02:07 +03:00
a74e42369b
rustfmt ghost metrics and fix typos
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2025-07-29 15:00:54 +03:00
7216f1d82b
rustfmt ghost slow clap and fix typos
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2025-07-29 14:58:23 +03:00
792e70c988
rustfmt ghost sudo and fix typos
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2025-07-29 14:57:58 +03:00
eb3b4f2651
rustfmt ghost rpc and fix typos
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2025-07-29 14:54:56 +03:00
24a6f803c5
rustfmt common runtime and fix typos
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2025-07-29 14:53:50 +03:00
8d69e5c87e
rustfmt casper runtime and fix typos
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2025-07-29 14:51:15 +03:00
48ff511685
rustfmt service and fix typos
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2025-07-29 14:49:16 +03:00
8f20b7ef5c
rustfmt tests and fix typos
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2025-07-29 14:45:41 +03:00
ce26787a11
rustfmt staking-miner and fix typos
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2025-07-29 14:38:49 +03:00
e21ac88235
rustfmt ghostkey and fix typos
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2025-07-29 14:27:53 +03:00
c933ed3809
rustfmt generate-bags and fix typos
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2025-07-29 14:27:08 +03:00
2ad43a56ba
rustfmt chain-spec-builder and fix typos
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2025-07-29 14:26:12 +03:00
6d06fcf9a0
rustfmt bags-utils and fix typos
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2025-07-29 14:24:30 +03:00
c2f9958c1a
prepare chain spec for the genesis
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2025-07-29 14:09:32 +03:00
84 changed files with 4263 additions and 3433 deletions

50
Cargo.lock generated
View File

@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 4
[[package]] [[package]]
name = "Inflector" name = "Inflector"
@ -1186,7 +1186,7 @@ dependencies = [
[[package]] [[package]]
name = "casper-runtime" name = "casper-runtime"
version = "3.5.25" version = "3.5.29"
dependencies = [ dependencies = [
"casper-runtime-constants", "casper-runtime-constants",
"frame-benchmarking", "frame-benchmarking",
@ -1203,6 +1203,7 @@ dependencies = [
"ghost-networks", "ghost-networks",
"ghost-runtime-common", "ghost-runtime-common",
"ghost-slow-clap", "ghost-slow-clap",
"ghost-sudo",
"log", "log",
"pallet-alliance", "pallet-alliance",
"pallet-authority-discovery", "pallet-authority-discovery",
@ -3528,7 +3529,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-cli" name = "ghost-cli"
version = "0.7.201" version = "0.8.0"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"clap 4.5.4", "clap 4.5.4",
@ -3560,7 +3561,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-client-cli" name = "ghost-client-cli"
version = "0.1.3" version = "0.1.4"
dependencies = [ dependencies = [
"array-bytes", "array-bytes",
"clap 4.5.4", "clap 4.5.4",
@ -3584,7 +3585,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-machine-primitives" name = "ghost-machine-primitives"
version = "0.7.201" version = "0.8.0"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"sc-sysinfo", "sc-sysinfo",
@ -3593,7 +3594,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-metrics" name = "ghost-metrics"
version = "0.7.201" version = "0.8.0"
dependencies = [ dependencies = [
"assert_cmd", "assert_cmd",
"bs58 0.5.1", "bs58 0.5.1",
@ -3616,7 +3617,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-miner" name = "ghost-miner"
version = "1.5.0" version = "1.5.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"assert_cmd", "assert_cmd",
@ -3648,7 +3649,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-networks" name = "ghost-networks"
version = "0.1.11" version = "0.1.13"
dependencies = [ dependencies = [
"frame-benchmarking", "frame-benchmarking",
"frame-support", "frame-support",
@ -3667,7 +3668,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-node" name = "ghost-node"
version = "0.7.201" version = "0.8.0"
dependencies = [ dependencies = [
"assert_cmd", "assert_cmd",
"color-eyre", "color-eyre",
@ -3683,7 +3684,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-remote-ext-tests-bags-list" name = "ghost-remote-ext-tests-bags-list"
version = "1.0.0" version = "1.0.1"
dependencies = [ dependencies = [
"casper-runtime", "casper-runtime",
"casper-runtime-constants", "casper-runtime-constants",
@ -3698,7 +3699,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-rpc" name = "ghost-rpc"
version = "0.7.201" version = "0.8.0"
dependencies = [ dependencies = [
"ghost-core-primitives", "ghost-core-primitives",
"jsonrpsee", "jsonrpsee",
@ -3727,7 +3728,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-runtime-common" name = "ghost-runtime-common"
version = "0.4.2" version = "0.4.3"
dependencies = [ dependencies = [
"frame-support", "frame-support",
"frame-system", "frame-system",
@ -3750,7 +3751,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-service" name = "ghost-service"
version = "0.7.201" version = "0.8.0"
dependencies = [ dependencies = [
"assert_matches", "assert_matches",
"async-trait", "async-trait",
@ -3834,7 +3835,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-slow-clap" name = "ghost-slow-clap"
version = "0.3.33" version = "0.3.35"
dependencies = [ dependencies = [
"frame-benchmarking", "frame-benchmarking",
"frame-support", "frame-support",
@ -3859,7 +3860,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-staging-chain-spec-builder" name = "ghost-staging-chain-spec-builder"
version = "1.6.1" version = "1.6.2"
dependencies = [ dependencies = [
"clap 4.5.4", "clap 4.5.4",
"log", "log",
@ -3868,6 +3869,21 @@ dependencies = [
"sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.12.0)", "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.12.0)",
] ]
[[package]]
name = "ghost-sudo"
version = "0.0.2"
dependencies = [
"docify",
"frame-benchmarking",
"frame-support",
"frame-system",
"parity-scale-codec",
"scale-info",
"sp-io 30.0.0",
"sp-runtime 31.0.1",
"sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.12.0)",
]
[[package]] [[package]]
name = "ghost-traits" name = "ghost-traits"
version = "0.3.23" version = "0.3.23"
@ -3878,7 +3894,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-voter-bags" name = "ghost-voter-bags"
version = "0.3.6" version = "0.3.7"
dependencies = [ dependencies = [
"casper-runtime", "casper-runtime",
"clap 4.5.4", "clap 4.5.4",
@ -3888,7 +3904,7 @@ dependencies = [
[[package]] [[package]]
name = "ghostkey" name = "ghostkey"
version = "0.3.15" version = "0.3.16"
dependencies = [ dependencies = [
"clap 4.5.4", "clap 4.5.4",
"ghost-client-cli", "ghost-client-cli",

View File

@ -17,7 +17,7 @@ homepage.workspace = true
[workspace.package] [workspace.package]
license = "GPL-3.0-only" license = "GPL-3.0-only"
authors = ["571nky", "57r37ch", "f4750"] authors = ["571nky", "57r37ch", "f4750"]
version = "0.7.204" version = "0.8.0"
edition = "2021" edition = "2021"
homepage = "https://ghostchain.io" homepage = "https://ghostchain.io"
repository = "https://git.ghostchain.io/ghostchain/ghost-node" repository = "https://git.ghostchain.io/ghostchain/ghost-node"

View File

@ -1,4 +1,4 @@
fn main () { fn main() {
if let Ok(profile) = std::env::var("PROFILE") { if let Ok(profile) = std::env::var("PROFILE") {
println!("cargo:rustc-cfg=build_type=\"{}\"", profile); println!("cargo:rustc-cfg=build_type=\"{}\"", profile);
} }

View File

@ -1,14 +1,13 @@
use crate::cli::{Cli, Subcommand}; use crate::cli::{Cli, Subcommand};
use frame_benchmarking_cli::{BenchmarkCmd, ExtrinsicFactory}; use frame_benchmarking_cli::{BenchmarkCmd, ExtrinsicFactory};
use futures::future::TryFutureExt; use futures::future::TryFutureExt;
use keyring::Sr25519Keyring;
use sc_cli::SubstrateCli; use sc_cli::SubstrateCli;
use service::{ use service::{
self, IdentifyVariant, self,
benchmarking::{ benchmarking::{benchmark_inherent_data, RemarkBuilder, TransferKeepAliveBuilder},
benchmark_inherent_data, RemarkBuilder, TransferKeepAliveBuilder IdentifyVariant,
},
}; };
use keyring::Sr25519Keyring;
pub use crate::{error::Error, service::BlockId}; pub use crate::{error::Error, service::BlockId};
#[cfg(feature = "pyroscope")] #[cfg(feature = "pyroscope")]
@ -68,28 +67,35 @@ impl SubstrateCli for Cli {
#[cfg(feature = "casper-native")] #[cfg(feature = "casper-native")]
"casper" => Box::new(service::chain_spec::casper_config()?), "casper" => Box::new(service::chain_spec::casper_config()?),
#[cfg(feature = "casper-native")] #[cfg(feature = "casper-native")]
"casper-dev" | "dev" | "development" => Box::new(service::chain_spec::casper_development_config()?), "casper-dev" | "dev" | "development" => {
Box::new(service::chain_spec::casper_development_config()?)
}
#[cfg(feature = "casper-native")] #[cfg(feature = "casper-native")]
"casper-local" | "local" => Box::new(service::chain_spec::casper_local_testnet_config()?), "casper-local" | "local" => {
Box::new(service::chain_spec::casper_local_testnet_config()?)
}
#[cfg(feature = "casper-native")] #[cfg(feature = "casper-native")]
"casper-staging" | "staging" => Box::new(service::chain_spec::casper_staging_testnet_config()?), "casper-staging" | "staging" => {
Box::new(service::chain_spec::casper_staging_testnet_config()?)
}
#[cfg(not(feature = "casper-native"))] #[cfg(not(feature = "casper-native"))]
name if name.starts_with("casper-") && !name.ends_with(".json") => name if name.starts_with("casper-") && !name.ends_with(".json") => Err(format!(
Err(format!("`{}` only supported with `casper-native` feature enabled.", name))?, "`{}` only supported with `casper-native` feature enabled.",
name
))?,
#[cfg(feature = "casper-native")] #[cfg(feature = "casper-native")]
path => { path => {
let path = std::path::PathBuf::from(path); let path = std::path::PathBuf::from(path);
let chain_spec = Box::new( let chain_spec = Box::new(service::GenericChainSpec::from_json_file(path.clone())?)
service::GenericChainSpec::from_json_file(path.clone())? as Box<dyn service::ChainSpec>;
) as Box<dyn service::ChainSpec>;
if chain_spec.is_casper() { if chain_spec.is_casper() {
Box::new(service::CasperChainSpec::from_json_file(path)?) Box::new(service::CasperChainSpec::from_json_file(path)?)
} else { } else {
chain_spec chain_spec
} }
}, }
}) })
} }
} }
@ -109,10 +115,7 @@ fn set_ss58_version(spec: &Box<dyn service::ChainSpec>) {
sp_core::crypto::set_default_ss58_version(ss58_version); sp_core::crypto::set_default_ss58_version(ss58_version);
} }
fn run_node_inner<F>( fn run_node_inner<F>(cli: Cli, logger_hook: F) -> Result<()>
cli: Cli,
logger_hook: F,
) -> Result<()>
where where
F: FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration), F: FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration),
{ {
@ -128,7 +131,8 @@ where
.then_some(config.database.path().map(|database_path| { .then_some(config.database.path().map(|database_path| {
let _ = std::fs::create_dir_all(&database_path); let _ = std::fs::create_dir_all(&database_path);
sc_sysinfo::gather_hwbench(Some(database_path)) sc_sysinfo::gather_hwbench(Some(database_path))
})).flatten(); }))
.flatten();
let database_source = config.database.clone(); let database_source = config.database.clone();
let task_manager = service::build_full( let task_manager = service::build_full(
@ -138,7 +142,8 @@ where
telemetry_worker_handle: None, telemetry_worker_handle: None,
hwbench, hwbench,
}, },
).map(|full| full.task_manager)?; )
.map(|full| full.task_manager)?;
if let Some(path) = database_source.path() { if let Some(path) = database_source.path() {
sc_storage_monitor::StorageMonitorService::try_spawn( sc_storage_monitor::StorageMonitorService::try_spawn(
@ -167,7 +172,9 @@ pub fn run() -> Result<()> {
let agent = pyro::Pyroscope::builder( let agent = pyro::Pyroscope::builder(
"http://".to_owned() + address.to_string().as_str(), "http://".to_owned() + address.to_string().as_str(),
"ghost".to_owned(), "ghost".to_owned(),
).backend(pprof_backend(PprofConfig::new().sample_rate(113))).build()?; )
.backend(pprof_backend(PprofConfig::new().sample_rate(113)))
.build()?;
Some(agent.start()?) Some(agent.start()?)
} else { } else {
@ -176,7 +183,7 @@ pub fn run() -> Result<()> {
#[cfg(not(feature = "pyroscope"))] #[cfg(not(feature = "pyroscope"))]
if cli.run.pyroscope_server.is_some() { if cli.run.pyroscope_server.is_some() {
return Err(Error::PyroscopeNotCompiledIn) return Err(Error::PyroscopeNotCompiledIn);
} }
match &cli.subcommand { match &cli.subcommand {
@ -184,7 +191,7 @@ pub fn run() -> Result<()> {
Some(Subcommand::BuildSpec(cmd)) => { Some(Subcommand::BuildSpec(cmd)) => {
let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?; let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?;
Ok(runner.sync_run(|config| cmd.run(config.chain_spec, config.network))?) Ok(runner.sync_run(|config| cmd.run(config.chain_spec, config.network))?)
}, }
Some(Subcommand::CheckBlock(cmd)) => { Some(Subcommand::CheckBlock(cmd)) => {
let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?; let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?;
let chain_spec = &runner.config().chain_spec; let chain_spec = &runner.config().chain_spec;
@ -192,11 +199,13 @@ pub fn run() -> Result<()> {
set_ss58_version(chain_spec); set_ss58_version(chain_spec);
runner.async_run(|mut config| { runner.async_run(|mut config| {
let (client, _, import_queue, task_manager) = let (client, _, import_queue, task_manager) = service::new_chain_ops(&mut config)?;
service::new_chain_ops(&mut config)?; Ok((
Ok((cmd.run(client, import_queue).map_err(Error::SubstrateCli), task_manager)) cmd.run(client, import_queue).map_err(Error::SubstrateCli),
task_manager,
))
}) })
}, }
Some(Subcommand::ExportBlocks(cmd)) => { Some(Subcommand::ExportBlocks(cmd)) => {
let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?; let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?;
let chain_spec = &runner.config().chain_spec; let chain_spec = &runner.config().chain_spec;
@ -204,11 +213,14 @@ pub fn run() -> Result<()> {
set_ss58_version(chain_spec); set_ss58_version(chain_spec);
Ok(runner.async_run(|mut config| { Ok(runner.async_run(|mut config| {
let ( client, _, _, task_manager ) = let (client, _, _, task_manager) = service::new_chain_ops(&mut config)?;
service::new_chain_ops(&mut config)?; Ok((
Ok((cmd.run(client, config.database).map_err(Error::SubstrateCli), task_manager)) cmd.run(client, config.database)
.map_err(Error::SubstrateCli),
task_manager,
))
})?) })?)
}, }
Some(Subcommand::ExportState(cmd)) => { Some(Subcommand::ExportState(cmd)) => {
let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?; let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?;
let chain_spec = &runner.config().chain_spec; let chain_spec = &runner.config().chain_spec;
@ -216,11 +228,14 @@ pub fn run() -> Result<()> {
set_ss58_version(chain_spec); set_ss58_version(chain_spec);
Ok(runner.async_run(|mut config| { Ok(runner.async_run(|mut config| {
let ( client, _, _, task_manager ) = let (client, _, _, task_manager) = service::new_chain_ops(&mut config)?;
service::new_chain_ops(&mut config)?; Ok((
Ok((cmd.run(client, config.chain_spec).map_err(Error::SubstrateCli), task_manager)) cmd.run(client, config.chain_spec)
.map_err(Error::SubstrateCli),
task_manager,
))
})?) })?)
}, }
Some(Subcommand::ImportBlocks(cmd)) => { Some(Subcommand::ImportBlocks(cmd)) => {
let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?; let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?;
let chain_spec = &runner.config().chain_spec; let chain_spec = &runner.config().chain_spec;
@ -228,15 +243,17 @@ pub fn run() -> Result<()> {
set_ss58_version(chain_spec); set_ss58_version(chain_spec);
Ok(runner.async_run(|mut config| { Ok(runner.async_run(|mut config| {
let ( client, _, import_queue, task_manager ) = let (client, _, import_queue, task_manager) = service::new_chain_ops(&mut config)?;
service::new_chain_ops(&mut config)?; Ok((
Ok((cmd.run(client, import_queue).map_err(Error::SubstrateCli), task_manager)) cmd.run(client, import_queue).map_err(Error::SubstrateCli),
task_manager,
))
})?) })?)
}, }
Some(Subcommand::PurgeChain(cmd)) => { Some(Subcommand::PurgeChain(cmd)) => {
let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?; let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?;
Ok(runner.sync_run(|config| cmd.run(config.database))?) Ok(runner.sync_run(|config| cmd.run(config.database))?)
}, }
Some(Subcommand::Revert(cmd)) => { Some(Subcommand::Revert(cmd)) => {
let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?; let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?;
let chain_spec = &runner.config().chain_spec; let chain_spec = &runner.config().chain_spec;
@ -244,62 +261,59 @@ pub fn run() -> Result<()> {
set_ss58_version(chain_spec); set_ss58_version(chain_spec);
Ok(runner.async_run(|mut config| { Ok(runner.async_run(|mut config| {
let (client, backend, _, task_manager) = let (client, backend, _, task_manager) = service::new_chain_ops(&mut config)?;
service::new_chain_ops(&mut config)?;
let aux_revert = Box::new(|client, backend, blocks| { let aux_revert = Box::new(|client, backend, blocks| {
service::revert_backend(client, backend, blocks).map_err(|err| { service::revert_backend(client, backend, blocks).map_err(|err| match err {
match err { service::Error::Blockchain(err) => err.into(),
service::Error::Blockchain(err) => err.into(), err => sc_cli::Error::Application(err.into()),
err => sc_cli::Error::Application(err.into()),
}
}) })
}); });
Ok(( Ok((
cmd.run(client, backend, Some(aux_revert)).map_err(Error::SubstrateCli), cmd.run(client, backend, Some(aux_revert))
task_manager .map_err(Error::SubstrateCli),
task_manager,
)) ))
})?) })?)
}, }
Some(Subcommand::Benchmark(cmd)) => { Some(Subcommand::Benchmark(cmd)) => {
let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?; let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?;
let chain_spec = &runner.config().chain_spec; let chain_spec = &runner.config().chain_spec;
match cmd { match cmd {
#[cfg(not(feature = "runtime-benchmarks"))] #[cfg(not(feature = "runtime-benchmarks"))]
BenchmarkCmd::Storage(_) => BenchmarkCmd::Storage(_) => {
return Err(sc_cli::Error::Input( return Err(sc_cli::Error::Input(
"Compile with `--feature=runtime-benchmarks \ "Compile with `--feature=runtime-benchmarks \
to enable storage benchmarks.".into() to enable storage benchmarks."
).into()), .into(),
)
.into())
}
#[cfg(feature = "runtime-benchmarks")] #[cfg(feature = "runtime-benchmarks")]
BenchmarkCmd::Storage(cmd) => runner.sync_run(|mut config| { BenchmarkCmd::Storage(cmd) => runner.sync_run(|mut config| {
let (client, backend, _, _,) = let (client, backend, _, _) = service::new_chain_ops(&mut config)?;
service::new_chain_ops(&mut config)?;
let db = backend.expose_db(); let db = backend.expose_db();
let storage = backend.expose_storage(); let storage = backend.expose_storage();
cmd.run(config, client.clone(), db, storage).map_err(Error::SubstrateCli) cmd.run(config, client.clone(), db, storage)
.map_err(Error::SubstrateCli)
}), }),
BenchmarkCmd::Block(cmd) => runner.sync_run(|mut config| { BenchmarkCmd::Block(cmd) => runner.sync_run(|mut config| {
let (client, _, _, _,) = let (client, _, _, _) = service::new_chain_ops(&mut config)?;
service::new_chain_ops(&mut config)?;
cmd.run(client.clone()).map_err(Error::SubstrateCli) cmd.run(client.clone()).map_err(Error::SubstrateCli)
}), }),
// These commands are very similar and can be handled in nearly the same way // These commands are very similar and can be handled in nearly the same way
BenchmarkCmd::Extrinsic(_) | BenchmarkCmd::Overhead(_) => BenchmarkCmd::Extrinsic(_) | BenchmarkCmd::Overhead(_) => {
runner.sync_run(|mut config| { runner.sync_run(|mut config| {
let (client, _, _, _) = let (client, _, _, _) = service::new_chain_ops(&mut config)?;
service::new_chain_ops(&mut config)?;
let inherent_data = benchmark_inherent_data() let inherent_data = benchmark_inherent_data()
.map_err(|e| format!("generating inherent data: {:?}", e))?; .map_err(|e| format!("generating inherent data: {:?}", e))?;
let remark_builder = RemarkBuilder::new( let remark_builder =
client.clone(), RemarkBuilder::new(client.clone(), config.chain_spec.identify_chain());
config.chain_spec.identify_chain(),
);
match cmd { match cmd {
BenchmarkCmd::Extrinsic(cmd) => { BenchmarkCmd::Extrinsic(cmd) => {
@ -316,17 +330,20 @@ pub fn run() -> Result<()> {
cmd.run(client.clone(), inherent_data, Vec::new(), &ext_factory) cmd.run(client.clone(), inherent_data, Vec::new(), &ext_factory)
.map_err(Error::SubstrateCli) .map_err(Error::SubstrateCli)
}, }
BenchmarkCmd::Overhead(cmd) => cmd.run( BenchmarkCmd::Overhead(cmd) => cmd
config, .run(
client.clone(), config,
inherent_data, client.clone(),
Vec::new(), inherent_data,
&remark_builder, Vec::new(),
).map_err(Error::SubstrateCli), &remark_builder,
)
.map_err(Error::SubstrateCli),
_ => unreachable!("Ensured by the outside match; qed"), _ => unreachable!("Ensured by the outside match; qed"),
} }
}), })
}
BenchmarkCmd::Pallet(cmd) => { BenchmarkCmd::Pallet(cmd) => {
set_ss58_version(chain_spec); set_ss58_version(chain_spec);
@ -334,30 +351,36 @@ pub fn run() -> Result<()> {
runner.sync_run(|config| { runner.sync_run(|config| {
cmd.run_with_spec::<sp_runtime::traits::HashingFor<service::Block>, ()>( cmd.run_with_spec::<sp_runtime::traits::HashingFor<service::Block>, ()>(
Some(config.chain_spec), Some(config.chain_spec),
).map_err(|e| Error::SubstrateCli(e)) )
.map_err(|e| Error::SubstrateCli(e))
}) })
} else { } else {
Err(sc_cli::Error::Input( Err(sc_cli::Error::Input(
"Benchmarking wasn't enabled when building the node. \ "Benchmarking wasn't enabled when building the node. \
You can enable it with `--features=runtime-benchmarks`.".into() You can enable it with `--features=runtime-benchmarks`."
).into()) .into(),
)
.into())
} }
}, }
BenchmarkCmd::Machine(cmd) => runner.sync_run(|config| { BenchmarkCmd::Machine(cmd) => runner.sync_run(|config| {
cmd.run(&config, ghost_machine_primitives::GHOST_NODE_REFERENCE_HARDWARE.clone()) cmd.run(
.map_err(Error::SubstrateCli) &config,
ghost_machine_primitives::GHOST_NODE_REFERENCE_HARDWARE.clone(),
)
.map_err(Error::SubstrateCli)
}), }),
// Note: this allows to implement additional new benchmark // Note: this allows to implement additional new benchmark
// commands. // commands.
#[allow(unreachable_patterns)] #[allow(unreachable_patterns)]
_ => Err(Error::CommandNotImplemented), _ => Err(Error::CommandNotImplemented),
} }
}, }
Some(Subcommand::Key(cmd)) => Ok(cmd.run(&cli)?), Some(Subcommand::Key(cmd)) => Ok(cmd.run(&cli)?),
Some(Subcommand::ChainInfo(cmd)) => { Some(Subcommand::ChainInfo(cmd)) => {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
Ok(runner.sync_run(|config| cmd.run::<service::Block>(&config))?) Ok(runner.sync_run(|config| cmd.run::<service::Block>(&config))?)
}, }
}?; }?;
#[cfg(feature = "pyroscope")] #[cfg(feature = "pyroscope")]

View File

@ -6,9 +6,7 @@ mod command;
mod error; mod error;
#[cfg(feature = "service")] #[cfg(feature = "service")]
pub use service::{ pub use service::{self, Block, CoreApi, IdentifyVariant, ProvideRuntimeApi, TFullClient};
self, Block, CoreApi, IdentifyVariant, ProvideRuntimeApi, TFullClient,
};
#[cfg(feature = "cli")] #[cfg(feature = "cli")]
pub use cli::*; pub use cli::*;

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-client-cli" name = "ghost-client-cli"
version = "0.1.3" version = "0.1.4"
description = "Ghost CLI interface" description = "Ghost CLI interface"
license.workspace = true license.workspace = true
authors.workspace = true authors.workspace = true

View File

@ -3,13 +3,10 @@
use bip39::Mnemonic; use bip39::Mnemonic;
use clap::Parser; use clap::Parser;
use itertools::Itertools; use itertools::Itertools;
use sc_cli::{ use sc_cli::{with_crypto_scheme, CryptoSchemeFlag, Error, KeystoreParams, OutputTypeFlag};
with_crypto_scheme, KeystoreParams, OutputTypeFlag,
CryptoSchemeFlag, Error,
};
use crate::params::NetworkSchemeFlag;
use crate::commands::utils::print_from_uri; use crate::commands::utils::print_from_uri;
use crate::params::NetworkSchemeFlag;
/// The `generate` command /// The `generate` command
#[derive(Debug, Clone, Parser)] #[derive(Debug, Clone, Parser)]
@ -17,58 +14,58 @@ use crate::commands::utils::print_from_uri;
pub struct GenerateCmd { pub struct GenerateCmd {
/// The number of words in the phrase to generate. One of 12 (default), /// The number of words in the phrase to generate. One of 12 (default),
/// 15, 18, 21 and 24. /// 15, 18, 21 and 24.
#[arg(short = 'w', long, value_name = "WORDS")] #[arg(short = 'w', long, value_name = "WORDS")]
words: Option<usize>, words: Option<usize>,
#[allow(missing_docs)] #[allow(missing_docs)]
#[clap(flatten)] #[clap(flatten)]
pub keystore_params: KeystoreParams, pub keystore_params: KeystoreParams,
#[allow(missing_docs)] #[allow(missing_docs)]
#[clap(flatten)] #[clap(flatten)]
pub network_scheme: NetworkSchemeFlag, pub network_scheme: NetworkSchemeFlag,
#[allow(missing_docs)] #[allow(missing_docs)]
#[clap(flatten)] #[clap(flatten)]
pub output_scheme: OutputTypeFlag, pub output_scheme: OutputTypeFlag,
#[allow(missing_docs)] #[allow(missing_docs)]
#[clap(flatten)] #[clap(flatten)]
pub crypto_scheme: CryptoSchemeFlag, pub crypto_scheme: CryptoSchemeFlag,
} }
impl GenerateCmd { impl GenerateCmd {
/// Run the command /// Run the command
pub fn run(&self) -> Result<(), Error> { pub fn run(&self) -> Result<(), Error> {
let words = match self.words { let words = match self.words {
Some(words_count) if [12, 15, 18, 21, 24].contains(&words_count) => Ok(words_count), Some(words_count) if [12, 15, 18, 21, 24].contains(&words_count) => Ok(words_count),
Some(_) => Err(Error::Input( Some(_) => Err(Error::Input(
"Invalid number of words given for phrase: must be 12/15/18/21/24".into(), "Invalid number of words given for phrase: must be 12/15/18/21/24".into(),
)), )),
None => Ok(12), None => Ok(12),
}?; }?;
let mnemonic = Mnemonic::generate(words) let mnemonic = Mnemonic::generate(words)
.map_err(|e| Error::Input(format!("Mnemonic generation failed: {e}").into()))?; .map_err(|e| Error::Input(format!("Mnemonic generation failed: {e}").into()))?;
let password = self.keystore_params.read_password()?; let password = self.keystore_params.read_password()?;
let output = self.output_scheme.output_type; let output = self.output_scheme.output_type;
let phrase = mnemonic.words().join(" "); let phrase = mnemonic.words().join(" ");
with_crypto_scheme!( with_crypto_scheme!(
self.crypto_scheme.scheme, self.crypto_scheme.scheme,
print_from_uri(&phrase, password, self.network_scheme.network, output) print_from_uri(&phrase, password, self.network_scheme.network, output)
); );
Ok(()) Ok(())
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
#[test] #[test]
fn generate() { fn generate() {
let generate = GenerateCmd::parse_from(&["generate", "--password", "12345"]); let generate = GenerateCmd::parse_from(&["generate", "--password", "12345"]);
assert!(generate.run().is_ok()) assert!(generate.run().is_ok())
} }
} }

View File

@ -1,102 +1,101 @@
//! Implementation of the `inspect` subcommand //! Implementation of the `inspect` subcommand
use crate::commands::utils::{print_from_public, print_from_uri};
use crate::params::NetworkSchemeFlag;
use clap::Parser; use clap::Parser;
use sc_cli::{
utils::read_uri, with_crypto_scheme, CryptoSchemeFlag, Error, KeystoreParams, OutputTypeFlag,
};
use sp_core::crypto::{ExposeSecret, SecretString, SecretUri, Ss58Codec}; use sp_core::crypto::{ExposeSecret, SecretString, SecretUri, Ss58Codec};
use std::str::FromStr; use std::str::FromStr;
use sc_cli::{
with_crypto_scheme, KeystoreParams, OutputTypeFlag, CryptoSchemeFlag, Error,
utils::read_uri,
};
use crate::params::NetworkSchemeFlag;
use crate::commands::utils::{print_from_public, print_from_uri};
/// The `inspect` command /// The `inspect` command
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
#[command( #[command(
name = "inspect", name = "inspect",
about = "Gets a public key and a SS58 address from the provided Secret URI" about = "Gets a public key and a SS58 address from the provided Secret URI"
)] )]
pub struct InspectKeyCmd { pub struct InspectKeyCmd {
/// A Key URI to be inspected. May be a secret seed, secret URI /// A Key URI to be inspected. May be a secret seed, secret URI
/// (with derivation paths and password), SS58, public URI or a hex encoded public key. /// (with derivation paths and password), SS58, public URI or a hex encoded public key.
/// ///
/// If it is a hex encoded public key, `--public` needs to be given as argument. /// If it is a hex encoded public key, `--public` needs to be given as argument.
/// ///
/// If the given value is a file, the file content will be used /// If the given value is a file, the file content will be used
/// as URI. /// as URI.
/// ///
/// If omitted, you will be prompted for the URI. /// If omitted, you will be prompted for the URI.
uri: Option<String>, uri: Option<String>,
/// Is the given `uri` a hex encoded public key? /// Is the given `uri` a hex encoded public key?
#[arg(long)] #[arg(long)]
public: bool, public: bool,
#[allow(missing_docs)] #[allow(missing_docs)]
#[clap(flatten)] #[clap(flatten)]
pub keystore_params: KeystoreParams, pub keystore_params: KeystoreParams,
#[allow(missing_docs)] #[allow(missing_docs)]
#[clap(flatten)] #[clap(flatten)]
pub network_scheme: NetworkSchemeFlag, pub network_scheme: NetworkSchemeFlag,
#[allow(missing_docs)] #[allow(missing_docs)]
#[clap(flatten)] #[clap(flatten)]
pub output_scheme: OutputTypeFlag, pub output_scheme: OutputTypeFlag,
#[allow(missing_docs)] #[allow(missing_docs)]
#[clap(flatten)] #[clap(flatten)]
pub crypto_scheme: CryptoSchemeFlag, pub crypto_scheme: CryptoSchemeFlag,
/// Expect that `--uri` has the given public key/account-id. /// Expect that `--uri` has the given public key/account-id.
/// ///
/// If `--uri` has any derivations, the public key is checked against the base `uri`, i.e. the /// If `--uri` has any derivations, the public key is checked against the base `uri`, i.e. the
/// `uri` without any derivation applied. However, if `uri` has a password or there is one /// `uri` without any derivation applied. However, if `uri` has a password or there is one
/// given by `--password`, it will be used to decrypt `uri` before comparing the public /// given by `--password`, it will be used to decrypt `uri` before comparing the public
/// key/account-id. /// key/account-id.
/// ///
/// If there is no derivation in `--uri`, the public key will be checked against the public key /// If there is no derivation in `--uri`, the public key will be checked against the public key
/// of `--uri` directly. /// of `--uri` directly.
#[arg(long, conflicts_with = "public")] #[arg(long, conflicts_with = "public")]
pub expect_public: Option<String>, pub expect_public: Option<String>,
} }
impl InspectKeyCmd { impl InspectKeyCmd {
/// Run the command /// Run the command
pub fn run(&self) -> Result<(), Error> { pub fn run(&self) -> Result<(), Error> {
let uri = read_uri(self.uri.as_ref())?; let uri = read_uri(self.uri.as_ref())?;
let password = self.keystore_params.read_password()?; let password = self.keystore_params.read_password()?;
if self.public { if self.public {
with_crypto_scheme!( with_crypto_scheme!(
self.crypto_scheme.scheme, self.crypto_scheme.scheme,
print_from_public( print_from_public(
&uri, &uri,
self.network_scheme.network, self.network_scheme.network,
self.output_scheme.output_type, self.output_scheme.output_type,
) )
)?; )?;
} else { } else {
if let Some(ref expect_public) = self.expect_public { if let Some(ref expect_public) = self.expect_public {
with_crypto_scheme!( with_crypto_scheme!(
self.crypto_scheme.scheme, self.crypto_scheme.scheme,
expect_public_from_phrase(expect_public, &uri, password.as_ref()) expect_public_from_phrase(expect_public, &uri, password.as_ref())
)?; )?;
} }
with_crypto_scheme!( with_crypto_scheme!(
self.crypto_scheme.scheme, self.crypto_scheme.scheme,
print_from_uri( print_from_uri(
&uri, &uri,
password, password,
self.network_scheme.network, self.network_scheme.network,
self.output_scheme.output_type, self.output_scheme.output_type,
) )
); );
} }
Ok(()) Ok(())
} }
} }
/// Checks that `expect_public` is the public key of `suri`. /// Checks that `expect_public` is the public key of `suri`.
@ -106,148 +105,156 @@ impl InspectKeyCmd {
/// ///
/// Returns an error if the public key does not match. /// Returns an error if the public key does not match.
fn expect_public_from_phrase<Pair: sp_core::Pair>( fn expect_public_from_phrase<Pair: sp_core::Pair>(
expect_public: &str, expect_public: &str,
suri: &str, suri: &str,
password: Option<&SecretString>, password: Option<&SecretString>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let secret_uri = SecretUri::from_str(suri).map_err(|e| format!("{:?}", e))?; let secret_uri = SecretUri::from_str(suri).map_err(|e| format!("{:?}", e))?;
let expected_public = if let Some(public) = expect_public.strip_prefix("0x") { let expected_public = if let Some(public) = expect_public.strip_prefix("0x") {
let hex_public = array_bytes::hex2bytes(public) let hex_public = array_bytes::hex2bytes(public)
.map_err(|_| format!("Invalid expected public key hex: `{}`", expect_public))?; .map_err(|_| format!("Invalid expected public key hex: `{}`", expect_public))?;
Pair::Public::try_from(&hex_public) Pair::Public::try_from(&hex_public)
.map_err(|_| format!("Invalid expected public key: `{}`", expect_public))? .map_err(|_| format!("Invalid expected public key: `{}`", expect_public))?
} else { } else {
Pair::Public::from_string_with_version(expect_public) Pair::Public::from_string_with_version(expect_public)
.map_err(|_| format!("Invalid expected account id: `{}`", expect_public))? .map_err(|_| format!("Invalid expected account id: `{}`", expect_public))?
.0 .0
}; };
let pair = Pair::from_string_with_seed( let pair = Pair::from_string_with_seed(
secret_uri.phrase.expose_secret().as_str(), secret_uri.phrase.expose_secret().as_str(),
password password
.or_else(|| secret_uri.password.as_ref()) .or_else(|| secret_uri.password.as_ref())
.map(|p| p.expose_secret().as_str()), .map(|p| p.expose_secret().as_str()),
) )
.map_err(|_| format!("Invalid secret uri: {}", suri))? .map_err(|_| format!("Invalid secret uri: {}", suri))?
.0; .0;
if pair.public() == expected_public { if pair.public() == expected_public {
Ok(()) Ok(())
} else { } else {
Err(format!("Expected public ({}) key does not match.", expect_public).into()) Err(format!("Expected public ({}) key does not match.", expect_public).into())
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use sp_core::crypto::{ByteArray, Pair}; use sp_core::crypto::{ByteArray, Pair};
use sp_runtime::traits::IdentifyAccount; use sp_runtime::traits::IdentifyAccount;
#[test] #[test]
fn inspect() { fn inspect() {
let words = let words =
"remember fiber forum demise paper uniform squirrel feel access exclude casual effort"; "remember fiber forum demise paper uniform squirrel feel access exclude casual effort";
let seed = "0xad1fb77243b536b90cfe5f0d351ab1b1ac40e3890b41dc64f766ee56340cfca5"; let seed = "0xad1fb77243b536b90cfe5f0d351ab1b1ac40e3890b41dc64f766ee56340cfca5";
let inspect = InspectKeyCmd::parse_from(&["inspect-key", words, "--password", "12345"]); let inspect = InspectKeyCmd::parse_from(&["inspect-key", words, "--password", "12345"]);
assert!(inspect.run().is_ok()); assert!(inspect.run().is_ok());
let inspect = InspectKeyCmd::parse_from(&["inspect-key", seed]); let inspect = InspectKeyCmd::parse_from(&["inspect-key", seed]);
assert!(inspect.run().is_ok()); assert!(inspect.run().is_ok());
} }
#[test] #[test]
fn inspect_public_key() { fn inspect_public_key() {
let public = "0x12e76e0ae8ce41b6516cce52b3f23a08dcb4cfeed53c6ee8f5eb9f7367341069"; let public = "0x12e76e0ae8ce41b6516cce52b3f23a08dcb4cfeed53c6ee8f5eb9f7367341069";
let inspect = InspectKeyCmd::parse_from(&["inspect-key", "--public", public]); let inspect = InspectKeyCmd::parse_from(&["inspect-key", "--public", public]);
assert!(inspect.run().is_ok()); assert!(inspect.run().is_ok());
} }
#[test] #[test]
fn inspect_with_expected_public_key() { fn inspect_with_expected_public_key() {
let check_cmd = |seed, expected_public, success| { let check_cmd = |seed, expected_public, success| {
let inspect = InspectKeyCmd::parse_from(&[ let inspect = InspectKeyCmd::parse_from(&[
"inspect-key", "inspect-key",
"--expect-public", "--expect-public",
expected_public, expected_public,
seed, seed,
]); ]);
let res = inspect.run(); let res = inspect.run();
if success { if success {
assert!(res.is_ok()); assert!(res.is_ok());
} else { } else {
assert!(res.unwrap_err().to_string().contains(&format!( assert!(res.unwrap_err().to_string().contains(&format!(
"Expected public ({}) key does not match.", "Expected public ({}) key does not match.",
expected_public expected_public
))); )));
} }
}; };
let seed = let seed =
"remember fiber forum demise paper uniform squirrel feel access exclude casual effort"; "remember fiber forum demise paper uniform squirrel feel access exclude casual effort";
let invalid_public = "0x12e76e0ae8ce41b6516cce52b3f23a08dcb4cfeed53c6ee8f5eb9f7367341069"; let invalid_public = "0x12e76e0ae8ce41b6516cce52b3f23a08dcb4cfeed53c6ee8f5eb9f7367341069";
let valid_public = sp_core::sr25519::Pair::from_string_with_seed(seed, None) let valid_public = sp_core::sr25519::Pair::from_string_with_seed(seed, None)
.expect("Valid") .expect("Valid")
.0 .0
.public(); .public();
let valid_public_hex = array_bytes::bytes2hex("0x", valid_public.as_slice()); let valid_public_hex = array_bytes::bytes2hex("0x", valid_public.as_slice());
let valid_accountid = format!("{}", valid_public.into_account()); let valid_accountid = format!("{}", valid_public.into_account());
// It should fail with the invalid public key // It should fail with the invalid public key
check_cmd(seed, invalid_public, false); check_cmd(seed, invalid_public, false);
// It should work with the valid public key & account id // It should work with the valid public key & account id
check_cmd(seed, &valid_public_hex, true); check_cmd(seed, &valid_public_hex, true);
check_cmd(seed, &valid_accountid, true); check_cmd(seed, &valid_accountid, true);
let password = "test12245"; let password = "test12245";
let seed_with_password = format!("{}///{}", seed, password); let seed_with_password = format!("{}///{}", seed, password);
let valid_public_with_password = let valid_public_with_password =
sp_core::sr25519::Pair::from_string_with_seed(&seed_with_password, Some(password)) sp_core::sr25519::Pair::from_string_with_seed(&seed_with_password, Some(password))
.expect("Valid") .expect("Valid")
.0 .0
.public(); .public();
let valid_public_hex_with_password = let valid_public_hex_with_password =
array_bytes::bytes2hex("0x", valid_public_with_password.as_slice()); array_bytes::bytes2hex("0x", valid_public_with_password.as_slice());
let valid_accountid_with_password = let valid_accountid_with_password =
format!("{}", &valid_public_with_password.into_account()); format!("{}", &valid_public_with_password.into_account());
// Only the public key that corresponds to the seed with password should be accepted. // Only the public key that corresponds to the seed with password should be accepted.
check_cmd(&seed_with_password, &valid_public_hex, false); check_cmd(&seed_with_password, &valid_public_hex, false);
check_cmd(&seed_with_password, &valid_accountid, false); check_cmd(&seed_with_password, &valid_accountid, false);
check_cmd(&seed_with_password, &valid_public_hex_with_password, true); check_cmd(&seed_with_password, &valid_public_hex_with_password, true);
check_cmd(&seed_with_password, &valid_accountid_with_password, true); check_cmd(&seed_with_password, &valid_accountid_with_password, true);
let seed_with_password_and_derivation = format!("{}//test//account///{}", seed, password); let seed_with_password_and_derivation = format!("{}//test//account///{}", seed, password);
let valid_public_with_password_and_derivation = let valid_public_with_password_and_derivation =
sp_core::sr25519::Pair::from_string_with_seed( sp_core::sr25519::Pair::from_string_with_seed(
&seed_with_password_and_derivation, &seed_with_password_and_derivation,
Some(password), Some(password),
) )
.expect("Valid") .expect("Valid")
.0 .0
.public(); .public();
let valid_public_hex_with_password_and_derivation = let valid_public_hex_with_password_and_derivation =
array_bytes::bytes2hex("0x", valid_public_with_password_and_derivation.as_slice()); array_bytes::bytes2hex("0x", valid_public_with_password_and_derivation.as_slice());
// They should still be valid, because we check the base secret key. // They should still be valid, because we check the base secret key.
check_cmd(&seed_with_password_and_derivation, &valid_public_hex_with_password, true); check_cmd(
check_cmd(&seed_with_password_and_derivation, &valid_accountid_with_password, true); &seed_with_password_and_derivation,
&valid_public_hex_with_password,
true,
);
check_cmd(
&seed_with_password_and_derivation,
&valid_accountid_with_password,
true,
);
// And these should be invalid. // And these should be invalid.
check_cmd(&seed_with_password_and_derivation, &valid_public_hex, false); check_cmd(&seed_with_password_and_derivation, &valid_public_hex, false);
check_cmd(&seed_with_password_and_derivation, &valid_accountid, false); check_cmd(&seed_with_password_and_derivation, &valid_accountid, false);
// The public of the derived account should fail. // The public of the derived account should fail.
check_cmd( check_cmd(
&seed_with_password_and_derivation, &seed_with_password_and_derivation,
&valid_public_hex_with_password_and_derivation, &valid_public_hex_with_password_and_derivation,
false, false,
); );
} }
} }

View File

@ -1,40 +1,37 @@
//! Key related CLI utilities //! Key related CLI utilities
use super::{generate::GenerateCmd, inspect_key::InspectKeyCmd}; use super::{generate::GenerateCmd, inspect_key::InspectKeyCmd};
use sc_cli::{ use sc_cli::{Error, GenerateKeyCmdCommon, InsertKeyCmd, InspectNodeKeyCmd, SubstrateCli};
GenerateKeyCmdCommon, InsertKeyCmd, InspectNodeKeyCmd, Error,
SubstrateCli,
};
/// Key utilities for the cli. /// Key utilities for the cli.
#[derive(Debug, clap::Subcommand)] #[derive(Debug, clap::Subcommand)]
pub enum KeySubcommand { pub enum KeySubcommand {
/// Generate a random node key, write it to a file or stdout and write the /// Generate a random node key, write it to a file or stdout and write the
/// corresponding peer-id to stderr /// corresponding peer-id to stderr
GenerateNodeKey(GenerateKeyCmdCommon), GenerateNodeKey(GenerateKeyCmdCommon),
/// Generate a Substrate-based random account /// Generate a Substrate-based random account
Generate(GenerateCmd), Generate(GenerateCmd),
/// Gets a public key and a SS58 address from the provided Secret URI /// Gets a public key and a SS58 address from the provided Secret URI
Inspect(InspectKeyCmd), Inspect(InspectKeyCmd),
/// Load a node key from a file or stdin and print the corresponding peer-id /// Load a node key from a file or stdin and print the corresponding peer-id
InspectNodeKey(InspectNodeKeyCmd), InspectNodeKey(InspectNodeKeyCmd),
/// Insert a key to the keystore of a node. /// Insert a key to the keystore of a node.
Insert(InsertKeyCmd), Insert(InsertKeyCmd),
} }
impl KeySubcommand { impl KeySubcommand {
/// run the key subcommands /// run the key subcommands
pub fn run<C: SubstrateCli>(&self, cli: &C) -> Result<(), Error> { pub fn run<C: SubstrateCli>(&self, cli: &C) -> Result<(), Error> {
match self { match self {
KeySubcommand::GenerateNodeKey(cmd) => cmd.run(), KeySubcommand::GenerateNodeKey(cmd) => cmd.run(),
KeySubcommand::Generate(cmd) => cmd.run(), KeySubcommand::Generate(cmd) => cmd.run(),
KeySubcommand::Inspect(cmd) => cmd.run(), KeySubcommand::Inspect(cmd) => cmd.run(),
KeySubcommand::Insert(cmd) => cmd.run(cli), KeySubcommand::Insert(cmd) => cmd.run(cli),
KeySubcommand::InspectNodeKey(cmd) => cmd.run(), KeySubcommand::InspectNodeKey(cmd) => cmd.run(),
} }
} }
} }

View File

@ -1,11 +1,13 @@
mod key;
mod generate; mod generate;
mod vanity;
mod inspect_key; mod inspect_key;
mod key;
mod utils; mod utils;
mod vanity;
pub use self::{ pub use self::{
key::KeySubcommand, vanity::VanityCmd, inspect_key::InspectKeyCmd,
generate::GenerateCmd, generate::GenerateCmd,
utils::{unwrap_or_default_ss58_name, print_from_uri, print_from_public}, inspect_key::InspectKeyCmd,
key::KeySubcommand,
utils::{print_from_public, print_from_uri, unwrap_or_default_ss58_name},
vanity::VanityCmd,
}; };

View File

@ -1,194 +1,206 @@
use serde_json::json;
use sc_cli::{ use sc_cli::{
OutputType,
utils::{PublicFor, SeedFor}, utils::{PublicFor, SeedFor},
OutputType,
}; };
use sp_runtime::{traits::IdentifyAccount, MultiSigner}; use serde_json::json;
use sp_core::{ use sp_core::{
crypto::{ crypto::{
unwrap_or_default_ss58_version, unwrap_or_default_ss58_version, ExposeSecret, SecretString, Ss58AddressFormat, Ss58Codec,
Ss58Codec, ExposeSecret, Ss58AddressFormat, SecretString,
}, },
hexdisplay::HexDisplay, hexdisplay::HexDisplay,
}; };
use sp_runtime::{traits::IdentifyAccount, MultiSigner};
pub fn print_from_uri<Pair>( pub fn print_from_uri<Pair>(
uri: &str, uri: &str,
password: Option<SecretString>, password: Option<SecretString>,
network_override: Option<Ss58AddressFormat>, network_override: Option<Ss58AddressFormat>,
output: OutputType, output: OutputType,
) where ) where
Pair: sp_core::Pair, Pair: sp_core::Pair,
Pair::Public: Into<MultiSigner>, Pair::Public: Into<MultiSigner>,
{ {
let password = password.as_ref().map(|s| s.expose_secret().as_str()); let password = password.as_ref().map(|s| s.expose_secret().as_str());
let network_id = unwrap_or_default_ss58_name(network_override); let network_id = unwrap_or_default_ss58_name(network_override);
if let Ok((pair, seed)) = Pair::from_phrase(uri, password) { if let Ok((pair, seed)) = Pair::from_phrase(uri, password) {
let public_key = pair.public(); let public_key = pair.public();
let network_override = unwrap_or_default_ss58_version(network_override); let network_override = unwrap_or_default_ss58_version(network_override);
match output { match output {
OutputType::Json => { OutputType::Json => {
let json = json!({ let json = json!({
"secretPhrase": uri, "secretPhrase": uri,
"networkId": network_id, "networkId": network_id,
"secretSeed": format_seed::<Pair>(seed), "secretSeed": format_seed::<Pair>(seed),
"publicKey": format_public_key::<Pair>(public_key.clone()), "publicKey": format_public_key::<Pair>(public_key.clone()),
"ss58PublicKey": public_key.to_ss58check_with_version(network_override), "ss58PublicKey": public_key.to_ss58check_with_version(network_override),
"accountId": format_account_id::<Pair>(public_key), "accountId": format_account_id::<Pair>(public_key),
"ss58Address": pair.public().into().into_account().to_ss58check_with_version(network_override), "ss58Address": pair.public().into().into_account().to_ss58check_with_version(network_override),
}); });
println!( println!(
"{}", "{}",
serde_json::to_string_pretty(&json).expect("Json pretty print failed") serde_json::to_string_pretty(&json).expect("Json pretty print failed")
); );
}, }
OutputType::Text => { OutputType::Text => {
println!( println!(
"Secret phrase: {}\n \ "Secret phrase: {}\n \
Network ID: {}\n \ Network ID: {}\n \
Secret seed: {}\n \ Secret seed: {}\n \
Public key (hex): {}\n \ Public key (hex): {}\n \
Account ID: {}\n \ Account ID: {}\n \
Public key (SS58): {}\n \ Public key (SS58): {}\n \
SS58 Address: {}", SS58 Address: {}",
uri, uri,
network_id, network_id,
format_seed::<Pair>(seed), format_seed::<Pair>(seed),
format_public_key::<Pair>(public_key.clone()), format_public_key::<Pair>(public_key.clone()),
format_account_id::<Pair>(public_key.clone()), format_account_id::<Pair>(public_key.clone()),
public_key.to_ss58check_with_version(network_override), public_key.to_ss58check_with_version(network_override),
pair.public().into().into_account().to_ss58check_with_version(network_override), pair.public()
); .into()
}, .into_account()
} .to_ss58check_with_version(network_override),
} else if let Ok((pair, seed)) = Pair::from_string_with_seed(uri, password) { );
let public_key = pair.public(); }
let network_override = unwrap_or_default_ss58_version(network_override); }
} else if let Ok((pair, seed)) = Pair::from_string_with_seed(uri, password) {
let public_key = pair.public();
let network_override = unwrap_or_default_ss58_version(network_override);
match output { match output {
OutputType::Json => { OutputType::Json => {
let json = json!({ let json = json!({
"secretKeyUri": uri, "secretKeyUri": uri,
"networkId": network_id, "networkId": network_id,
"secretSeed": if let Some(seed) = seed { format_seed::<Pair>(seed) } else { "n/a".into() }, "secretSeed": if let Some(seed) = seed { format_seed::<Pair>(seed) } else { "n/a".into() },
"publicKey": format_public_key::<Pair>(public_key.clone()), "publicKey": format_public_key::<Pair>(public_key.clone()),
"ss58PublicKey": public_key.to_ss58check_with_version(network_override), "ss58PublicKey": public_key.to_ss58check_with_version(network_override),
"accountId": format_account_id::<Pair>(public_key), "accountId": format_account_id::<Pair>(public_key),
"ss58Address": pair.public().into().into_account().to_ss58check_with_version(network_override), "ss58Address": pair.public().into().into_account().to_ss58check_with_version(network_override),
}); });
println!( println!(
"{}", "{}",
serde_json::to_string_pretty(&json).expect("Json pretty print failed") serde_json::to_string_pretty(&json).expect("Json pretty print failed")
); );
}, }
OutputType::Text => { OutputType::Text => {
println!( println!(
"Secret Key URI `{}` is account:\n \ "Secret Key URI `{}` is account:\n \
Network ID: {}\n \ Network ID: {}\n \
Secret seed: {}\n \ Secret seed: {}\n \
Public key (hex): {}\n \ Public key (hex): {}\n \
Account ID: {}\n \ Account ID: {}\n \
Public key (SS58): {}\n \ Public key (SS58): {}\n \
SS58 Address: {}", SS58 Address: {}",
uri, uri,
network_id, network_id,
if let Some(seed) = seed { format_seed::<Pair>(seed) } else { "n/a".into() }, if let Some(seed) = seed {
format_public_key::<Pair>(public_key.clone()), format_seed::<Pair>(seed)
format_account_id::<Pair>(public_key.clone()), } else {
public_key.to_ss58check_with_version(network_override), "n/a".into()
pair.public().into().into_account().to_ss58check_with_version(network_override), },
); format_public_key::<Pair>(public_key.clone()),
}, format_account_id::<Pair>(public_key.clone()),
} public_key.to_ss58check_with_version(network_override),
} else if let Ok((public_key, network)) = Pair::Public::from_string_with_version(uri) { pair.public()
let network_override = network_override.unwrap_or(network); .into()
.into_account()
.to_ss58check_with_version(network_override),
);
}
}
} else if let Ok((public_key, network)) = Pair::Public::from_string_with_version(uri) {
let network_override = network_override.unwrap_or(network);
match output { match output {
OutputType::Json => { OutputType::Json => {
let json = json!({ let json = json!({
"publicKeyUri": uri, "publicKeyUri": uri,
"networkId": String::from(network_override), "networkId": String::from(network_override),
"publicKey": format_public_key::<Pair>(public_key.clone()), "publicKey": format_public_key::<Pair>(public_key.clone()),
"accountId": format_account_id::<Pair>(public_key.clone()), "accountId": format_account_id::<Pair>(public_key.clone()),
"ss58PublicKey": public_key.to_ss58check_with_version(network_override), "ss58PublicKey": public_key.to_ss58check_with_version(network_override),
"ss58Address": public_key.to_ss58check_with_version(network_override), "ss58Address": public_key.to_ss58check_with_version(network_override),
}); });
println!( println!(
"{}", "{}",
serde_json::to_string_pretty(&json).expect("Json pretty print failed") serde_json::to_string_pretty(&json).expect("Json pretty print failed")
); );
}, }
OutputType::Text => { OutputType::Text => {
println!( println!(
"Public Key URI `{}` is account:\n \ "Public Key URI `{}` is account:\n \
Network ID/Version: {}\n \ Network ID/Version: {}\n \
Public key (hex): {}\n \ Public key (hex): {}\n \
Account ID: {}\n \ Account ID: {}\n \
Public key (SS58): {}\n \ Public key (SS58): {}\n \
SS58 Address: {}", SS58 Address: {}",
uri, uri,
String::from(network_override), String::from(network_override),
format_public_key::<Pair>(public_key.clone()), format_public_key::<Pair>(public_key.clone()),
format_account_id::<Pair>(public_key.clone()), format_account_id::<Pair>(public_key.clone()),
public_key.to_ss58check_with_version(network_override), public_key.to_ss58check_with_version(network_override),
public_key.to_ss58check_with_version(network_override), public_key.to_ss58check_with_version(network_override),
); );
}, }
} }
} else { } else {
println!("Invalid phrase/URI given"); println!("Invalid phrase/URI given");
} }
} }
/// Try to parse given `public` as hex encoded public key and print relevant information. /// Try to parse given `public` as hex encoded public key and print relevant information.
pub fn print_from_public<Pair>( pub fn print_from_public<Pair>(
public_str: &str, public_str: &str,
network_override: Option<Ss58AddressFormat>, network_override: Option<Ss58AddressFormat>,
output: OutputType, output: OutputType,
) -> Result<(), sc_cli::Error> ) -> Result<(), sc_cli::Error>
where where
Pair: sp_core::Pair, Pair: sp_core::Pair,
Pair::Public: Into<MultiSigner>, Pair::Public: Into<MultiSigner>,
{ {
let public = array_bytes::hex2bytes(public_str)?; let public = array_bytes::hex2bytes(public_str)?;
let public_key = Pair::Public::try_from(&public) let public_key = Pair::Public::try_from(&public)
.map_err(|_| "Failed to construct public key from given hex")?; .map_err(|_| "Failed to construct public key from given hex")?;
let network_override = unwrap_or_default_ss58_version(network_override); let network_override = unwrap_or_default_ss58_version(network_override);
match output { match output {
OutputType::Json => { OutputType::Json => {
let json = json!({ let json = json!({
"networkId": String::from(network_override), "networkId": String::from(network_override),
"publicKey": format_public_key::<Pair>(public_key.clone()), "publicKey": format_public_key::<Pair>(public_key.clone()),
"accountId": format_account_id::<Pair>(public_key.clone()), "accountId": format_account_id::<Pair>(public_key.clone()),
"ss58PublicKey": public_key.to_ss58check_with_version(network_override), "ss58PublicKey": public_key.to_ss58check_with_version(network_override),
"ss58Address": public_key.to_ss58check_with_version(network_override), "ss58Address": public_key.to_ss58check_with_version(network_override),
}); });
println!("{}", serde_json::to_string_pretty(&json).expect("Json pretty print failed")); println!(
}, "{}",
OutputType::Text => { serde_json::to_string_pretty(&json).expect("Json pretty print failed")
println!( );
"Network ID/Version: {}\n \ }
OutputType::Text => {
println!(
"Network ID/Version: {}\n \
Public key (hex): {}\n \ Public key (hex): {}\n \
Account ID: {}\n \ Account ID: {}\n \
Public key (SS58): {}\n \ Public key (SS58): {}\n \
SS58 Address: {}", SS58 Address: {}",
String::from(network_override), String::from(network_override),
format_public_key::<Pair>(public_key.clone()), format_public_key::<Pair>(public_key.clone()),
format_account_id::<Pair>(public_key.clone()), format_account_id::<Pair>(public_key.clone()),
public_key.to_ss58check_with_version(network_override), public_key.to_ss58check_with_version(network_override),
public_key.to_ss58check_with_version(network_override), public_key.to_ss58check_with_version(network_override),
); );
}, }
} }
Ok(()) Ok(())
} }
pub fn unwrap_or_default_ss58_name(x: Option<Ss58AddressFormat>) -> String { pub fn unwrap_or_default_ss58_name(x: Option<Ss58AddressFormat>) -> String {
@ -216,5 +228,8 @@ fn format_account_id<P: sp_core::Pair>(public_key: PublicFor<P>) -> String
where where
PublicFor<P>: Into<MultiSigner>, PublicFor<P>: Into<MultiSigner>,
{ {
format!("0x{}", HexDisplay::from(&public_key.into().into_account().as_ref())) format!(
"0x{}",
HexDisplay::from(&public_key.into().into_account().as_ref())
)
} }

View File

@ -2,213 +2,218 @@
use clap::Parser; use clap::Parser;
use rand::{rngs::OsRng, RngCore}; use rand::{rngs::OsRng, RngCore};
use sp_core::crypto::{ use sc_cli::{utils::format_seed, with_crypto_scheme, CryptoSchemeFlag, Error, OutputTypeFlag};
unwrap_or_default_ss58_version, Ss58AddressFormat, Ss58Codec, use sp_core::crypto::{unwrap_or_default_ss58_version, Ss58AddressFormat, Ss58Codec};
};
use sp_runtime::traits::IdentifyAccount; use sp_runtime::traits::IdentifyAccount;
use sc_cli::{
with_crypto_scheme, Error, OutputTypeFlag, CryptoSchemeFlag,
utils::format_seed,
};
use crate::commands::utils::print_from_uri; use crate::commands::utils::print_from_uri;
use crate::params::NetworkSchemeFlag; use crate::params::NetworkSchemeFlag;
/// The `vanity` command /// The `vanity` command
#[derive(Debug, Clone, Parser)] #[derive(Debug, Clone, Parser)]
#[command(name = "vanity", about = "Generate a seed that provides a vanity address")] #[command(
name = "vanity",
about = "Generate a seed that provides a vanity address"
)]
pub struct VanityCmd { pub struct VanityCmd {
/// Desired pattern /// Desired pattern
#[arg(long, value_parser = assert_non_empty_string)] #[arg(long, value_parser = assert_non_empty_string)]
pattern: String, pattern: String,
#[allow(missing_docs)] #[allow(missing_docs)]
#[clap(flatten)] #[clap(flatten)]
network_scheme: NetworkSchemeFlag, network_scheme: NetworkSchemeFlag,
#[allow(missing_docs)] #[allow(missing_docs)]
#[clap(flatten)] #[clap(flatten)]
output_scheme: OutputTypeFlag, output_scheme: OutputTypeFlag,
#[allow(missing_docs)] #[allow(missing_docs)]
#[clap(flatten)] #[clap(flatten)]
crypto_scheme: CryptoSchemeFlag, crypto_scheme: CryptoSchemeFlag,
} }
impl VanityCmd { impl VanityCmd {
/// Run the command /// Run the command
pub fn run(&self) -> Result<(), Error> { pub fn run(&self) -> Result<(), Error> {
let formated_seed = with_crypto_scheme!( let formated_seed = with_crypto_scheme!(
self.crypto_scheme.scheme, self.crypto_scheme.scheme,
generate_key( generate_key(
&self.pattern, &self.pattern,
unwrap_or_default_ss58_version(self.network_scheme.network) unwrap_or_default_ss58_version(self.network_scheme.network)
), ),
)?; )?;
with_crypto_scheme!( with_crypto_scheme!(
self.crypto_scheme.scheme, self.crypto_scheme.scheme,
print_from_uri( print_from_uri(
&formated_seed, &formated_seed,
None, None,
self.network_scheme.network, self.network_scheme.network,
self.output_scheme.output_type, self.output_scheme.output_type,
), ),
); );
Ok(()) Ok(())
} }
} }
/// genertae a key based on given pattern /// genertae a key based on given pattern
fn generate_key<Pair>( fn generate_key<Pair>(
desired: &str, desired: &str,
network_override: Ss58AddressFormat, network_override: Ss58AddressFormat,
) -> Result<String, &'static str> ) -> Result<String, &'static str>
where where
Pair: sp_core::Pair, Pair: sp_core::Pair,
Pair::Public: IdentifyAccount, Pair::Public: IdentifyAccount,
<Pair::Public as IdentifyAccount>::AccountId: Ss58Codec, <Pair::Public as IdentifyAccount>::AccountId: Ss58Codec,
{ {
println!("Generating key containing pattern '{}'", desired); println!("Generating key containing pattern '{}'", desired);
let top = 45 + (desired.len() * 48); let top = 45 + (desired.len() * 48);
let mut best = 0; let mut best = 0;
let mut seed = Pair::Seed::default(); let mut seed = Pair::Seed::default();
let mut done = 0; let mut done = 0;
loop { loop {
if done % 100000 == 0 { if done % 100000 == 0 {
OsRng.fill_bytes(seed.as_mut()); OsRng.fill_bytes(seed.as_mut());
} else { } else {
next_seed(seed.as_mut()); next_seed(seed.as_mut());
} }
let p = Pair::from_seed(&seed); let p = Pair::from_seed(&seed);
let ss58 = p.public().into_account().to_ss58check_with_version(network_override); let ss58 = p
.public()
.into_account()
.to_ss58check_with_version(network_override);
println!("{:?}", ss58); println!("{:?}", ss58);
let score = calculate_score(desired, &ss58); let score = calculate_score(desired, &ss58);
if score > best || desired.len() < 2 { if score > best || desired.len() < 2 {
best = score; best = score;
if best >= top { if best >= top {
println!("best: {} == top: {}", best, top); println!("best: {} == top: {}", best, top);
return Ok(format_seed::<Pair>(seed.clone())) return Ok(format_seed::<Pair>(seed.clone()));
} }
} }
done += 1; done += 1;
if done % good_waypoint(done) == 0 { if done % good_waypoint(done) == 0 {
println!("{} keys searched; best is {}/{} complete", done, best, top); println!("{} keys searched; best is {}/{} complete", done, best, top);
} }
} }
} }
fn good_waypoint(done: u64) -> u64 { fn good_waypoint(done: u64) -> u64 {
match done { match done {
0..=1_000_000 => 100_000, 0..=1_000_000 => 100_000,
1_000_001..=10_000_000 => 1_000_000, 1_000_001..=10_000_000 => 1_000_000,
10_000_001..=100_000_000 => 10_000_000, 10_000_001..=100_000_000 => 10_000_000,
100_000_001.. => 100_000_000, 100_000_001.. => 100_000_000,
} }
} }
fn next_seed(seed: &mut [u8]) { fn next_seed(seed: &mut [u8]) {
for s in seed { for s in seed {
match s { match s {
255 => { 255 => {
*s = 0; *s = 0;
}, }
_ => { _ => {
*s += 1; *s += 1;
break break;
}, }
} }
} }
} }
/// Calculate the score of a key based on the desired /// Calculate the score of a key based on the desired
/// input. /// input.
fn calculate_score(_desired: &str, key: &str) -> usize { fn calculate_score(_desired: &str, key: &str) -> usize {
for truncate in 0.._desired.len() { for truncate in 0.._desired.len() {
let snip_size = _desired.len() - truncate; let snip_size = _desired.len() - truncate;
let truncated = &_desired[0..snip_size]; let truncated = &_desired[0..snip_size];
if let Some(pos) = key.find(truncated) { if let Some(pos) = key.find(truncated) {
return (47 - pos) + (snip_size * 48) return (47 - pos) + (snip_size * 48);
} }
} }
0 0
} }
/// checks that `pattern` is non-empty /// checks that `pattern` is non-empty
fn assert_non_empty_string(pattern: &str) -> Result<String, &'static str> { fn assert_non_empty_string(pattern: &str) -> Result<String, &'static str> {
if pattern.is_empty() { if pattern.is_empty() {
Err("Pattern must not be empty") Err("Pattern must not be empty")
} else { } else {
Ok(pattern.to_string()) Ok(pattern.to_string())
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use sp_core::{ use sp_core::{
crypto::{default_ss58_version, Ss58AddressFormatRegistry, Ss58Codec}, crypto::{default_ss58_version, Ss58AddressFormatRegistry, Ss58Codec},
sr25519, Pair, sr25519, Pair,
}; };
#[test] #[test]
fn vanity() { fn vanity() {
let vanity = VanityCmd::parse_from(&["vanity", "--pattern", "j"]); let vanity = VanityCmd::parse_from(&["vanity", "--pattern", "j"]);
assert!(vanity.run().is_ok()); assert!(vanity.run().is_ok());
} }
#[test] #[test]
fn test_generation_with_single_char() { fn test_generation_with_single_char() {
let seed = generate_key::<sr25519::Pair>("ab", default_ss58_version()).unwrap(); let seed = generate_key::<sr25519::Pair>("ab", default_ss58_version()).unwrap();
assert!(sr25519::Pair::from_seed_slice(&array_bytes::hex2bytes_unchecked(&seed)) assert!(
.unwrap() sr25519::Pair::from_seed_slice(&array_bytes::hex2bytes_unchecked(&seed))
.public() .unwrap()
.to_ss58check() .public()
.contains("ab")); .to_ss58check()
} .contains("ab")
);
}
#[test] #[test]
fn generate_key_respects_network_override() { fn generate_key_respects_network_override() {
let seed = let seed =
generate_key::<sr25519::Pair>("ab", Ss58AddressFormatRegistry::PolkadotAccount.into()) generate_key::<sr25519::Pair>("ab", Ss58AddressFormatRegistry::PolkadotAccount.into())
.unwrap(); .unwrap();
assert!(sr25519::Pair::from_seed_slice(&array_bytes::hex2bytes_unchecked(&seed)) assert!(
.unwrap() sr25519::Pair::from_seed_slice(&array_bytes::hex2bytes_unchecked(&seed))
.public() .unwrap()
.to_ss58check_with_version(Ss58AddressFormatRegistry::PolkadotAccount.into()) .public()
.contains("ab")); .to_ss58check_with_version(Ss58AddressFormatRegistry::PolkadotAccount.into())
} .contains("ab")
);
}
#[test] #[test]
fn test_score_1_char_100() { fn test_score_1_char_100() {
let score = calculate_score("j", "sYrjWiZkEP1PQe2kKEZiC1Bi9L8yFSsB5RPEkzEPd5NThsB5H"); let score = calculate_score("j", "sYrjWiZkEP1PQe2kKEZiC1Bi9L8yFSsB5RPEkzEPd5NThsB5H");
assert_eq!(score, 96); assert_eq!(score, 96);
} }
#[test] #[test]
fn test_score_100() { fn test_score_100() {
let score = calculate_score("ghst", "sYsghstuhYd9p6unUC3kPxjD2gv2zRCztYQaEDCMJpYrPTqTG"); let score = calculate_score("ghst", "sYsghstuhYd9p6unUC3kPxjD2gv2zRCztYQaEDCMJpYrPTqTG");
assert_eq!(score, 246); assert_eq!(score, 246);
} }
#[test] #[test]
fn test_score_50_2() { fn test_score_50_2() {
// 50% for the position + 50% for the size // 50% for the position + 50% for the size
assert_eq!( assert_eq!(
calculate_score("ghst", "sYsghXXuhYd9p6unUC3kPxjD2gv2zRCztYQaEDCMJpYrPTqTG"), calculate_score("ghst", "sYsghXXuhYd9p6unUC3kPxjD2gv2zRCztYQaEDCMJpYrPTqTG"),
146 146
); );
} }
#[test] #[test]
fn test_score_0() { fn test_score_0() {
assert_eq!( assert_eq!(
calculate_score("ghst", "sYrjWiZkEP1PQe2kKEZiC1Bi9L8yFSsB5RPEkzEPd5NThsB5H"), calculate_score("ghst", "sYrjWiZkEP1PQe2kKEZiC1Bi9L8yFSsB5RPEkzEPd5NThsB5H"),
0 0
); );
} }
} }

View File

@ -1,5 +1,5 @@
pub mod params;
pub mod commands; pub mod commands;
pub mod params;
pub use commands::KeySubcommand; pub use commands::KeySubcommand;
pub use commands::VanityCmd; pub use commands::VanityCmd;

View File

@ -21,19 +21,25 @@ pub struct InnerSs58AddressFormat(Ss58AddressFormat);
impl InnerSs58AddressFormat { impl InnerSs58AddressFormat {
#[inline] #[inline]
pub fn custom(prefix: u16) -> Self { pub fn custom(prefix: u16) -> Self {
Self { 0: Ss58AddressFormat::custom(prefix) } Self {
0: Ss58AddressFormat::custom(prefix),
}
} }
} }
impl std::fmt::Display for InnerSs58AddressFormat { impl std::fmt::Display for InnerSs58AddressFormat {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{} network", ALL_POSSIBLE_IDS write!(
.binary_search(&u16::from(self.0)) f,
.expect("always be found")) "{} network",
ALL_POSSIBLE_IDS
.binary_search(&u16::from(self.0))
.expect("always be found")
)
} }
} }
impl<'a>TryFrom<&'a str> for InnerSs58AddressFormat { impl<'a> TryFrom<&'a str> for InnerSs58AddressFormat {
type Error = ParseError; type Error = ParseError;
fn try_from(x: &'a str) -> Result<Self, Self::Error> { fn try_from(x: &'a str) -> Result<Self, Self::Error> {
@ -44,13 +50,13 @@ impl<'a>TryFrom<&'a str> for InnerSs58AddressFormat {
} }
} }
pub fn parse_s58_prefix_address_format(x: &str,) -> Result<Ss58AddressFormat, String> { pub fn parse_s58_prefix_address_format(x: &str) -> Result<Ss58AddressFormat, String> {
match InnerSs58AddressFormat::try_from(x) { match InnerSs58AddressFormat::try_from(x) {
Ok(format_registry) => Ok(format_registry.0.into()), Ok(format_registry) => Ok(format_registry.0.into()),
Err(_) => Err(format!( Err(_) => Err(format!(
"Unable to parse variant. Known variants: {:?}", "Unable to parse variant. Known variants: {:?}",
&ALL_POSSIBLE_NAMES &ALL_POSSIBLE_NAMES
)) )),
} }
} }

View File

@ -22,7 +22,11 @@ impl Metronome {
/// Create a new metronome source with a defined cycle duration. /// Create a new metronome source with a defined cycle duration.
pub fn new(cycle: Duration) -> Self { pub fn new(cycle: Duration) -> Self {
let period = cycle.into(); let period = cycle.into();
Self { period, delay: Delay::new(period), state: MetronomeState::Snooze } Self {
period,
delay: Delay::new(period),
state: MetronomeState::Snooze,
}
} }
} }
@ -36,14 +40,14 @@ impl futures::Stream for Metronome {
let val = self.period; let val = self.period;
self.delay.reset(val); self.delay.reset(val);
self.state = MetronomeState::Snooze; self.state = MetronomeState::Snooze;
}, }
MetronomeState::Snooze => { MetronomeState::Snooze => {
if !Pin::new(&mut self.delay).poll(cx).is_ready() { if !Pin::new(&mut self.delay).poll(cx).is_ready() {
break break;
} }
self.state = MetronomeState::SetAlarm; self.state = MetronomeState::SetAlarm;
return Poll::Ready(Some(())) return Poll::Ready(Some(()));
}, }
} }
} }
Poll::Pending Poll::Pending

View File

@ -2,19 +2,16 @@
use codec::Decode; use codec::Decode;
use core_primitives::{ use core_primitives::{
metrics_definitions::{ metrics_definitions::{CounterDefinition, CounterVecDefinition, HistogramDefinition},
CounterDefinition, CounterVecDefinition, HistogramDefinition,
},
RuntimeMetricLabelValues, RuntimeMetricOp, RuntimeMetricUpdate, RuntimeMetricLabelValues, RuntimeMetricOp, RuntimeMetricUpdate,
}; };
use prometheus_endpoint::{ use prometheus_endpoint::{
register, Counter, CounterVec, Histogram, HistogramOpts, Opts, Registry, register, Counter, CounterVec, Histogram, HistogramOpts, Opts, PrometheusError, Registry, U64,
PrometheusError, U64,
}; };
use std::{ use std::{
collections::hash_map::HashMap, collections::hash_map::HashMap,
sync::{Arc, Mutex, MutexGuard}, sync::{Arc, Mutex, MutexGuard},
} };
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Metrics { pub struct Metrics {
@ -32,13 +29,15 @@ impl RuntimeMetricsProvider {
pub fn register_countervec(&self, countervec: CounterVecDefinition) { pub fn register_countervec(&self, countervec: CounterVecDefinition) {
self.with_counter_vecs_lock_held(|mut hashmap| { self.with_counter_vecs_lock_held(|mut hashmap| {
hashmap.entry(countervec.name.to_owned()).or_insert(register( hashmap
CounterVec::new( .entry(countervec.name.to_owned())
Opts::new(countervec.name, countervec.description), .or_insert(register(
countervec.labels, CounterVec::new(
)?, Opts::new(countervec.name, countervec.description),
&self.0, countervec.labels,
)?); )?,
&self.0,
)?);
Ok(()) Ok(())
}) })
} }
@ -46,10 +45,7 @@ impl RuntimeMetricsProvider {
pub fn register_counter(&self, counter: CounterDefinition) { pub fn register_counter(&self, counter: CounterDefinition) {
self.with_counters_lock_held(|mut hashmap| { self.with_counters_lock_held(|mut hashmap| {
hashmap.entry(counter.name.to_owned()).or_insert(register( hashmap.entry(counter.name.to_owned()).or_insert(register(
Counter::new( Counter::new(counter.name, counter.description)?,
counter.name,
counter.description,
)?,
&self.0, &self.0,
)?); )?);
Ok(()) Ok(())
@ -60,8 +56,7 @@ impl RuntimeMetricsProvider {
self.with_histograms_lock_held(|mut hashmap| { self.with_histograms_lock_held(|mut hashmap| {
hashmap.entry(hist.name.to_owned()).or_insert(register( hashmap.entry(hist.name.to_owned()).or_insert(register(
Histogram::with_opts( Histogram::with_opts(
HistogramOpts::new(hist.name, hist.description) HistogramOpts::new(hist.name, hist.description).buckets(hist.buckets.to_vec()),
.buckets(hist.buckets.to_vec()),
)?, )?,
&self.0, &self.0,
)?); )?);
@ -69,15 +64,12 @@ impl RuntimeMetricsProvider {
}) })
} }
pub fn inc_counter_vec_by( pub fn inc_counter_vec_by(&self, name: &str, value: u64, labels: &RuntimeMetricsProvider) {
&self,
name: &str,
value: u64,
labels: &RuntimeMetricsProvider,
) {
self.with_counter_vecs_lock_held(|mut hashmap| { self.with_counter_vecs_lock_held(|mut hashmap| {
hashmap.entry(name.to_owned()).and_modify(|counter_vec| { hashmap.entry(name.to_owned()).and_modify(|counter_vec| {
counter_vec.with_label_values(&labels.as_str_vec()).inc_by(value) counter_vec
.with_label_values(&labels.as_str_vec())
.inc_by(value)
}); });
Ok(()) Ok(())
}) })
@ -85,7 +77,8 @@ impl RuntimeMetricsProvider {
pub fn inc_counter_by(&self, name: &str, value: u64) { pub fn inc_counter_by(&self, name: &str, value: u64) {
self.with_counters_lock_held(|mut hashmap| { self.with_counters_lock_held(|mut hashmap| {
hashmap.entry(name.to_owned()) hashmap
.entry(name.to_owned())
.and_modify(|counter_vec| counter_vec.inc_by(value)); .and_modify(|counter_vec| counter_vec.inc_by(value));
Ok(()) Ok(())
}) })
@ -93,8 +86,9 @@ impl RuntimeMetricsProvider {
pub fn observe_histogram(&self, name: &str, value: u128) { pub fn observe_histogram(&self, name: &str, value: u128) {
self.with_histograms_lock_held(|mut hashmap| { self.with_histograms_lock_held(|mut hashmap| {
hashmap.entry(name.to_owned()) hashmap
and_modify(|histogram| histogram.observe(value as f64 / 1_000_000_000.0)); .entry(name.to_owned())
.and_modify(|histogram| histogram.observe(value as f64 / 1_000_000_000.0));
Ok(()) Ok(())
}) })
} }
@ -103,21 +97,36 @@ impl RuntimeMetricsProvider {
where where
F: FnOnce(MutexGuard<'_, HashMap<String, Counter<U64>>>) -> Result<(), PrometheusError>, F: FnOnce(MutexGuard<'_, HashMap<String, Counter<U64>>>) -> Result<(), PrometheusError>,
{ {
let _ = self.1.counters.lock().map(do_something).or_else(|error| Err(error)); let _ = self
.1
.counters
.lock()
.map(do_something)
.or_else(|error| Err(error));
} }
fn with_counter_vecs_lock_held<F>(&self, do_something: F) fn with_counter_vecs_lock_held<F>(&self, do_something: F)
where where
F: FnOnce(MutexGuard<'_, HashMap<String, CounterVec<U64>>>) -> Result<(), PrometheusError>, F: FnOnce(MutexGuard<'_, HashMap<String, CounterVec<U64>>>) -> Result<(), PrometheusError>,
{ {
let _ = self.1.counter_vecs.lock().map(do_something).or_else(|error| Err(error)); let _ = self
.1
.counter_vecs
.lock()
.map(do_something)
.or_else(|error| Err(error));
} }
fn with_histograms_lock_held<F>(&self, do_something: F) fn with_histograms_lock_held<F>(&self, do_something: F)
where where
F: FnOnce(MutexGuard<'_, HashMap<String, Histogram>>) -> Result<(), PrometheusError>, F: FnOnce(MutexGuard<'_, HashMap<String, Histogram>>) -> Result<(), PrometheusError>,
{ {
let _ = self.1.histograms.lock().map(do_something).or_else(|error| Err(error)); let _ = self
.1
.histograms
.lock()
.map(do_something)
.or_else(|error| Err(error));
} }
} }
@ -131,7 +140,7 @@ impl sc_tracing::TraceHandler for RuntimeMetricsProvider {
.unwrap_or(&String::default()) .unwrap_or(&String::default())
.ne("metrics") .ne("metrics")
{ {
return return;
} }
if let Some(update_op_bs58) = event.values.string_values.get("params") { if let Some(update_op_bs58) = event.values.string_values.get("params") {
@ -141,7 +150,7 @@ impl sc_tracing::TraceHandler for RuntimeMetricsProvider {
.as_slice(), .as_slice(),
) { ) {
Ok(update_op) => self.parse_metric_update(update_op), Ok(update_op) => self.parse_metric_update(update_op),
Err(_) => {}, Err(_) => {}
} }
} }
} }
@ -150,12 +159,15 @@ impl sc_tracing::TraceHandler for RuntimeMetricsProvider {
impl RuntimeMetricsProvider { impl RuntimeMetricsProvider {
fn parse_metric_update(&self, update: RuntimeMetricUpdate) { fn parse_metric_update(&self, update: RuntimeMetricUpdate) {
match update.op { match update.op {
RuntimeMetricOp::IncrementCounterVec(value, ref labels) => RuntimeMetricOp::IncrementCounterVec(value, ref labels) => {
self.inc_counter_vec_by(update.metric_name(), value, labels), self.inc_counter_vec_by(update.metric_name(), value, labels)
RuntimeMetricOp::IncrementCounter(value) => }
self.inc_counter_by(update.metric_name(), value), RuntimeMetricOp::IncrementCounter(value) => {
RuntimeMetricOp::ObserveHistogram(value) => self.inc_counter_by(update.metric_name(), value)
self.observe_histogram(update.metric_name(), value), }
RuntimeMetricOp::ObserveHistogram(value) => {
self.observe_histogram(update.metric_name(), value)
}
} }
} }
@ -178,7 +190,7 @@ impl RuntimeMetricsProvider {
pub fn logger_hook() -> impl FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration) -> () { pub fn logger_hook() -> impl FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration) -> () {
|logger_builder, config| { |logger_builder, config| {
if config.prometheus_registry().is_none() { if config.prometheus_registry().is_none() {
return return;
} }
let registry = config.prometheus_registry().cloned().unwrap(); let registry = config.prometheus_registry().cloned().unwrap();

View File

@ -1,5 +1,5 @@
use hyper::{Client, Uri};
use ghost_test_service::{node_config, run_validator_node, test_prometheus_config}; use ghost_test_service::{node_config, run_validator_node, test_prometheus_config};
use hyper::{Client, Uri};
use keyring::AccountKeyring::*; use keyring::AccountKeyring::*;
use std::collections::HashMap; use std::collections::HashMap;
@ -7,8 +7,13 @@ const DEFAULT_PROMETHEUS_PORT: u16 = 9616;
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn runtime_can_publish_metrics() { async fn runtime_can_publish_metrics() {
let mut alice_config = let mut alice_config = node_config(
node_config(|| {}, tokio::runtime::Handle::current(), Alice, Vec::new(), true); || {},
tokio::runtime::Handle::current(),
Alice,
Vec::new(),
true,
);
// Enable prometheus metrics for Alice. // Enable prometheus metrics for Alice.
alice_config.prometheus_config = Some(test_prometheus_config(DEFAULT_PROMETHEUS_PORT)); alice_config.prometheus_config = Some(test_prometheus_config(DEFAULT_PROMETHEUS_PORT));
@ -26,8 +31,13 @@ async fn runtime_can_publish_metrics() {
// Start validator Alice // Start validator Alice
let alice = run_validator_node(alice_config, None); let alice = run_validator_node(alice_config, None);
let bob_config = let bob_config = node_config(
node_config(|| {}, tokio::runtime::Handle::current(), Bob, vec![alice.addr.clone()], true); || {},
tokio::runtime::Handle::current(),
Bob,
vec![alice.addr.clone()],
true,
);
// Start validator Bob // Start validator Bob
let _bob = run_validator_node(bob_config, None); let _bob = run_validator_node(bob_config, None);
@ -48,19 +58,25 @@ async fn scrape_prometheus_metrics(metrics_uri: &str) -> HashMap<String, u64> {
.expect("GET request failed"); .expect("GET request failed");
let body = String::from_utf8( let body = String::from_utf8(
hyper::body::to_bytes(res).await.expect("can't get body as bytes").to_vec(), hyper::body::to_bytes(res)
).expect("body is not an UTF8 string"); .await
.expect("can't get body as bytes")
.to_vec(),
)
.expect("body is not an UTF8 string");
let lines: Vec<_> = body.lines().map(|s| Ok(s.to_owned())).collect(); let lines: Vec<_> = body.lines().map(|s| Ok(s.to_owned())).collect();
prometheus_parse::Scrape::parse(lines.into_iter()) prometheus_parse::Scrape::parse(lines.into_iter())
.expect("Scraper failed to parse Prometheus metrics") .expect("Scraper failed to parse Prometheus metrics")
.samples .samples
.into_iter() .into_iter()
.filter_map(|prometheus_parse::Sample { metric, value, .. }| match value { .filter_map(
prometheus_parse::Value::Counter(value) => Some((metric, value as u64)), |prometheus_parse::Sample { metric, value, .. }| match value {
prometheus_parse::Value::Gauge(value) => Some((metric, value as u64)), prometheus_parse::Value::Counter(value) => Some((metric, value as u64)),
prometheus_parse::Value::Untyped(value) => Some((metric, value as u64)), prometheus_parse::Value::Gauge(value) => Some((metric, value as u64)),
_ => None, prometheus_parse::Value::Untyped(value) => Some((metric, value as u64)),
}) _ => None,
},
)
.collect() .collect()
} }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-slow-clap" name = "ghost-slow-clap"
version = "0.3.34" version = "0.3.35"
description = "Applause protocol for the EVM bridge" description = "Applause protocol for the EVM bridge"
license.workspace = true license.workspace = true
authors.workspace = true authors.workspace = true

View File

@ -702,23 +702,27 @@ impl<T: Config> Pallet<T> {
); );
let random_seed = sp_io::offchain::random_seed(); let random_seed = sp_io::offchain::random_seed();
let random_number = <u32>::decode( let random_number = <u32>::decode(&mut TrailingZeroInput::new(random_seed.as_ref()))
&mut TrailingZeroInput::new(random_seed.as_ref()) .expect("input is padded with zeroes; qed");
).expect("input is padded with zeroes; qed");
let rpc_endpoint = if stored_endpoints.len() > 0 { let rpc_endpoint = if stored_endpoints.len() > 0 {
stored_endpoints stored_endpoints
.iter() .iter()
.nth((random_number as usize) .nth(
.checked_rem(stored_endpoints.len()) (random_number as usize)
.unwrap_or_default()) .checked_rem(stored_endpoints.len())
.unwrap_or_default(),
)
.expect("stored endpoint should be non empty; qed") .expect("stored endpoint should be non empty; qed")
} else { } else {
network_data.default_endpoints network_data
.default_endpoints
.iter() .iter()
.nth((random_number as usize) .nth(
.checked_rem(network_data.default_endpoints.len()) (random_number as usize)
.unwrap_or_default()) .checked_rem(network_data.default_endpoints.len())
.unwrap_or_default(),
)
.expect("default endpoint should be non empty; qed") .expect("default endpoint should be non empty; qed")
}; };

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-sudo" name = "ghost-sudo"
version = "0.0.1" version = "0.0.2"
description = "Port of the sudo pallet because of dependencies issue" description = "Port of the sudo pallet because of dependencies issue"
license.workspace = true license.workspace = true
authors.workspace = true authors.workspace = true

View File

@ -4,67 +4,74 @@ use frame_benchmarking::v2::*;
use frame_system::RawOrigin; use frame_system::RawOrigin;
fn assert_last_event<T: Config>(generic_event: crate::Event<T>) { fn assert_last_event<T: Config>(generic_event: crate::Event<T>) {
let re: <T as Config>::RuntimeEvent = generic_event.into(); let re: <T as Config>::RuntimeEvent = generic_event.into();
frame_system::Pallet::<T>::assert_last_event(re.into()); frame_system::Pallet::<T>::assert_last_event(re.into());
} }
#[benchmarks(where <T as Config>::RuntimeCall: From<frame_system::Call<T>>)] #[benchmarks(where <T as Config>::RuntimeCall: From<frame_system::Call<T>>)]
mod benchmarks { mod benchmarks {
use super::*; use super::*;
#[benchmark] #[benchmark]
fn set_key() { fn set_key() {
let caller: T::AccountId = whitelisted_caller(); let caller: T::AccountId = whitelisted_caller();
Key::<T>::put(&caller); Key::<T>::put(&caller);
let new_sudoer: T::AccountId = account("sudoer", 0, 0); let new_sudoer: T::AccountId = account("sudoer", 0, 0);
let new_sudoer_lookup = T::Lookup::unlookup(new_sudoer.clone()); let new_sudoer_lookup = T::Lookup::unlookup(new_sudoer.clone());
#[extrinsic_call] #[extrinsic_call]
_(RawOrigin::Signed(caller.clone()), new_sudoer_lookup); _(RawOrigin::Signed(caller.clone()), new_sudoer_lookup);
assert_last_event::<T>(Event::KeyChanged { old: Some(caller), new: new_sudoer }); assert_last_event::<T>(Event::KeyChanged {
} old: Some(caller),
new: new_sudoer,
});
}
#[benchmark] #[benchmark]
fn sudo() { fn sudo() {
let caller: T::AccountId = whitelisted_caller(); let caller: T::AccountId = whitelisted_caller();
Key::<T>::put(&caller); Key::<T>::put(&caller);
let call = frame_system::Call::remark { remark: vec![] }.into(); let call = frame_system::Call::remark { remark: vec![] }.into();
#[extrinsic_call] #[extrinsic_call]
_(RawOrigin::Signed(caller), Box::new(call)); _(RawOrigin::Signed(caller), Box::new(call));
assert_last_event::<T>(Event::Sudid { sudo_result: Ok(()) }) assert_last_event::<T>(Event::Sudid {
} sudo_result: Ok(()),
})
}
#[benchmark] #[benchmark]
fn sudo_as() { fn sudo_as() {
let caller: T::AccountId = whitelisted_caller(); let caller: T::AccountId = whitelisted_caller();
Key::<T>::put(caller.clone()); Key::<T>::put(caller.clone());
let call = frame_system::Call::remark { remark: vec![] }.into(); let call = frame_system::Call::remark { remark: vec![] }.into();
let who: T::AccountId = account("as", 0, 0); let who: T::AccountId = account("as", 0, 0);
let who_lookup = T::Lookup::unlookup(who); let who_lookup = T::Lookup::unlookup(who);
#[extrinsic_call] #[extrinsic_call]
_(RawOrigin::Signed(caller), who_lookup, Box::new(call)); _(RawOrigin::Signed(caller), who_lookup, Box::new(call));
assert_last_event::<T>(Event::SudoAsDone { sudo_result: Ok(()) }) assert_last_event::<T>(Event::SudoAsDone {
} sudo_result: Ok(()),
})
}
#[benchmark] #[benchmark]
fn remove_key() { fn remove_key() {
let caller: T::AccountId = whitelisted_caller(); let caller: T::AccountId = whitelisted_caller();
Key::<T>::put(&caller); Key::<T>::put(&caller);
#[extrinsic_call] #[extrinsic_call]
_(RawOrigin::Signed(caller.clone())); _(RawOrigin::Signed(caller.clone()));
assert_last_event::<T>(Event::KeyRemoved {}); assert_last_event::<T>(Event::KeyRemoved {});
} }
impl_benchmark_test_suite!(Pallet, crate::mock::new_bench_ext(), crate::mock::Test); impl_benchmark_test_suite!(Pallet, crate::mock::new_bench_ext(), crate::mock::Test);
} }

View File

@ -3,11 +3,11 @@ use codec::{Decode, Encode};
use frame_support::{dispatch::DispatchInfo, ensure}; use frame_support::{dispatch::DispatchInfo, ensure};
use scale_info::TypeInfo; use scale_info::TypeInfo;
use sp_runtime::{ use sp_runtime::{
traits::{DispatchInfoOf, Dispatchable, SignedExtension}, traits::{DispatchInfoOf, Dispatchable, SignedExtension},
transaction_validity::{ transaction_validity::{
InvalidTransaction, TransactionPriority, TransactionValidity, TransactionValidityError, InvalidTransaction, TransactionPriority, TransactionValidity, TransactionValidityError,
UnknownTransaction, ValidTransaction, UnknownTransaction, ValidTransaction,
}, },
}; };
use sp_std::{fmt, marker::PhantomData}; use sp_std::{fmt, marker::PhantomData};
@ -16,67 +16,67 @@ use sp_std::{fmt, marker::PhantomData};
pub struct CheckOnlySudoAccount<T: Config + Send + Sync>(PhantomData<T>); pub struct CheckOnlySudoAccount<T: Config + Send + Sync>(PhantomData<T>);
impl<T: Config + Send + Sync> Default for CheckOnlySudoAccount<T> { impl<T: Config + Send + Sync> Default for CheckOnlySudoAccount<T> {
fn default() -> Self { fn default() -> Self {
Self(Default::default()) Self(Default::default())
} }
} }
impl<T: Config + Send + Sync> fmt::Debug for CheckOnlySudoAccount<T> { impl<T: Config + Send + Sync> fmt::Debug for CheckOnlySudoAccount<T> {
#[cfg(feature = "std")] #[cfg(feature = "std")]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "CheckOnlySudoAccount") write!(f, "CheckOnlySudoAccount")
} }
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
Ok(()) Ok(())
} }
} }
impl<T: Config + Send + Sync> CheckOnlySudoAccount<T> { impl<T: Config + Send + Sync> CheckOnlySudoAccount<T> {
/// Creates new `SignedExtension` to check sudo key. /// Creates new `SignedExtension` to check sudo key.
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
} }
} }
impl<T: Config + Send + Sync> SignedExtension for CheckOnlySudoAccount<T> impl<T: Config + Send + Sync> SignedExtension for CheckOnlySudoAccount<T>
where where
<T as Config>::RuntimeCall: Dispatchable<Info = DispatchInfo>, <T as Config>::RuntimeCall: Dispatchable<Info = DispatchInfo>,
{ {
const IDENTIFIER: &'static str = "CheckOnlySudoAccount"; const IDENTIFIER: &'static str = "CheckOnlySudoAccount";
type AccountId = T::AccountId; type AccountId = T::AccountId;
type Call = <T as Config>::RuntimeCall; type Call = <T as Config>::RuntimeCall;
type AdditionalSigned = (); type AdditionalSigned = ();
type Pre = (); type Pre = ();
fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError> { fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError> {
Ok(()) Ok(())
} }
fn validate( fn validate(
&self, &self,
who: &Self::AccountId, who: &Self::AccountId,
_call: &Self::Call, _call: &Self::Call,
info: &DispatchInfoOf<Self::Call>, info: &DispatchInfoOf<Self::Call>,
_len: usize, _len: usize,
) -> TransactionValidity { ) -> TransactionValidity {
let sudo_key: T::AccountId = Key::<T>::get().ok_or(UnknownTransaction::CannotLookup)?; let sudo_key: T::AccountId = Key::<T>::get().ok_or(UnknownTransaction::CannotLookup)?;
ensure!(*who == sudo_key, InvalidTransaction::BadSigner); ensure!(*who == sudo_key, InvalidTransaction::BadSigner);
Ok(ValidTransaction { Ok(ValidTransaction {
priority: info.weight.ref_time() as TransactionPriority, priority: info.weight.ref_time() as TransactionPriority,
..Default::default() ..Default::default()
}) })
} }
fn pre_dispatch( fn pre_dispatch(
self, self,
who: &Self::AccountId, who: &Self::AccountId,
call: &Self::Call, call: &Self::Call,
info: &DispatchInfoOf<Self::Call>, info: &DispatchInfoOf<Self::Call>,
len: usize, len: usize,
) -> Result<Self::Pre, TransactionValidityError> { ) -> Result<Self::Pre, TransactionValidityError> {
self.validate(who, call, info, len).map(|_| ()) self.validate(who, call, info, len).map(|_| ())
} }
} }

View File

@ -23,181 +23,190 @@ type AccountIdLookupOf<T> = <<T as frame_system::Config>::Lookup as StaticLookup
#[frame_support::pallet] #[frame_support::pallet]
pub mod pallet { pub mod pallet {
use super::{DispatchResult, *}; use super::{DispatchResult, *};
use frame_support::pallet_prelude::*; use frame_support::pallet_prelude::*;
use frame_system::{pallet_prelude::*, RawOrigin}; use frame_system::{pallet_prelude::*, RawOrigin};
pub mod config_preludes { pub mod config_preludes {
use super::*; use super::*;
use frame_support::derive_impl; use frame_support::derive_impl;
pub struct TestDefaultConfig; pub struct TestDefaultConfig;
#[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)] #[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)]
impl frame_system::DefaultConfig for TestDefaultConfig {} impl frame_system::DefaultConfig for TestDefaultConfig {}
#[frame_support::register_default_impl(TestDefaultConfig)] #[frame_support::register_default_impl(TestDefaultConfig)]
impl DefaultConfig for TestDefaultConfig { impl DefaultConfig for TestDefaultConfig {
type WeightInfo = (); type WeightInfo = ();
#[inject_runtime_type] #[inject_runtime_type]
type RuntimeEvent = (); type RuntimeEvent = ();
#[inject_runtime_type] #[inject_runtime_type]
type RuntimeCall = (); type RuntimeCall = ();
} }
} }
#[pallet::config(with_default)] #[pallet::config(with_default)]
pub trait Config: frame_system::Config { pub trait Config: frame_system::Config {
#[pallet::no_default_bounds] #[pallet::no_default_bounds]
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>; type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
#[pallet::no_default_bounds] #[pallet::no_default_bounds]
type RuntimeCall: Parameter type RuntimeCall: Parameter
+ UnfilteredDispatchable<RuntimeOrigin = Self::RuntimeOrigin> + UnfilteredDispatchable<RuntimeOrigin = Self::RuntimeOrigin>
+ GetDispatchInfo; + GetDispatchInfo;
type WeightInfo: WeightInfo; type WeightInfo: WeightInfo;
} }
#[pallet::pallet] #[pallet::pallet]
pub struct Pallet<T>(_); pub struct Pallet<T>(_);
#[pallet::call] #[pallet::call]
impl<T: Config> Pallet<T> { impl<T: Config> Pallet<T> {
#[pallet::call_index(0)] #[pallet::call_index(0)]
#[pallet::weight({ #[pallet::weight({
let dispatch_info = call.get_dispatch_info(); let dispatch_info = call.get_dispatch_info();
( (
T::WeightInfo::sudo().saturating_add(dispatch_info.weight), T::WeightInfo::sudo().saturating_add(dispatch_info.weight),
dispatch_info.class dispatch_info.class
) )
})] })]
pub fn sudo( pub fn sudo(
origin: OriginFor<T>, origin: OriginFor<T>,
call: Box<<T as Config>::RuntimeCall>, call: Box<<T as Config>::RuntimeCall>,
) -> DispatchResultWithPostInfo { ) -> DispatchResultWithPostInfo {
Self::ensure_sudo(origin)?; Self::ensure_sudo(origin)?;
let res = call.dispatch_bypass_filter(RawOrigin::Root.into()); let res = call.dispatch_bypass_filter(RawOrigin::Root.into());
Self::deposit_event(Event::Sudid { sudo_result: res.map(|_| ()).map_err(|e| e.error) }); Self::deposit_event(Event::Sudid {
sudo_result: res.map(|_| ()).map_err(|e| e.error),
});
Ok(Pays::No.into()) Ok(Pays::No.into())
} }
#[pallet::call_index(1)] #[pallet::call_index(1)]
#[pallet::weight((*weight, call.get_dispatch_info().class))] #[pallet::weight((*weight, call.get_dispatch_info().class))]
pub fn sudo_unchecked_weight( pub fn sudo_unchecked_weight(
origin: OriginFor<T>, origin: OriginFor<T>,
call: Box<<T as Config>::RuntimeCall>, call: Box<<T as Config>::RuntimeCall>,
weight: Weight, weight: Weight,
) -> DispatchResultWithPostInfo { ) -> DispatchResultWithPostInfo {
Self::ensure_sudo(origin)?; Self::ensure_sudo(origin)?;
let _ = weight; let _ = weight;
let res = call.dispatch_bypass_filter(RawOrigin::Root.into()); let res = call.dispatch_bypass_filter(RawOrigin::Root.into());
Self::deposit_event(Event::Sudid { sudo_result: res.map(|_| ()).map_err(|e| e.error) }); Self::deposit_event(Event::Sudid {
sudo_result: res.map(|_| ()).map_err(|e| e.error),
});
Ok(Pays::No.into()) Ok(Pays::No.into())
} }
#[pallet::call_index(2)] #[pallet::call_index(2)]
#[pallet::weight(T::WeightInfo::set_key())] #[pallet::weight(T::WeightInfo::set_key())]
pub fn set_key( pub fn set_key(
origin: OriginFor<T>, origin: OriginFor<T>,
new: AccountIdLookupOf<T>, new: AccountIdLookupOf<T>,
) -> DispatchResultWithPostInfo { ) -> DispatchResultWithPostInfo {
Self::ensure_sudo(origin)?; Self::ensure_sudo(origin)?;
let new = T::Lookup::lookup(new)?; let new = T::Lookup::lookup(new)?;
Self::deposit_event(Event::KeyChanged { old: Key::<T>::get(), new: new.clone() }); Self::deposit_event(Event::KeyChanged {
Key::<T>::put(new); old: Key::<T>::get(),
new: new.clone(),
});
Key::<T>::put(new);
Ok(Pays::No.into()) Ok(Pays::No.into())
} }
#[pallet::call_index(3)] #[pallet::call_index(3)]
#[pallet::weight({ #[pallet::weight({
let dispatch_info = call.get_dispatch_info(); let dispatch_info = call.get_dispatch_info();
( (
T::WeightInfo::sudo_as().saturating_add(dispatch_info.weight), T::WeightInfo::sudo_as().saturating_add(dispatch_info.weight),
dispatch_info.class, dispatch_info.class,
) )
})] })]
pub fn sudo_as( pub fn sudo_as(
origin: OriginFor<T>, origin: OriginFor<T>,
who: AccountIdLookupOf<T>, who: AccountIdLookupOf<T>,
call: Box<<T as Config>::RuntimeCall>, call: Box<<T as Config>::RuntimeCall>,
) -> DispatchResultWithPostInfo { ) -> DispatchResultWithPostInfo {
Self::ensure_sudo(origin)?; Self::ensure_sudo(origin)?;
let who = T::Lookup::lookup(who)?; let who = T::Lookup::lookup(who)?;
let res = call.dispatch_bypass_filter(RawOrigin::Signed(who).into()); let res = call.dispatch_bypass_filter(RawOrigin::Signed(who).into());
Self::deposit_event(Event::SudoAsDone { Self::deposit_event(Event::SudoAsDone {
sudo_result: res.map(|_| ()).map_err(|e| e.error), sudo_result: res.map(|_| ()).map_err(|e| e.error),
}); });
Ok(Pays::No.into()) Ok(Pays::No.into())
} }
#[pallet::call_index(4)] #[pallet::call_index(4)]
#[pallet::weight(T::WeightInfo::remove_key())] #[pallet::weight(T::WeightInfo::remove_key())]
pub fn remove_key(origin: OriginFor<T>) -> DispatchResultWithPostInfo { pub fn remove_key(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
Self::ensure_sudo(origin)?; Self::ensure_sudo(origin)?;
Self::deposit_event(Event::KeyRemoved {}); Self::deposit_event(Event::KeyRemoved {});
Key::<T>::kill(); Key::<T>::kill();
Ok(Pays::No.into()) Ok(Pays::No.into())
} }
} }
#[pallet::event] #[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)] #[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> { pub enum Event<T: Config> {
Sudid { Sudid {
sudo_result: DispatchResult, sudo_result: DispatchResult,
}, },
KeyChanged { KeyChanged {
old: Option<T::AccountId>, old: Option<T::AccountId>,
new: T::AccountId, new: T::AccountId,
}, },
KeyRemoved, KeyRemoved,
SudoAsDone { sudo_result: DispatchResult }, SudoAsDone {
} sudo_result: DispatchResult,
},
}
#[pallet::error] #[pallet::error]
pub enum Error<T> { pub enum Error<T> {
RequireSudo, RequireSudo,
} }
#[pallet::storage] #[pallet::storage]
pub(super) type Key<T: Config> = StorageValue<_, T::AccountId, OptionQuery>; pub(super) type Key<T: Config> = StorageValue<_, T::AccountId, OptionQuery>;
#[pallet::genesis_config] #[pallet::genesis_config]
#[derive(frame_support::DefaultNoBound)] #[derive(frame_support::DefaultNoBound)]
pub struct GenesisConfig<T: Config> { pub struct GenesisConfig<T: Config> {
pub key: Option<T::AccountId>, pub key: Option<T::AccountId>,
} }
#[pallet::genesis_build] #[pallet::genesis_build]
impl<T: Config> BuildGenesisConfig for GenesisConfig<T> { impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
fn build(&self) { fn build(&self) {
Key::<T>::set(self.key.clone()); Key::<T>::set(self.key.clone());
} }
} }
impl<T: Config> Pallet<T> { impl<T: Config> Pallet<T> {
pub(crate) fn ensure_sudo(origin: OriginFor<T>) -> DispatchResult { pub(crate) fn ensure_sudo(origin: OriginFor<T>) -> DispatchResult {
let sender = ensure_signed_or_root(origin)?; let sender = ensure_signed_or_root(origin)?;
if let Some(sender) = sender { if let Some(sender) = sender {
if Key::<T>::get().map_or(false, |k| k == sender) { if Key::<T>::get().map_or(false, |k| k == sender) {
Ok(()) Ok(())
} else { } else {
Err(Error::<T>::RequireSudo.into()) Err(Error::<T>::RequireSudo.into())
} }
} else { } else {
Ok(()) Ok(())
} }
} }
} }
} }

View File

@ -6,104 +6,122 @@ use sp_runtime::BuildStorage;
#[frame_support::pallet] #[frame_support::pallet]
pub mod logger { pub mod logger {
use frame_support::pallet_prelude::*; use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*; use frame_system::pallet_prelude::*;
#[pallet::config] #[pallet::config]
pub trait Config: frame_system::Config { pub trait Config: frame_system::Config {
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>; type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
} }
#[pallet::pallet] #[pallet::pallet]
pub struct Pallet<T>(_); pub struct Pallet<T>(_);
#[pallet::call] #[pallet::call]
impl<T: Config> Pallet<T> { impl<T: Config> Pallet<T> {
#[pallet::call_index(0)] #[pallet::call_index(0)]
#[pallet::weight(*weight)] #[pallet::weight(*weight)]
pub fn privileged_i32_log( pub fn privileged_i32_log(
origin: OriginFor<T>, origin: OriginFor<T>,
i: i32, i: i32,
weight: Weight, weight: Weight,
) -> DispatchResultWithPostInfo { ) -> DispatchResultWithPostInfo {
ensure_root(origin)?; ensure_root(origin)?;
<I32Log<T>>::try_append(i).map_err(|_| "could not append")?; <I32Log<T>>::try_append(i).map_err(|_| "could not append")?;
Self::deposit_event(Event::AppendI32 { value: i, weight }); Self::deposit_event(Event::AppendI32 { value: i, weight });
Ok(().into()) Ok(().into())
} }
#[pallet::call_index(1)] #[pallet::call_index(1)]
#[pallet::weight(*weight)] #[pallet::weight(*weight)]
pub fn non_privileged_log( pub fn non_privileged_log(
origin: OriginFor<T>, origin: OriginFor<T>,
i: i32, i: i32,
weight: Weight, weight: Weight,
) -> DispatchResultWithPostInfo { ) -> DispatchResultWithPostInfo {
let sender = ensure_signed(origin)?; let sender = ensure_signed(origin)?;
<I32Log<T>>::try_append(i).map_err(|_| "could not append")?; <I32Log<T>>::try_append(i).map_err(|_| "could not append")?;
<AccountLog<T>>::try_append(sender.clone()).map_err(|_| "could not append")?; <AccountLog<T>>::try_append(sender.clone()).map_err(|_| "could not append")?;
Self::deposit_event(Event::AppendI32AndAccount { sender, value: i, weight }); Self::deposit_event(Event::AppendI32AndAccount {
Ok(().into()) sender,
} value: i,
} weight,
});
Ok(().into())
}
}
#[pallet::event] #[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)] #[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> { pub enum Event<T: Config> {
AppendI32 { value: i32, weight: Weight }, AppendI32 {
AppendI32AndAccount { sender: T::AccountId, value: i32, weight: Weight }, value: i32,
} weight: Weight,
},
AppendI32AndAccount {
sender: T::AccountId,
value: i32,
weight: Weight,
},
}
#[pallet::storage] #[pallet::storage]
#[pallet::getter(fn account_log)] #[pallet::getter(fn account_log)]
pub(super) type AccountLog<T: Config> = pub(super) type AccountLog<T: Config> =
StorageValue<_, BoundedVec<T::AccountId, ConstU32<1_000>>, ValueQuery>; StorageValue<_, BoundedVec<T::AccountId, ConstU32<1_000>>, ValueQuery>;
#[pallet::storage] #[pallet::storage]
#[pallet::getter(fn i32_log)] #[pallet::getter(fn i32_log)]
pub(super) type I32Log<T> = StorageValue<_, BoundedVec<i32, ConstU32<1_000>>, ValueQuery>; pub(super) type I32Log<T> = StorageValue<_, BoundedVec<i32, ConstU32<1_000>>, ValueQuery>;
} }
type Block = frame_system::mocking::MockBlock<Test>; type Block = frame_system::mocking::MockBlock<Test>;
frame_support::construct_runtime!( frame_support::construct_runtime!(
pub enum Test pub enum Test
{ {
System: frame_system, System: frame_system,
Sudo: sudo, Sudo: sudo,
Logger: logger, Logger: logger,
} }
); );
#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] #[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
impl frame_system::Config for Test { impl frame_system::Config for Test {
type Block = Block; type Block = Block;
} }
impl logger::Config for Test { impl logger::Config for Test {
type RuntimeEvent = RuntimeEvent; type RuntimeEvent = RuntimeEvent;
} }
impl Config for Test { impl Config for Test {
type RuntimeEvent = RuntimeEvent; type RuntimeEvent = RuntimeEvent;
type RuntimeCall = RuntimeCall; type RuntimeCall = RuntimeCall;
type WeightInfo = (); type WeightInfo = ();
} }
pub type SudoCall = sudo::Call<Test>; pub type SudoCall = sudo::Call<Test>;
pub type LoggerCall = logger::Call<Test>; pub type LoggerCall = logger::Call<Test>;
pub fn new_test_ext(root_key: u64) -> sp_io::TestExternalities { pub fn new_test_ext(root_key: u64) -> sp_io::TestExternalities {
let mut t = frame_system::GenesisConfig::<Test>::default().build_storage().unwrap(); let mut t = frame_system::GenesisConfig::<Test>::default()
sudo::GenesisConfig::<Test> { key: Some(root_key) } .build_storage()
.assimilate_storage(&mut t) .unwrap();
.unwrap(); sudo::GenesisConfig::<Test> {
let mut ext: sp_io::TestExternalities = t.into(); key: Some(root_key),
ext.execute_with(|| System::set_block_number(1)); }
ext .assimilate_storage(&mut t)
.unwrap();
let mut ext: sp_io::TestExternalities = t.into();
ext.execute_with(|| System::set_block_number(1));
ext
} }
#[cfg(feature = "runtime-benchmarks")] #[cfg(feature = "runtime-benchmarks")]
pub fn new_bench_ext() -> sp_io::TestExternalities { pub fn new_bench_ext() -> sp_io::TestExternalities {
frame_system::GenesisConfig::<Test>::default().build_storage().unwrap().into() frame_system::GenesisConfig::<Test>::default()
.build_storage()
.unwrap()
.into()
} }

View File

@ -1,188 +1,217 @@
use super::*; use super::*;
use frame_support::{assert_noop, assert_ok, weights::Weight}; use frame_support::{assert_noop, assert_ok, weights::Weight};
use mock::{ use mock::{
new_test_ext, Logger, LoggerCall, RuntimeCall, RuntimeEvent as TestEvent, RuntimeOrigin, Sudo, new_test_ext, Logger, LoggerCall, RuntimeCall, RuntimeEvent as TestEvent, RuntimeOrigin, Sudo,
SudoCall, System, Test, SudoCall, System, Test,
}; };
#[test] #[test]
fn test_setup_works() { fn test_setup_works() {
new_test_ext(1).execute_with(|| { new_test_ext(1).execute_with(|| {
assert_eq!(Key::<Test>::get(), Some(1u64)); assert_eq!(Key::<Test>::get(), Some(1u64));
assert!(Logger::i32_log().is_empty()); assert!(Logger::i32_log().is_empty());
assert!(Logger::account_log().is_empty()); assert!(Logger::account_log().is_empty());
}); });
} }
#[docify::export] #[docify::export]
#[test] #[test]
fn sudo_basics() { fn sudo_basics() {
new_test_ext(1).execute_with(|| { new_test_ext(1).execute_with(|| {
let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log { let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log {
i: 42, i: 42,
weight: Weight::from_parts(1_000, 0), weight: Weight::from_parts(1_000, 0),
})); }));
assert_ok!(Sudo::sudo(RuntimeOrigin::signed(1), call)); assert_ok!(Sudo::sudo(RuntimeOrigin::signed(1), call));
assert_eq!(Logger::i32_log(), vec![42i32]); assert_eq!(Logger::i32_log(), vec![42i32]);
let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log { let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log {
i: 42, i: 42,
weight: Weight::from_parts(1_000, 0), weight: Weight::from_parts(1_000, 0),
})); }));
assert_noop!(Sudo::sudo(RuntimeOrigin::signed(2), call), Error::<Test>::RequireSudo); assert_noop!(
}); Sudo::sudo(RuntimeOrigin::signed(2), call),
Error::<Test>::RequireSudo
);
});
} }
#[test] #[test]
fn sudo_emits_events_correctly() { fn sudo_emits_events_correctly() {
new_test_ext(1).execute_with(|| { new_test_ext(1).execute_with(|| {
let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log { let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log {
i: 42, i: 42,
weight: Weight::from_parts(1, 0), weight: Weight::from_parts(1, 0),
})); }));
assert_ok!(Sudo::sudo(RuntimeOrigin::signed(1), call)); assert_ok!(Sudo::sudo(RuntimeOrigin::signed(1), call));
System::assert_has_event(TestEvent::Sudo(Event::Sudid { sudo_result: Ok(()) })); System::assert_has_event(TestEvent::Sudo(Event::Sudid {
}) sudo_result: Ok(()),
}));
})
} }
#[test] #[test]
fn sudo_unchecked_weight_basics() { fn sudo_unchecked_weight_basics() {
new_test_ext(1).execute_with(|| { new_test_ext(1).execute_with(|| {
let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log { let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log {
i: 42, i: 42,
weight: Weight::from_parts(1_000, 0), weight: Weight::from_parts(1_000, 0),
})); }));
assert_ok!(Sudo::sudo_unchecked_weight( assert_ok!(Sudo::sudo_unchecked_weight(
RuntimeOrigin::signed(1), RuntimeOrigin::signed(1),
call, call,
Weight::from_parts(1_000, 0) Weight::from_parts(1_000, 0)
)); ));
assert_eq!(Logger::i32_log(), vec![42i32]); assert_eq!(Logger::i32_log(), vec![42i32]);
let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log { let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log {
i: 42, i: 42,
weight: Weight::from_parts(1_000, 0), weight: Weight::from_parts(1_000, 0),
})); }));
assert_noop!( assert_noop!(
Sudo::sudo_unchecked_weight( Sudo::sudo_unchecked_weight(
RuntimeOrigin::signed(2), RuntimeOrigin::signed(2),
call, call,
Weight::from_parts(1_000, 0) Weight::from_parts(1_000, 0)
), ),
Error::<Test>::RequireSudo, Error::<Test>::RequireSudo,
); );
assert_eq!(Logger::i32_log(), vec![42i32]); assert_eq!(Logger::i32_log(), vec![42i32]);
let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log { let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log {
i: 42, i: 42,
weight: Weight::from_parts(1, 0), weight: Weight::from_parts(1, 0),
})); }));
let sudo_unchecked_weight_call = let sudo_unchecked_weight_call = SudoCall::sudo_unchecked_weight {
SudoCall::sudo_unchecked_weight { call, weight: Weight::from_parts(1_000, 0) }; call,
let info = sudo_unchecked_weight_call.get_dispatch_info(); weight: Weight::from_parts(1_000, 0),
assert_eq!(info.weight, Weight::from_parts(1_000, 0)); };
}); let info = sudo_unchecked_weight_call.get_dispatch_info();
assert_eq!(info.weight, Weight::from_parts(1_000, 0));
});
} }
#[test] #[test]
fn sudo_unchecked_weight_emits_events_correctly() { fn sudo_unchecked_weight_emits_events_correctly() {
new_test_ext(1).execute_with(|| { new_test_ext(1).execute_with(|| {
let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log { let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log {
i: 42, i: 42,
weight: Weight::from_parts(1, 0), weight: Weight::from_parts(1, 0),
})); }));
assert_ok!(Sudo::sudo_unchecked_weight( assert_ok!(Sudo::sudo_unchecked_weight(
RuntimeOrigin::signed(1), RuntimeOrigin::signed(1),
call, call,
Weight::from_parts(1_000, 0) Weight::from_parts(1_000, 0)
)); ));
System::assert_has_event(TestEvent::Sudo(Event::Sudid { sudo_result: Ok(()) })); System::assert_has_event(TestEvent::Sudo(Event::Sudid {
}) sudo_result: Ok(()),
}));
})
} }
#[docify::export] #[docify::export]
#[test] #[test]
fn set_key_basics() { fn set_key_basics() {
new_test_ext(1).execute_with(|| { new_test_ext(1).execute_with(|| {
assert_ok!(Sudo::set_key(RuntimeOrigin::signed(1), 2)); assert_ok!(Sudo::set_key(RuntimeOrigin::signed(1), 2));
assert_eq!(Key::<Test>::get(), Some(2u64)); assert_eq!(Key::<Test>::get(), Some(2u64));
}); });
new_test_ext(1).execute_with(|| { new_test_ext(1).execute_with(|| {
assert_noop!(Sudo::set_key(RuntimeOrigin::signed(2), 3), Error::<Test>::RequireSudo); assert_noop!(
}); Sudo::set_key(RuntimeOrigin::signed(2), 3),
Error::<Test>::RequireSudo
);
});
} }
#[test] #[test]
fn set_key_emits_events_correctly() { fn set_key_emits_events_correctly() {
new_test_ext(1).execute_with(|| { new_test_ext(1).execute_with(|| {
assert_ok!(Sudo::set_key(RuntimeOrigin::signed(1), 2)); assert_ok!(Sudo::set_key(RuntimeOrigin::signed(1), 2));
System::assert_has_event(TestEvent::Sudo(Event::KeyChanged { old: Some(1), new: 2 })); System::assert_has_event(TestEvent::Sudo(Event::KeyChanged {
assert_ok!(Sudo::set_key(RuntimeOrigin::signed(2), 4)); old: Some(1),
System::assert_has_event(TestEvent::Sudo(Event::KeyChanged { old: Some(2), new: 4 })); new: 2,
}); }));
assert_ok!(Sudo::set_key(RuntimeOrigin::signed(2), 4));
System::assert_has_event(TestEvent::Sudo(Event::KeyChanged {
old: Some(2),
new: 4,
}));
});
} }
#[test] #[test]
fn remove_key_works() { fn remove_key_works() {
new_test_ext(1).execute_with(|| { new_test_ext(1).execute_with(|| {
assert_ok!(Sudo::remove_key(RuntimeOrigin::signed(1))); assert_ok!(Sudo::remove_key(RuntimeOrigin::signed(1)));
assert!(Key::<Test>::get().is_none()); assert!(Key::<Test>::get().is_none());
System::assert_has_event(TestEvent::Sudo(Event::KeyRemoved {})); System::assert_has_event(TestEvent::Sudo(Event::KeyRemoved {}));
assert_noop!(Sudo::remove_key(RuntimeOrigin::signed(1)), Error::<Test>::RequireSudo); assert_noop!(
assert_noop!(Sudo::set_key(RuntimeOrigin::signed(1), 1), Error::<Test>::RequireSudo); Sudo::remove_key(RuntimeOrigin::signed(1)),
}); Error::<Test>::RequireSudo
);
assert_noop!(
Sudo::set_key(RuntimeOrigin::signed(1), 1),
Error::<Test>::RequireSudo
);
});
} }
#[test] #[test]
fn using_root_origin_works() { fn using_root_origin_works() {
new_test_ext(1).execute_with(|| { new_test_ext(1).execute_with(|| {
assert_ok!(Sudo::remove_key(RuntimeOrigin::root())); assert_ok!(Sudo::remove_key(RuntimeOrigin::root()));
assert!(Key::<Test>::get().is_none()); assert!(Key::<Test>::get().is_none());
System::assert_has_event(TestEvent::Sudo(Event::KeyRemoved {})); System::assert_has_event(TestEvent::Sudo(Event::KeyRemoved {}));
assert_ok!(Sudo::set_key(RuntimeOrigin::root(), 1)); assert_ok!(Sudo::set_key(RuntimeOrigin::root(), 1));
assert_eq!(Some(1), Key::<Test>::get()); assert_eq!(Some(1), Key::<Test>::get());
}); });
} }
#[test] #[test]
fn sudo_as_basics() { fn sudo_as_basics() {
new_test_ext(1).execute_with(|| { new_test_ext(1).execute_with(|| {
let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log { let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log {
i: 42, i: 42,
weight: Weight::from_parts(1_000, 0), weight: Weight::from_parts(1_000, 0),
})); }));
assert_ok!(Sudo::sudo_as(RuntimeOrigin::signed(1), 2, call)); assert_ok!(Sudo::sudo_as(RuntimeOrigin::signed(1), 2, call));
assert!(Logger::i32_log().is_empty()); assert!(Logger::i32_log().is_empty());
assert!(Logger::account_log().is_empty()); assert!(Logger::account_log().is_empty());
let call = Box::new(RuntimeCall::Logger(LoggerCall::non_privileged_log { let call = Box::new(RuntimeCall::Logger(LoggerCall::non_privileged_log {
i: 42, i: 42,
weight: Weight::from_parts(1, 0), weight: Weight::from_parts(1, 0),
})); }));
assert_noop!(Sudo::sudo_as(RuntimeOrigin::signed(3), 2, call), Error::<Test>::RequireSudo); assert_noop!(
Sudo::sudo_as(RuntimeOrigin::signed(3), 2, call),
Error::<Test>::RequireSudo
);
let call = Box::new(RuntimeCall::Logger(LoggerCall::non_privileged_log { let call = Box::new(RuntimeCall::Logger(LoggerCall::non_privileged_log {
i: 42, i: 42,
weight: Weight::from_parts(1, 0), weight: Weight::from_parts(1, 0),
})); }));
assert_ok!(Sudo::sudo_as(RuntimeOrigin::signed(1), 2, call)); assert_ok!(Sudo::sudo_as(RuntimeOrigin::signed(1), 2, call));
assert_eq!(Logger::i32_log(), vec![42i32]); assert_eq!(Logger::i32_log(), vec![42i32]);
assert_eq!(Logger::account_log(), vec![2]); assert_eq!(Logger::account_log(), vec![2]);
}); });
} }
#[docify::export] #[docify::export]
#[test] #[test]
fn sudo_as_emits_events_correctly() { fn sudo_as_emits_events_correctly() {
new_test_ext(1).execute_with(|| { new_test_ext(1).execute_with(|| {
let call = Box::new(RuntimeCall::Logger(LoggerCall::non_privileged_log { let call = Box::new(RuntimeCall::Logger(LoggerCall::non_privileged_log {
i: 42, i: 42,
weight: Weight::from_parts(1, 0), weight: Weight::from_parts(1, 0),
})); }));
assert_ok!(Sudo::sudo_as(RuntimeOrigin::signed(1), 2, call)); assert_ok!(Sudo::sudo_as(RuntimeOrigin::signed(1), 2, call));
System::assert_has_event(TestEvent::Sudo(Event::SudoAsDone { sudo_result: Ok(()) })); System::assert_has_event(TestEvent::Sudo(Event::SudoAsDone {
}); sudo_result: Ok(()),
}));
});
} }

View File

@ -1,17 +1,15 @@
use std::sync::Arc; use std::sync::Arc;
use jsonrpsee::RpcModule; use babe_primitives::BabeApi;
use primitives::{ use block_builder_api::BlockBuilder;
AccountId, Balance, Block, BlockNumber, Hash, Nonce, use consensus_common::SelectChain;
};
use sc_client_api::AuxStore;
use grandpa::FinalityProofProvider; use grandpa::FinalityProofProvider;
use jsonrpsee::RpcModule;
use primitives::{AccountId, Balance, Block, BlockNumber, Hash, Nonce};
use sc_client_api::AuxStore;
pub use sc_rpc::{DenyUnsafe, SubscriptionTaskExecutor}; pub use sc_rpc::{DenyUnsafe, SubscriptionTaskExecutor};
use sp_api::ProvideRuntimeApi; use sp_api::ProvideRuntimeApi;
use block_builder_api::BlockBuilder;
use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};
use consensus_common::SelectChain;
use babe_primitives::BabeApi;
use sp_keystore::KeystorePtr; use sp_keystore::KeystorePtr;
use tx_pool_api::TransactionPool; use tx_pool_api::TransactionPool;
@ -61,7 +59,16 @@ pub struct FullDeps<C, P, SC, B> {
} }
pub fn create_full_rpc<C, P, SC, B>( pub fn create_full_rpc<C, P, SC, B>(
FullDeps { client, pool, select_chain, chain_spec, deny_unsafe, babe, grandpa, backend } : FullDeps<C, P, SC, B>, FullDeps {
client,
pool,
select_chain,
chain_spec,
deny_unsafe,
babe,
grandpa,
backend,
}: FullDeps<C, P, SC, B>,
) -> Result<RpcExtension, Box<dyn std::error::Error + Send + Sync>> ) -> Result<RpcExtension, Box<dyn std::error::Error + Send + Sync>>
where where
C: ProvideRuntimeApi<Block> C: ProvideRuntimeApi<Block>
@ -80,20 +87,19 @@ where
B: sc_client_api::Backend<Block> + Send + Sync + 'static, B: sc_client_api::Backend<Block> + Send + Sync + 'static,
B::State: sc_client_api::StateBackend<sp_runtime::traits::HashingFor<Block>>, B::State: sc_client_api::StateBackend<sp_runtime::traits::HashingFor<Block>>,
{ {
use frame_rpc_system::{System, SystemApiServer};
use pallet_transaction_payment_rpc::{
TransactionPayment, TransactionPaymentApiServer,
};
use babe_rpc::{Babe, BabeApiServer}; use babe_rpc::{Babe, BabeApiServer};
use frame_rpc_system::{System, SystemApiServer};
use grandpa_rpc::{Grandpa, GrandpaApiServer}; use grandpa_rpc::{Grandpa, GrandpaApiServer};
use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer};
use sc_rpc_spec_v2::chain_spec::{ChainSpec, ChainSpecApiServer}; use sc_rpc_spec_v2::chain_spec::{ChainSpec, ChainSpecApiServer};
use sc_sync_state_rpc::{SyncState, SyncStateApiServer}; use sc_sync_state_rpc::{SyncState, SyncStateApiServer};
use substrate_state_trie_migration_rpc::{ use substrate_state_trie_migration_rpc::{StateMigration, StateMigrationApiServer};
StateMigration, StateMigrationApiServer,
};
let mut io = RpcModule::new(()); let mut io = RpcModule::new(());
let BabeDeps { babe_worker_handle, keystore } = babe; let BabeDeps {
babe_worker_handle,
keystore,
} = babe;
let GrandpaDeps { let GrandpaDeps {
shared_voter_state, shared_voter_state,
shared_authority_set, shared_authority_set,
@ -103,10 +109,13 @@ where
} = grandpa; } = grandpa;
let chain_name = chain_spec.name().to_string(); let chain_name = chain_spec.name().to_string();
let genesis_hash = client.hash(0).ok().flatten().expect("Genesis block exists; qed;"); let genesis_hash = client
.hash(0)
.ok()
.flatten()
.expect("Genesis block exists; qed;");
let properties = chain_spec.properties(); let properties = chain_spec.properties();
io.merge(ChainSpec::new(chain_name, genesis_hash, properties).into_rpc())?; io.merge(ChainSpec::new(chain_name, genesis_hash, properties).into_rpc())?;
io.merge(StateMigration::new(client.clone(), backend.clone(), deny_unsafe).into_rpc())?; io.merge(StateMigration::new(client.clone(), backend.clone(), deny_unsafe).into_rpc())?;
io.merge(System::new(client.clone(), pool.clone(), deny_unsafe).into_rpc())?; io.merge(System::new(client.clone(), pool.clone(), deny_unsafe).into_rpc())?;
@ -119,7 +128,8 @@ where
keystore, keystore,
select_chain, select_chain,
deny_unsafe, deny_unsafe,
).into_rpc() )
.into_rpc(),
)?; )?;
io.merge( io.merge(
@ -129,7 +139,8 @@ where
shared_voter_state, shared_voter_state,
justification_stream, justification_stream,
finality_provider, finality_provider,
).into_rpc(), )
.into_rpc(),
)?; )?;
io.merge( io.merge(
@ -137,8 +148,9 @@ where
chain_spec, chain_spec,
client.clone(), client.clone(),
shared_authority_set, shared_authority_set,
babe_worker_handle babe_worker_handle,
)?.into_rpc(), )?
.into_rpc(),
)?; )?;
Ok(io) Ok(io)

View File

@ -1,6 +1,6 @@
[package] [package]
name = "casper-runtime" name = "casper-runtime"
version = "3.5.28" version = "3.5.29"
build = "build.rs" build = "build.rs"
description = "Runtime of the Casper Network" description = "Runtime of the Casper Network"
edition.workspace = true edition.workspace = true

View File

@ -10,15 +10,15 @@ pub mod currency {
/// Constant values used within runtime. /// Constant values used within runtime.
pub const FTSO: Balance = 1_000_000_000; // 10^9 pub const FTSO: Balance = 1_000_000_000; // 10^9
pub const STNK: Balance = 1_000 * FTSO; // 10^12 pub const STNK: Balance = 1_000 * FTSO; // 10^12
pub const STRH: Balance = 1_000 * STNK; // 10^15 pub const STRH: Balance = 1_000 * STNK; // 10^15
pub const CSPR: Balance = 1_000 * STRH; // 10^18 pub const CSPR: Balance = 1_000 * STRH; // 10^18
/// The existential deposit. /// The existential deposit.
pub const EXISTENTIAL_DEPOSIT: Balance = STNK; pub const EXISTENTIAL_DEPOSIT: Balance = STNK;
pub const fn deposit(items: u32, bytes: u32) -> Balance { pub const fn deposit(items: u32, bytes: u32) -> Balance {
(items as Balance) * 200 * STRH + (bytes as Balance) * 1000 * STNK (items as Balance) * 200 * STRH + (bytes as Balance) * 1000 * STNK
} }
} }
@ -86,7 +86,7 @@ pub mod fee {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{ use super::{
currency::{STNK, STRH, CSPR}, currency::{CSPR, STNK, STRH},
fee::WeightToFee, fee::WeightToFee,
}; };
use crate::weights::ExtrinsicBaseWeight; use crate::weights::ExtrinsicBaseWeight;

View File

@ -37,43 +37,43 @@ use sp_core::parameter_types;
use sp_weights::{constants::WEIGHT_REF_TIME_PER_NANOS, Weight}; use sp_weights::{constants::WEIGHT_REF_TIME_PER_NANOS, Weight};
parameter_types! { parameter_types! {
/// Time to execute an empty block. /// Time to execute an empty block.
/// Calculated by multiplying the *Average* with `1.0` and adding `0`. /// Calculated by multiplying the *Average* with `1.0` and adding `0`.
/// ///
/// Stats nanoseconds: /// Stats nanoseconds:
/// Min, Max: 64_363_191, 66_078_314 /// Min, Max: 64_363_191, 66_078_314
/// Average: 64_551_214 /// Average: 64_551_214
/// Median: 64_500_078 /// Median: 64_500_078
/// Std-Dev: 229678.99 /// Std-Dev: 229678.99
/// ///
/// Percentiles nanoseconds: /// Percentiles nanoseconds:
/// 99th: 65_668_012 /// 99th: 65_668_012
/// 95th: 64_888_421 /// 95th: 64_888_421
/// 75th: 64_563_448 /// 75th: 64_563_448
pub const BlockExecutionWeight: Weight = pub const BlockExecutionWeight: Weight =
Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(64_551_214), 0); Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(64_551_214), 0);
} }
#[cfg(test)] #[cfg(test)]
mod test_weights { mod test_weights {
use sp_weights::constants; use sp_weights::constants;
/// Checks that the weight exists and is sane. /// Checks that the weight exists and is sane.
// NOTE: If this test fails but you are sure that the generated values are fine, // NOTE: If this test fails but you are sure that the generated values are fine,
// you can delete it. // you can delete it.
#[test] #[test]
fn sane() { fn sane() {
let w = super::BlockExecutionWeight::get(); let w = super::BlockExecutionWeight::get();
// At least 100 µs. // At least 100 µs.
assert!( assert!(
w.ref_time() >= 100u64 * constants::WEIGHT_REF_TIME_PER_MICROS, w.ref_time() >= 100u64 * constants::WEIGHT_REF_TIME_PER_MICROS,
"Weight should be at least 100 µs." "Weight should be at least 100 µs."
); );
// At most 50 ms. // At most 50 ms.
assert!( assert!(
w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS,
"Weight should be at most 50 ms." "Weight should be at most 50 ms."
); );
} }
} }

View File

@ -37,43 +37,43 @@ use sp_core::parameter_types;
use sp_weights::{constants::WEIGHT_REF_TIME_PER_NANOS, Weight}; use sp_weights::{constants::WEIGHT_REF_TIME_PER_NANOS, Weight};
parameter_types! { parameter_types! {
/// Time to execute a NO-OP extrinsic, for example `System::remark`. /// Time to execute a NO-OP extrinsic, for example `System::remark`.
/// Calculated by multiplying the *Average* with `1.0` and adding `0`. /// Calculated by multiplying the *Average* with `1.0` and adding `0`.
/// ///
/// Stats nanoseconds: /// Stats nanoseconds:
/// Min, Max: 402_868, 1_292_427 /// Min, Max: 402_868, 1_292_427
/// Average: 565_926 /// Average: 565_926
/// Median: 414_626 /// Median: 414_626
/// Std-Dev: 283192.19 /// Std-Dev: 283192.19
/// ///
/// Percentiles nanoseconds: /// Percentiles nanoseconds:
/// 99th: 1_251_123 /// 99th: 1_251_123
/// 95th: 1_196_903 /// 95th: 1_196_903
/// 75th: 491_329 /// 75th: 491_329
pub const ExtrinsicBaseWeight: Weight = pub const ExtrinsicBaseWeight: Weight =
Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(565_926), 0); Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(565_926), 0);
} }
#[cfg(test)] #[cfg(test)]
mod test_weights { mod test_weights {
use sp_weights::constants; use sp_weights::constants;
/// Checks that the weight exists and is sane. /// Checks that the weight exists and is sane.
// NOTE: If this test fails but you are sure that the generated values are fine, // NOTE: If this test fails but you are sure that the generated values are fine,
// you can delete it. // you can delete it.
#[test] #[test]
fn sane() { fn sane() {
let w = super::ExtrinsicBaseWeight::get(); let w = super::ExtrinsicBaseWeight::get();
// At least 10 µs. // At least 10 µs.
assert!( assert!(
w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS,
"Weight should be at least 10 µs." "Weight should be at least 10 µs."
); );
// At most 1 ms. // At most 1 ms.
assert!( assert!(
w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS,
"Weight should be at most 1 ms." "Weight should be at most 1 ms."
); );
} }
} }

View File

@ -1,9 +1,9 @@
pub mod block_weights; pub mod block_weights;
pub mod extrinsic_weights; pub mod extrinsic_weights;
pub mod rocksdb_weights;
pub mod paritydb_weights; pub mod paritydb_weights;
pub mod rocksdb_weights;
pub use block_weights::BlockExecutionWeight; pub use block_weights::BlockExecutionWeight;
pub use extrinsic_weights::ExtrinsicBaseWeight; pub use extrinsic_weights::ExtrinsicBaseWeight;
pub use rocksdb_weights::constants::RocksDbWeight;
pub use paritydb_weights::constants::ParityDbWeight; pub use paritydb_weights::constants::ParityDbWeight;
pub use rocksdb_weights::constants::RocksDbWeight;

View File

@ -37,47 +37,47 @@
/// Storage DB weights for the `Development` runtime and `ParityDb`. /// Storage DB weights for the `Development` runtime and `ParityDb`.
pub mod constants { pub mod constants {
use frame_support::weights::constants; use frame_support::weights::constants;
use sp_core::parameter_types; use sp_core::parameter_types;
use sp_weights::RuntimeDbWeight; use sp_weights::RuntimeDbWeight;
parameter_types! { parameter_types! {
/// `ParityDB` can be enabled with a feature flag, but is still experimental. These weights /// `ParityDB` can be enabled with a feature flag, but is still experimental. These weights
/// are available for brave runtime engineers who may want to try this out as default. /// are available for brave runtime engineers who may want to try this out as default.
pub const ParityDbWeight: RuntimeDbWeight = RuntimeDbWeight { pub const ParityDbWeight: RuntimeDbWeight = RuntimeDbWeight {
read: 40_820 * constants::WEIGHT_REF_TIME_PER_NANOS, read: 40_820 * constants::WEIGHT_REF_TIME_PER_NANOS,
write: 293_659 * constants::WEIGHT_REF_TIME_PER_NANOS, write: 293_659 * constants::WEIGHT_REF_TIME_PER_NANOS,
}; };
} }
#[cfg(test)] #[cfg(test)]
mod test_db_weights { mod test_db_weights {
use super::constants::ParityDbWeight as W; use super::constants::ParityDbWeight as W;
use sp_weights::constants; use sp_weights::constants;
/// Checks that all weights exist and have sane values. /// Checks that all weights exist and have sane values.
// NOTE: If this test fails but you are sure that the generated values are fine, // NOTE: If this test fails but you are sure that the generated values are fine,
// you can delete it. // you can delete it.
#[test] #[test]
fn bound() { fn bound() {
// At least 1 µs. // At least 1 µs.
assert!( assert!(
W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS,
"Read weight should be at least 1 µs." "Read weight should be at least 1 µs."
); );
assert!( assert!(
W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS,
"Write weight should be at least 1 µs." "Write weight should be at least 1 µs."
); );
// At most 1 ms. // At most 1 ms.
assert!( assert!(
W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS,
"Read weight should be at most 1 ms." "Read weight should be at most 1 ms."
); );
assert!( assert!(
W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS,
"Write weight should be at most 1 ms." "Write weight should be at most 1 ms."
); );
} }
} }
} }

View File

@ -36,47 +36,47 @@
/// Storage DB weights for the `Development` runtime and `RocksDb`. /// Storage DB weights for the `Development` runtime and `RocksDb`.
pub mod constants { pub mod constants {
use frame_support::weights::constants; use frame_support::weights::constants;
use sp_core::parameter_types; use sp_core::parameter_types;
use sp_weights::RuntimeDbWeight; use sp_weights::RuntimeDbWeight;
parameter_types! { parameter_types! {
/// By default, Substrate uses `RocksDB`, so this will be the weight used throughout /// By default, Substrate uses `RocksDB`, so this will be the weight used throughout
/// the runtime. /// the runtime.
pub const RocksDbWeight: RuntimeDbWeight = RuntimeDbWeight { pub const RocksDbWeight: RuntimeDbWeight = RuntimeDbWeight {
read: 31_627 * constants::WEIGHT_REF_TIME_PER_NANOS, read: 31_627 * constants::WEIGHT_REF_TIME_PER_NANOS,
write: 412_279 * constants::WEIGHT_REF_TIME_PER_NANOS, write: 412_279 * constants::WEIGHT_REF_TIME_PER_NANOS,
}; };
} }
#[cfg(test)] #[cfg(test)]
mod test_db_weights { mod test_db_weights {
use super::constants::RocksDbWeight as W; use super::constants::RocksDbWeight as W;
use sp_weights::constants; use sp_weights::constants;
/// Checks that all weights exist and have sane values. /// Checks that all weights exist and have sane values.
// NOTE: If this test fails but you are sure that the generated values are fine, // NOTE: If this test fails but you are sure that the generated values are fine,
// you can delete it. // you can delete it.
#[test] #[test]
fn bound() { fn bound() {
// At least 1 µs. // At least 1 µs.
assert!( assert!(
W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS,
"Read weight should be at least 1 µs." "Read weight should be at least 1 µs."
); );
assert!( assert!(
W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS,
"Write weight should be at least 1 µs." "Write weight should be at least 1 µs."
); );
// At most 1 ms. // At most 1 ms.
assert!( assert!(
W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS,
"Read weight should be at most 1 ms." "Read weight should be at most 1 ms."
); );
assert!( assert!(
W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS,
"Write weight should be at most 1 ms." "Write weight should be at most 1 ms."
); );
} }
} }
} }

View File

@ -1,4 +1,3 @@
//! Autogenerated bag thresholds. //! Autogenerated bag thresholds.
//! //!
//! Generated on 2024-06-30T17:36:29.986756974+00:00 //! Generated on 2024-06-30T17:36:29.986756974+00:00
@ -19,204 +18,204 @@ pub const CONSTANT_RATIO: f64 = 1.1717610304252650;
/// Upper thresholds delimiting the bag list. /// Upper thresholds delimiting the bag list.
pub const THRESHOLDS: [u64; 200] = [ pub const THRESHOLDS: [u64; 200] = [
368_934, 368_934,
432_302, 432_302,
506_555, 506_555,
593_561, 593_561,
695_512, 695_512,
814_974, 814_974,
954_955, 954_955,
1_118_979, 1_118_979,
1_311_176, 1_311_176,
1_536_385, 1_536_385,
1_800_276, 1_800_276,
2_109_493, 2_109_493,
2_471_822, 2_471_822,
2_896_385, 2_896_385,
3_393_871, 3_393_871,
3_976_806, 3_976_806,
4_659_866, 4_659_866,
5_460_249, 5_460_249,
6_398_107, 6_398_107,
7_497_052, 7_497_052,
8_784_753, 8_784_753,
10_293_631, 10_293_631,
12_061_676, 12_061_676,
14_133_402, 14_133_402,
16_560_970, 16_560_970,
19_405_499, 19_405_499,
22_738_608, 22_738_608,
26_644_215, 26_644_215,
31_220_653, 31_220_653,
36_583_145, 36_583_145,
42_866_704, 42_866_704,
50_229_533, 50_229_533,
58_857_009, 58_857_009,
68_966_350, 68_966_350,
80_812_081, 80_812_081,
94_692_447, 94_692_447,
110_956_919, 110_956_919,
130_014_994, 130_014_994,
152_346_503, 152_346_503,
178_513_695, 178_513_695,
209_175_391, 209_175_391,
245_103_572, 245_103_572,
287_202_814, 287_202_814,
336_533_065, 336_533_065,
394_336_331, 394_336_331,
462_067_946, 462_067_946,
541_433_213, 541_433_213,
634_430_340, 634_430_340,
743_400_749, 743_400_749,
871_088_028, 871_088_028,
1_020_707_005, 1_020_707_005,
1_196_024_692, 1_196_024_692,
1_401_455_126, 1_401_455_126,
1_642_170_503, 1_642_170_503,
1_924_231_401, 1_924_231_401,
2_254_739_369, 2_254_739_369,
2_642_015_726, 2_642_015_726,
3_095_811_069, 3_095_811_069,
3_627_550_768, 3_627_550_768,
4_250_622_626, 4_250_622_626,
4_980_713_948, 4_980_713_948,
5_836_206_508, 5_836_206_508,
6_838_639_352, 6_838_639_352,
8_013_251_094, 8_013_251_094,
9_389_615_359, 9_389_615_359,
11_002_385_368, 11_002_385_368,
12_892_166_416, 12_892_166_416,
15_106_538_204, 15_106_538_204,
17_701_252_772, 17_701_252_772,
20_741_638_188, 20_741_638_188,
24_304_243_336, 24_304_243_336,
28_478_765_215, 28_478_765_215,
33_370_307_274, 33_370_307_274,
39_102_025_637, 39_102_025_637,
45_818_229_852, 45_818_229_852,
53_688_016_224, 53_688_016_224,
62_909_525_212, 62_909_525_212,
73_714_930_086, 73_714_930_086,
86_376_282_435, 86_376_282_435,
101_212_361_710, 101_212_361_710,
118_596_701_249, 118_596_701_249,
138_966_992_861, 138_966_992_861,
162_836_106_750, 162_836_106_750,
190_805_004_236, 190_805_004_236,
223_577_868_374, 223_577_868_374,
261_979_833_426, 261_979_833_426,
306_977_759_566, 306_977_759_566,
359_704_575_867, 359_704_575_867,
421_487_804_467, 421_487_804_467,
493_882_984_074, 493_882_984_074,
578_712_834_328, 578_712_834_328,
678_113_147_073, 678_113_147_073,
794_586_559_959, 794_586_559_959,
931_065_566_260, 931_065_566_260,
1_090_986_347_314, 1_090_986_347_314,
1_278_375_286_509, 1_278_375_286_509,
1_497_950_342_990, 1_497_950_342_990,
1_755_239_837_428, 1_755_239_837_428,
2_056_721_640_548, 2_056_721_640_548,
2_409_986_268_826, 2_409_986_268_826,
2_823_927_993_670, 2_823_927_993_670,
3_308_968_775_710, 3_308_968_775_710,
3_877_320_662_271, 3_877_320_662_271,
4_543_293_254_512, 4_543_293_254_512,
5_323_653_985_431, 5_323_653_985_431,
6_238_050_279_596, 6_238_050_279_596,
7_309_504_223_464, 7_309_504_223_464,
8_564_992_200_784, 8_564_992_200_784,
10_036_124_086_775, 10_036_124_086_775,
11_759_939_101_395, 11_759_939_101_395,
13_779_838_359_189, 13_779_838_359_189,
16_146_677_594_857, 16_146_677_594_857,
18_920_047_576_494, 18_920_047_576_494,
22_169_774_443_928, 22_169_774_443_928,
25_977_677_746_713, 25_977_677_746_713,
30_439_630_444_544, 30_439_630_444_544,
35_667_972_735_463, 35_667_972_735_463,
41_794_340_485_686, 41_794_340_485_686,
48_972_979_473_452, 48_972_979_473_452,
57_384_628_890_807, 57_384_628_890_807,
67_241_071_879_663, 67_241_071_879_663,
78_790_467_672_613, 78_790_467_672_613,
92_323_599_587_750, 92_323_599_587_750,
108_181_196_185_512, 108_181_196_185_512,
126_762_509_914_973, 126_762_509_914_973,
148_535_369_237_262, 148_535_369_237_262,
174_047_957_312_051, 174_047_957_312_051,
203_942_613_803_381, 203_942_613_803_381,
238_972_007_297_872, 238_972_007_297_872,
280_018_085_514_148, 280_018_085_514_148,
328_114_280_419_768, 328_114_280_419_768,
384_471_527_321_912, 384_471_527_321_912,
450_508_753_023_899, 450_508_753_023_899,
527_888_600_658_885, 527_888_600_658_885,
618_559_290_657_806, 618_559_290_657_806,
724_803_671_800_312, 724_803_671_800_312,
849_296_697_324_749, 849_296_697_324_749,
995_172_773_194_022, 995_172_773_194_022,
1_166_104_674_168_996, 1_166_104_674_168_996,
1_366_396_014_587_981, 1_366_396_014_587_981,
1_601_089_602_022_588, 1_601_089_602_022_588,
1_876_094_401_869_165, 1_876_094_401_869_165,
2_198_334_309_509_284, 2_198_334_309_509_284,
2_575_922_475_729_812, 2_575_922_475_729_812,
3_018_365_574_456_765, 3_018_365_574_456_765,
3_536_803_155_725_606, 3_536_803_155_725_606,
4_144_288_110_164_365, 4_144_288_110_164_365,
4_856_115_306_345_371, 4_856_115_306_345_371,
5_690_206_675_227_153, 5_690_206_675_227_153,
6_667_562_437_096_890, 6_667_562_437_096_890,
7_812_789_831_717_443, 7_812_789_831_717_443,
9_154_722_663_709_264, 9_154_722_663_709_264,
10_727_147_261_685_494, 10_727_147_261_685_494,
12_569_653_128_876_154, 12_569_653_128_876_154,
14_728_629_702_380_078, 14_728_629_702_380_078,
17_258_434_316_813_044, 17_258_434_316_813_044,
20_222_760_778_595_608, 20_222_760_778_595_608,
23_696_243_007_970_824, 23_696_243_007_970_824,
27_766_334_124_227_376, 27_766_334_124_227_376,
32_535_508_284_536_868, 32_535_508_284_536_868,
38_123_840_712_898_664, 38_123_840_712_898_664,
44_672_030_877_514_808, 44_672_030_877_514_808,
52_344_944_932_226_008, 52_344_944_932_226_008,
61_335_766_611_338_904, 61_335_766_611_338_904,
71_870_861_086_426_040, 71_870_861_086_426_040,
84_215_474_244_181_664, 84_215_474_244_181_664,
98_680_410_878_114_672, 98_680_410_878_114_672,
115_629_859_933_328_176, 115_629_859_933_328_176,
135_490_563_823_405_696, 135_490_563_823_405_696,
158_762_562_678_613_984, 158_762_562_678_613_984,
186_031_784_037_248_448, 186_031_784_037_248_448,
217_984_794_955_336_608, 217_984_794_955_336_608,
255_426_087_953_905_344, 255_426_087_953_905_344,
299_298_336_018_362_496, 299_298_336_018_362_496,
350_706_126_617_443_648, 350_706_126_617_443_648,
410_943_772_301_709_248, 410_943_772_301_709_248,
481_527_898_079_096_320, 481_527_898_079_096_320,
564_235_626_031_673_920, 564_235_626_031_673_920,
661_149_318_561_518_720, 661_149_318_561_518_720,
774_709_006_782_606_976, 774_709_006_782_606_976,
907_773_824_067_321_216, 907_773_824_067_321_216,
1_063_693_991_482_207_616, 1_063_693_991_482_207_616,
1_246_395_167_516_354_560, 1_246_395_167_516_354_560,
1_460_477_285_806_034_432, 1_460_477_285_806_034_432,
1_711_330_369_328_773_120, 1_711_330_369_328_773_120,
2_005_270_236_962_732_544, 2_005_270_236_962_732_544,
2_349_697_519_144_566_784, 2_349_697_519_144_566_784,
2_753_283_986_220_526_592, 2_753_283_986_220_526_592,
3_226_190_880_747_145_216, 3_226_190_880_747_145_216,
3_780_324_750_772_868_096, 3_780_324_750_772_868_096,
4_429_637_225_307_749_376, 4_429_637_225_307_749_376,
5_190_476_279_536_719_872, 5_190_476_279_536_719_872,
6_081_997_833_707_842_560, 6_081_997_833_707_842_560,
7_126_648_048_669_730_816, 7_126_648_048_669_730_816,
8_350_728_460_987_448_320, 8_350_728_460_987_448_320,
9_785_058_186_248_239_104, 9_785_058_186_248_239_104,
11_465_749_863_089_412_096, 11_465_749_863_089_412_096,
13_435_118_874_171_990_016, 13_435_118_874_171_990_016,
15_742_748_735_885_697_024, 15_742_748_735_885_697_024,
18_446_744_073_709_551_615, 18_446_744_073_709_551_615,
]; ];

View File

@ -2,25 +2,34 @@ use super::*;
use frame_support::{ use frame_support::{
parameter_types, parameter_types,
traits::{ traits::{
EitherOf, EitherOfDiverse, MapSuccess, OriginTrait, TryWithMorphedArg, tokens::pay::PayFromAccount, EitherOf, EitherOfDiverse, MapSuccess, OriginTrait,
tokens::pay::PayFromAccount, TryWithMorphedArg,
}, },
}; };
use frame_system::EnsureRootWithSuccess; use frame_system::EnsureRootWithSuccess;
use pallet_ranked_collective::EnsureOfRank;
use sp_core::{ConstU128, ConstU32}; use sp_core::{ConstU128, ConstU32};
use sp_runtime::traits::{ConstU16, TakeFirst}; use sp_runtime::traits::{ConstU16, TakeFirst};
use pallet_ranked_collective::EnsureOfRank;
use crate::{ use crate::{
AccountId,
Balance,
Balances,
Preimage,
Runtime,
// weights, // weights,
RuntimeCall, RuntimeEvent, Scheduler, DAYS, CSPR, AccountId, Balance, RuntimeCall,
TreasuryAccount, Balances, Preimage, Runtime, RuntimeEvent,
Scheduler,
TreasuryAccount,
CSPR,
DAYS,
}; };
mod origins; mod origins;
pub use origins::{ pub use origins::{
pallet_cult_origins, Geniuses, Degens, Zombies, Skeletons, Ghosts, pallet_cult_origins, CultTreasurySpender, Degens, EnsureCanPromoteTo, EnsureCanRetainAt,
EnsureCanRetainAt, EnsureCanPromoteTo, EnsureCult, ToVoice, CultTreasurySpender, EnsureCult, Geniuses, Ghosts, Skeletons, ToVoice, Zombies,
}; };
mod tracks; mod tracks;
@ -45,14 +54,10 @@ parameter_types! {
impl pallet_whitelist::Config for Runtime { impl pallet_whitelist::Config for Runtime {
type RuntimeCall = RuntimeCall; type RuntimeCall = RuntimeCall;
type RuntimeEvent = RuntimeEvent; type RuntimeEvent = RuntimeEvent;
type WhitelistOrigin = EitherOfDiverse< type WhitelistOrigin =
EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>, EitherOfDiverse<EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>, Skeletons>;
Skeletons, type DispatchWhitelistedOrigin =
>; EitherOf<EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>, Geniuses>;
type DispatchWhitelistedOrigin = EitherOf<
EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>,
Geniuses,
>;
type Preimages = Preimage; type Preimages = Preimage;
type WeightInfo = weights::pallet_whitelist::WeightInfo<Runtime>; type WeightInfo = weights::pallet_whitelist::WeightInfo<Runtime>;
} }
@ -81,7 +86,7 @@ impl pallet_referenda::Config<CultReferendaInstance> for Runtime {
(AccountId, u16), (AccountId, u16),
>, >,
TakeFirst, TakeFirst,
> >,
>; >;
type CancelOrigin = Skeletons; type CancelOrigin = Skeletons;
type KillOrigin = Ghosts; type KillOrigin = Ghosts;
@ -135,10 +140,13 @@ impl pallet_core_fellowship::Config<CultCoreInstance> for Runtime {
type Members = pallet_ranked_collective::Pallet<Runtime, CultCollectiveInstance>; type Members = pallet_ranked_collective::Pallet<Runtime, CultCollectiveInstance>;
type Balance = Balance; type Balance = Balance;
type ParamsOrigin = EitherOf<EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>, Skeletons>; type ParamsOrigin =
EitherOf<EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>, Skeletons>;
type InductOrigin = EitherOf<EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>, Zombies>; type InductOrigin = EitherOf<EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>, Zombies>;
type ApproveOrigin = EitherOf<EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>, EnsureCanRetainAt>; type ApproveOrigin =
type PromoteOrigin = EitherOf<EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>, EnsureCanPromoteTo>; EitherOf<EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>, EnsureCanRetainAt>;
type PromoteOrigin =
EitherOf<EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>, EnsureCanPromoteTo>;
type EvidenceSize = ConstU32<65536>; type EvidenceSize = ConstU32<65536>;
} }

View File

@ -5,8 +5,8 @@ pub use pallet_cult_origins::*;
#[frame_support::pallet] #[frame_support::pallet]
pub mod pallet_cult_origins { pub mod pallet_cult_origins {
use crate::{Balance, CSPR};
use super::ranks; use super::ranks;
use crate::{Balance, CSPR};
use frame_support::pallet_prelude::*; use frame_support::pallet_prelude::*;
use pallet_ranked_collective::Rank; use pallet_ranked_collective::Rank;

View File

@ -1,4 +1,4 @@
use crate::{Balance, BlockNumber, RuntimeOrigin, DAYS, CSPR, HOURS, MINUTES}; use crate::{Balance, BlockNumber, RuntimeOrigin, CSPR, DAYS, HOURS, MINUTES};
use pallet_ranked_collective::Rank; use pallet_ranked_collective::Rank;
use sp_runtime::{traits::Convert, Perbill}; use sp_runtime::{traits::Convert, Perbill};
@ -255,7 +255,6 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo<Balance, BlockNumber>); 15
min_support: RETAIN_MIN_SUPPORT, min_support: RETAIN_MIN_SUPPORT,
}, },
), ),
( (
constants::PROMOTE_TO_GENIUSES, constants::PROMOTE_TO_GENIUSES,
pallet_referenda::TrackInfo { pallet_referenda::TrackInfo {
@ -347,7 +346,7 @@ impl pallet_referenda::TracksInfo<Balance, BlockNumber> for TracksInfo {
// It is important that this is NOT availiable in production! // It is important that this is NOT availiable in production!
let root: Self::RuntimeOrigin = frame_system::RawOrigin::Root.into(); let root: Self::RuntimeOrigin = frame_system::RawOrigin::Root.into();
if &root == id { if &root == id {
return Ok(tracks::GHOSTS) return Ok(tracks::GHOSTS);
} }
} }

View File

@ -3,20 +3,20 @@ use pallet_staking::Forcing;
use sp_staking::StakerStatus; use sp_staking::StakerStatus;
use crate::{opaque::SessionKeys, BABE_GENESIS_EPOCH_CONFIG}; use crate::{opaque::SessionKeys, BABE_GENESIS_EPOCH_CONFIG};
use primitives::{AccountId, AccountPublic};
use casper_runtime_constants::currency::CSPR; use casper_runtime_constants::currency::CSPR;
use primitives::{AccountId, AccountPublic};
use ghost_slow_clap::sr25519::AuthorityId as SlowClapId;
use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId; use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
use babe_primitives::AuthorityId as BabeId; use babe_primitives::AuthorityId as BabeId;
use ghost_slow_clap::sr25519::AuthorityId as SlowClapId;
use grandpa_primitives::AuthorityId as GrandpaId; use grandpa_primitives::AuthorityId as GrandpaId;
use sp_core::{sr25519, Pair, Public};
use sp_runtime::{traits::IdentifyAccount, Perbill};
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
use sp_std::alloc::format; use sp_std::alloc::format;
use sp_std::vec::Vec;
use sp_std::prelude::*; use sp_std::prelude::*;
use sp_core::{sr25519, Pair, Public}; use sp_std::vec::Vec;
use sp_runtime::{Perbill, traits::IdentifyAccount};
#[derive(Encode, Clone)] #[derive(Encode, Clone)]
struct PreparedNetworkData { struct PreparedNetworkData {
@ -84,40 +84,69 @@ fn casper_testnet_accounts() -> Vec<AccountId> {
fn casper_testnet_evm_accounts() -> Vec<(AccountId, u128, u8)> { fn casper_testnet_evm_accounts() -> Vec<(AccountId, u128, u8)> {
vec![ vec![
// 01c928771aea942a1e7ac06adf2b73dfbc9a25d9eaa516e3673116af7f345198 // 01c928771aea942a1e7ac06adf2b73dfbc9a25d9eaa516e3673116af7f345198
(get_account_id_from_seed::<sr25519::Public>("1A69d2D5568D1878023EeB121a73d33B9116A760"), 1337 * CSPR, 1), (
get_account_id_from_seed::<sr25519::Public>("1A69d2D5568D1878023EeB121a73d33B9116A760"),
1337 * CSPR,
1,
),
// b19a435901872f817185f7234a1484eae837613f9d10cf21927a23c2d8cb9139 // b19a435901872f817185f7234a1484eae837613f9d10cf21927a23c2d8cb9139
(get_account_id_from_seed::<sr25519::Public>("2f86cfBED3fbc1eCf2989B9aE5fc019a837A9C12"), 1337 * CSPR, 2), (
get_account_id_from_seed::<sr25519::Public>("2f86cfBED3fbc1eCf2989B9aE5fc019a837A9C12"),
1337 * CSPR,
2,
),
// d3baf57b74d65719b2dc33f5a464176022d0cc5edbca002234229f3e733875fc // d3baf57b74d65719b2dc33f5a464176022d0cc5edbca002234229f3e733875fc
(get_account_id_from_seed::<sr25519::Public>("e83f67361Ac74D42A48E2DAfb6706eb047D8218D"), 69 * CSPR, 3), (
get_account_id_from_seed::<sr25519::Public>("e83f67361Ac74D42A48E2DAfb6706eb047D8218D"),
69 * CSPR,
3,
),
// c4683d566436af6b58b4a59c8f501319226e85b21869bf93d5eeb4596d4791d4 // c4683d566436af6b58b4a59c8f501319226e85b21869bf93d5eeb4596d4791d4
(get_account_id_from_seed::<sr25519::Public>("827ee4ad9b259b6fa1390ed60921508c78befd63"), 69 * CSPR, 4), (
get_account_id_from_seed::<sr25519::Public>("827ee4ad9b259b6fa1390ed60921508c78befd63"),
69 * CSPR,
4,
),
] ]
} }
fn casper_testnet_evm_networks() -> Vec<(u32, Vec<u8>)> { fn casper_testnet_evm_networks() -> Vec<(u32, Vec<u8>)> {
vec![ vec![
(1, PreparedNetworkData { (
chain_name: "ethereum-mainnet".into(), 1,
default_endpoint: "https://nd-422-757-666.p2pify.com/0a9d79d93fb2f4a4b1e04695da2b77a7/".into(), PreparedNetworkData {
finality_delay: Some(40), chain_name: "ethereum-mainnet".into(),
release_delay: Some(80), default_endpoint:
network_type: Default::default(), "https://nd-422-757-666.p2pify.com/0a9d79d93fb2f4a4b1e04695da2b77a7/".into(),
gatekeeper: "0x4d224452801aced8b2f0aebe155379bb5d594381".into(), finality_delay: Some(40),
topic_name: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef".into(), release_delay: Some(80),
incoming_fee: 0, network_type: Default::default(),
outgoing_fee: 0, gatekeeper: "0x4d224452801aced8b2f0aebe155379bb5d594381".into(),
}.encode()), topic_name: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
(56, PreparedNetworkData { .into(),
chain_name: "bnb-mainnet".into(), incoming_fee: 0,
default_endpoint: "https://bsc-mainnet.core.chainstack.com/35848e183f3e3303c8cfeacbea831cab/".into(), outgoing_fee: 0,
finality_delay: Some(20), }
release_delay: Some(40), .encode(),
network_type: Default::default(), ),
gatekeeper: "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82".into(), (
topic_name: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef".into(), 56,
incoming_fee: 0, PreparedNetworkData {
outgoing_fee: 0, chain_name: "bnb-mainnet".into(),
}.encode()) default_endpoint:
"https://bsc-mainnet.core.chainstack.com/35848e183f3e3303c8cfeacbea831cab/"
.into(),
finality_delay: Some(20),
release_delay: Some(40),
network_type: Default::default(),
gatekeeper: "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82".into(),
topic_name: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
.into(),
incoming_fee: 0,
outgoing_fee: 0,
}
.encode(),
),
] ]
} }
@ -127,7 +156,12 @@ fn casper_session_keys(
authority_discovery: AuthorityDiscoveryId, authority_discovery: AuthorityDiscoveryId,
slow_clap: SlowClapId, slow_clap: SlowClapId,
) -> SessionKeys { ) -> SessionKeys {
SessionKeys { babe, grandpa, authority_discovery, slow_clap } SessionKeys {
babe,
grandpa,
authority_discovery,
slow_clap,
}
} }
fn testnet_config_genesis( fn testnet_config_genesis(
@ -143,8 +177,7 @@ fn testnet_config_genesis(
ghost_accounts: Option<Vec<(AccountId, u128, u8)>>, ghost_accounts: Option<Vec<(AccountId, u128, u8)>>,
evm_networks: Option<Vec<(u32, Vec<u8>)>>, evm_networks: Option<Vec<(u32, Vec<u8>)>>,
) -> serde_json::Value { ) -> serde_json::Value {
let endowed_accounts: Vec<AccountId> = let endowed_accounts: Vec<AccountId> = endowed_accounts.unwrap_or_else(casper_testnet_accounts);
endowed_accounts.unwrap_or_else(casper_testnet_accounts);
let ghost_accounts: Vec<(AccountId, u128, u8)> = let ghost_accounts: Vec<(AccountId, u128, u8)> =
ghost_accounts.unwrap_or_else(casper_testnet_evm_accounts); ghost_accounts.unwrap_or_else(casper_testnet_evm_accounts);
@ -218,7 +251,9 @@ fn testnet_config_genesis(
fn casper_development_config_genesis() -> serde_json::Value { fn casper_development_config_genesis() -> serde_json::Value {
testnet_config_genesis( testnet_config_genesis(
vec![get_authority_keys_from_seed("Alice")], vec![get_authority_keys_from_seed("Alice")],
None, None, None, None,
None,
None,
) )
} }
@ -229,7 +264,9 @@ fn casper_local_config_genesis() -> serde_json::Value {
get_authority_keys_from_seed("Alice"), get_authority_keys_from_seed("Alice"),
get_authority_keys_from_seed("Bob"), get_authority_keys_from_seed("Bob"),
], ],
None, None, None, None,
None,
None,
) )
} }
@ -240,9 +277,11 @@ pub fn get_preset(id: &sp_genesis_builder::PresetId) -> Option<sp_std::vec::Vec<
Ok("local_testnet") => casper_local_config_genesis(), Ok("local_testnet") => casper_local_config_genesis(),
_ => return None, _ => return None,
}; };
Some(serde_json::to_string(&patch) Some(
.expect("serialization to json is expected to work; qed") serde_json::to_string(&patch)
.into_bytes()) .expect("serialization to json is expected to work; qed")
.into_bytes(),
)
} }
/// Returns a list of identifiers for available builtin `RuntimeGenesisConfig` presets. /// Returns a list of identifiers for available builtin `RuntimeGenesisConfig` presets.

View File

@ -1,8 +1,5 @@
use super::*; use super::*;
use frame_support::{ use frame_support::{dispatch::DispatchResultWithPostInfo, traits::PrivilegeCmp};
dispatch::DispatchResultWithPostInfo,
traits::PrivilegeCmp,
};
use pallet_alliance::{ProposalIndex, ProposalProvider}; use pallet_alliance::{ProposalIndex, ProposalProvider};
use sp_runtime::DispatchError; use sp_runtime::DispatchError;
use sp_std::{cmp::Ordering, marker::PhantomData}; use sp_std::{cmp::Ordering, marker::PhantomData};
@ -14,7 +11,8 @@ type HashOf<T> = <T as frame_system::Config>::Hash;
/// Proposal provider for alliance pallet. /// Proposal provider for alliance pallet.
/// Adapter from collective pallet to alliance proposal provider trait. /// Adapter from collective pallet to alliance proposal provider trait.
pub struct AllianceProposalProvider<T, I = ()>(PhantomData<(T, I)>); pub struct AllianceProposalProvider<T, I = ()>(PhantomData<(T, I)>);
impl <T, I> ProposalProvider<AccountIdOf<T>, HashOf<T>, ProposalOf<T, I>> for AllianceProposalProvider<T, I> impl<T, I> ProposalProvider<AccountIdOf<T>, HashOf<T>, ProposalOf<T, I>>
for AllianceProposalProvider<T, I>
where where
T: pallet_collective::Config<I> + frame_system::Config, T: pallet_collective::Config<I> + frame_system::Config,
I: 'static, I: 'static,
@ -25,7 +23,12 @@ where
proposal: Box<ProposalOf<T, I>>, proposal: Box<ProposalOf<T, I>>,
length_bound: u32, length_bound: u32,
) -> Result<(u32, u32), DispatchError> { ) -> Result<(u32, u32), DispatchError> {
pallet_collective::Pallet::<T, I>::do_propose_proposed(who, threshold, proposal, length_bound) pallet_collective::Pallet::<T, I>::do_propose_proposed(
who,
threshold,
proposal,
length_bound,
)
} }
fn vote_proposal( fn vote_proposal(
@ -61,7 +64,7 @@ pub struct EqualOrGreatestRootCmp;
impl PrivilegeCmp<OriginCaller> for EqualOrGreatestRootCmp { impl PrivilegeCmp<OriginCaller> for EqualOrGreatestRootCmp {
fn cmp_privilege(left: &OriginCaller, right: &OriginCaller) -> Option<Ordering> { fn cmp_privilege(left: &OriginCaller, right: &OriginCaller) -> Option<Ordering> {
if left == right { if left == right {
return Some(Ordering::Equal) return Some(Ordering::Equal);
} }
match (left, right) { match (left, right) {

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-runtime-common" name = "ghost-runtime-common"
version = "0.4.2" version = "0.4.3"
authors.workspace = true authors.workspace = true
edition.workspace = true edition.workspace = true
homepage.workspace = true homepage.workspace = true

View File

@ -1,11 +1,13 @@
use primitives::{AccountId, Balance};
use pallet_treasury::ArgumentsFactory;
use sp_core::crypto::FromEntropy;
use frame_support::traits::tokens::{Pay, PaymentStatus}; use frame_support::traits::tokens::{Pay, PaymentStatus};
use pallet_treasury::ArgumentsFactory;
use primitives::{AccountId, Balance};
use sp_core::crypto::FromEntropy;
pub struct BenchmarkTreasuryHelper; pub struct BenchmarkTreasuryHelper;
impl ArgumentsFactory<(), AccountId> for BenchmarkTreasuryHelper { impl ArgumentsFactory<(), AccountId> for BenchmarkTreasuryHelper {
fn create_asset_kind(_seed: u32) -> () { () } fn create_asset_kind(_seed: u32) -> () {
()
}
fn create_beneficiary(seed: [u8; 32]) -> AccountId { fn create_beneficiary(seed: [u8; 32]) -> AccountId {
AccountId::from_entropy(&mut seed.as_slice()).unwrap() AccountId::from_entropy(&mut seed.as_slice()).unwrap()
} }
@ -19,8 +21,16 @@ impl Pay for BenchmarkTreasuryPaymaster {
type AssetKind = (); type AssetKind = ();
type Error = (); type Error = ();
fn pay(_: &Self::Beneficiary, _: Self::AssetKind, _: Self::Balance) -> Result<Self::Id, Self::Error> { Ok(()) } fn pay(
fn check_payment(_: Self::Id) -> PaymentStatus { PaymentStatus::Success } _: &Self::Beneficiary,
_: Self::AssetKind,
_: Self::Balance,
) -> Result<Self::Id, Self::Error> {
Ok(())
}
fn check_payment(_: Self::Id) -> PaymentStatus {
PaymentStatus::Success
}
fn ensure_successful(_: &Self::Beneficiary, _: Self::AssetKind, _: Self::Balance) {} fn ensure_successful(_: &Self::Beneficiary, _: Self::AssetKind, _: Self::Balance) {}
fn ensure_concluded(_: Self::Id) {} fn ensure_concluded(_: Self::Id) {}
} }

View File

@ -55,7 +55,7 @@ mod tests {
parameter_types, parameter_types,
traits::{ traits::{
tokens::{PayFromAccount, UnityAssetBalanceConversion}, tokens::{PayFromAccount, UnityAssetBalanceConversion},
ConstU32, FindAuthor ConstU32, FindAuthor,
}, },
weights::Weight, weights::Weight,
PalletId, PalletId,
@ -65,7 +65,7 @@ mod tests {
use sp_core::{ConstU64, H256}; use sp_core::{ConstU64, H256};
use sp_runtime::{ use sp_runtime::{
traits::{BlakeTwo256, IdentityLookup}, traits::{BlakeTwo256, IdentityLookup},
Perbill, BuildStorage, BuildStorage, Perbill,
}; };
type Block = frame_system::mocking::MockingBlock<Test>; type Block = frame_system::mocking::MockingBlock<Test>;
@ -172,7 +172,10 @@ mod tests {
pub struct OneAuthor; pub struct OneAuthor;
impl FindAuthor<AccountId> for OneAuthor { impl FindAuthor<AccountId> for OneAuthor {
fn find_author<'a, I>(_: I) -> Option<AccountId> where I: 'a { fn find_author<'a, I>(_: I) -> Option<AccountId>
where
I: 'a,
{
Some(TEST_ACCOUNT) Some(TEST_ACCOUNT)
} }
} }
@ -185,7 +188,9 @@ mod tests {
} }
pub fn new_test_ext() -> sp_io::TestExternalities { pub fn new_test_ext() -> sp_io::TestExternalities {
let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap(); let mut t = frame_system::GenesisConfig::default()
.build_storage::<Test>()
.unwrap();
// We use default for brevity, but you can configure as desired if needed. // We use default for brevity, but you can configure as desired if needed.
pallet_balances::GenesisConfig::<Test>::default() pallet_balances::GenesisConfig::<Test>::default()
.assimilate_storage(&mut t) .assimilate_storage(&mut t)
@ -196,8 +201,14 @@ mod tests {
#[test] #[test]
fn test_fees_and_tips_split() { fn test_fees_and_tips_split() {
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
let fee = <paller_balances::Pallet<Test> as frame_support::traits::fungible::Balanced<AccountId>>::issue(10); let fee =
let tip = <paller_balances::Pallet<Test> as frame_support::traits::fungible::Balanced<AccountId>>::issue(20); <paller_balances::Pallet<Test> as frame_support::traits::fungible::Balanced<
AccountId,
>>::issue(10);
let tip =
<paller_balances::Pallet<Test> as frame_support::traits::fungible::Balanced<
AccountId,
>>::issue(20);
assert_eq!(Balances::free_balance(Treasury::account_id()), 0); assert_eq!(Balances::free_balance(Treasury::account_id()), 0);
assert_eq!(Balances::free_balance(TEST_ACCOUNT), 0); assert_eq!(Balances::free_balance(TEST_ACCOUNT), 0);
@ -242,11 +253,23 @@ mod tests {
#[test] #[test]
fn era_payout_should_give_sensible_results() { fn era_payout_should_give_sensible_results() {
assert_eq!( assert_eq!(
era_payout(75, 100, Perquintill::from_percent(10), Perquintill::one(), 0, ), era_payout(
75,
100,
Perquintill::from_percent(10),
Perquintill::one(),
0,
),
(10, 0) (10, 0)
); );
assert_eq!( assert_eq!(
era_payout(80, 100, Perquintill::from_percent(10), Perquintill::one(), 0, ), era_payout(
80,
100,
Perquintill::from_percent(10),
Perquintill::one(),
0,
),
(6, 4) (6, 4)
); );
} }

View File

@ -1,7 +1,7 @@
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
pub mod impls;
pub mod elections; pub mod elections;
pub mod impls;
#[cfg(feature = "try-runtime")] #[cfg(feature = "try-runtime")]
pub mod elections; pub mod elections;
@ -10,7 +10,8 @@ pub mod elections;
pub mod benchmarking; pub mod benchmarking;
use frame_support::{ use frame_support::{
parameter_types, traits::ConstU32, parameter_types,
traits::ConstU32,
weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight}, weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight},
}; };
use frame_system::limits; use frame_system::limits;
@ -92,8 +93,8 @@ macro_rules! impl_runtime_weights {
use frame_system::limits; use frame_system::limits;
use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment}; use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment};
pub use runtime_common::{ pub use runtime_common::{
impl_elections_weights, AVERAGE_ON_INITIALIZE_RATIO, impl_elections_weights, AVERAGE_ON_INITIALIZE_RATIO, MAXIMUM_BLOCK_WEIGHT,
MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, NORMAL_DISPATCH_RATIO,
}; };
use sp_runtime::{FixedPointNumber, Perquintill}; use sp_runtime::{FixedPointNumber, Perquintill};
@ -101,8 +102,7 @@ macro_rules! impl_runtime_weights {
// Expose the weight from the runtime constants module. // Expose the weight from the runtime constants module.
pub use $runtime::weights::{ pub use $runtime::weights::{
BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, BlockExecutionWeight, ExtrinsicBaseWeight, ParityDbWeight, RocksDbWeight,
ParityDbWeight,
}; };
parameter_types! { parameter_types! {
@ -129,7 +129,6 @@ macro_rules! impl_runtime_weights {
}; };
} }
/// The type used for currency conversion. /// The type used for currency conversion.
/// ///
/// This must be only be used as long as the balance type is `u128`. /// This must be only be used as long as the balance type is `u128`.

View File

@ -4,7 +4,7 @@ use frame_support::{
}; };
use pallet_fast_unstake::{Pallet as FastUnstake, *}; use pallet_fast_unstake::{Pallet as FastUnstake, *};
use pallet_staking::*; use pallet_staking::*;
use sp_std::{collections::btree_set::BTreeSet, prelude:*}; use sp_std::{collections::btree_set::BTreeSet, prelude::*};
/// Register all inactive nominators for fast unstake, and progress until they /// Register all inactive nominators for fast unstake, and progress until they
/// have all benn processed. /// have all benn processed.
@ -16,7 +16,9 @@ where
let mut unstaked_err = 0; let mut unstaked_err = 0;
let mut unstaked_slashed = 0; let mut unstaked_slashed = 0;
let all_stakers = Ledger::<T>::iter().map(|(ctrl, l)| (ctrl, l.stash)).collect::<BTreeSet<_>>(); let all_stakers = Ledger::<T>::iter()
.map(|(ctrl, l)| (ctrl, l.stash))
.collect::<BTreeSet<_>>();
let mut all_exposed = BTreeSet::new(); let mut all_exposed = BTreeSet::new();
ErasStakers::<T>::iter().for_each(|(_, val, expo)| { ErasStakers::<T>::iter().for_each(|(_, val, expo)| {
all_exposed.insert(val); all_exposed.insert(val);
@ -70,15 +72,16 @@ where
maybe_fast_unstake_event maybe_fast_unstake_event
}) })
.for_each(|e: pallet_fast_unstake::Event<T>| match e { .for_each(|e: pallet_fast_unstake::Event<T>| match e {
pallet_fast_unstake::Event<T>::Unstaked { result, .. } => pallet_fast_unstake::Event::<T>::Unstaked { result, .. } => {
if result.is_ok() { if result.is_ok() {
unstaked_ok += 1; unstaked_ok += 1;
} else { } else {
unstaked_err += 1; unstaked_err += 1;
}, }
}
pallet_fast_unstake::Event::<T>::Slashed { .. } => unstaked_slashed += 1, pallet_fast_unstake::Event::<T>::Slashed { .. } => unstaked_slashed += 1,
pallet_fast_unstake::Event::<T>::InternalError { .. } => unreachable!(), pallet_fast_unstake::Event::<T>::InternalError { .. } => unreachable!(),
_ => {}, _ => {}
}); });
if now % 100u32.into() == sp_runtime::traits::Zero::zero() { if now % 100u32.into() == sp_runtime::traits::Zero::zero() {

View File

@ -80,6 +80,29 @@ extract_seed() {
echo $seed echo $seed
} }
downgrade_compiler_if_needed() {
# TODO: uncomment later
# echo "[+] fetching the latest ghost-node source code"
# git switch main
# git pull origin main
# 1.83.0 works fine, tested with:
# ...
# 1.87.0 throws errors during compilation
# 1.88.0 throws errors during compilation
LATEST_TESTED_VERSION=83
cargo_version=$(cargo --version | cut -d'.' -f2)
if [ "$cargo_version" -gt "$LATEST_TESTED_VERSION" ]; then
echo "[+] downgrading rustc compiler version to 1.83.0"
rustup default 1.83.0
toolchain_name=$(rustup show | grep default | head -n 1 | cut -d' ' -f1)
rustup target add wasm32-unknown-unknown --toolchain $toolchain_name
rustup component add rust-src --toolchain $toolchain_name
else
echo "[+] rustc compiler version is compatible"
fi
}
help() { help() {
echo -e "Ghost Node Build automation tool. Helper for Ghost Node environment preparation.\n" echo -e "Ghost Node Build automation tool. Helper for Ghost Node environment preparation.\n"
echo -e "With no OPTION nothing will happen, possible OPTION:\n" echo -e "With no OPTION nothing will happen, possible OPTION:\n"
@ -195,22 +218,11 @@ if [[ $HARD_RESET = true ]]; then
exit 1 exit 1
fi fi
cd $PROJECT_FOLDER downgrade_compiler_if_needed
# TODO: uncomment later
# echo "[+] fetching the latest ghost-node source code"
# git switch main
# git pull origin main
# rustc version control, this works fine
# cargo --version | cut -d'.' -f2, if higher then do
# rustup default 1.83.0
# rustup target add wasm32-unknown-unknown --toolchain 1.83.0-x86_64-unknown-linux-gnu
# rustup component add rust-src --toolchain 1.83.0-x86_64-unknown-linux-gnu
#
# I think we need to do clean before recompilation
# cargo clean
cd $PROJECT_FOLDER cd $PROJECT_FOLDER
echo "[+] clean build cache..."
cargo clean
echo "[+] starting build in 3 seconds..." echo "[+] starting build in 3 seconds..."
sleep 3 sleep 3
cargo build $RELEASE $FEATURES cargo build $RELEASE $FEATURES
@ -228,8 +240,9 @@ if [[ $HARD_RESET = true ]]; then
echo "[+] ghost executable copied in '$EXECUTABLE_PATH' from '$TARGET'" echo "[+] ghost executable copied in '$EXECUTABLE_PATH' from '$TARGET'"
echo "[+] specification '$SPECIFICATION_NAME.json' copied to '$SPECIFICATION_PATH'" echo "[+] specification '$SPECIFICATION_NAME.json' copied to '$SPECIFICATION_PATH'"
echo "[+] starting ghost-node" # TODO: uncomment later
sudo systemctl start ghost-node # echo "[+] starting ghost-node"
# sudo systemctl start ghost-node
exit 0 exit 0
fi fi
@ -312,13 +325,12 @@ if [[ $SET_ENVIRONMENT = true ]]; then
if prompt "[?] setup the rust environment (e.g. WASM support)?"; then if prompt "[?] setup the rust environment (e.g. WASM support)?"; then
rustup default stable rustup default stable
rustup update downgrade_compiler_if_needed
rustup target add wasm32-unknown-unknown
rustup component add rust-src
fi fi
fi fi
if [[ ! -z $RELEASE ]]; then if [[ ! -z $RELEASE ]]; then
downgrade_compiler_if_needed
if prompt "[?] 'cargo build $RELEASE $FEATURES' is what you want?"; then if prompt "[?] 'cargo build $RELEASE $FEATURES' is what you want?"; then
cd $PROJECT_FOLDER cd $PROJECT_FOLDER
echo "[+] starting build in 3 seconds..." echo "[+] starting build in 3 seconds..."

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,7 @@
use keyring::Sr25519Keyring;
use primitives::AccountId; use primitives::AccountId;
use sc_client_api::UsageProvider; use sc_client_api::UsageProvider;
use sp_runtime::OpaqueExtrinsic; use sp_runtime::OpaqueExtrinsic;
use keyring::Sr25519Keyring;
use crate::*; use crate::*;
@ -21,27 +21,41 @@ macro_rules! identify_chain {
{ {
use ghost_runtime as runtime; use ghost_runtime as runtime;
let call = $generic_code; let call = $generic_code;
Ok(ghost_sign_call(call, $nonce, $current_block, $period, $genesis, $signer)) Ok(ghost_sign_call(
call,
$nonce,
$current_block,
$period,
$genesis,
$signer,
))
} }
#[cfg(not(feature = "ghost-native"))] #[cfg(not(feature = "ghost-native"))]
{ {
Err("`ghost-native` feature not enabled") Err("`ghost-native` feature not enabled")
} }
}, }
Chain::Casper => { Chain::Casper => {
#[cfg(feature = "casper-native")] #[cfg(feature = "casper-native")]
{ {
use casper_runtime as runtime; use casper_runtime as runtime;
let call = $generic_code; let call = $generic_code;
Ok(casper_sign_call(call, $nonce, $current_block, $period, $genesis, $signer)) Ok(casper_sign_call(
call,
$nonce,
$current_block,
$period,
$genesis,
$signer,
))
} }
#[cfg(not(feature = "casper-native"))] #[cfg(not(feature = "casper-native"))]
{ {
Err("`casper-native` feature not enabled") Err("`casper-native` feature not enabled")
} }
}, }
Chain::Unknown => { Chain::Unknown => {
let _ = $nonce; let _ = $nonce;
let _ = $current_block; let _ = $current_block;
@ -50,7 +64,7 @@ macro_rules! identify_chain {
let _ = $signer; let _ = $signer;
Err("Unknown chain") Err("Unknown chain")
}, }
} }
}; };
} }
@ -105,7 +119,11 @@ pub struct TransferKeepAliveBuilder {
impl TransferKeepAliveBuilder { impl TransferKeepAliveBuilder {
pub fn new(client: Arc<FullClient>, dest: AccountId, chain: Chain) -> Self { pub fn new(client: Arc<FullClient>, dest: AccountId, chain: Chain) -> Self {
Self { client, dest, chain } Self {
client,
dest,
chain,
}
} }
} }
@ -159,10 +177,9 @@ fn casper_sign_call(
frame_system::CheckSpecVersion::<casper_runtime::Runtime>::new(), frame_system::CheckSpecVersion::<casper_runtime::Runtime>::new(),
frame_system::CheckTxVersion::<casper_runtime::Runtime>::new(), frame_system::CheckTxVersion::<casper_runtime::Runtime>::new(),
frame_system::CheckGenesis::<casper_runtime::Runtime>::new(), frame_system::CheckGenesis::<casper_runtime::Runtime>::new(),
frame_system::CheckMortality::<casper_runtime::Runtime>::from(sp_runtime::generic::Era::mortal( frame_system::CheckMortality::<casper_runtime::Runtime>::from(
period, sp_runtime::generic::Era::mortal(period, current_block),
current_block, ),
)),
frame_system::CheckNonce::<casper_runtime::Runtime>::from(nonce), frame_system::CheckNonce::<casper_runtime::Runtime>::from(nonce),
frame_system::CheckWeight::<casper_runtime::Runtime>::new(), frame_system::CheckWeight::<casper_runtime::Runtime>::new(),
pallet_transaction_payment::ChargeTransactionPayment::<casper_runtime::Runtime>::from(0), pallet_transaction_payment::ChargeTransactionPayment::<casper_runtime::Runtime>::from(0),
@ -189,7 +206,8 @@ fn casper_sign_call(
sp_runtime::AccountId32::from(acc.public()).into(), sp_runtime::AccountId32::from(acc.public()).into(),
primitives::Signature::Sr25519(signature), primitives::Signature::Sr25519(signature),
extra, extra,
).into() )
.into()
} }
pub fn benchmark_inherent_data() -> std::result::Result<inherents::InherentData, inherents::Error> { pub fn benchmark_inherent_data() -> std::result::Result<inherents::InherentData, inherents::Error> {

View File

@ -2,13 +2,13 @@
use codec::Encode; use codec::Encode;
use ghost_slow_clap::sr25519::AuthorityId as SlowClapId;
use primitives::{AccountId, AccountPublic};
use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId; use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
use grandpa_primitives::AuthorityId as GrandpaId;
use babe_primitives::AuthorityId as BabeId; use babe_primitives::AuthorityId as BabeId;
use ghost_slow_clap::sr25519::AuthorityId as SlowClapId;
use grandpa_primitives::AuthorityId as GrandpaId;
#[cfg(feature = "casper-native")] #[cfg(feature = "casper-native")]
use pallet_staking::Forcing; use pallet_staking::Forcing;
use primitives::{AccountId, AccountPublic};
#[cfg(feature = "casper-native")] #[cfg(feature = "casper-native")]
use casper_runtime as casper; use casper_runtime as casper;
@ -58,7 +58,7 @@ pub type CasperChainSpec = sc_service::GenericChainSpec<(), Extensions>;
pub type CasperChainSpec = GenericChainSpec; pub type CasperChainSpec = GenericChainSpec;
pub fn casper_config() -> Result<CasperChainSpec, String> { pub fn casper_config() -> Result<CasperChainSpec, String> {
CasperChainSpec::from_json_bytes(&include_bytes!("../chain-specs/casper.json")[..]) CasperChainSpec::from_json_bytes(&include_bytes!("../chain-specs/casper.json")[..])
} }
#[cfg(feature = "casper-native")] #[cfg(feature = "casper-native")]
@ -76,7 +76,6 @@ fn casper_session_keys(
} }
} }
pub fn casper_chain_spec_properties() -> serde_json::map::Map<String, serde_json::Value> { pub fn casper_chain_spec_properties() -> serde_json::map::Map<String, serde_json::Value> {
serde_json::json!({ serde_json::json!({
"ss58Format": 1996, "ss58Format": 1996,
@ -161,48 +160,60 @@ fn casper_testnet_accounts() -> Vec<AccountId> {
fn casper_testnet_evm_accounts() -> Vec<(AccountId, u128, u8)> { fn casper_testnet_evm_accounts() -> Vec<(AccountId, u128, u8)> {
vec![ vec![
// 01c928771aea942a1e7ac06adf2b73dfbc9a25d9eaa516e3673116af7f345198 // 01c928771aea942a1e7ac06adf2b73dfbc9a25d9eaa516e3673116af7f345198
(get_account_id_from_seed::<sr25519::Public>("1A69d2D5568D1878023EeB121a73d33B9116A760"), 1337 * CSPR, 1), (
get_account_id_from_seed::<sr25519::Public>("1A69d2D5568D1878023EeB121a73d33B9116A760"),
1337 * CSPR,
1,
),
// b19a435901872f817185f7234a1484eae837613f9d10cf21927a23c2d8cb9139 // b19a435901872f817185f7234a1484eae837613f9d10cf21927a23c2d8cb9139
(get_account_id_from_seed::<sr25519::Public>("2f86cfBED3fbc1eCf2989B9aE5fc019a837A9C12"), 1337 * CSPR, 2), (
get_account_id_from_seed::<sr25519::Public>("2f86cfBED3fbc1eCf2989B9aE5fc019a837A9C12"),
1337 * CSPR,
2,
),
// d3baf57b74d65719b2dc33f5a464176022d0cc5edbca002234229f3e733875fc // d3baf57b74d65719b2dc33f5a464176022d0cc5edbca002234229f3e733875fc
(get_account_id_from_seed::<sr25519::Public>("e83f67361Ac74D42A48E2DAfb6706eb047D8218D"), 69 * CSPR, 3), (
get_account_id_from_seed::<sr25519::Public>("e83f67361Ac74D42A48E2DAfb6706eb047D8218D"),
69 * CSPR,
3,
),
// c4683d566436af6b58b4a59c8f501319226e85b21869bf93d5eeb4596d4791d4 // c4683d566436af6b58b4a59c8f501319226e85b21869bf93d5eeb4596d4791d4
(get_account_id_from_seed::<sr25519::Public>("827ee4ad9b259b6fa1390ed60921508c78befd63"), 69 * CSPR, 4), (
get_account_id_from_seed::<sr25519::Public>("827ee4ad9b259b6fa1390ed60921508c78befd63"),
69 * CSPR,
4,
),
] ]
} }
#[cfg(feature = "casper-native")] #[cfg(feature = "casper-native")]
fn casper_testnet_evm_networks() -> Vec<(u32, Vec<u8>)> { fn casper_testnet_evm_networks() -> Vec<(u32, Vec<u8>)> {
vec![ vec![(
(1, ghost_networks::NetworkData { 11155111,
chain_name: "ethereum-mainnet".into(), ghost_networks::NetworkData {
chain_name: "sepolia-ethereum-testnet".into(),
default_endpoints: vec![ default_endpoints: vec![
"https://nd-422-757-666.p2pify.com/0a9d79d93fb2f4a4b1e04695da2b77a7/".into(), "https://sepolia.drpc.org".into(),
"https://sepolia.gateway.tenderly.co".into(),
"https://api.zan.top/eth-sepolia".into(),
"https://rpc.sepolia.ethpandaops.io".into(),
"https://ethereum-sepolia-rpc.publicnode.com".into(),
"https://rpc-sepolia.rockx.com".into(),
"https://1rpc.io/sepolia".into(),
"https://0xrpc.io/sep".into(),
"https://eth-sepolia.api.onfinality.io/public".into(),
], ],
finality_delay: 40u64, finality_delay: 40u64,
rate_limit_delay: 1_000u64, rate_limit_delay: 3_000u64,
block_distance: 50u64, block_distance: 20u64,
network_type: ghost_networks::NetworkType::Evm, network_type: ghost_networks::NetworkType::Evm,
gatekeeper: "0x4d224452801aced8b2f0aebe155379bb5d594381".into(), gatekeeper: "0xc85129A097773B7F8970a7364c928C05f265E6A1".into(),
topic_name: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef".into(), topic_name: "0x7ab52ec05c331e6257a3d705d6bea6e4c27277351764ad139209e06b203811a6".into(),
incoming_fee: 0u32, incoming_fee: 69_000_000u32,
outgoing_fee: 0u32, outgoing_fee: 0u32,
}.encode()), }
(56, ghost_networks::NetworkData { .encode(),
chain_name: "bnb-mainnet".into(), )]
default_endpoints: vec![
"https://bsc-mainnet.core.chainstack.com/35848e183f3e3303c8cfeacbea831cab/".into(),
],
finality_delay: 20u64,
rate_limit_delay: 1_000u64,
block_distance: 50u64,
network_type: ghost_networks::NetworkType::Evm,
gatekeeper: "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82".into(),
topic_name: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef".into(),
incoming_fee: 0u32,
outgoing_fee: 0u32,
}.encode())
]
} }
/// Helper function to create casper `GenesisConfig` for testing /// Helper function to create casper `GenesisConfig` for testing
@ -220,14 +231,11 @@ pub fn testnet_config_genesis(
ghost_accounts: Option<Vec<(AccountId, u128, u8)>>, ghost_accounts: Option<Vec<(AccountId, u128, u8)>>,
evm_networks: Option<Vec<(u32, Vec<u8>)>>, evm_networks: Option<Vec<(u32, Vec<u8>)>>,
) -> serde_json::Value { ) -> serde_json::Value {
let endowed_accounts: Vec<AccountId> = endowed_accounts let endowed_accounts: Vec<AccountId> = endowed_accounts.unwrap_or_else(casper_testnet_accounts);
.unwrap_or_else(casper_testnet_accounts);
let ghost_accounts: Vec<(AccountId, u128, u8)> = ghost_accounts let ghost_accounts: Vec<(AccountId, u128, u8)> = ghost_accounts.unwrap_or_default();
.unwrap_or_default();
let evm_networks: Vec<(u32, Vec<u8>)> = evm_networks let evm_networks: Vec<(u32, Vec<u8>)> = evm_networks.unwrap_or_default();
.unwrap_or_default();
const ENDOWMENT: u128 = 1_000 * CSPR; const ENDOWMENT: u128 = 1_000 * CSPR;
const STASH: u128 = 500 * CSPR; const STASH: u128 = 500 * CSPR;
@ -299,148 +307,6 @@ fn casper_staging_config_genesis() -> serde_json::Value {
use hex_literal::hex; use hex_literal::hex;
use sp_core::crypto::UncheckedInto; use sp_core::crypto::UncheckedInto;
// Endowments for the whales from previous testnet.
let whales_endowments = [
// sfHXFVNvLVp8uSZauMyMijqXfoods8kkkik2MKnmr5MTdsweh
(hex!["a8ab31b36aae0dc29d2b92714cee75ee2784037c6f150d759d9aa757ab5a4666"].into(), 25 * CSPR),
// sfEtW9ijdwbU17oderTmwseMV84c7c9Xi1JW7T94rBbYKMMZq
(hex!["342c0035531136ff50d8488eb4d4772dfd10e565f6a5d28c7298b354d33f2dfe"].into(), 14 * CSPR),
// sfJtE2J5yVQBHdzwmXhzTwQZLtS853MFkUVYv5AfnB7TEVp2E
(hex!["e4e6a493d23633bf72b16ead89ab1451611b08311a9a49cc874a92e6ac4f5b1d"].into(), 31 * CSPR),
// sfFf48EnVLjD4wMecZh7meP5RWwYXZr54QiW2xQyPKPjxsxNo
(hex!["56266f27a02869f9498a113cbd4d1507ae5f4b8c91a6b8ccecda3331c21fd67f"].into(), 6 * CSPR),
// sfHxHVmMKZfUUzXRzKrV3oXSSynG1uAJ7c6dhFSq4CwE8qLn3
(hex!["bbc31594a2338e91c248aba474d892f41811a072c7e7c692fcae07fdb398b89f"].into(), 3 * CSPR),
// sfGvSkgfv99AndiEuhmL6t49ekbb2og2aYVRisAeNMPHueACW
(hex!["8e1f85cc6bb89182bc473859287b82fc2b9c89f461431090c2246a1a8d92d911"].into(), 14 * CSPR),
// sfHfByscdWfjzQNXc5g2q2ScMhop5pr5TiqiZosKxtMit1bRy
(hex!["aeb95893ab118bf02f5cd80ebab71ba58490c645e4302773fdc90b659f5c5e22"].into(), 11 * CSPR),
// sfGh1jtdTwWEco2N6cymxKgaoAJwYFMj2K2tdEbuML5LjUprc
(hex!["83e120fa3994efedc51092a8d90882803997f39f552a37699e3acb06c1f8158d"].into(), 28 * CSPR),
// sfJHvJDgdKdo1ZFXB146jhKVgngDrDeKTKF3GV5Eyvg1tJqTq
(hex!["cabca1450cbdc5769fa8f7b80d5bfd00df35b65613d8694e02517c9415fc5462"].into(), 12 * CSPR),
// sfE4SvLvh66FSThDnrTx5Qf5vHNCmBkrAJy8Zt8pMPN8h6dzw
(hex!["0f85589e37f3c0859ba7c055dec527a63796d6285b73cf8bd4657da052ff893c"].into(), 2 * CSPR),
// sfHJF1dYfzCpjJ8QHRBexNMfvSfsJvE75eCzgosrB6PwFXmpz
(hex!["9ebf64b6bc73baf1428da1cfcf36fde9695be0a56a855ddabb5612a70b10e447"].into(), 6 * CSPR),
// sfEEixqLWYct7au1PWkQAKbyso5VQhrgXQ2RXVW5TjcBm3vZ6
(hex!["175bce3674e24ec942112d91df594ba551b329ae7183b0faaef79fa051a85948"].into(), 21 * CSPR),
// sfH5nCFu2wNXnfD1Fic1weyLHncxHb7qpa8yXXQuNbQRUm9HH
(hex!["953e2cdbf7a66e34c50c51d199ad8970b1b2233da5604eb79a1de8d277c03061"].into(), 10 * CSPR),
// sfJnVLd4PMfoABtQiPmifeqkpQQKoV4wbXyAzhXKdSDHfi1bY
(hex!["e086ba892126243d6ef1c2b9132790e4455a3b1271baac8033306d55c8473af4"].into(), 30 * CSPR),
// sfECamJamifU5XyHH27ekuWY3MHAwj1z3rDcV2rpWdeGdAe2Y
(hex!["15b9b710a589968804e6e00f2ccb576ded431627a733b7f9fa0845f59e73f5cc"].into(), 31 * CSPR),
// sfEAhZrKxxChBR5SHQML6gNDJCK2FTMnRZZ2s2KVCFRxqFFTG
(hex!["144a1fa97fdba679efd2a36696a0d40f585b649143bb7da5cbd7458ea4a0f674"].into(), 2 * CSPR),
// sfDrDchmoxEfzyyPFWGX2fekP4mic99D6inhPnRvwokRZCbv5
(hex!["06319d9539108995233c48032bda04d50115fe829a2c4b5b23e54a4d17188606"].into(), 14 * CSPR),
// sfEb6NRc4ZbcuWUGJAnBkvEoacoXLbHZSM1asLpHiXqeY6YkE
(hex!["26e4c66dab5d9df3cb196ce320314e2565489f7d56b9868299a68cc4a1b4c917"].into(), 24 * CSPR),
// sfHfQMwpzNaA3D1uRGrzNPwZDeFbdXQDBJMay1oFDmD7C2RLn
(hex!["aee305cf2e015ef860c96815bb34ff9ac7df36db95f0587b6ded75218ae0d526"].into(), 22 * CSPR),
// sfKPnkuxV9u7AEk6bqU4i83NpAeG5w6VjcXYER5yfoojkkcN4
(hex!["fb72f46bd61ce821d12f5bdd6dc587afe5ae5821632b7e4b09464ea9e04111e3"].into(), 4 * CSPR),
// sfJGyU6k2gPVhmQJvgtY3iaVsakKQuD56jdgKZTGRLwjkHcbQ
(hex!["ca040e9167e0e7675ea2163506706cb7883a601a9ece1ba702fd253446f69e5d"].into(), 19 * CSPR),
// sfF8tAs7Z9R3GU8AnWgHEubxbwGt4zk7V6gSBeJJSqvt1xs8e
(hex!["3f238fbe70fdf9df12ed42416be91fa556802e7be7ea43c4de33314f5fb2da53"].into(), 22 * CSPR),
// sfHtQ3XxjAc3fbr4rxnx5P5ejV7LPXnN8nXwxevJ5MZwPJFCa
(hex!["b8cc24f449bd14c9903431b710842e1398a83d2ced33c5ea8fa4b75461db2f1f"].into(), 28 * CSPR),
// sfG5KDhmeKs6jXC2Jt1otffwHQyLR58dMGHwJCizUJHr4a7pU
(hex!["68a722b719350846a1f5a83143e01fdf18422d0d3d489877510062498ba74e5b"].into(), 17 * CSPR),
// sfH28MB4HFrE8YmtAcj95oTyMsQ9GgYWqxVtisWPqV5SwSMVS
(hex!["9275098141352f7e4fb3a4be9b2e50269947b7f54ecf2a493454955dd327274a"].into(), 28 * CSPR),
// sfEBNrjumQ8GLJTxeu3HvUDqHki3UxHCoSzg1x8SDJkfWfhWc
(hex!["14ce63bf285ad88594a93af2f1b8fd822c4db73030ae0783836083201876cb71"].into(), 14 * CSPR),
// sfFMYowKRoik3N9tYoSaPZ4vGPaPrDaezXiTVGZUBGWEwSKWQ
(hex!["48cc93d26f56df01cbd642e2d6eca745a9e2b84616e7f3b405411963c9aefa2f"].into(), 11 * CSPR),
// sfHPg4uVcq3s3TnfqHcsT6nEmeKJuNiJCW2eHk8Uk5aRfS7jr
(hex!["a2e3f7cfc7d8b7992a17b7aa8a85b47f1e0d254f3f0b760764f79af5a8349b33"].into(), 22 * CSPR),
// sfFo97CYcVqhjeiQiu6umcDggkNRWNjNu3XA6pU67F2C4Zs7g
(hex!["5c512b2cdb7da57ac056d6573ae3d1ae027bcec1b3b3d4dd79dc50160b24101b"].into(), 3 * CSPR),
// sfGxyWHjTMDVfmScYXjRFwXuVLyPj6XB8nzVjeZTLZ8RQkXQU
(hex!["900d88832e0748670c2358f2238bd34aaf49e070aa41aba84d931a0d1fef0978"].into(), 15 * CSPR),
// sfJHHLnAf9kbZz1PL4ESDpEMuAw7GXfFigC9wJD7ZArqRPwVG
(hex!["ca4039b68f9924c12399808da77247f2f45b0a9e397de94a33104c610cd8287f"].into(), 1 * CSPR),
// sfHqoR2AnJgWckgFY4HE2p5SK5gf6mUZGCXV5S3Ck7mnpTWps
(hex!["b6d11481813a6968a1d056794e6f0b85408480c5e8a6056769fbec9b5424314d"].into(), 18 * CSPR),
// sfJCVDhbVQzg7Y9JTm9mYiowUg2SuGQLLKGPwtstLVgtrcnmu
(hex!["c697fbb0ecf8069a0f88292d0a2097ba24b8c6998d04d21a02d92f6a23a65b43"].into(), 11 * CSPR),
// sfFFc7sBndJG1sZpxXfzti9K4Z7cNNfW8EQtEzsX9B1BWXoBv
(hex!["44443e9670b7f6decd4da7b042b6c9f740bd6b82e564fd51c1453fa442f0192f"].into(), 15 * CSPR),
// sfJbxCLF7tdMQRqzVgTiGyJQ2V2tEJXeC9pmeZqRaH3kNqYFA
(hex!["d87d702b99b8b3d58d8a48e5d750f40338b3a3d43fab09c23c50036226ba5325"].into(), 28 * CSPR),
// sfDrr9Vh9k3hC8JnpN4BG15z5yJPfMhHuPwFsZrd3S62b5U2Y
(hex!["06ac96e99519ae0a38f2475edfda3e432d3ae8d1f889a82e9ded1f1ccc850505"].into(), 15 * CSPR),
// sfJq7W4AboVKNgeG33y2oCE5o6h3eJaG6cyoKwtqjTkjSZXs4
(hex!["e286f428cd368ae7249d4ea76ad17df9350b0dcb437eadbf60053177769fbc5a"].into(), 14 * CSPR),
// sfG8ERVrJaoaJZdxT8tt9ZBRH4y1q9RHkyW1juiQBFjfqNm5s
(hex!["6ae0b990e482c499d93382e6183c0d2f3e8228e603de7c154ffb93e2299f152a"].into(), 14 * CSPR),
// sfG7q2arcyPyzNWrEZRoFvrf6go5PuhwofYVcthR3Mpu8dHgz
(hex!["6a91f855ff00e83c9b03cc222291cd6d098be0318eb60b88e6c167ce9e513a50"].into(), 11 * CSPR),
// sfFoee91wxv2u9LRFxCv9pzpM9L9YWGX2CPZveLFWbntrq6zd
(hex!["5cb4964925c2061492b88ff8daea2804b5770c044946c4ff0ac5a170eab1422c"].into(), 26 * CSPR),
// sfGkHJcQDaqeagPGrpaNFKR1kdRShUZH4Ec8iYMj6kyH8M2Tg
(hex!["865f4233b54d0903f5fdad05b0ec715b0ad9613fc69df18df4a013d3c7d3ab73"].into(), 2 * CSPR),
// sfFXJNrot6ou3UAmcynzSrD1RZnZzyhKM4gdMPfuDLUhCPyDs
(hex!["503c72a0f2c549a62d876dea81aa2e597b88503fa639ab0e9b65db599785f61d"].into(), 26 * CSPR),
// sfJyW71FYeFRb3YSQSVJAEp3CjPpNcUmzkw7riKMSkCiBEAs6
(hex!["e8ed0109c607d78aec9d8aa3575a565e34d65b399a5bd0e0102032d807ea0975"].into(), 5 * CSPR),
// sfKCXSvdcMTWyJDXDdZ2QP88ZsHDiwnGPfDVRPetf6KQfDAKY
(hex!["f2dbb77f0f922e5e92d98de7d43612d2f0b0d503aff20607d6c771fe8ee4a623"].into(), 31 * CSPR),
// sfJjXxYZNuXNirgQFE4MxuJ1w2ekxXHvXtowqUqEN52BNRryW
(hex!["de45cf59f588af5ee252c0ee0c805be8fa1ce172f8a6187d3b63dce1dc9c0b60"].into(), 8 * CSPR),
// sfGZf5wgfaLUq3h3JwHgZ52Fg2P27JYn2tSCgjosp4gL2Mdpx
(hex!["7e44e1ede822621cc9f618480433fe002bb8edde02d2fcd4fcf406409e154e68"].into(), 28 * CSPR),
// sfETREDdpH8vyT6zHEfcF5qdJhNw8iJVFeSfspKHv2BeUGQg5
(hex!["210a4b979e39c3136be105df1974fc036f4fe9b035936c149bdb94a3f4820487"].into(), 6 * CSPR),
// sfHA9NkB5Bb5hgt1f58jf1UminCdrmyu94VGoKB3jo9YRoPjW
(hex!["98927535310e1b910ca19860e1539a15c5dc02df780a66a22f5796cec3768812"].into(), 12 * CSPR),
// sfJeYC8LPe41yBP8WptgSzkYgfM39y3derRV4YeYXkpEysT7b
(hex!["da765f0ad9bedffdc9aa88da6fdacf4afa4463395785b6e03acb0811395a8f5d"].into(), 20 * CSPR),
// sfEu7ZzgjwEuhS1EkebXfkvH3wMyxpSgcvH8btDi6EMqG4goQ
(hex!["34a33af049f4f1b65d518e51f38c7afb0cd973c649588808b2ba0211f4ada535"].into(), 5 * CSPR),
// sfHZx1bZK6aoJKfQ1XQfpRD5VZBXZM1uREGcBsnKJdTZDnDod
(hex!["aaba173e1cd257c1ba67afbed0fbf2c4aadbfac329f129f12c4941b8b6bc5865"].into(), 5 * CSPR),
// sfJHhyq2r19nHEbKbVn3NEWqkDWnK53rU9mpRVPEYh7dqkCwU
(hex!["ca932abf1648393d722ad23c2cd97515a436840d905d3dd2b4d1913989abbc12"].into(), 2 * CSPR),
// sfE8Hv37BNfZfdj6aKC8XuBPQRG6eLRJPuRqEmrCfPGF4F7Ag
(hex!["1274036453f19a410d99cd7a13235422062ff5b0d2dbd608d87ad33b9b7b544c"].into(), 17 * CSPR),
// sfJHHALMCEmBTJHEdHkgMbUt2XMFP4K2AcYPiwgtz429YUqWv
(hex!["ca3f9e8480f200b6afe9661cb96a30259fc88b947c3ab466bd2b8e902a859719"].into(), 2 * CSPR),
// sfKTaDy3Yw6eXz4GFfXLRx9LnDf8qEt4JpqnPJc8bQVAu6kET
(hex!["fe55bea13108c5f9e070689c96d63c40ca79db709bebe921289003e56a1fdf27"].into(), 3 * CSPR),
// sfJ4NLMc92S6gSvQLsxUvhh4zXwde1yHYJCBu2WFjwL1Hxgfh
(hex!["c066d79465a7bd3138c770f52c1ad160272705e98f9b3dacc22bc70f010a1564"].into(), 12 * CSPR),
// sfJcMpW8ESzTzpmftos8MoJ7pUyRbxPabxPHSuigfxQxy8GBR
(hex!["d8ccf65eb5e93fdf7af47e9c6962a6822c7f0e8ed14d84f2bebdae0c5623e62b"].into(), 16 * CSPR),
// sfESZE2fNkkRCR2bSmmKZ5VzmMGHFh8eUdE2isdjne7JGW9AU
(hex!["2061f823e814d8c6b524da2f26ba2bfa048bbce57a1186e560b84c47a162b927"].into(), 1 * CSPR),
// sfFSxdDQWSnuF2zJ3tRv3B9Xxzu8boEkByCSXkq1T1F6vRky5
(hex!["4cecf92b37e6954f086002cf7b6a61ac7d9ba40c83ef963005e3cacfb5c1e13f"].into(), 21 * CSPR),
// sfEivpTTfp6Xh7nHaco1sxXQiy163pT474cS2dj8d8MREaJ2x
(hex!["2cde961358bf934533495f186755eb538a925aaa19ab4bad097f9d23665a9553"].into(), 24 * CSPR),
// sfJHPU8JPeCg35QvgTwZ2iFAwiavxem4McAYtgvTKpePSnUrw
(hex!["ca54d983c77c48c948fa9a6f9261ce2d9c4f20abf6632e28da3ec41d4752d519"].into(), 8 * CSPR),
// sfDyruPst6vv93A1pUYtmNQa95iypWhMw1n4PWDfpP9g1WHTQ
(hex!["0c05daf23268fdae4efd5bc1211f662c63399be10666ad3bdc75f3470a5b3378"].into(), 11 * CSPR),
// sfG5dZrh8trJRWewe1THxhvCTdR1Qq6NDUkoGuQg4VA6iAm2z
(hex!["68e4e6131e6a7aaf5ab2629d2ee721031df2e2a6573701862508fa3dc5765f5c"].into(), 4 * CSPR),
// sfHNVjWNHs6fwPpHmmPj4nJQ7evN35qr9KkJVeiJjmyf3fGxj
(hex!["a1fdef07d92813b10b15914afe763aa16bbf3feca8db73fabf1422cd48e05db0"].into(), 16 * CSPR),
// sfEYCLQnQzp8EYfqqhWmB1mtWNPX9AmVLGiwhVpFVQ5JuuGmu
(hex!["24af1eab02801a2d1afe16c75baa55f930138d58229f02f2840f387241529424"].into(), 18 * CSPR),
// sfDwQQ2Zy16Hx5qnHQbsXw8reMewJ684yUydmTXT7E3Y489se
(hex!["0a2622dc4be5606375d3a47e56e2580636b0057c46ec85bd44e149bff55fb943"].into(), 27 * CSPR),
// sfFMhheEBKGwDcJ9aqpYvVsAAq3tu2tEcVaRd66zfxY8qaShs
(hex!["48ea8240144388abb847a7b2c52f6290aeb77f1b6d8e10cda7d14a2f48b05035"].into(), 3 * CSPR),
// sfE66BLe2b6wM9dWctMnizM7yzadJrzGtTDC64cMTmJxZqGG1
(hex!["10c603d5a51516d1ee97212cf0b79f106332439750673b8605a527ffe1d45c50"].into(), 3 * CSPR),
// sfEiXa1R4CGPDZcdJ7oEnTuwiicA5Dhtny8z7aYhSrbDQNygK
(hex!["2c90529d502a1f3c51fcf487782b4defa09bd0e7470d1d080e44da713058241c"].into(), 24 * CSPR),
];
// Following keys are used in genesis config for testing (casper) chains. // Following keys are used in genesis config for testing (casper) chains.
// DO NOT use them in production chains such as ghost. // DO NOT use them in production chains such as ghost.
let endowed_accounts = vec![ let endowed_accounts = vec![
@ -448,28 +314,10 @@ fn casper_staging_config_genesis() -> serde_json::Value {
hex!["328d3b7c3046ef7700937d99fb2e98ce2591682c2b5dcf3f562e4da157650237"].into(), hex!["328d3b7c3046ef7700937d99fb2e98ce2591682c2b5dcf3f562e4da157650237"].into(),
// sfEwRjyvEQcpRQ1qbCZum27nEkTggKEt7DtqxwyYQULt9UuUN // sfEwRjyvEQcpRQ1qbCZum27nEkTggKEt7DtqxwyYQULt9UuUN
hex!["3666e4e19f87bb8680495f31864ce1f1c69d4178002cc01911aef2cc7313f203"].into(), hex!["3666e4e19f87bb8680495f31864ce1f1c69d4178002cc01911aef2cc7313f203"].into(),
// sfHcJxw5cgkvukZZyxcNUMCdbm9e7773orByLrGgAREka81TK
hex!["ac871e8bab00dd56ba3a1c0bd289357203dcaf10010b0b04ad7472870cd22a3c"].into(),
// sfFD7KSRi2aSREJWc9X75sVTN4a5pbPM5VSSJefmPvMuiVbPr // sfFD7KSRi2aSREJWc9X75sVTN4a5pbPM5VSSJefmPvMuiVbPr
hex!["425ccd7bda4f5c76788ba23bc0381d7a2e496179c93301208c57501c80a4232a"].into(), hex!["425ccd7bda4f5c76788ba23bc0381d7a2e496179c93301208c57501c80a4232a"].into(),
// sfH29zyFYtoFj6fSXskAEXG5XyyMCa5YycahJkYMwSUz8CcEU // sfH29zyFYtoFj6fSXskAEXG5XyyMCa5YycahJkYMwSUz8CcEU
hex!["927a98dcf8f721103005f168476c24b91d7d10d580f457006a908e10e62c7729"].into(), hex!["927a98dcf8f721103005f168476c24b91d7d10d580f457006a908e10e62c7729"].into(),
// sfHcRoUmrL8GDmWxUcPcZEWVfJbnaXyjWuaBxu5pNtdW5nERK
hex!["ac9e227e30a63ce6eeb55cfbb1fb832aa7e1d3fad2bcb3f663de4a91d744fd50"].into(),
// sfFJuDxqSc3skWaNUQgqmtCDYvcRj9c56urEky7ByD26aXQEW
hex!["46c78fcacffd80abc9cca4917ef8369a37e21a1691ca11e7a3b53f80be745313"].into(),
// sfKNNbANdBuBpA4n1sXwPBhV57HBgV2y3R3YjHz1S1uWKfKAy
hex!["fa5e5a295ec74c3dda81118d9240db1552b28f831838465ae0712e97e78a6728"].into(),
// sfFAdZQQVdbCTA7eWomTrJXe5L8ZcwZRfkyyRkMQZftDqbcMg
hex!["4078ddb1ba1388f768fe6aa40ba9124a72692ecbcc83dc088fa86c735e4dc128"].into(),
// sfFqT8fmF15Ddshio5rnucmqzMxtUoHZVh7qSALSdAaM7Y6zb
hex!["5e1456904c40192cd3a18183df7dffea90d97739830a902cabb702ecdae4f649"].into(),
// sfFzUcPxuourb6JtdiudRkrsbnkxne1KEcpksVMJYGau5BVTG
hex!["64f685baa838323c0ef8c45259a3036b3e2bc54edf6553ce323e25b5e37a3721"].into(),
// sfHLkJNKVyAsVMC4bQQwsm1EMyWgKLQH8FFnZzLC78dYJDqSp
hex!["a0a87a75dba18037aa2e7b8036ce951e8d8356104758e15c9f44e2fd7d1bbc41"].into(),
// sfGCg772bqKp3wH23EQbgSbCQ5Q8BCwmCJ39XjR3xLwq6foYD
hex!["6e4429a8fa85cfe2a60488af446d57e719207831b2579b937325645e110bb666"].into(),
]; ];
let initial_authorities: Vec<( let initial_authorities: Vec<(
@ -486,13 +334,17 @@ fn casper_staging_config_genesis() -> serde_json::Value {
// sfFXZmnDVnkQ781J2gbqUpi7K5KgMWMdM4eeii74xxGgKYnNN // sfFXZmnDVnkQ781J2gbqUpi7K5KgMWMdM4eeii74xxGgKYnNN
hex!["507045c82be367f95408466cd054ca39bfa52697a3ef22809af14cf9de304f02"].into(), hex!["507045c82be367f95408466cd054ca39bfa52697a3ef22809af14cf9de304f02"].into(),
// sfJeojACBa7WiH6tBwikBKAMU2oKmseEBD1GYUYATvfWuLcPa // sfJeojACBa7WiH6tBwikBKAMU2oKmseEBD1GYUYATvfWuLcPa
hex!["daaaaab6a6e574099e24ae9bb75b543610edef9d374fa85a378edb573b47615f"].unchecked_into(), hex!["daaaaab6a6e574099e24ae9bb75b543610edef9d374fa85a378edb573b47615f"]
.unchecked_into(),
// sfFdtzNxJdeEkgHxvk144rJKxf7wcYvgX5tqfgZRutW9YvAKE // sfFdtzNxJdeEkgHxvk144rJKxf7wcYvgX5tqfgZRutW9YvAKE
hex!["55446f9a7aa99ced06b317c80ce90d56b84e56526775683af2525969e8da0b64"].unchecked_into(), hex!["55446f9a7aa99ced06b317c80ce90d56b84e56526775683af2525969e8da0b64"]
.unchecked_into(),
// sfE8gsMYAjAJHk5gyYZN7AW6pfmJ7V9H7xxWto24nmhzCUXaQ // sfE8gsMYAjAJHk5gyYZN7AW6pfmJ7V9H7xxWto24nmhzCUXaQ
hex!["12c14850562021eb99f58f90ab624fb6cfaf3ac9228a92f8b60115fe6a6af15a"].unchecked_into(), hex!["12c14850562021eb99f58f90ab624fb6cfaf3ac9228a92f8b60115fe6a6af15a"]
.unchecked_into(),
// sfE3GKSrKZzrZpdapJ2VGRpPor45T4D4i8QBZNumSNGqGv7PX // sfE3GKSrKZzrZpdapJ2VGRpPor45T4D4i8QBZNumSNGqGv7PX
hex!["0e9e698c7b2bf5ce3861cb4bc4ddf9e200237c282025b093ada850d764d12a35"].unchecked_into(), hex!["0e9e698c7b2bf5ce3861cb4bc4ddf9e200237c282025b093ada850d764d12a35"]
.unchecked_into(),
), ),
( (
// sfHLqWNC4hMKHhwvPWmWcxZsDPhCTQKgh1Ap7pm3qML5GBTBa // sfHLqWNC4hMKHhwvPWmWcxZsDPhCTQKgh1Ap7pm3qML5GBTBa
@ -500,27 +352,17 @@ fn casper_staging_config_genesis() -> serde_json::Value {
// sfHLqWNC4hMKHhwvPWmWcxZsDPhCTQKgh1Ap7pm3qML5GBTBa // sfHLqWNC4hMKHhwvPWmWcxZsDPhCTQKgh1Ap7pm3qML5GBTBa
hex!["a0ba0196e6ee7e6b5b0553035c5cb5c04e9725001b5732839d0529cbc00c9600"].into(), hex!["a0ba0196e6ee7e6b5b0553035c5cb5c04e9725001b5732839d0529cbc00c9600"].into(),
// sfGA6tPPF8dAc8QpMCMjxitG3j8sXPhkdpm5bwz4UsXAApUiw // sfGA6tPPF8dAc8QpMCMjxitG3j8sXPhkdpm5bwz4UsXAApUiw
hex!["6c4dd88b43e2011cf9a6a73d53446336ac9e04cdd4ca23587df63187ac455e49"].unchecked_into(), hex!["6c4dd88b43e2011cf9a6a73d53446336ac9e04cdd4ca23587df63187ac455e49"]
.unchecked_into(),
// sfGxQZXFUQH1AXv82rpjiJHFs7YsdEuVGdyvKiS2Tajpvw6Se // sfGxQZXFUQH1AXv82rpjiJHFs7YsdEuVGdyvKiS2Tajpvw6Se
hex!["8f9ea20bf4a807a8e710f7559dece86e94672b5b361de157bdaa5c1f37849f8d"].unchecked_into(), hex!["8f9ea20bf4a807a8e710f7559dece86e94672b5b361de157bdaa5c1f37849f8d"]
.unchecked_into(),
// sfGz2enFUR22cQ5ey61MdtPqbCeEWZA1wsCFFSLGaK7vKnv8C // sfGz2enFUR22cQ5ey61MdtPqbCeEWZA1wsCFFSLGaK7vKnv8C
hex!["90db5ed339a559ed157995a48d781f44c7df972dfba4bc855e4b59fa46438e17"].unchecked_into(), hex!["90db5ed339a559ed157995a48d781f44c7df972dfba4bc855e4b59fa46438e17"]
.unchecked_into(),
// sfEtwe5BoroNjkdLsvnjnMemUKiw8MS1X4YW8bepbbGvhS4LZ // sfEtwe5BoroNjkdLsvnjnMemUKiw8MS1X4YW8bepbbGvhS4LZ
hex!["3481cdcbcf37a4669c29a78cf9ceb39383a10ef0a18b36b92d149fdd0c24ae00"].unchecked_into(), hex!["3481cdcbcf37a4669c29a78cf9ceb39383a10ef0a18b36b92d149fdd0c24ae00"]
), .unchecked_into(),
(
// sfGq75CrCrkcfqNzyyidu3D4jW3AoJSzL5tKKuv1UbS16ezzy
hex!["8a0d0b66e827bf20e79f9a499317e73925ce4f422371067edfab690e43857f13"].into(),
// sfGq75CrCrkcfqNzyyidu3D4jW3AoJSzL5tKKuv1UbS16ezzy
hex!["8a0d0b66e827bf20e79f9a499317e73925ce4f422371067edfab690e43857f13"].into(),
// sfJo2ogBpssRAU9ZPTvuXFZEdmJw9pKsPydLjXe8DypRScjzT
hex!["e0f0a776ecc9fa5e1f22e2fa001fe3fba5aea52b9444bc894b45589d42132475"].unchecked_into(),
// sfHq3EVT1sqY7o5ki3zA6LEdRDfdFc29YaZN3w2Thhz6JD5ZF
hex!["b63c5a0cf342b9b04931bc8ed74d7d0165ab99ab5f8a4514797d4b299a4501fe"].unchecked_into(),
// sfEj3wrDy9EDLCAodyEdQEYxJpNnM8Etaj3RJ5bCBRzdaDced
hex!["2cf69452e9f2a8457119139408884941ed50f590c0fc0f2b044c4d82c69e4245"].unchecked_into(),
// sfE32RmBp1xX4KRTphVGLUJBxLGPN3Dzg9BwCJktxMf3iEwck
hex!["0e6fa6934f9e99fa84874f2ed9318825a0d5443a0ced984acfbd24ece72ba55e"].unchecked_into(),
), ),
( (
// sfG9iWUS7AKBzvqdz3uDZv7f1t79vvSTYL1VxzYPHjhmLnQVn // sfG9iWUS7AKBzvqdz3uDZv7f1t79vvSTYL1VxzYPHjhmLnQVn
@ -528,13 +370,17 @@ fn casper_staging_config_genesis() -> serde_json::Value {
// sfG9iWUS7AKBzvqdz3uDZv7f1t79vvSTYL1VxzYPHjhmLnQVn // sfG9iWUS7AKBzvqdz3uDZv7f1t79vvSTYL1VxzYPHjhmLnQVn
hex!["6c0283f4c688f0e75ad546c790bbd5961c1a6931543aa589f368f8272c44b758"].into(), hex!["6c0283f4c688f0e75ad546c790bbd5961c1a6931543aa589f368f8272c44b758"].into(),
// sfGMUYXSjHgwGBpbGiHFoqT1DdJwZdHk49H5ViaQM7HUnayvZ // sfGMUYXSjHgwGBpbGiHFoqT1DdJwZdHk49H5ViaQM7HUnayvZ
hex!["74fa7381a7a74b316afb6793a00387eed9d95d46a69866cbb316b5d9c918af0e"].unchecked_into(), hex!["74fa7381a7a74b316afb6793a00387eed9d95d46a69866cbb316b5d9c918af0e"]
.unchecked_into(),
// sfEWYhczV6PbmeNXZTcA4LvhpzvCfNMatYoSNKvDphmNaQzqB // sfEWYhczV6PbmeNXZTcA4LvhpzvCfNMatYoSNKvDphmNaQzqB
hex!["236d2fa03f4ed8cb65de7e514d7540159b328f1c170dd402b094ad7fbf547218"].unchecked_into(), hex!["236d2fa03f4ed8cb65de7e514d7540159b328f1c170dd402b094ad7fbf547218"]
.unchecked_into(),
// sfDirg32ityDvrjxh4822unhP4qm4S9yTqN99gesN322swn7h // sfDirg32ityDvrjxh4822unhP4qm4S9yTqN99gesN322swn7h
hex!["00946618c353e4c6546b87f9ca1089b846b0ea4658ee8e6d9d1200c24cb5ee27"].unchecked_into(), hex!["00946618c353e4c6546b87f9ca1089b846b0ea4658ee8e6d9d1200c24cb5ee27"]
.unchecked_into(),
// sfFZgp1Z5diFAZ16swuQD5GojGCsMMFVR19uWnCrppMLuYjRv // sfFZgp1Z5diFAZ16swuQD5GojGCsMMFVR19uWnCrppMLuYjRv
hex!["520e74f8c5853ec8577932327ad3247656db25b74c79ad09adb431b271002401"].unchecked_into(), hex!["520e74f8c5853ec8577932327ad3247656db25b74c79ad09adb431b271002401"]
.unchecked_into(),
), ),
( (
// sfHjtrXFzRmxwjE4rjVxFJXpvVv7furjdymZS7PQRFiANpodz // sfHjtrXFzRmxwjE4rjVxFJXpvVv7furjdymZS7PQRFiANpodz
@ -542,125 +388,17 @@ fn casper_staging_config_genesis() -> serde_json::Value {
// sfHjtrXFzRmxwjE4rjVxFJXpvVv7furjdymZS7PQRFiANpodz // sfHjtrXFzRmxwjE4rjVxFJXpvVv7furjdymZS7PQRFiANpodz
hex!["b24feb55b2cac4b365a9245c2a97525b01bd1a594d2d42b91f6bc38c9c2e6517"].into(), hex!["b24feb55b2cac4b365a9245c2a97525b01bd1a594d2d42b91f6bc38c9c2e6517"].into(),
// sfF5XWwvNPjZEsBz1HWs5Ys5zcE85UHnN1BV8TBBectqFQZRm // sfF5XWwvNPjZEsBz1HWs5Ys5zcE85UHnN1BV8TBBectqFQZRm
hex!["3c944c704cae203619b9e7a5a4b6742736da6a8e76c762291bebdc7652cfec2f"].unchecked_into(), hex!["3c944c704cae203619b9e7a5a4b6742736da6a8e76c762291bebdc7652cfec2f"]
.unchecked_into(),
// sfDx3gj4wFHg3cK6bopnypHQ6TxW1VgyPsYVbXKhRHtLDLxQb // sfDx3gj4wFHg3cK6bopnypHQ6TxW1VgyPsYVbXKhRHtLDLxQb
hex!["0aa3a88f6b777c95c3dfe7e997b76798413f16aa325f34824cae0c9102b281d5"].unchecked_into(), hex!["0aa3a88f6b777c95c3dfe7e997b76798413f16aa325f34824cae0c9102b281d5"]
.unchecked_into(),
// sfHXZbnZV3YWwnH28q2xumm7stvuC8LweYYxPNuHGonnX7QHL // sfHXZbnZV3YWwnH28q2xumm7stvuC8LweYYxPNuHGonnX7QHL
hex!["a8e828d10cf7b74481b6e746e5532d4740ea8014a0d3d856540a59847f8a6b76"].unchecked_into(), hex!["a8e828d10cf7b74481b6e746e5532d4740ea8014a0d3d856540a59847f8a6b76"]
.unchecked_into(),
// sfEaHBrBgeMhRTA3WHE9Nbyvn3h7xkhYKi7go4yo81L88o9zJ // sfEaHBrBgeMhRTA3WHE9Nbyvn3h7xkhYKi7go4yo81L88o9zJ
hex!["2645f1f6820dd3a917eebbdab033088d8862477c1c14759b218685f9a0893377"].unchecked_into(), hex!["2645f1f6820dd3a917eebbdab033088d8862477c1c14759b218685f9a0893377"]
), .unchecked_into(),
(
// sfFFYKBEwmJAQEJR73Q4Gfs1sH1c8wyuBGnHc1UdzWucAYrKC
hex!["44376f8fa786be1f16fcb45232cfb07300cea845b2fc6e30dde61952de3e5e33"].into(),
// sfFFYKBEwmJAQEJR73Q4Gfs1sH1c8wyuBGnHc1UdzWucAYrKC
hex!["44376f8fa786be1f16fcb45232cfb07300cea845b2fc6e30dde61952de3e5e33"].into(),
// sfK4K5bS7M6bHeKHoGec9bw1PMngNyzhTx9YZq6hkqibos4LJ
hex!["ec981eb1ef1ddbc8ded2db16198cb03667b4b39a8ea58f28ad469ddfaf256161"].unchecked_into(),
// sfECakKMW2xf5dK8Ut55tnwadoKTNGKdRLh5E7dYRmV6sW812
hex!["15b9a867891cf449584b108e512d60b945b1a065bec1703c4c5709ee5093c03d"].unchecked_into(),
// sfErEin4Ljy11VGnYtTYJZ9LLcDP4fvsKV6f9LXYRwRXtrNqa
hex!["3271915dc67eba8ad2759a30c2537702f4fbf45647cba565e3a464ab75b91f05"].unchecked_into(),
// sfGD5sHSa1h8NGpUD29ZogBJW6fatg8Sg6Pzg9Q7RPUm24Mkr
hex!["6e9426dc78fba9eeb264dcab98be86daf3d8cf510ecfb2acddec370295ff8176"].unchecked_into(),
),
(
// sfFPZZNrhDuY9MKJCBHyBCkgJecgDqPJBPSjA37be4czdX6t3
hex!["4a5596e97c602e7846d54fae81dcdc5a553b7422231e32f9567ac30a6b7c743a"].into(),
// sfFPZZNrhDuY9MKJCBHyBCkgJecgDqPJBPSjA37be4czdX6t3
hex!["4a5596e97c602e7846d54fae81dcdc5a553b7422231e32f9567ac30a6b7c743a"].into(),
// sfJP8aW6eSUs14AfUG6ZDFFjtyJxDed5Ubk1CFh7dNmL69rbx
hex!["ceb63298b1b7a1277fddf6eee735dbbf9921fd5ebaac0132eee1963e22cf5935"].unchecked_into(),
// sfH6jAeHqDpwtYGv9KJWNJ8aom8ivSvVztRSwAHw4bXd1isoP
hex!["95f73a6271b517f2016fa91411bdeeb990158066c95f106a79697446ba9f78b4"].unchecked_into(),
// sfEXSdKyx6uQBzgR3a7oH53XSCLrjUM2B7fbcvUvm21b5J6Uf
hex!["241bfc05caa2d3e53e671df7261599c13f069a37f6cc4be10b5d49502c3a1e1c"].unchecked_into(),
// sfGXqJTwJTkh3bwhECju7XCdgvJXYJZUtYSEJ2PbfpXGak42s
hex!["7ce0c80ee65fb00e229d8c8fa5484144eca3d45d733165fbffcdb4de24c14951"].unchecked_into(),
),
(
// sfESE7VifnknxVe71z3zsqC3xiirXyzHurKjdQoD537WpwJjW
hex!["2021a16182e3af39a79d20021a1b8755d589c04292d361d6b387411f7e975602"].into(),
// sfESE7VifnknxVe71z3zsqC3xiirXyzHurKjdQoD537WpwJjW
hex!["2021a16182e3af39a79d20021a1b8755d589c04292d361d6b387411f7e975602"].into(),
// sfFzQmYYckD8XLV7XGU1pJAyt1K3foCpPumpKBqdb5sJGHXrc
hex!["64e9968f3af2e1a86ee8d4be9ad77a1d66f50138527988bf93ede25baaf2e671"].unchecked_into(),
// sfFHjCLzWetvQJQzNwxeWcrkHmnPS1mVz7gT63yiRdvxFZ9T8
hex!["45e28f333bf0d4a9956ae20341cd07db8d471c4b482ed15d5cf7edd70201670d"].unchecked_into(),
// sfHJAk4HiVuMjXqaXoFEKTCF6938Lta7qd9w3zbyyuWCs1T5L
hex!["9eb1063afcaf568e7a62458ef33237a41ca500c89e084f7a5dd75bf5d89b105a"].unchecked_into(),
// sfEm2SME5H6GiezhYokZWmrZLMTUNFbLV7xwgKrMXz3NwppKb
hex!["2e77fde21162d1f21ca371846d70c3b75931329074101ee668e614336d25c120"].unchecked_into(),
),
(
// sfHpvEbP79MrDMVw4GhTvgLSU987ZSJ21VAsDWiJdgjG3ijse
hex!["b624cb291f7464773f3b449ee2252165f3934ace08b1e10611a53e174766fc73"].into(),
// sfHpvEbP79MrDMVw4GhTvgLSU987ZSJ21VAsDWiJdgjG3ijse
hex!["b624cb291f7464773f3b449ee2252165f3934ace08b1e10611a53e174766fc73"].into(),
// sfJHYLgjoHotvKi46URmtaVoG4p54SPE2ASTrauym99WxFcAn
hex!["ca72b6ea2c83f9e429479bf51c324ea90cbf01e08d2850ced2590c8796cfe222"].unchecked_into(),
// sfFVPqgCsDQe3k4qhGmUH4UoZaxsGb9majPgoH3WaYCZjFhTf
hex!["4ec8584ca9da16d8c60e1770e98fbca8bec648e13c69601e3dfdc1330bf1f999"].unchecked_into(),
// sfJ6nxM1SvcdbV2Gmf8WKkPKeX6rRYaEmSj7V9r64799acqHV
hex!["c2403683be24a92ae8489e28fb502e2bab16d815c4f6c865c50ffb34430a8d7c"].unchecked_into(),
// sfK1sQY3GL8waX2htW9EaBo9MjWGuy4VGeiUfP4NCq5tCjt37
hex!["eabb3463e300f357b9886683d5a240a395f6bd41182057f03b0e9697a8b3465e"].unchecked_into(),
),
(
// sfJeU4TBQyuGxfsCqNDPax1TcfAseEmBDPqx5YEm7kXUvnnPa
hex!["da6875e9df9a7894e065ef5befcde567dec4dc2c0b73a6ad5514dcca26a90702"].into(),
// sfJeU4TBQyuGxfsCqNDPax1TcfAseEmBDPqx5YEm7kXUvnnPa
hex!["da6875e9df9a7894e065ef5befcde567dec4dc2c0b73a6ad5514dcca26a90702"].into(),
// sfGbxmQAD2jbktjRkq6NsJxHKHWnkdtvoR14fFPAX85t148ej
hex!["8006e3f6e3d92c4c5f2e2f001452e4993e6d5c2b1136f2ae6060c6e9c9523b4a"].unchecked_into(),
// sfGm1jJagueW5dCng6xKCDx3FX2JohtsYMuNjf2tJGXN5ePUL
hex!["86ee138c9e7e67c1c2e157c0ba888761a122d8b9aa6a8653e886ac329e34255d"].unchecked_into(),
// sfEB68auUQmSCK8M3Zr7WuzRSipj9sQ5ykfDmvLmT8FDY5bg6
hex!["1496150847d512e0491899eba72ee36f76b882ae29fccf18201fd9fbd5bfd300"].unchecked_into(),
// sfHZqUptNXpRNGPHKn2Tfv8K1RjFGJ9XCdSw41nPAw9ZXM37T
hex!["aaa41b6ade4c30b5792aa6e5604c444e424900ddf649b23eed4bd0d7f5d3a34f"].unchecked_into(),
),
(
// sfFBEdrB1J7jLJKQp3fABEiHkwec1gCgGeTxMVyVm4UjWwvRs
hex!["40eef1c6c8d8242ccbd3f03144bd4ea1a7374cbd8219e2849d3a3ee78f1da045"].into(),
// sfFBEdrB1J7jLJKQp3fABEiHkwec1gCgGeTxMVyVm4UjWwvRs
hex!["40eef1c6c8d8242ccbd3f03144bd4ea1a7374cbd8219e2849d3a3ee78f1da045"].into(),
// sfF2FRJSuQSCidfbpu8DwpsHwezCcBJcZfh7Pds5vqtEF3Rbw
hex!["3a145fb664353e473f1937058c881b14ed150285f3cec1aff348c5209d56d96d"].unchecked_into(),
// sfDysi9h3PJoA5BGeJ2vfAkx3wXS9oK7yTDUyuJG2CRMJvXnh
hex!["0c0891a518270014530061bd217606269686abdf3c1d237a3c6a3db308fc2d0d"].unchecked_into(),
// sfGsyqzBAT7a9oBGdDBykyRwF95wRBL4yaGs4QFWznXHw5xsF
hex!["8c3e730f6e6ecfb96581091e71556175384f077bee31b0199f13321df018427d"].unchecked_into(),
// sfJP7W9aZe2F6G5w7xZtHhzSUCg86SvUcur4GPm2LMs7N2f5w
hex!["ceb294227950d177b63e6c1d10a66131f5da3792428b03f5b83be84a33db215f"].unchecked_into(),
),
(
// sfFCsSaJrPqkCZMdkm7WoyHP7w3UbNaC3aCHQfWbUaLbDqfdR
hex!["422e16b0c58f03af378d1638fe56127f337abf1d1a4a740c3371714616abd43d"].into(),
// sfFCsSaJrPqkCZMdkm7WoyHP7w3UbNaC3aCHQfWbUaLbDqfdR
hex!["422e16b0c58f03af378d1638fe56127f337abf1d1a4a740c3371714616abd43d"].into(),
// sfGShS9zKf8nzDr71qPv9LZJtK1LCMxPV4QUMYG8jvZhVe9pS
hex!["78f612068566eb6cc5cb5d9f1fda92c5dc3e3888eb61eb1af27af6855365ba3c"].unchecked_into(),
// sfJg5cPBkyrcu7zZaKaUkjp2vDVGfpGNjjT1sn8fS6qjv9mDU
hex!["dba3613933d60ca248ee024deac42bc9c8c2d9fe8734b6052cd9a148978cbedb"].unchecked_into(),
// sfFav2ALRGkJtmEHEpz2LiRmshGPzn4aWdAZeFUyKA56LqDDF
hex!["52fe2b63b03a0d439923967278442418a2d1f0d250bcab26f85f12ea212cbd3e"].unchecked_into(),
// sfDmN4zoicQ54R5MmSpCf9ojg8zE2eD3x39pnba412oDivkBc
hex!["027dd852bf20bef53545afd1e08bf8760abb6b1af1df6c17e73f4cf88210ee46"].unchecked_into(),
),
(
// sfF2fiFe2PteoYe286cZNJpxaT1omCPuTgwHjB1Z8tqjsLxRn
hex!["3a6626211a2dd35683fd7cb5f2f343d75f2b698d6c48c2d6eb1cdbe116e32315"].into(),
// sfF2fiFe2PteoYe286cZNJpxaT1omCPuTgwHjB1Z8tqjsLxRn
hex!["3a6626211a2dd35683fd7cb5f2f343d75f2b698d6c48c2d6eb1cdbe116e32315"].into(),
// sfG9m1LEV1sjUwyLwp1UQPUGnuMGF1oaCjSC4PVx9q4zgJRMr
hex!["6c0aec49974aaff08ff962a2d8d7857227d027ed27a272cbc4acaa1ee937db0f"].unchecked_into(),
// sfH3JwHTbimvG3SZLd5d8Ad8Ztvgb8NVSwxxzxYfArpXVYqFD
hex!["935becdfb2e0d4fcd46ba82e680cfc447180de6b85ec42d17f1396a520b0c04f"].unchecked_into(),
// sfGkKjBX5UdujuTrbxyepUzdU4Jew7DvgNs1UUM2HBLj4xNM5
hex!["86676ad3cd2d970b86dee2f25d4318f9bba40455111f16300e114e7f00c58706"].unchecked_into(),
// sfDisU5wryao4kcd4WuHyZZB6LfJrDuoQoU14cTiiJqD7Whoc
hex!["009712519ba7dad1c682c871b94573ccaba8b7d530f7194fb16bf553fd7ae67d"].unchecked_into(),
), ),
]; ];
@ -676,7 +414,6 @@ fn casper_staging_config_genesis() -> serde_json::Value {
.iter() .iter()
.map(|k: &AccountId| (k.clone(), ENDOWMENT)) .map(|k: &AccountId| (k.clone(), ENDOWMENT))
.chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH))) .chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH)))
.chain(whales_endowments)
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
}, },
"session": { "session": {
@ -742,7 +479,9 @@ fn casper_staging_config_genesis() -> serde_json::Value {
fn casper_development_config_genesis() -> serde_json::Value { fn casper_development_config_genesis() -> serde_json::Value {
testnet_config_genesis( testnet_config_genesis(
vec![get_authority_keys_from_seed("Alice")], vec![get_authority_keys_from_seed("Alice")],
None, None, None, None,
None,
None,
) )
} }

View File

@ -7,15 +7,15 @@ pub mod chain_spec;
use { use {
grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider}, grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider},
sc_client_api::BlockBackend, sc_client_api::BlockBackend,
tx_pool_api::OffchainTransactionPoolFactory,
sp_blockchain::HeaderBackend,
sc_service::{KeystoreContainer, RpcHandlers}, sc_service::{KeystoreContainer, RpcHandlers},
sp_blockchain::HeaderBackend,
telemetry::{Telemetry, TelemetryWorkerHandle}, telemetry::{Telemetry, TelemetryWorkerHandle},
tx_pool_api::OffchainTransactionPoolFactory,
}; };
use sc_executor::{HeapAllocStrategy, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY};
use std::{sync::Arc, time::Duration}; use std::{sync::Arc, time::Duration};
use telemetry::TelemetryWorker; use telemetry::TelemetryWorker;
use sc_executor::{HeapAllocStrategy, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY};
pub use chain_spec::GenericChainSpec; pub use chain_spec::GenericChainSpec;
pub use consensus_common::{Proposal, SelectChain}; pub use consensus_common::{Proposal, SelectChain};
@ -23,27 +23,23 @@ pub use primitives::{Block, BlockId, BlockNumber, Hash};
pub use sc_client_api::{Backend, CallExecutor}; pub use sc_client_api::{Backend, CallExecutor};
pub use sc_consensus::BlockImport; pub use sc_consensus::BlockImport;
pub use sc_executor::NativeExecutionDispatch; pub use sc_executor::NativeExecutionDispatch;
pub use sp_api::{ApiRef, ConstructRuntimeApi, Core as CoreApi, ProvideRuntimeApi};
pub use sc_service::{ pub use sc_service::{
config::{DatabaseSource, PrometheusConfig}, config::{DatabaseSource, PrometheusConfig},
ChainSpec, Configuration, Error as SubstrateServiceError, PruningMode, Role, ChainSpec, Configuration, Error as SubstrateServiceError, PruningMode, Role, RuntimeGenesis,
RuntimeGenesis, TFullBackend, TFullCallExecutor, TFullClient, TaskManager, TFullBackend, TFullCallExecutor, TFullClient, TaskManager, TransactionPoolOptions,
TransactionPoolOptions,
}; };
pub use sp_api::{ApiRef, ConstructRuntimeApi, Core as CoreApi, ProvideRuntimeApi};
pub use sp_runtime::{ pub use sp_runtime::{
generic, generic,
traits::{ traits::{self as runtime_traits, BlakeTwo256, Block as BlockT, Header as HeaderT, NumberFor},
self as runtime_traits, BlakeTwo256, Block as BlockT, Header as HeaderT,
NumberFor,
},
}; };
#[cfg(feature = "casper-native")]
use casper_runtime::RuntimeApi;
#[cfg(feature = "casper-native")] #[cfg(feature = "casper-native")]
pub use chain_spec::CasperChainSpec; pub use chain_spec::CasperChainSpec;
#[cfg(feature = "casper-native")] #[cfg(feature = "casper-native")]
pub use {casper_runtime, casper_runtime_constants}; pub use {casper_runtime, casper_runtime_constants};
#[cfg(feature = "casper-native")]
use casper_runtime::RuntimeApi;
#[cfg(feature = "full-node")] #[cfg(feature = "full-node")]
pub type FullBackend = sc_service::TFullBackend<Block>; pub type FullBackend = sc_service::TFullBackend<Block>;
@ -177,9 +173,13 @@ impl IdentifyVariant for Box<dyn ChainSpec> {
} }
fn identify_chain(&self) -> Chain { fn identify_chain(&self) -> Chain {
if self.is_ghost() { Chain::Ghost } if self.is_ghost() {
else if self.is_casper() { Chain::Casper } Chain::Ghost
else { Chain::Unknown } } else if self.is_casper() {
Chain::Casper
} else {
Chain::Unknown
}
} }
} }
@ -222,7 +222,9 @@ fn new_partial_basics(
let heap_pages = config let heap_pages = config
.default_heap_pages .default_heap_pages
.map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |h| HeapAllocStrategy::Static { extra_pages: h as _ }); .map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |h| HeapAllocStrategy::Static {
extra_pages: h as _,
});
let executor = WasmExecutor::builder() let executor = WasmExecutor::builder()
.with_execution_method(config.wasm_method) .with_execution_method(config.wasm_method)
@ -251,13 +253,25 @@ fn new_partial_basics(
telemetry telemetry
}); });
Ok(Basics { task_manager, client, backend, keystore_container, telemetry }) Ok(Basics {
task_manager,
client,
backend,
keystore_container,
telemetry,
})
} }
#[cfg(feature = "full-node")] #[cfg(feature = "full-node")]
fn new_partial<ChainSelection>( fn new_partial<ChainSelection>(
config: &mut Configuration, config: &mut Configuration,
Basics { task_manager, backend, client, keystore_container, telemetry }: Basics, Basics {
task_manager,
backend,
client,
keystore_container,
telemetry,
}: Basics,
select_chain: ChainSelection, select_chain: ChainSelection,
) -> Result< ) -> Result<
sc_service::PartialComponents< sc_service::PartialComponents<
@ -272,11 +286,7 @@ fn new_partial<ChainSelection>(
ghost_rpc::SubscriptionTaskExecutor, ghost_rpc::SubscriptionTaskExecutor,
) -> Result<ghost_rpc::RpcExtension, SubstrateServiceError>, ) -> Result<ghost_rpc::RpcExtension, SubstrateServiceError>,
( (
babe::BabeBlockImport< babe::BabeBlockImport<Block, FullClient, FullGrandpaBlockImport<ChainSelection>>,
Block,
FullClient,
FullGrandpaBlockImport<ChainSelection>,
>,
grandpa::LinkHalf<Block, FullClient, ChainSelection>, grandpa::LinkHalf<Block, FullClient, ChainSelection>,
babe::BabeLink<Block>, babe::BabeLink<Block>,
), ),
@ -297,14 +307,13 @@ where
client.clone(), client.clone(),
); );
let (grandpa_block_import, grandpa_link) = let (grandpa_block_import, grandpa_link) = grandpa::block_import(
grandpa::block_import( client.clone(),
client.clone(), GRANDPA_JUSTIFICATION_PERIOD,
GRANDPA_JUSTIFICATION_PERIOD, &(client.clone() as Arc<_>),
&(client.clone() as Arc<_>), select_chain.clone(),
select_chain.clone(), telemetry.as_ref().map(|x| x.handle()),
telemetry.as_ref().map(|x| x.handle()), )?;
)?;
let justification_import = grandpa_block_import.clone(); let justification_import = grandpa_block_import.clone();
let babe_config = babe::configuration(&*client)?; let babe_config = babe::configuration(&*client)?;
@ -312,27 +321,26 @@ where
babe::block_import(babe_config.clone(), grandpa_block_import, client.clone())?; babe::block_import(babe_config.clone(), grandpa_block_import, client.clone())?;
let slot_duration = babe_link.config().slot_duration(); let slot_duration = babe_link.config().slot_duration();
let (import_queue, babe_worker_handle) = let (import_queue, babe_worker_handle) = babe::import_queue(babe::ImportQueueParams {
babe::import_queue(babe::ImportQueueParams { link: babe_link.clone(),
link: babe_link.clone(), block_import: block_import.clone(),
block_import: block_import.clone(), justification_import: Some(Box::new(justification_import)),
justification_import: Some(Box::new(justification_import)), client: client.clone(),
client: client.clone(), select_chain: select_chain.clone(),
select_chain: select_chain.clone(), create_inherent_data_providers: move |_, ()| async move {
create_inherent_data_providers: move |_, ()| async move { let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let slot =
let slot = babe_primitives::inherents::InherentDataProvider::from_timestamp_and_slot_duration(
babe_primitives::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp,
*timestamp, slot_duration,
slot_duration, );
); Ok((slot, timestamp))
Ok((slot, timestamp)) },
}, spawner: &task_manager.spawn_essential_handle(),
spawner: &task_manager.spawn_essential_handle(), registry: config.prometheus_registry(),
registry: config.prometheus_registry(), telemetry: telemetry.as_ref().map(|x| x.handle()),
telemetry: telemetry.as_ref().map(|x| x.handle()), offchain_tx_pool_factory: OffchainTransactionPoolFactory::new(transaction_pool.clone()),
offchain_tx_pool_factory: OffchainTransactionPoolFactory::new(transaction_pool.clone()), })?;
})?;
let justification_stream = grandpa_link.justification_stream(); let justification_stream = grandpa_link.justification_stream();
let shared_authority_set = grandpa_link.shared_authority_set().clone(); let shared_authority_set = grandpa_link.shared_authority_set().clone();
@ -353,10 +361,9 @@ where
let chain_spec = config.chain_spec.cloned_box(); let chain_spec = config.chain_spec.cloned_box();
let backend = backend.clone(); let backend = backend.clone();
move | move |deny_unsafe,
deny_unsafe, subscription_executor: ghost_rpc::SubscriptionTaskExecutor|
subscription_executor: ghost_rpc::SubscriptionTaskExecutor, -> Result<ghost_rpc::RpcExtension, sc_service::Error> {
| -> Result<ghost_rpc::RpcExtension, sc_service::Error> {
let deps = ghost_rpc::FullDeps { let deps = ghost_rpc::FullDeps {
client: client.clone(), client: client.clone(),
pool: transaction_pool.clone(), pool: transaction_pool.clone(),
@ -428,8 +435,7 @@ pub fn new_full<Network: sc_network::NetworkBackend<Block, <Block as BlockT>::Ha
let backoff_authoring_blocks = if !force_authoring_backoff { let backoff_authoring_blocks = if !force_authoring_backoff {
None None
} else { } else {
let mut backoff = let mut backoff = sc_consensus_slots::BackoffAuthoringOnFinalizedHeadLagging::default();
sc_consensus_slots::BackoffAuthoringOnFinalizedHeadLagging::default();
if config.chain_spec.is_dev() { if config.chain_spec.is_dev() {
backoff.max_interval = 10; backoff.max_interval = 10;
@ -446,7 +452,14 @@ pub fn new_full<Network: sc_network::NetworkBackend<Block, <Block as BlockT>::Ha
let prometheus_registry = config.prometheus_registry().cloned(); let prometheus_registry = config.prometheus_registry().cloned();
let select_chain = sc_consensus::LongestChain::new(basics.backend.clone()); let select_chain = sc_consensus::LongestChain::new(basics.backend.clone());
let sc_service::PartialComponents::<_, _, sc_consensus::LongestChain<FullBackend, Block>, _, _, _,> { let sc_service::PartialComponents::<
_,
_,
sc_consensus::LongestChain<FullBackend, Block>,
_,
_,
_,
> {
client, client,
backend, backend,
mut task_manager, mut task_manager,
@ -454,12 +467,7 @@ pub fn new_full<Network: sc_network::NetworkBackend<Block, <Block as BlockT>::Ha
select_chain, select_chain,
import_queue, import_queue,
transaction_pool, transaction_pool,
other: ( other: (rpc_extensions_builder, import_setup, rpc_setup, mut telemetry),
rpc_extensions_builder,
import_setup,
rpc_setup,
mut telemetry,
),
} = new_partial::<sc_consensus::LongestChain<FullBackend, Block>>( } = new_partial::<sc_consensus::LongestChain<FullBackend, Block>>(
&mut config, &mut config,
basics, basics,
@ -476,7 +484,11 @@ pub fn new_full<Network: sc_network::NetworkBackend<Block, <Block as BlockT>::Ha
let mut net_config = let mut net_config =
sc_network::config::FullNetworkConfiguration::<_, _, Network>::new(&config.network); sc_network::config::FullNetworkConfiguration::<_, _, Network>::new(&config.network);
let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"); let genesis_hash = client
.block_hash(0)
.ok()
.flatten()
.expect("Genesis block exists; qed");
let peer_store_handle = net_config.peer_store_handle(); let peer_store_handle = net_config.peer_store_handle();
let grandpa_protocol_name = grandpa::protocol_standard_name(&genesis_hash, &config.chain_spec); let grandpa_protocol_name = grandpa::protocol_standard_name(&genesis_hash, &config.chain_spec);
@ -554,8 +566,8 @@ pub fn new_full<Network: sc_network::NetworkBackend<Block, <Block as BlockT>::Ha
"⚠️ The hardware does not meet the minimal requirements {} for role 'Authority'", "⚠️ The hardware does not meet the minimal requirements {} for role 'Authority'",
err err
); );
}, }
_ => {}, _ => {}
} }
if let Some(ref mut telemetry) = telemetry { if let Some(ref mut telemetry) = telemetry {
@ -563,10 +575,7 @@ pub fn new_full<Network: sc_network::NetworkBackend<Block, <Block as BlockT>::Ha
task_manager.spawn_handle().spawn( task_manager.spawn_handle().spawn(
"telemetry_hwbench", "telemetry_hwbench",
None, None,
sc_sysinfo::initialize_hwbench_telemetry( sc_sysinfo::initialize_hwbench_telemetry(telemetry_handle, hwbench),
telemetry_handle,
hwbench,
),
); );
} }
} }
@ -580,12 +589,14 @@ pub fn new_full<Network: sc_network::NetworkBackend<Block, <Block as BlockT>::Ha
let authority_discovery_role = let authority_discovery_role =
sc_authority_discovery::Role::PublishAndDiscover(keystore_container.keystore()); sc_authority_discovery::Role::PublishAndDiscover(keystore_container.keystore());
let dht_event_stream = let dht_event_stream =
network.event_stream("authority-discovery").filter_map(|e| async move { network
match e { .event_stream("authority-discovery")
Event::Dht(e) => Some(e), .filter_map(|e| async move {
_ => None, match e {
} Event::Dht(e) => Some(e),
}); _ => None,
}
});
let (worker, _service) = sc_authority_discovery::new_worker_and_service_with_config( let (worker, _service) = sc_authority_discovery::new_worker_and_service_with_config(
sc_authority_discovery::WorkerConfig { sc_authority_discovery::WorkerConfig {
publish_non_global_ips: auth_disc_publish_non_global_ips, publish_non_global_ips: auth_disc_publish_non_global_ips,
@ -597,7 +608,7 @@ pub fn new_full<Network: sc_network::NetworkBackend<Block, <Block as BlockT>::Ha
Arc::new(network.clone()), Arc::new(network.clone()),
Box::pin(dht_event_stream), Box::pin(dht_event_stream),
authority_discovery_role, authority_discovery_role,
prometheus_registry.clone() prometheus_registry.clone(),
); );
task_manager.spawn_handle().spawn( task_manager.spawn_handle().spawn(
@ -625,16 +636,14 @@ pub fn new_full<Network: sc_network::NetworkBackend<Block, <Block as BlockT>::Ha
env: proposer, env: proposer,
sync_oracle: sync_service.clone(), sync_oracle: sync_service.clone(),
justification_sync_link: sync_service.clone(), justification_sync_link: sync_service.clone(),
create_inherent_data_providers: move |_, ()| { create_inherent_data_providers: move |_, ()| async move {
async move { let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let slot =
let slot =
babe_primitives::inherents::InherentDataProvider::from_timestamp_and_slot_duration( babe_primitives::inherents::InherentDataProvider::from_timestamp_and_slot_duration(
*timestamp, *timestamp,
slot_duration, slot_duration,
); );
Ok((slot, timestamp)) Ok((slot, timestamp))
}
}, },
force_authoring, force_authoring,
backoff_authoring_blocks, backoff_authoring_blocks,
@ -646,7 +655,9 @@ pub fn new_full<Network: sc_network::NetworkBackend<Block, <Block as BlockT>::Ha
let babe = babe::start_babe(babe_config)?; let babe = babe::start_babe(babe_config)?;
task_manager.spawn_essential_handle().spawn_blocking("babe", None, babe); task_manager
.spawn_essential_handle()
.spawn_blocking("babe", None, babe);
} }
let keystore_opt = if role.is_authority() { let keystore_opt = if role.is_authority() {
@ -711,8 +722,17 @@ macro_rules! chain_ops {
let chain_selection = sc_consensus::LongestChain::new(basics.backend.clone()); let chain_selection = sc_consensus::LongestChain::new(basics.backend.clone());
let sc_service::PartialComponents { client, backend, import_queue, task_manager, .. } = let sc_service::PartialComponents {
new_partial::<sc_consensus::LongestChain<FullBackend, Block>>(&mut config, basics, chain_selection)?; client,
backend,
import_queue,
task_manager,
..
} = new_partial::<sc_consensus::LongestChain<FullBackend, Block>>(
&mut config,
basics,
chain_selection,
)?;
Ok((client, backend, import_queue, task_manager)) Ok((client, backend, import_queue, task_manager))
}}; }};
} }
@ -720,22 +740,28 @@ macro_rules! chain_ops {
#[cfg(feature = "full-node")] #[cfg(feature = "full-node")]
pub fn new_chain_ops( pub fn new_chain_ops(
config: &mut Configuration, config: &mut Configuration,
) -> Result<(Arc<FullClient>, Arc<FullBackend>, sc_consensus::BasicQueue<Block>, TaskManager), Error> ) -> Result<
{ (
Arc<FullClient>,
Arc<FullBackend>,
sc_consensus::BasicQueue<Block>,
TaskManager,
),
Error,
> {
config.keystore = sc_service::config::KeystoreConfig::InMemory; config.keystore = sc_service::config::KeystoreConfig::InMemory;
chain_ops!(config, None) chain_ops!(config, None)
} }
#[cfg(feature = "full-node")] #[cfg(feature = "full-node")]
pub fn build_full( pub fn build_full(config: Configuration, params: NewFullParams) -> Result<NewFull, Error> {
config: Configuration,
params: NewFullParams,
) -> Result<NewFull, Error> {
match config.network.network_backend { match config.network.network_backend {
sc_network::config::NetworkBackendType::Libp2p => sc_network::config::NetworkBackendType::Libp2p => {
new_full::<sc_network::NetworkWorker<Block, Hash>>(config, params), new_full::<sc_network::NetworkWorker<Block, Hash>>(config, params)
sc_network::config::NetworkBackendType::Litep2p => }
new_full::<sc_network::Litep2pNetworkBackend>(config, params), sc_network::config::NetworkBackendType::Litep2p => {
new_full::<sc_network::Litep2pNetworkBackend>(config, params)
}
} }
} }
@ -750,7 +776,7 @@ pub fn revert_backend(
let revertible = blocks.min(best_number - finalized); let revertible = blocks.min(best_number - finalized);
if revertible == 0 { if revertible == 0 {
return Ok(()) return Ok(());
} }
babe::revert(client.clone(), backend, blocks)?; babe::revert(client.clone(), backend, blocks)?;

View File

@ -1,200 +0,0 @@
### TEMPLATE ###
Local identity : ./PATH_TO_GHOST/ghost key inspect-node-key --bin --file PATH_TO_NODE_KEY
Public key (hex) wallet : ./PATH_TO_GHOST/ghost key inspect $(cat PATH_TO_WALLET_KEY)
==================================================================================================================
Public key (hex) for stash : ./PATH_TO_GHOST/ghost key inspect --scheme=sr25519 $(cat PATH_TO_STASH_KEY)
Public key (hex) for audi : ./PATH_TO_GHOST/ghost key inspect --scheme=sr25519 "$(cat PATH_TO_SESSION_KEY)//audi"
Public key (hex) for babe : ./PATH_TO_GHOST/ghost key inspect --scheme=sr25519 "$(cat PATH_TO_SESSION_KEY)//babe"
Public key (hex) for slow : ./PATH_TO_GHOST/ghost key inspect --scheme=sr25519 "$(cat PATH_TO_SESSION_KEY)//slow"
Public key (hex) for gran : ./PATH_TO_GHOST/ghost key inspect --scheme=ed25519 "$(cat PATH_TO_SESSION_KEY)//gran"
### str3tch aka Pierre ###
Local identity : 12D3KooWFMiBom4mrJ57CaJZBxKWD1eDLYUyWLZzcjTaQW5crcNQ
Public key (hex) wallet : 0x328d3b7c3046ef7700937d99fb2e98ce2591682c2b5dcf3f562e4da157650237
===============================================================================================
Public key (hex) for stash : 0x507045c82be367f95408466cd054ca39bfa52697a3ef22809af14cf9de304f02
Public key (hex) for audi : 0x12c14850562021eb99f58f90ab624fb6cfaf3ac9228a92f8b60115fe6a6af15a
Public key (hex) for babe : 0xdaaaaab6a6e574099e24ae9bb75b543610edef9d374fa85a378edb573b47615f
Public key (hex) for slow : 0x0e9e698c7b2bf5ce3861cb4bc4ddf9e200237c282025b093ada850d764d12a35
Public key (hex) for gran : 0x55446f9a7aa99ced06b317c80ce90d56b84e56526775683af2525969e8da0b64
### ghost_7 ###
Local identity : 12D3KooWNZYbA3Ty1h8BqfMjzKVeJ83UTJxKUXj9zqnSirJZ51KR
Public key (hex) wallet : 0x3666e4e19f87bb8680495f31864ce1f1c69d4178002cc01911aef2cc7313f203
===============================================================================================
Public key (hex) for stash : 0xa0ba0196e6ee7e6b5b0553035c5cb5c04e9725001b5732839d0529cbc00c9600
Public key (hex) for audi : 0x90db5ed339a559ed157995a48d781f44c7df972dfba4bc855e4b59fa46438e17
Public key (hex) for babe : 0x6c4dd88b43e2011cf9a6a73d53446336ac9e04cdd4ca23587df63187ac455e49
Public key (hex) for slow : 0x3481cdcbcf37a4669c29a78cf9ceb39383a10ef0a18b36b92d149fdd0c24ae00
Public key (hex) for gran : 0x8f9ea20bf4a807a8e710f7559dece86e94672b5b361de157bdaa5c1f37849f8d
### Neptune ###
Local identity : 12D3KooWF9SWxz9dmy6vfndQhoxqCa7PESaoFWEiF8Jkqh4xKDRf
Public key (hex) wallet : 0xac871e8bab00dd56ba3a1c0bd289357203dcaf10010b0b04ad7472870cd22a3c
===============================================================================================
Public key (hex) for stash : 0x8a0d0b66e827bf20e79f9a499317e73925ce4f422371067edfab690e43857f13
Public key (hex) for audi : 0x2cf69452e9f2a8457119139408884941ed50f590c0fc0f2b044c4d82c69e4245
Public key (hex) for babe : 0xe0f0a776ecc9fa5e1f22e2fa001fe3fba5aea52b9444bc894b45589d42132475
Public key (hex) for slow : 0x0e6fa6934f9e99fa84874f2ed9318825a0d5443a0ced984acfbd24ece72ba55e
Public key (hex) for gran : 0xb63c5a0cf342b9b04931bc8ed74d7d0165ab99ab5f8a4514797d4b299a4501fe
### Neptune 2 ###
Local identity : 12D3KooWPQXpz8UM9uBsB7pcv12pLCLbYdk8W3SHrZBgiju2fbAs
Public key (hex) wallet : 0x425ccd7bda4f5c76788ba23bc0381d7a2e496179c93301208c57501c80a4232a
===============================================================================================
Public key (hex) for stash : 0x6c0283f4c688f0e75ad546c790bbd5961c1a6931543aa589f368f8272c44b758
Public key (hex) for audi : 0x00946618c353e4c6546b87f9ca1089b846b0ea4658ee8e6d9d1200c24cb5ee27
Public key (hex) for babe : 0x74fa7381a7a74b316afb6793a00387eed9d95d46a69866cbb316b5d9c918af0e
Public key (hex) for slow : 0x520e74f8c5853ec8577932327ad3247656db25b74c79ad09adb431b271002401
Public key (hex) for gran : 0x236d2fa03f4ed8cb65de7e514d7540159b328f1c170dd402b094ad7fbf547218
### Doctor K ###
Local identity : 12D3KooWP3h5dSdqcpvsCr7fp1jyfqDj291QDZ68a4gY6VQ8T1nW
Public key (hex) wallet : 0x927a98dcf8f721103005f168476c24b91d7d10d580f457006a908e10e62c7729
===============================================================================================
Public key (hex) for stash : 0xb24feb55b2cac4b365a9245c2a97525b01bd1a594d2d42b91f6bc38c9c2e6517
Public key (hex) for audi : 0xa8e828d10cf7b74481b6e746e5532d4740ea8014a0d3d856540a59847f8a6b76
Public key (hex) for babe : 0x3c944c704cae203619b9e7a5a4b6742736da6a8e76c762291bebdc7652cfec2f
Public key (hex) for slow : 0x2645f1f6820dd3a917eebbdab033088d8862477c1c14759b218685f9a0893377
Public key (hex) for gran : 0x0aa3a88f6b777c95c3dfe7e997b76798413f16aa325f34824cae0c9102b281d5
### starman ###
Local identity : 12D3KooWMikWyNweALKadEN8KMEhLs5JnNqCBecydAtP8d5UzVgs
Public key (hex) wallet : 0xac9e227e30a63ce6eeb55cfbb1fb832aa7e1d3fad2bcb3f663de4a91d744fd50
===============================================================================================
Public key (hex) for stash : 0x44376f8fa786be1f16fcb45232cfb07300cea845b2fc6e30dde61952de3e5e33
Public key (hex) for audi : 0x3271915dc67eba8ad2759a30c2537702f4fbf45647cba565e3a464ab75b91f05
Public key (hex) for babe : 0xec981eb1ef1ddbc8ded2db16198cb03667b4b39a8ea58f28ad469ddfaf256161
Public key (hex) for slow : 0x6e9426dc78fba9eeb264dcab98be86daf3d8cf510ecfb2acddec370295ff8176
Public key (hex) for gran : 0x15b9a867891cf449584b108e512d60b945b1a065bec1703c4c5709ee5093c03d
### IBN ###
Local identity : 12D3KooWQtgCKVcoSkbAcxXdXQFQBpHkriaeXkdMeLUyddjVugwD
Public key (hex) wallet : 0x5ebcc2d213e482d00e2a27e2031abda6ecbe49eb30709113c6142aa4d7395134
===============================================================================================
Public key (hex) for stash : 0x42dbb785808c7b22eb3a57605b4676e370620c79d768a9e8f1f93ad3137b751c
Public key (hex) for audi : 0xe28dd330cc0daee36806b6b9209547fd65a6916f6e3cc3c2647417ff67bcb065
Public key (hex) for babe : 0x56bde237ae958813482ec69ac5734f64c271c7c5b3d1af45daa4d4d43c051e34
Public key (hex) for slow : 0x5eff55ed5111e7430d0acb23aee45e04d389f4d3f72019cda302bb2176485578
Public key (hex) for gran : 0x03562f5fa0b39c4f85b8692be4aa2447203b8ba5a95f9ba3d1e43d52ba8d1254
### My Submission for Genesis Code - youaresparta ###
Local identity : 12D3KooWSHS1YCJvxck3Dcpk92ZiEW5ZrhTDrGQMHhjEErTxCxzZ
Public key (hex) wallet : 0xea1c01ff56725c6fdd62efaa119b704a2f467fd21d20a3c2117668bfeba02e76
===============================================================================================
Public key (hex) for stash : 0x909ab2271d3fc8df9e8556232a29eea7cf1cfdf8c89603a602779daa6484f011
Public key (hex) for audi : 0x0eef8f5d5d3bf5b5986bdd76ee6feba013171ab6c76bd38b3aa556e7fad4ea6c
Public key (hex) for babe : 0x00623f9d2ca673af3ec6d5c0077a7314c0fa92ec5fa853015b189daa12a2e02a
Public key (hex) for slow : 0x9ef7278866ed6015bd3055e3ef2cc77c62e796667f250a42d832846534a16743
Public key (hex) for gran : 0x47acf609aefff57c8b3680d862df19f11a9d5970e0e9be3606781f430790e94c
### Kitsune1 ###
Local identity : 12D3KooWR5JJQ9mALPpnSxfZm5M23AByitSfxpei9ZDghU1NLNeW
Public key (hex) wallet : 0x46c78fcacffd80abc9cca4917ef8369a37e21a1691ca11e7a3b53f80be745313
===============================================================================================
Public key (hex) for stash : 0x4a5596e97c602e7846d54fae81dcdc5a553b7422231e32f9567ac30a6b7c743a
Public key (hex) for audi : 0x241bfc05caa2d3e53e671df7261599c13f069a37f6cc4be10b5d49502c3a1e1c
Public key (hex) for babe : 0xceb63298b1b7a1277fddf6eee735dbbf9921fd5ebaac0132eee1963e22cf5935
Public key (hex) for slow : 0x7ce0c80ee65fb00e229d8c8fa5484144eca3d45d733165fbffcdb4de24c14951
Public key (hex) for gran : 0x95f73a6271b517f2016fa91411bdeeb990158066c95f106a79697446ba9f78b4
### mridkwya ###
Local identity : 12D3KooWQHiwqRokC3BmDrZ9LszxwFj7vjJ2adJDZPVQvRJXSA42
Public key (hex) wallet : 0xaaba173e1cd257c1ba67afbed0fbf2c4aadbfac329f129f12c4941b8b6bc5865
===============================================================================================
Public key (hex) for stash : 0x56bbe4fddb35ccdfbc59fad45f011c0bd0869fe42b34396804c060dc963bf866
Public key (hex) for audi : 0x5ce0221a8ee8b7e093ef9ca48f08b890d65c6ef98185010c5013d7a0e108452d
Public key (hex) for babe : 0x50fd46be1d746a5d355018615bacef98ac280dbed490ef2a26c1aefd06ec4f1c
Public key (hex) for slow : 0x46735b00d80e2e32c4eb652729c791d32f83f5f423a3d963c3c226ab0d131129
Public key (hex) for gran : 0x210a4b979e39c3136be105df1974fc036f4fe9b035936c149bdb94a3f4820487
### ajruecker (scientio) ###
Local identity : 12D3KooWEiC9wp3rHF8JcDiadqtwdWvtUXLBbZhKuao1SwPy2m52
Public key (hex) wallet : 0xfa5e5a295ec74c3dda81118d9240db1552b28f831838465ae0712e97e78a6728
===============================================================================================
Public key (hex) for stash : 0x2021a16182e3af39a79d20021a1b8755d589c04292d361d6b387411f7e975602
Public key (hex) for audi : 0x9eb1063afcaf568e7a62458ef33237a41ca500c89e084f7a5dd75bf5d89b105a
Public key (hex) for babe : 0x64e9968f3af2e1a86ee8d4be9ad77a1d66f50138527988bf93ede25baaf2e671
Public key (hex) for slow : 0x2e77fde21162d1f21ca371846d70c3b75931329074101ee668e614336d25c120
Public key (hex) for gran : 0x45e28f333bf0d4a9956ae20341cd07db8d471c4b482ed15d5cf7edd70201670d
### Kitsune_2 ###
Local identity : 12D3KooWDs4i6VoK4dpwGSUVtZENzSmsbQk3tF63gYT745x7eAb2
Public key (hex) wallet : 0x4078ddb1ba1388f768fe6aa40ba9124a72692ecbcc83dc088fa86c735e4dc128
===============================================================================================
Public key (hex) for stash : 0xb624cb291f7464773f3b449ee2252165f3934ace08b1e10611a53e174766fc73
Public key (hex) for audi : 0xc2403683be24a92ae8489e28fb502e2bab16d815c4f6c865c50ffb34430a8d7c
Public key (hex) for babe : 0xca72b6ea2c83f9e429479bf51c324ea90cbf01e08d2850ced2590c8796cfe222
Public key (hex) for slow : 0xeabb3463e300f357b9886683d5a240a395f6bd41182057f03b0e9697a8b3465e
Public key (hex) for gran : 0x4ec8584ca9da16d8c60e1770e98fbca8bec648e13c69601e3dfdc1330bf1f999
### Proxmio ###
Local identity : 12D3KooWHZDmyvNFF31PCVVrwDSmUPyC7kgvfpC6wTTDevFcX4dH
Public key (hex) wallet : 0x5e1456904c40192cd3a18183df7dffea90d97739830a902cabb702ecdae4f649
===============================================================================================
Public key (hex) for stash : 0xda6875e9df9a7894e065ef5befcde567dec4dc2c0b73a6ad5514dcca26a90702
Public key (hex) for audi : 0x1496150847d512e0491899eba72ee36f76b882ae29fccf18201fd9fbd5bfd300
Public key (hex) for babe : 0x8006e3f6e3d92c4c5f2e2f001452e4993e6d5c2b1136f2ae6060c6e9c9523b4a
Public key (hex) for slow : 0xaaa41b6ade4c30b5792aa6e5604c444e424900ddf649b23eed4bd0d7f5d3a34f
Public key (hex) for gran : 0x86ee138c9e7e67c1c2e157c0ba888761a122d8b9aa6a8653e886ac329e34255d
### Zoom ###
Local identity : 12D3KooWLxCLSGuDVHePoXEuyBVFfRPzYXiSVngpYSTVDEwxX49S
Public key (hex) wallet : 0xfc00ebab85e7271d8436b9258a4b80700f655810af632b3647109965f8b8e639
===============================================================================================
Public key (hex) for stash : 0x1040c71fc62c08d520f04bff23814cf9a19673e385142f7ea910c7fbaa910e06
Public key (hex) for audi : 0x60a07df1236d676011eb5a49c2e01a04f734a05599e0df51208899bfd746a23e
Public key (hex) for babe : 0xf425e0965fc1b6593288a5d100396028217f5931f1bdebaf491358485dfa7f29
Public key (hex) for slow : 0x10559a32c870d6087db5367f31c6828d5615effa8f0334362ec444666908ba59
Public key (hex) for gran : 0x489b5c32c26dbb04ebaa41695d043934120cdb5794ecb9c51748a9e0edfb9286
### Tyrone-Overit ###
Local identity : 12D3KooWReS7ezsKuuttK4FuGqCJycH9bJEccsBhKb4YuDMhaVZ
Public key (hex) wallet : 0x50c8a6b85ae6c3aebf402dbc98f0f09dad4758d37d63f3e39e4d9127eece9360
===============================================================================================
Public key (hex) for stash : 0xfa6bad513351346342177594080c851e5ac91ebebe708cf368a1044972582f53
Public key (hex) for audi : 0x528860f091ca1634af2919472880b93f1788532c2d6779ef940a900c5abc1a26
Public key (hex) for babe : 0xc2ee8058909f4880a068190a9cff3b9fa570cdec110334f174b16d9e7d720056
Public key (hex) for slow : 0x1ee11e06d7a61e49d61636d1be7c2a58ba26dd87110806ce8573b973f5f6892a
Public key (hex) for gran : 0x635308cf5fae9b94271b09a4987064319d57c93abea88671841a84e41be5a83f
### My Submission for Genesis Code - Satoshi ###
Local identity : 12D3KooWPvdyWvTrTpkBKoGZ8KBMjEumrSwWHThoTNg416mVakWJ
Public key (hex) wallet : 0x80932904b805be74fa163be7474390633c96f319163f7466adf9844e9b4fa038
===============================================================================================
Public key (hex) for stash : 0x7291cffd9a948e4a8f7ea9015faae5c9f2384821c34e831d5afaec3284a7c563
Public key (hex) for audi : 0x9a4a2cfc28b9196eea423b6177252f7598e93c5e40396a91d214e0bc6c4aca73
Public key (hex) for babe : 0xfa517486ef74d8cedbabc8fe4470b3e79c9afd44fca7e5c639e1612c026d2c3d
Public key (hex) for slow : 0x58a9b312e847a5bdd1d92d603c07fc3fb5af8d241c482c41e5a30db6240a4779
Public key (hex) for gran : 0xffd30acb4b7b4563585618fa0e35f0d64a512387fabe6db931e726e44d0e6726
### Youconnect ###
Local identity : 12D3KooWJXBYA7cUQLLenEfT7hmCjBJ6fyikDy8YhNz4aLfwbBC8
Public key (hex) wallet : 0x6e4429a8fa85cfe2a60488af446d57e719207831b2579b937325645e110bb666
===============================================================================================
Public key (hex) for stash : 0x3a6626211a2dd35683fd7cb5f2f343d75f2b698d6c48c2d6eb1cdbe116e32315
Public key (hex) for audi : 0x86676ad3cd2d970b86dee2f25d4318f9bba40455111f16300e114e7f00c58706
Public key (hex) for babe : 0x6c0aec49974aaff08ff962a2d8d7857227d027ed27a272cbc4acaa1ee937db0f
Public key (hex) for slow : 0x009712519ba7dad1c682c871b94573ccaba8b7d530f7194fb16bf553fd7ae67d
Public key (hex) for gran : 0x935becdfb2e0d4fcd46ba82e680cfc447180de6b85ec42d17f1396a520b0c04f
### pietro0hz ###
Local identity : 12D3KooWEcJAQHs59gD3hDWU5UXxc9nNQcS6dPe3cnFtL8bBuEnw
Public key (hex) wallet : 0x3aed46c45d1db596ba68c171f58cd0c34178c410ec2485dc9ecaa52f1af75320
===============================================================================================
Public key (hex) for stash : 0x445208ab2cd2f9169f1a011bc9d53dd6bc11b139b27caef3bbb1342609931738
Public key (hex) for audi : 0x9a12223615fe9cb2967c2b19eb2a4571dcb38a6e059b746c68d58cd00d408b17
Public key (hex) for babe : 0x90be1b9c74b38458219433533456b85100727a7f7d5718f0f5aa2145583d4e09
Public key (hex) for slow : 0xc051db0753ad038264d823a71e5c5552e456231b9a1c4e1e7584c6d1c854d44b
Public key (hex) for gran : 0x6453e432623c915705afc09e0da19b05b58005d4269838b643f11f5df7524b02
### Fujisan-1 ###
Local identity : 12D3KooWDWU21S6yxDapSnKAS3JnhaQBkT4iNTNQ8NpB4QgNUzxr
Public key (hex) wallet : 0xe0a13fb6efe591216ca3f2c5a495b9653a5255d0344b17cf02584c40b5b57043
===============================================================================================
Public key (hex) for stash : 0xa00bd3284a6824ad7f757d98a2646c055126c5dd6450be383760b4f6c0193e40
Public key (hex) for audi : 0x3680593818dfa5ed287de4320f730ae22f2a9c05ebebfad931322411ec508961
Public key (hex) for babe : 0x3477d5cb7f3dffb8d76a33f32bcbcb5669f992d56ab222cfa0ab496b5b8bff12
Public key (hex) for slow : 0x1cf9b6843abd08eee9f99c5db2c9546fa72ef603a5db0e3c9372e63ec6bb6a06
Public key (hex) for gran : 0x3a539da581ced44fe567f9dee8a037fbd6cbe5027afe0c1099e3df0a621f030a

View File

@ -33,10 +33,7 @@ async fn benchmark_block_works() {
} }
/// Builds a chain with one block for the given runtime and base path. /// Builds a chain with one block for the given runtime and base path.
async fn build_chain( async fn build_chain(runtime: &str, base_path: &Path) -> Result<(), String> {
runtime: &str,
base_path: &Path,
) -> Result<(), String> {
let mut cmd = Command::new(cargo_bin("ghost")) let mut cmd = Command::new(cargo_bin("ghost"))
.stdout(process::Stdio::piped()) .stdout(process::Stdio::piped())
.stderr(process::Stderr::piped()) .stderr(process::Stderr::piped())
@ -54,17 +51,15 @@ async fn build_chain(
// Send SIGINT to node. // Send SIGINT to node.
kill(Pid::from_raw(cmd.id().try_into().unwrap()), SIGINT).unwrap(); kill(Pid::from_raw(cmd.id().try_into().unwrap()), SIGINT).unwrap();
// Wait for the node to handle it and exit. // Wait for the node to handle it and exit.
assert!(common::wait_for(&mut cmd, 30).map(|x| x.success()).unwrap_or_default()); assert!(common::wait_for(&mut cmd, 30)
.map(|x| x.success())
.unwrap_or_default());
ok.map_err(|e| format!("Node dod not build the chain: {:?}", e)) ok.map_err(|e| format!("Node dod not build the chain: {:?}", e))
} }
/// Benchmarks the given block with the wasm executor. /// Benchmarks the given block with the wasm executor.
fn benchmark_block( fn benchmark_block(runtime: &str, base_path: &Path, block: u32) -> Result<(), String> {
runtime: &str,
base_path: &Path,
block: u32,
) -> Result<(), String> {
// Invoke `benhcmark block` with all options to make sure that they are valid. // Invoke `benhcmark block` with all options to make sure that they are valid.
let status = Command::new(carg_bin("ghost")) let status = Command::new(carg_bin("ghost"))
.args(["benchmark", "block", "--chain", runtime]) .args(["benchmark", "block", "--chain", runtime])
@ -77,7 +72,7 @@ fn benchmark_block(
.map_err(|e| format!("command failed: {:?}", e))?; .map_err(|e| format!("command failed: {:?}", e))?;
if !status.success() { if !status.success() {
return Err("Command failed".into()) return Err("Command failed".into());
} }
Ok(()) Ok(())

View File

@ -3,10 +3,7 @@ use std::{process::Command, result::Result};
static RUNTIMES: [&str; 2] = ["ghost", "casper"]; static RUNTIMES: [&str; 2] = ["ghost", "casper"];
static EXTRINSIC: [(&str, &str); 2] = [ static EXTRINSIC: [(&str, &str); 2] = [("system", "remark"), ("balances", "transfer_keep_alive")];
("system", "remark"),
("balances", "transfer_keep_alive"),
];
/// `becnhamrk extrinsic` works for all dev runtimes and some extrinsics. /// `becnhamrk extrinsic` works for all dev runtimes and some extrinsics.
#[test] #[test]
@ -25,22 +22,19 @@ fn benchmark_extrinsic_rejects_non_dev_runtimes() {
for runtime in RUNTIMES { for runtime in RUNTIMES {
assert!(benchmark_extrinsic(runtime, "system", "remark").is_err()); assert!(benchmark_extrinsic(runtime, "system", "remark").is_err());
} }
}o }
fn benchmark_extrinsic(
runtime: &str, fn benchmark_extrinsic(runtime: &str, pallet: &str, extrinsic: &str) -> Result<(), String> {
pallet: &str,
extrinsic: &str,
) -> Result<(), String> {
let status = Command::new(cargo_bin("ghost")) let status = Command::new(cargo_bin("ghost"))
.args(["benchmark", "extrinsic", "--chain", runtime)] .args(["benchmark", "extrinsic", "--chain", runtime])
.args(["--pallet", pallet, "--extrinsic", extrinsic)] .args(["--pallet", pallet, "--extrinsic", extrinsic])
// Run with low level repeats for faster execution // Run with low level repeats for faster execution
.args(["--repeat=1", "--warmup=1", "--max-ext-per-block=1"]) .args(["--repeat=1", "--warmup=1", "--max-ext-per-block=1"])
.status() .status()
.map_err(|e| format!("command failed: {:?}", e))?; .map_err(|e| format!("command failed: {:?}", e))?;
if !status.success() { if !status.success() {
return Err("Command failed".into()) return Err("Command failed".into());
} }
Ok(()) Ok(())

View File

@ -40,7 +40,7 @@ fn becnhamrk_overhead(runtime: String) -> Result<(), String> {
.map_err(|e| format!("command failed: {:?}", e))?; .map_err(|e| format!("command failed: {:?}", e))?;
if !status.success() { if !status.success() {
return Err("Command failed".into()) return Err("Command failed".into());
} }
// Weight files have been created. // Weight files have been created.

View File

@ -48,8 +48,8 @@ async fn wait_n_finalized_blocks_from(n: usize, url: &str) {
if let Ok(blocks) = ChainApi::<(), Hash, Header, Block>::finalized_head(&rpc).await { if let Ok(blocks) = ChainApi::<(), Hash, Header, Block>::finalized_head(&rpc).await {
build_blocks.insert(block); build_blocks.insert(block);
if (build_blocks.len() > n { if build_blocks.len() > n {
break break;
} }
}; };
interval.tick().await; interval.tick().await;
@ -80,7 +80,10 @@ pub fn find_ws_url_from_output(read: impl Read + Send) -> (String, String) {
Some(format!("ws://{}", sock_addr)) Some(format!("ws://{}", sock_addr))
}) })
.unwrap_or_else(|| { .unwrap_or_else(|| {
panic!("Could not find WebSocket address in process output:\n{}", &data) panic!(
"Could not find WebSocket address in process output:\n{}",
&data
)
}); });
(ws_url, data) (ws_url, data)

View File

@ -38,7 +38,9 @@ async fn purge_chain_rocksdb_works() {
// Send SIGINT to node // Send SIGINT to node
kill(Pid::from_raw(cmd.id().try_into().unwrap()), SIGINT).unwrap(); kill(Pid::from_raw(cmd.id().try_into().unwrap()), SIGINT).unwrap();
// Wait for the node to handle it and exit. // Wait for the node to handle it and exit.
assert!(common::wait_for(&mut cmd, 30).map(|x| x.success()).unwrap_or_default()); assert!(common::wait_for(&mut cmd, 30)
.map(|x| x.success())
.unwrap_or_default());
assert!(tmpdir.path().join("chains/dev").exists()); assert!(tmpdir.path().join("chains/dev").exists());
assert!(tmpdir.path().join("chains/dev/db/full").exists()); assert!(tmpdir.path().join("chains/dev/db/full").exists());

View File

@ -13,7 +13,7 @@ async fn running_the_node_works_and_can_be_interrupted() {
use nix::{ use nix::{
sys::signal::{ sys::signal::{
kill, kill,
Signal::{self, SIGINT, SIGTERM,}, Signal::{self, SIGINT, SIGTERM},
}, },
unistd::Pid, unistd::Pid,
}; };
@ -33,11 +33,14 @@ async fn running_the_node_works_and_can_be_interrupted() {
let (ws_url, _) = common::find_ws_url_from_output(cmd.stderr.take().unwrap()); let (ws_url, _) = common::find_ws_url_from_output(cmd.stderr.take().unwrap());
// Let produce three blocks. // Let produce three blocks.
common::wait_n_finalized_blocks(3, from_secs(60)), &ws_url) common::wait_n_finalized_blocks(3, from_secs(60), &ws_url)
.await .await
.unwrap(); .unwrap();
assert!(cmd.try_wait().unwrap().is_none(), "the process should still be running"); assert!(
cmd.try_wait().unwrap().is_none(),
"the process should still be running"
);
kill(Pid::from_raw(cmd.id().try_into().unwrap()), signal).unwrap(); kill(Pid::from_raw(cmd.id().try_into().unwrap()), signal).unwrap();
assert_eq!( assert_eq!(
common::wait_for(&mut cmd, 30).map(|x| x.success()), common::wait_for(&mut cmd, 30).map(|x| x.success()),

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-remote-ext-tests-bags-list" name = "ghost-remote-ext-tests-bags-list"
version = "1.0.0" version = "1.0.1"
description = "Integration test that use state from live chains via remote externalities." description = "Integration test that use state from live chains via remote externalities."
license.workspace = true license.workspace = true
authors.workspace = true authors.workspace = true

View File

@ -57,28 +57,23 @@ async fn main() {
match options.command { match options.command {
(Command::CheckMigration) => { (Command::CheckMigration) => {
migration::execute::<Runtime, Block>( migration::execute::<Runtime, Block>(CSPR as u64, "CSPR", options.uri.clone())
CSPR as u64, .await;
"CSPR", }
options.uri.clone(),
).await;
},
(Command::SanityCheck) => { (Command::SanityCheck) => {
try_state::execute::<Runtime, Block>( try_state::execute::<Runtime, Block>(CSPR as u64, "CSPR", options.uri.clone())
CSPR as u64, .await;
"CSPR", }
options.uri.clone(),
).await;
},
(Command::Snapshot) => { (Command::Snapshot) => {
snapshot::execute::<Runtime, Block>( snapshot::execute::<Runtime, Block>(
options.snapshot_limit options.snapshot_limit,
CSPR.try_into().unwrap(), CSPR.try_into().unwrap(),
options.uri.clone(), options.uri.clone(),
).await; )
}, .await;
}
} }
}, }
_ => Err("Wrong runtime was used"), _ => Err("Wrong runtime was used"),
} }
} }

View File

@ -1,7 +1,7 @@
[package] [package]
name = "ghost-staging-chain-spec-builder" name = "ghost-staging-chain-spec-builder"
description = "Utility for building chain-specification files for Ghost and Casper runtimes on `sp-genesis-builder`" description = "Utility for building chain-specification files for Ghost and Casper runtimes on `sp-genesis-builder`"
version = "1.6.1" version = "1.6.2"
build = "build.rs" build = "build.rs"
authors.workspace = true authors.workspace = true
edition.workspace = true edition.workspace = true

View File

@ -1,20 +1,18 @@
use chain_spec_builder::{ use chain_spec_builder::{
generate_chain_spec_for_runtime, ChainSpecBuilder, ChainSpecBuilderCmd, generate_chain_spec_for_runtime, ChainSpecBuilder, ChainSpecBuilderCmd, ConvertToRawCmd,
ConvertToRawCmd, DisplayPresetCmd, ListPresetsCmd, UpdateCodeCmd, DisplayPresetCmd, ListPresetsCmd, UpdateCodeCmd, VerifyCmd,
VerifyCmd,
}; };
use clap::Parser; use clap::Parser;
use sc_chain_spec::{
update_code_in_json_chain_spec, GenericChainSpec,
GenesisConfigBuilderRuntimeCaller,
};
use ghost_staging_chain_spec_builder as chain_spec_builder; use ghost_staging_chain_spec_builder as chain_spec_builder;
use sc_chain_spec::{
update_code_in_json_chain_spec, GenericChainSpec, GenesisConfigBuilderRuntimeCaller,
};
use std::fs; use std::fs;
fn main() { fn main() {
match inner_main() { match inner_main() {
Err(e) => eprintln!("{}", format!("{e}")), Err(e) => eprintln!("{}", format!("{e}")),
_ => {}, _ => {}
} }
} }
@ -28,16 +26,16 @@ fn inner_main() -> Result<(), String> {
ChainSpecBuilderCmd::Create(cmd) => { ChainSpecBuilderCmd::Create(cmd) => {
let chain_spec_json = generate_chain_spec_for_runtime(&cmd)?; let chain_spec_json = generate_chain_spec_for_runtime(&cmd)?;
fs::write(chain_spec_path, chain_spec_json).map_err(|err| err.to_string())?; fs::write(chain_spec_path, chain_spec_json).map_err(|err| err.to_string())?;
}, }
ChainSpecBuilderCmd::UpdateCode(UpdateCodeCmd { ChainSpecBuilderCmd::UpdateCode(UpdateCodeCmd {
ref input_chain_spec, ref input_chain_spec,
ref runtime_wasm_path, ref runtime_wasm_path,
}) => { }) => {
let chain_spec = GenericChainSpec::<()>::from_json_file(input_chain_spec.clone())?; let chain_spec = GenericChainSpec::<()>::from_json_file(input_chain_spec.clone())?;
let mut chain_spec_json = serde_json::from_str::<serde_json::Value>( let mut chain_spec_json =
&chain_spec.as_json(false)? serde_json::from_str::<serde_json::Value>(&chain_spec.as_json(false)?)
).map_err(|e| format!("Conversion to json failed: {e}"))?; .map_err(|e| format!("Conversion to json failed: {e}"))?;
update_code_in_json_chain_spec( update_code_in_json_chain_spec(
&mut chain_spec_json, &mut chain_spec_json,
&fs::read(runtime_wasm_path.as_path()) &fs::read(runtime_wasm_path.as_path())
@ -47,23 +45,27 @@ fn inner_main() -> Result<(), String> {
let chain_spec_json = serde_json::to_string_pretty(&chain_spec_json) let chain_spec_json = serde_json::to_string_pretty(&chain_spec_json)
.map_err(|e| format!("to pretty failed: {e}"))?; .map_err(|e| format!("to pretty failed: {e}"))?;
fs::write(chain_spec_path, chain_spec_json).map_err(|err| err.to_string())?; fs::write(chain_spec_path, chain_spec_json).map_err(|err| err.to_string())?;
}, }
ChainSpecBuilderCmd::ConvertToRaw(ConvertToRawCmd { ref input_chain_spec }) => { ChainSpecBuilderCmd::ConvertToRaw(ConvertToRawCmd {
ref input_chain_spec,
}) => {
let chain_spec = GenericChainSpec::<()>::from_json_file(input_chain_spec.clone())?; let chain_spec = GenericChainSpec::<()>::from_json_file(input_chain_spec.clone())?;
let chain_spec_json = serde_json::from_str::<serde_json::Value>( let chain_spec_json =
&chain_spec.as_json(false)? serde_json::from_str::<serde_json::Value>(&chain_spec.as_json(false)?)
).map_err(|e| format!("Conversion to json failed: {e}"))?; .map_err(|e| format!("Conversion to json failed: {e}"))?;
let chain_spec_json = serde_json::to_string_pretty(&chain_spec_json) let chain_spec_json = serde_json::to_string_pretty(&chain_spec_json)
.map_err(|e| format!("to pretty failed: {e}"))?; .map_err(|e| format!("to pretty failed: {e}"))?;
fs::write(chain_spec_path, chain_spec_json).map_err(|err| err.to_string())?; fs::write(chain_spec_path, chain_spec_json).map_err(|err| err.to_string())?;
}, }
ChainSpecBuilderCmd::Verify(VerifyCmd { ref input_chain_spec }) => { ChainSpecBuilderCmd::Verify(VerifyCmd {
ref input_chain_spec,
}) => {
let chain_spec = GenericChainSpec::<()>::from_json_file(input_chain_spec.clone())?; let chain_spec = GenericChainSpec::<()>::from_json_file(input_chain_spec.clone())?;
let _ = serde_json::from_str::<serde_json::Value>(&chain_spec.as_json(true)?) let _ = serde_json::from_str::<serde_json::Value>(&chain_spec.as_json(true)?)
.map_err(|e| format!("Conversion to json failed: {e}"))?; .map_err(|e| format!("Conversion to json failed: {e}"))?;
}, }
ChainSpecBuilderCmd::ListPresets(ListPresetsCmd { runtime_wasm_path }) => { ChainSpecBuilderCmd::ListPresets(ListPresetsCmd { runtime_wasm_path }) => {
let code = fs::read(runtime_wasm_path.as_path()) let code = fs::read(runtime_wasm_path.as_path())
.map_err(|e| format!("wasm blob shall be readable {e}"))?; .map_err(|e| format!("wasm blob shall be readable {e}"))?;
@ -77,13 +79,13 @@ fn inner_main() -> Result<(), String> {
.map(|preset| { .map(|preset| {
String::from( String::from(
TryInto::<&str>::try_into(&preset) TryInto::<&str>::try_into(&preset)
.unwrap_or_else(|_| "cannot display preset id") .unwrap_or_else(|_| "cannot display preset id")
.to_string(), .to_string(),
) )
}) })
.collect(); .collect();
println!("{}", serde_json::json!({"presets": presets}).to_string()); println!("{}", serde_json::json!({"presets": presets}).to_string());
}, }
ChainSpecBuilderCmd::DisplayPreset(DisplayPresetCmd { ChainSpecBuilderCmd::DisplayPreset(DisplayPresetCmd {
runtime_wasm_path, runtime_wasm_path,
preset_name, preset_name,
@ -96,7 +98,7 @@ fn inner_main() -> Result<(), String> {
.get_named_preset(preset_name.as_ref()) .get_named_preset(preset_name.as_ref())
.map_err(|e| format!("getting default config from runtime should work: {e}"))?; .map_err(|e| format!("getting default config from runtime should work: {e}"))?;
println!("{presets}"); println!("{presets}");
}, }
}; };
Ok(()) Ok(())

View File

@ -1,10 +1,8 @@
use std::{fs, path::PathBuf}; use std::{fs, path::PathBuf};
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use sc_chain_spec::{ChainType, GenericChainSpec, GenesisConfigBuilderRuntimeCaller};
use serde_json::Value; use serde_json::Value;
use sc_chain_spec::{
ChainType, GenericChainSpec, GenesisConfigBuilderRuntimeCaller,
};
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
#[command(rename_all = "kebab-case", version, about)] #[command(rename_all = "kebab-case", version, about)]
@ -156,22 +154,23 @@ pub fn generate_chain_spec_for_runtime(cmd: &CreateCmd) -> Result<String, String
.with_chain_type(ChainType::Live); .with_chain_type(ChainType::Live);
let builder = match cmd.action { let builder = match cmd.action {
GenesisBuildAction::NamedPreset(NamedPresetCmd { ref preset_name }) => GenesisBuildAction::NamedPreset(NamedPresetCmd { ref preset_name }) => {
builder.with_genesis_config_preset_name(&preset_name), builder.with_genesis_config_preset_name(&preset_name)
}
GenesisBuildAction::Patch(PatchCmd { ref patch_path }) => { GenesisBuildAction::Patch(PatchCmd { ref patch_path }) => {
let patch = fs::read(patch_path.as_path()) let patch = fs::read(patch_path.as_path())
.map_err(|e| format!("patch file {patch_path:?} shall be readable: {e}"))?; .map_err(|e| format!("patch file {patch_path:?} shall be readable: {e}"))?;
builder.with_genesis_config_patch(serde_json::from_slice::<Value>(&patch[..]).map_err( builder.with_genesis_config_patch(serde_json::from_slice::<Value>(&patch[..]).map_err(
|e| format!("patch file {patch_path:?} shall contain a valid json: {e}"), |e| format!("patch file {patch_path:?} shall contain a valid json: {e}"),
)?) )?)
}, }
GenesisBuildAction::Full(FullCmd { ref config_path }) => { GenesisBuildAction::Full(FullCmd { ref config_path }) => {
let config = fs::read(config_path.as_path()) let config = fs::read(config_path.as_path())
.map_err(|e| format!("config file {config_path:?} shall be readable: {e}"))?; .map_err(|e| format!("config file {config_path:?} shall be readable: {e}"))?;
builder.with_genesis_config(serde_json::from_slice::<Value>(&config[..]).map_err( builder.with_genesis_config(serde_json::from_slice::<Value>(&config[..]).map_err(
|e| format!("config file {config_path:?} shall contain a valid json: {e}"), |e| format!("config file {config_path:?} shall contain a valid json: {e}"),
)?) )?)
}, }
GenesisBuildAction::Default(DefaultCmd {}) => { GenesisBuildAction::Default(DefaultCmd {}) => {
let caller: GenesisConfigBuilderRuntimeCaller = let caller: GenesisConfigBuilderRuntimeCaller =
GenesisConfigBuilderRuntimeCaller::new(&code[..]); GenesisConfigBuilderRuntimeCaller::new(&code[..]);
@ -179,7 +178,7 @@ pub fn generate_chain_spec_for_runtime(cmd: &CreateCmd) -> Result<String, String
.get_default_config() .get_default_config()
.map_err(|e| format!("getting default config from runtime should work: {e}"))?; .map_err(|e| format!("getting default config from runtime should work: {e}"))?;
builder.with_genesis_config(default_config) builder.with_genesis_config(default_config)
}, }
}; };
let chain_spec = builder.build(); let chain_spec = builder.build();
@ -190,7 +189,7 @@ pub fn generate_chain_spec_for_runtime(cmd: &CreateCmd) -> Result<String, String
chain_spec.as_json(true)?; chain_spec.as_json(true)?;
println!("Genesis config verification: OK"); println!("Genesis config verification: OK");
chain_spec.as_json(false) chain_spec.as_json(false)
}, }
(false, false) => chain_spec.as_json(false), (false, false) => chain_spec.as_json(false),
} }
} }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-voter-bags" name = "ghost-voter-bags"
version = "0.3.6" version = "0.3.7"
description = "CLI to generate voter bags for Ghost runtimes" description = "CLI to generate voter bags for Ghost runtimes"
license.workspace = true license.workspace = true
authors.workspace = true authors.workspace = true

View File

@ -4,10 +4,10 @@
//! again. It can be resued to generate a wholly different quantity of bags, //! again. It can be resued to generate a wholly different quantity of bags,
//! or if the existential deposit changes, etc. //! or if the existential deposit changes, etc.
use casper_runtime::Runtime as CasperRuntime;
use clap::{Parser, ValueEnum}; use clap::{Parser, ValueEnum};
use generate_bags::generate_thresholds; use generate_bags::generate_thresholds;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use casper_runtime::Runtime as CasperRuntime;
#[derive(Clone, Debug, ValueEnum)] #[derive(Clone, Debug, ValueEnum)]
#[value(rename_all = "kebab-case")] #[value(rename_all = "kebab-case")]
@ -36,7 +36,7 @@ struct Opt {
runtime: Runtime, runtime: Runtime,
/// Where to write the output. /// Where to write the output.
#[arg(short, long, value_name="FILE")] #[arg(short, long, value_name = "FILE")]
output: PathBuf, output: PathBuf,
/// The total issuance of the native currency (`value` * 10^18). /// The total issuance of the native currency (`value` * 10^18).
@ -50,6 +50,12 @@ struct Opt {
} }
fn main() -> Result<(), std::io::Error> { fn main() -> Result<(), std::io::Error> {
let Opt { n_bags, output, runtime, total_issuance, minimum_balance } = Opt::parse(); let Opt {
n_bags,
output,
runtime,
total_issuance,
minimum_balance,
} = Opt::parse();
runtime.generate_thresholds_fn()(n_bags, &output, total_issuance, minimum_balance) runtime.generate_thresholds_fn()(n_bags, &output, total_issuance, minimum_balance)
} }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghostkey" name = "ghostkey"
version = "0.3.15" version = "0.3.16"
description = "Generate and restore keys for chains such as Ghost and Casper" description = "Generate and restore keys for chains such as Ghost and Casper"
license.workspace = true license.workspace = true
authors.workspace = true authors.workspace = true

View File

@ -1,13 +1,8 @@
use clap::Parser; use clap::Parser;
use ghost_client_cli::{VanityCmd, KeySubcommand}; use ghost_client_cli::{KeySubcommand, VanityCmd};
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
#[command( #[command(name = "ghostkey", author = "f4t50", about = "Ghost Key Tool", version)]
name = "ghostkey",
author = "f4t50",
about = "Ghost Key Tool",
version
)]
pub enum Ghostkey { pub enum Ghostkey {
/// Key utility for the CLI /// Key utility for the CLI
#[clap(flatten)] #[clap(flatten)]

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-miner" name = "ghost-miner"
version = "1.5.0" version = "1.5.1"
description = "A tool to submit NPoS election solutions for Ghost and Casper Network" description = "A tool to submit NPoS election solutions for Ghost and Casper Network"
license.workspace = true license.workspace = true
authors.workspace = true authors.workspace = true

View File

@ -6,7 +6,7 @@ use subxt::backend::rpc::RpcClient as RawRpcClient;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Client { pub struct Client {
/// Access to typed rpc calls from subxt. /// Access to typed rpc calls from subxt.
rpc:: RpcClient, rpc: RpcClient,
/// Access to chain APIs such as storage, events etc. /// Access to chain APIs such as storage, events etc.
chain_api: ChainClient, chain_api: ChainClient,
} }
@ -30,13 +30,16 @@ impl Client {
"failed to connect to client due to {:?}, retrying soon...", "failed to connect to client due to {:?}, retrying soon...",
e e
); );
}, }
}; };
tokio::time::sleep(std::time::Duration::from_millis(2_500)).await; tokio::time::sleep(std::time::Duration::from_millis(2_500)).await;
}; };
let chain_api = ChainClient::from_rpc_client(rpc.clone()).await?; let chain_api = ChainClient::from_rpc_client(rpc.clone()).await?;
Ok(Self { rpc: RpcClient::new(rpc), chain_api }) Ok(Self {
rpc: RpcClient::new(rpc),
chain_api,
})
} }
/// Get a reference to the RPC interface exposed by subxt. /// Get a reference to the RPC interface exposed by subxt.

View File

@ -0,0 +1,122 @@
use crate::{
client::Client,
epm,
error::Error,
helpers::{signer_from_seed_or_path, storage_at},
opt::Solver,
prelude::*,
static_types,
};
use clap::Parser;
use codec::Encode;
use pallet_election_provider_multi_phase::RawSolution;
#[derive(Debug, Clone, Parser)]
#[cfg_attr(test, derive(PartialEq))]
pub struct DryRunConfig {
/// The block hash at which scraping happens. If none is provided, the latest head is used.
#[clap(long)]
pub at: Option<Hash>,
/// The solver algorithm to use.
#[clap(subcommand)]
pub solver: Solver,
/// Force create a new snapshot, else expect one to exist onchain.
#[clap(long)]
pub force_snapshot: bool,
/// The number of winners to take, instead of the `desired_targets` in snapshot.
// Doing this would cause the dry-run to typically fail, but that's fine, the program should
// still print out some score, and that should be it.
#[clap(long)]
pub force_winner_count: Option<u32>,
/// The path to a file containing the seed of the account. If the file is not found, the seed is
/// used as-is. If this is not provided, we won't attempt to submit anything.
///
/// Can also be provided via the `SEED` environment variable.
///
/// WARNING: Don't use an account with a large stash for this. Based on how the bot is
/// configured, it might re-try and lose funds through transaction fees/deposits.
#[clap(long, short, env = "SEED")]
pub seed_or_path: Option<String>,
}
pub async fn dry_run_cmd<T>(client: Client, config: DryRunConfig) -> Result<(), Error>
where
T: MinerConfig<AccountId = AccountId, MaxVotesPerVoter = static_types::MaxVotesPerVoter>
+ Send
+ Sync
+ 'static,
T::Solution: Send,
{
let storage = storage_at(config.at, client.chain_api()).await?;
let round = storage
.fetch_or_default(&runtime::storage().election_provider_multi_phase().round())
.await?;
let miner_solution = epm::fetch_snapshot_and_mine_solution::<T>(
client.chain_api(),
config.at,
config.solver,
round,
config.force_winner_count,
)
.await?;
let solution = miner_solution.solution();
let score = miner_solution.score();
let raw_solution = RawSolution {
solution,
score,
round,
};
log::info!(
target: LOG_TARGET,
"solution score {:?} / length {:?}",
score,
raw_solution.encode().len(),
);
// Now we've logged the score, check whether the solution makes sense. No point doing this
// if force_winner_count is selected since it'll definitely fail in that case.
if config.force_winner_count.is_none() {
miner_solution.feasibility_check()?;
}
// If an account seed or path is provided, then do a dry run to the node. Otherwise,
// we've logged the solution above and we do nothing else.
if let Some(seed_or_path) = &config.seed_or_path {
let signer = signer_from_seed_or_path(seed_or_path)?;
let account_info = storage
.fetch(
&runtime::storage()
.system()
.account(signer.public_key().to_account_id()),
)
.await?
.ok_or(Error::AccountDoesNotExists)?;
log::info!(target: LOG_TARGET, "Loaded account {}, {:?}", signer.public_key().to_account_id(), account_info);
let nonce = client
.rpc()
.system_account_next_index(&signer.public_key().to_account_id())
.await?;
let tx = epm::signed_solution(raw_solution)?;
let xt = client.chain_api().tx().create_signed_with_nonce(
&tx,
&signer,
nonce,
Default::default(),
)?;
let dry_run_bytes = client.rpc().dry_run(xt.encoded(), config.at).await?;
let dry_run_result = dry_run_bytes.into_dry_run_result(&client.chain_api().metadata())?;
log::info!(target: LOG_TARGET, "dry-run outcome is {:?}", dry_run_result);
}
Ok(())
}

View File

@ -0,0 +1,90 @@
use crate::{
client::Client, epm, error::Error, helpers::storage_at, opt::Solver, prelude::*, static_types,
};
use clap::Parser;
use codec::Encode;
use sp_core::hexdisplay::HexDisplay;
use std::io::Write;
use subxt::tx::TxPayload;
#[derive(Debug, Clone, Parser)]
#[cfg_attr(test, derive(PartialEq))]
pub struct EmergencySolutionConfig {
/// The block hash at which scraping happens. If none is provided, the latest head is used.
#[clap(long)]
pub at: Option<Hash>,
/// The solver algorithm to use.
#[clap(subcommand)]
pub solver: Solver,
/// The number of top backed winners to take instead. All are taken, if not provided.
pub force_winner_count: Option<u32>,
}
pub async fn emergency_solution_cmd<T>(
client: Client,
config: EmergencySolutionConfig,
) -> Result<(), Error>
where
T: MinerConfig<AccountId = AccountId, MaxVotesPerVoter = static_types::MaxVotesPerVoter>
+ Send
+ Sync
+ 'static,
T::Solution: Send,
{
if let Some(max_winners) = config.force_winner_count {
static_types::MaxWinners::set(max_winners);
}
let storage = storage_at(config.at, client.chain_api()).await?;
let round = storage
.fetch_or_default(&runtime::storage().election_provider_multi_phase().round())
.await?;
let miner_solution = epm::fetch_snapshot_and_mine_solution::<T>(
client.chain_api(),
config.at,
config.solver,
round,
config.force_winner_count,
)
.await?;
let ready_solution = miner_solution.feasibility_check()?;
let encoded_size = ready_solution.encoded_size();
let score = ready_solution.score;
let mut supports: Vec<_> = ready_solution.supports.into_inner();
// maybe truncate.
if let Some(force_winner_count) = config.force_winner_count {
log::info!(
target: LOG_TARGET,
"truncating {} winners to {}",
supports.len(),
force_winner_count
);
supports.sort_unstable_by_key(|(_, s)| s.total);
supports.truncate(force_winner_count as usize);
}
let call = epm::set_emergency_result(supports.clone())?;
let encoded_call = call.encode_call_data(&client.chain_api().metadata())?;
let encoded_supports = supports.encode();
// write results to files.
let mut supports_file = std::fs::File::create("solution.supports.bin")?;
let mut encoded_call_file = std::fs::File::create("encoded.call")?;
supports_file.write_all(&encoded_supports)?;
encoded_call_file.write_all(&encoded_call)?;
let hex = HexDisplay::from(&encoded_call);
log::info!(target: LOG_TARGET, "Hex call:\n {:?}", hex);
log::info!(target: LOG_TARGET, "Use the hex encoded call above to construct the governance proposal or the extrinsic to submit.");
log::info!(target: LOG_TARGET, "ReadySolution: size {:?} / score = {:?}", encoded_size, score);
log::info!(target: LOG_TARGET, "`set_emergency_result` encoded call written to ./encoded.call");
Ok(())
}

View File

@ -0,0 +1,7 @@
pub mod dry_run;
pub mod emergency_solution;
pub mod monitor;
pub use dry_run::{dry_run_cmd, DryRunConfig};
pub use emergency_solution::{emergency_solution_cmd, EmergencySolutionConfig};
pub use monitor::{monitor_cmd, MonitorConfig};

View File

@ -0,0 +1,858 @@
use crate::{
client::Client,
epm,
error::Error,
helpers::{kill_main_task_if_critical_err, signer_from_seed_or_path, TimedFuture},
opt::Solver,
prelude::*,
prometheus, static_types,
};
use clap::Parser;
use codec::{Decode, Encode};
use frame_election_provider_support::NposSolution;
use futures::future::TryFutureExt;
use jsonrpsee::core::Error as JsonRpseeError;
use pallet_election_provider_multi_phase::{RawSolution, SolutionOf};
use sp_runtime::Perbill;
use std::{str::FromStr, sync::Arc};
use subxt::{
backend::{legacy::rpc_methods::DryRunResult, rpc::RpcSubscription},
config::{DefaultExtrinsicParamsBuilder, Header as _},
error::RpcError,
tx::{TxInBlock, TxProgress},
Error as SubxtError,
};
use tokio::sync::Mutex;
#[derive(Debug, Clone, Parser)]
#[cfg_attr(test, derive(PartialEq))]
pub struct MonitorConfig {
/// They type of event to listen to.
///
/// Typically, finalized is safer and there is no chance of anything going wrong, but it can be
/// slower. It is recommended to use finalized, if the duration of the signed phase is longer
/// than the the finality delay.
#[clap(long, value_enum, default_value_t = Listen::Finalized)]
pub listen: Listen,
/// The solver algorithm to use.
#[clap(subcommand)]
pub solver: Solver,
/// Submission strategy to use.
///
/// Possible options:
///
/// `--submission-strategy if-leading`: only submit if leading.
///
/// `--submission-strategy always`: always submit.
///
/// `--submission-strategy "percent-better <percent>"`: submit if the submission is `n` percent better.
///
/// `--submission-strategy "no-worse-than <percent>"`: submit if submission is no more than `n` percent worse.
#[clap(long, value_parser, default_value = "if-leading")]
pub submission_strategy: SubmissionStrategy,
/// The path to a file containing the seed of the account. If the file is not found, the seed is
/// used as-is.
///
/// Can also be provided via the `SEED` environment variable.
///
/// WARNING: Don't use an account with a large stash for this. Based on how the bot is
/// configured, it might re-try and lose funds through transaction fees/deposits.
#[clap(long, short, env = "SEED")]
pub seed_or_path: String,
/// Delay in number seconds to wait until starting mining a solution.
///
/// At every block when a solution is attempted
/// a delay can be enforced to avoid submitting at
/// "same time" and risk potential races with other miners.
///
/// When this is enabled and there are competing solutions, your solution might not be submitted
/// if the scores are equal.
#[clap(long, default_value_t = 0)]
pub delay: usize,
/// Verify the submission by `dry-run` the extrinsic to check the validity.
/// If the extrinsic is invalid then the submission is ignored and the next block will attempted again.
///
/// This requires a RPC endpoint that exposes unsafe RPC methods, if the RPC endpoint doesn't expose unsafe RPC methods
/// then the miner will be terminated.
#[clap(long)]
pub dry_run: bool,
}
/// The type of event to listen to.
///
///
/// Typically, finalized is safer and there is no chance of anything going wrong, but it can be
/// slower. It is recommended to use finalized, if the duration of the signed phase is longer
/// than the the finality delay.
#[cfg_attr(test, derive(PartialEq))]
#[derive(clap::ValueEnum, Debug, Copy, Clone)]
pub enum Listen {
/// Latest finalized head of the canonical chain.
Finalized,
/// Latest head of the canonical chain.
Head,
}
/// Submission strategy to use.
#[derive(Debug, Copy, Clone)]
#[cfg_attr(test, derive(PartialEq))]
pub enum SubmissionStrategy {
/// Always submit.
Always,
// Submit if we are leading, or if the solution that's leading is more that the given `Perbill`
// better than us. This helps detect obviously fake solutions and still combat them.
/// Only submit if at the time, we are the best (or equal to it).
IfLeading,
/// Submit if we are no worse than `Perbill` worse than the best.
ClaimNoWorseThan(Perbill),
/// Submit if we are leading, or if the solution that's leading is more that the given `Perbill`
/// better than us. This helps detect obviously fake solutions and still combat them.
ClaimBetterThan(Perbill),
}
/// Custom `impl` to parse `SubmissionStrategy` from CLI.
///
/// Possible options:
/// * --submission-strategy if-leading: only submit if leading
/// * --submission-strategy always: always submit
/// * --submission-strategy "percent-better <percent>": submit if submission is `n` percent better.
///
impl FromStr for SubmissionStrategy {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = s.trim();
let res = if s == "if-leading" {
Self::IfLeading
} else if s == "always" {
Self::Always
} else if let Some(percent) = s.strip_prefix("no-worse-than ") {
let percent: u32 = percent.parse().map_err(|e| format!("{:?}", e))?;
Self::ClaimNoWorseThan(Perbill::from_percent(percent))
} else if let Some(percent) = s.strip_prefix("percent-better ") {
let percent: u32 = percent.parse().map_err(|e| format!("{:?}", e))?;
Self::ClaimBetterThan(Perbill::from_percent(percent))
} else {
return Err(s.into());
};
Ok(res)
}
}
pub async fn monitor_cmd<T>(client: Client, config: MonitorConfig) -> Result<(), Error>
where
T: MinerConfig<AccountId = AccountId, MaxVotesPerVoter = static_types::MaxVotesPerVoter>
+ Send
+ Sync
+ 'static,
T::Solution: Send,
{
let signer = signer_from_seed_or_path(&config.seed_or_path)?;
let account_info = {
let addr = runtime::storage()
.system()
.account(signer.public_key().to_account_id());
client
.chain_api()
.storage()
.at_latest()
.await?
.fetch(&addr)
.await?
.ok_or(Error::AccountDoesNotExists)?
};
log::info!(target: LOG_TARGET, "Loaded account {}, {:?}", signer.public_key().to_account_id(), account_info);
if config.dry_run {
// if we want to try-run, ensure the node supports it.
dry_run_works(client.rpc()).await?;
}
let mut subscription = heads_subscription(client.rpc(), config.listen).await?;
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::<Error>();
let submit_lock = Arc::new(Mutex::new(()));
loop {
let at = tokio::select! {
maybe_rp = subscription.next() => {
match maybe_rp {
Some(Ok(r)) => r,
Some(Err(e)) => {
log::error!(target: LOG_TARGET, "subscription failed to decode Header {:?}, this is bug please file an issue", e);
return Err(e.into());
}
// The subscription was dropped, should only happen if:
// - the connection was closed.
// - the subscription could not keep up with the server.
None => {
log::warn!(target: LOG_TARGET, "subscription to `{:?}` terminated. Retrying..", config.listen);
subscription = heads_subscription(client.rpc(), config.listen).await?;
continue
}
}
},
maybe_err = rx.recv() => {
match maybe_err {
Some(err) => return Err(err),
None => unreachable!("at least one sender kept in the main loop should always return Some; qed"),
}
}
};
// Spawn task and non-recoverable errors are sent back to the main task
// such as if the connection has been closed.
let tx2 = tx.clone();
let client2 = client.clone();
let signer2 = signer.clone();
let config2 = config.clone();
let submit_lock2 = submit_lock.clone();
tokio::spawn(async move {
if let Err(err) =
mine_and_submit_solution::<T>(at, client2, signer2, config2, submit_lock2).await
{
kill_main_task_if_critical_err(&tx2, err)
}
});
let account_info = client
.chain_api()
.storage()
.at_latest()
.await?
.fetch(
&runtime::storage()
.system()
.account(signer.public_key().to_account_id()),
)
.await?
.ok_or(Error::AccountDoesNotExists)?;
// this is lossy but fine for now.
prometheus::set_balance(account_info.data.free as f64);
}
}
/// Construct extrinsic at given block and watch it.
async fn mine_and_submit_solution<T>(
at: Header,
client: Client,
signer: Signer,
config: MonitorConfig,
submit_lock: Arc<Mutex<()>>,
) -> Result<(), Error>
where
T: MinerConfig<AccountId = AccountId, MaxVotesPerVoter = static_types::MaxVotesPerVoter>
+ Send
+ Sync
+ 'static,
T::Solution: Send,
{
let block_hash = at.hash();
log::trace!(target: LOG_TARGET, "new event at #{:?} ({:?})", at.number, block_hash);
// NOTE: as we try to send at each block then the nonce is used guard against
// submitting twice. Because once a solution has been accepted on chain
// the "next transaction" at a later block but with the same nonce will be rejected
let nonce = client
.rpc()
.system_account_next_index(&signer.public_key().to_account_id())
.await?;
ensure_signed_phase(client.chain_api(), block_hash)
.inspect_err(|e| {
log::debug!(
target: LOG_TARGET,
"ensure_signed_phase failed: {:?}; skipping block: {}",
e,
at.number
)
})
.await?;
let round_fut = async {
client
.chain_api()
.storage()
.at(block_hash)
.fetch_or_default(&runtime::storage().election_provider_multi_phase().round())
.await
};
let round = round_fut
.inspect_err(|e| log::error!(target: LOG_TARGET, "Mining solution failed: {:?}", e))
.await?;
ensure_no_previous_solution::<T::Solution>(
client.chain_api(),
block_hash,
&signer.public_key().0.into(),
)
.inspect_err(|e| {
log::debug!(
target: LOG_TARGET,
"ensure_no_previous_solution failed: {:?}; skipping block: {}",
e,
at.number
)
})
.await?;
tokio::time::sleep(std::time::Duration::from_secs(config.delay as u64)).await;
let _lock = submit_lock.lock().await;
let (solution, score) = match epm::fetch_snapshot_and_mine_solution::<T>(
&client.chain_api(),
Some(block_hash),
config.solver,
round,
None,
)
.timed()
.await
{
(Ok(mined_solution), elapsed) => {
// check that the solution looks valid:
mined_solution.feasibility_check()?;
// and then get the values we need from it:
let solution = mined_solution.solution();
let score = mined_solution.score();
let size = mined_solution.size();
let elapsed_ms = elapsed.as_millis();
let encoded_len = solution.encoded_size();
let active_voters = solution.voter_count() as u32;
let desired_targets = solution.unique_targets().len() as u32;
let final_weight = tokio::task::spawn_blocking(move || {
T::solution_weight(size.voters, size.targets, active_voters, desired_targets)
})
.await?;
log::info!(
target: LOG_TARGET,
"Mined solution with {:?} size: {:?} round: {:?} at: {}, took: {} ms, len: {:?}, weight = {:?}",
score,
size,
round,
at.number(),
elapsed_ms,
encoded_len,
final_weight,
);
prometheus::set_length(encoded_len);
prometheus::set_weight(final_weight);
prometheus::observe_mined_solution_duration(elapsed_ms as f64);
prometheus::set_score(score);
(solution, score)
}
(Err(e), _) => return Err(Error::Other(e.to_string())),
};
let best_head = get_latest_head(client.rpc(), config.listen).await?;
ensure_signed_phase(client.chain_api(), best_head)
.inspect_err(|e| {
log::debug!(
target: LOG_TARGET,
"ensure_signed_phase failed: {:?}; skipping block: {}",
e,
at.number
)
})
.await?;
ensure_no_previous_solution::<T::Solution>(
client.chain_api(),
best_head,
&signer.public_key().0.into(),
)
.inspect_err(|e| {
log::debug!(
target: LOG_TARGET,
"ensure_no_previous_solution failed: {:?}; skipping block: {:?}",
e,
best_head,
)
})
.await?;
match ensure_solution_passes_strategy(
client.chain_api(),
best_head,
score,
config.submission_strategy,
)
.timed()
.await
{
(Ok(_), now) => {
log::trace!(
target: LOG_TARGET,
"Solution validity verification took: {} ms",
now.as_millis()
);
}
(Err(e), _) => {
log::debug!(
target: LOG_TARGET,
"ensure_no_better_solution failed: {:?}; skipping block: {}",
e,
at.number
);
return Err(e);
}
};
prometheus::on_submission_attempt();
match submit_and_watch_solution::<T>(
&client,
signer,
(solution, score, round),
nonce,
config.listen,
config.dry_run,
&at,
)
.timed()
.await
{
(Ok(_), now) => {
prometheus::on_submission_success();
prometheus::observe_submit_and_watch_duration(now.as_millis() as f64);
}
(Err(e), _) => {
log::warn!(
target: LOG_TARGET,
"submit_and_watch_solution failed: {e}; skipping block: {}",
at.number
);
}
};
Ok(())
}
/// Ensure that now is the signed phase.
async fn ensure_signed_phase(api: &ChainClient, block_hash: Hash) -> Result<(), Error> {
use pallet_election_provider_multi_phase::Phase;
let addr = runtime::storage()
.election_provider_multi_phase()
.current_phase();
let phase = api.storage().at(block_hash).fetch(&addr).await?;
if let Some(Phase::Signed) = phase.map(|p| p.0) {
Ok(())
} else {
Err(Error::IncorrectPhase)
}
}
/// Ensure that our current `us` have not submitted anything previously.
async fn ensure_no_previous_solution<T>(
api: &ChainClient,
block_hash: Hash,
us: &AccountId,
) -> Result<(), Error>
where
T: NposSolution + scale_info::TypeInfo + Decode + 'static,
{
let addr = runtime::storage()
.election_provider_multi_phase()
.signed_submission_indices();
let indices = api.storage().at(block_hash).fetch_or_default(&addr).await?;
for (_score, _, idx) in indices.0 {
let submission = epm::signed_submission_at::<T>(idx, Some(block_hash), api).await?;
if let Some(submission) = submission {
if &submission.who == us {
return Err(Error::AlreadySubmitted);
}
}
}
Ok(())
}
async fn ensure_solution_passes_strategy(
api: &ChainClient,
block_hash: Hash,
score: sp_npos_elections::ElectionScore,
strategy: SubmissionStrategy,
) -> Result<(), Error> {
// don't care about current scores.
if matches!(strategy, SubmissionStrategy::Always) {
return Ok(());
}
let addr = runtime::storage()
.election_provider_multi_phase()
.signed_submission_indices();
let indices = api.storage().at(block_hash).fetch_or_default(&addr).await?;
log::debug!(target: LOG_TARGET, "submitted solutions: {:?}", indices.0);
if indices.0.last().map_or(true, |(best_score, _, _)| {
score_passes_strategy(score, best_score.0, strategy)
}) {
Ok(())
} else {
Err(Error::BetterScoreExist)
}
}
async fn submit_and_watch_solution<T: MinerConfig + Send + Sync + 'static>(
client: &Client,
signer: Signer,
(solution, score, round): (SolutionOf<T>, sp_npos_elections::ElectionScore, u32),
nonce: u64,
listen: Listen,
dry_run: bool,
at: &Header,
) -> Result<(), Error> {
let tx = epm::signed_solution(RawSolution {
solution,
score,
round,
})?;
// TODO: https://github.com/paritytech/polkadot-staking-miner/issues/730
//
// The extrinsic mortality length is static and doesn't know when the
// signed phase ends.
let signed_phase_len = client.chain_api().constants().at(&runtime::constants()
.election_provider_multi_phase()
.signed_phase())?;
let xt_cfg = DefaultExtrinsicParamsBuilder::default()
.mortal(at, signed_phase_len as u64)
.build();
let xt =
client
.chain_api()
.tx()
.create_signed_with_nonce(&tx, &signer, nonce as u64, xt_cfg)?;
if dry_run {
let dry_run_bytes = client.rpc().dry_run(xt.encoded(), None).await?;
match dry_run_bytes.into_dry_run_result(&client.chain_api().metadata())? {
DryRunResult::Success => (),
DryRunResult::DispatchError(e) => {
return Err(Error::TransactionRejected(e.to_string()))
}
DryRunResult::TransactionValidityError => {
return Err(Error::TransactionRejected(
"TransactionValidityError".into(),
))
}
}
}
let tx_progress = xt.submit_and_watch().await.map_err(|e| {
log::warn!(target: LOG_TARGET, "submit solution failed: {:?}", e);
e
})?;
match listen {
Listen::Head => {
let in_block = wait_for_in_block(tx_progress).await?;
let events = in_block.fetch_events().await.expect("events should exist");
let solution_stored = events
.find_first::<runtime::election_provider_multi_phase::events::SolutionStored>(
);
if let Ok(Some(_)) = solution_stored {
log::info!("Included at {:?}", in_block.block_hash());
} else {
return Err(Error::Other(format!(
"No SolutionStored event found at {:?}",
in_block.block_hash()
)));
}
}
Listen::Finalized => {
let finalized = tx_progress.wait_for_finalized_success().await?;
let solution_stored = finalized
.find_first::<runtime::election_provider_multi_phase::events::SolutionStored>(
);
if let Ok(Some(_)) = solution_stored {
log::info!("Finalized at {:?}", finalized.block_hash());
} else {
return Err(Error::Other(format!(
"No SolutionStored event found at {:?}",
finalized.block_hash()
)));
}
}
};
Ok(())
}
async fn heads_subscription(
rpc: &RpcClient,
listen: Listen,
) -> Result<RpcSubscription<Header>, Error> {
match listen {
Listen::Head => rpc.chain_subscribe_new_heads().await,
Listen::Finalized => rpc.chain_subscribe_finalized_heads().await,
}
.map_err(Into::into)
}
async fn get_latest_head(rpc: &RpcClient, listen: Listen) -> Result<Hash, Error> {
match listen {
Listen::Head => match rpc.chain_get_block_hash(None).await {
Ok(Some(hash)) => Ok(hash),
Ok(None) => Err(Error::Other("Latest block not found".into())),
Err(e) => Err(e.into()),
},
Listen::Finalized => rpc.chain_get_finalized_head().await.map_err(Into::into),
}
}
/// Returns `true` if `our_score` better the onchain `best_score` according the given strategy.
pub(crate) fn score_passes_strategy(
our_score: sp_npos_elections::ElectionScore,
best_score: sp_npos_elections::ElectionScore,
strategy: SubmissionStrategy,
) -> bool {
match strategy {
SubmissionStrategy::Always => true,
SubmissionStrategy::IfLeading => {
our_score.strict_threshold_better(best_score, Perbill::zero())
}
SubmissionStrategy::ClaimBetterThan(epsilon) => {
our_score.strict_threshold_better(best_score, epsilon)
}
SubmissionStrategy::ClaimNoWorseThan(epsilon) => {
!best_score.strict_threshold_better(our_score, epsilon)
}
}
}
async fn dry_run_works(rpc: &RpcClient) -> Result<(), Error> {
if let Err(SubxtError::Rpc(RpcError::ClientError(e))) = rpc.dry_run(&[], None).await {
let rpc_err = match e.downcast::<JsonRpseeError>() {
Ok(e) => *e,
Err(_) => {
return Err(Error::Other(
"Failed to downcast RPC error; this is a bug please file an issue".to_string(),
))
}
};
if let JsonRpseeError::Call(e) = rpc_err {
if e.message() == "RPC call is unsafe to be called externally" {
return Err(Error::Other(
"dry-run requires a RPC endpoint with `--rpc-methods unsafe`; \
either connect to another RPC endpoint or disable dry-run"
.to_string(),
));
}
}
}
Ok(())
}
/// Wait for the transaction to be in a block.
///
/// **Note:** transaction statuses like `Invalid`/`Usurped`/`Dropped` indicate with some
/// probability that the transaction will not make it into a block but there is no guarantee
/// that this is true. In those cases the stream is closed however, so you currently have no way to find
/// out if they finally made it into a block or not.
async fn wait_for_in_block<T, C>(mut tx: TxProgress<T, C>) -> Result<TxInBlock<T, C>, subxt::Error>
where
T: subxt::Config,
C: subxt::client::OnlineClientT<T>,
{
use subxt::{error::TransactionError, tx::TxStatus};
while let Some(status) = tx.next().await {
match status? {
// Finalized or otherwise in a block! Return.
TxStatus::InBestBlock(s) | TxStatus::InFinalizedBlock(s) => return Ok(s),
// Error scenarios; return the error.
TxStatus::Error { message } => return Err(TransactionError::Error(message).into()),
TxStatus::Invalid { message } => return Err(TransactionError::Invalid(message).into()),
TxStatus::Dropped { message } => return Err(TransactionError::Dropped(message).into()),
// Ignore anything else and wait for next status event:
_ => continue,
}
}
Err(RpcError::SubscriptionDropped.into())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn score_passes_strategy_works() {
let s = |x| sp_npos_elections::ElectionScore {
minimal_stake: x,
..Default::default()
};
let two = Perbill::from_percent(2);
// anything passes Always
assert!(score_passes_strategy(
s(0),
s(0),
SubmissionStrategy::Always
));
assert!(score_passes_strategy(
s(5),
s(0),
SubmissionStrategy::Always
));
assert!(score_passes_strategy(
s(5),
s(10),
SubmissionStrategy::Always
));
// if leading
assert!(!score_passes_strategy(
s(0),
s(0),
SubmissionStrategy::IfLeading
));
assert!(score_passes_strategy(
s(1),
s(0),
SubmissionStrategy::IfLeading
));
assert!(score_passes_strategy(
s(2),
s(0),
SubmissionStrategy::IfLeading
));
assert!(!score_passes_strategy(
s(5),
s(10),
SubmissionStrategy::IfLeading
));
assert!(!score_passes_strategy(
s(9),
s(10),
SubmissionStrategy::IfLeading
));
assert!(!score_passes_strategy(
s(10),
s(10),
SubmissionStrategy::IfLeading
));
// if better by 2%
assert!(!score_passes_strategy(
s(50),
s(100),
SubmissionStrategy::ClaimBetterThan(two)
));
assert!(!score_passes_strategy(
s(100),
s(100),
SubmissionStrategy::ClaimBetterThan(two)
));
assert!(!score_passes_strategy(
s(101),
s(100),
SubmissionStrategy::ClaimBetterThan(two)
));
assert!(!score_passes_strategy(
s(102),
s(100),
SubmissionStrategy::ClaimBetterThan(two)
));
assert!(score_passes_strategy(
s(103),
s(100),
SubmissionStrategy::ClaimBetterThan(two)
));
assert!(score_passes_strategy(
s(150),
s(100),
SubmissionStrategy::ClaimBetterThan(two)
));
// if no less than 2% worse
assert!(!score_passes_strategy(
s(50),
s(100),
SubmissionStrategy::ClaimNoWorseThan(two)
));
assert!(!score_passes_strategy(
s(97),
s(100),
SubmissionStrategy::ClaimNoWorseThan(two)
));
assert!(score_passes_strategy(
s(98),
s(100),
SubmissionStrategy::ClaimNoWorseThan(two)
));
assert!(score_passes_strategy(
s(99),
s(100),
SubmissionStrategy::ClaimNoWorseThan(two)
));
assert!(score_passes_strategy(
s(100),
s(100),
SubmissionStrategy::ClaimNoWorseThan(two)
));
assert!(score_passes_strategy(
s(101),
s(100),
SubmissionStrategy::ClaimNoWorseThan(two)
));
assert!(score_passes_strategy(
s(102),
s(100),
SubmissionStrategy::ClaimNoWorseThan(two)
));
assert!(score_passes_strategy(
s(103),
s(100),
SubmissionStrategy::ClaimNoWorseThan(two)
));
assert!(score_passes_strategy(
s(150),
s(100),
SubmissionStrategy::ClaimNoWorseThan(two)
));
}
#[test]
fn submission_strategy_from_str_works() {
assert_eq!(
SubmissionStrategy::from_str("if-leading"),
Ok(SubmissionStrategy::IfLeading)
);
assert_eq!(
SubmissionStrategy::from_str("always"),
Ok(SubmissionStrategy::Always)
);
assert_eq!(
SubmissionStrategy::from_str(" percent-better 99 "),
Ok(SubmissionStrategy::ClaimBetterThan(Accuracy::from_percent(
99
)))
);
}
}

View File

@ -13,13 +13,10 @@ use std::{
}; };
use codec::{Decode, Encode}; use codec::{Decode, Encode};
use frame_election_provider_support::{ use frame_election_provider_support::{Get, NposSolution, PhragMMS, SequentialPhragmen};
Get, NposSolution, PhragMMS, SequentialPhragmen,
};
use frame_support::{weights::Weight, BoundedVec}; use frame_support::{weights::Weight, BoundedVec};
use pallet_election_provider_multi_phase::{ use pallet_election_provider_multi_phase::{
usigned::TrimmingStatus, RawSolution, ReadySolution, SolutionOf, usigned::TrimmingStatus, RawSolution, ReadySolution, SolutionOf, SolutionOrSnapshotSize,
SolutionOrSnapshotSize,
}; };
use scale_info::{PortableRegistry, TypeInfo}; use scale_info::{PortableRegistry, TypeInfo};
use scale_value::scale::decode_as_type; use scale_value::scale::decode_as_type;
@ -29,12 +26,16 @@ use subxt::{dynamic::Value, tx::DynamicPayload};
const EPM_PALLET_NAME: &str = "ElectionProviderMultiPhase"; const EPM_PALLET_NAME: &str = "ElectionProviderMultiPhase";
type TypeId = u32; type TypeId = u32;
type MinerVoterOf = frame_election_provider_support::Voter<AccountId, crate::static_types::MaxVotesPerVoter>; type MinerVoterOf =
frame_election_provider_support::Voter<AccountId, crate::static_types::MaxVotesPerVoter>;
type RoundSnapshot = pallet_election_provider_multi_phase::RoundSnapshot<AccountId, MinerVoterOf>; type RoundSnapshot = pallet_election_provider_multi_phase::RoundSnapshot<AccountId, MinerVoterOf>;
type Voters = Vec<(AccountId, VoteWeight, BoundedVec<AccountId, crate::static_types::MaxVotesPerVoter>)>; type Voters = Vec<(
AccountId,
VoteWeight,
BoundedVec<AccountId, crate::static_types::MaxVotesPerVoter>,
)>;
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, Debug)]
#[derive(Debug)]
struct EpmConstant { struct EpmConstant {
epm: &'static str, epm: &'static str,
constant: &'static str, constant: &'static str,
@ -42,7 +43,10 @@ struct EpmConstant {
impl EpmConstant { impl EpmConstant {
const fn new(constant: &'static str) -> Self { const fn new(constant: &'static str) -> Self {
Self { epm: EPM_PALLET_NAME, constant } Self {
epm: EPM_PALLET_NAME,
constant,
}
} }
const fn to_parts(self) -> (&'static str, &'static str) { const fn to_parts(self) -> (&'static str, &'static str) {
@ -101,18 +105,24 @@ where
let est_weight: Weight = tokio::task::spawn_blocking(move || { let est_weight: Weight = tokio::task::spawn_blocking(move || {
T::solution_weight(active_voters, targets_len, active_voters, desired_targets) T::solution_weight(active_voters, targets_len, active_voters, desired_targets)
}).await?; })
.await?;
let max_weight: Weight = T::MaxWeight::get(); let max_weight: Weight = T::MaxWeight::get();
if est_weight.all_lt(max_weight) { if est_weight.all_lt(max_weight) {
return Ok(Self { return Ok(Self {
state: State { voters, voters_by_stake }, state: State {
_marker: PhantomData voters,
voters_by_stake,
},
_marker: PhantomData,
}); });
} }
let Some((_, idx)) = voters_by_stake.pop_first() else { break }; let Some((_, idx)) = voters_by_stake.pop_first() else {
break;
};
let rm = voters[idx].0.clone(); let rm = voters[idx].0.clone();
for (_voter, _stake, supports) in &mut voters { for (_voter, _stake, supports) in &mut voters {
@ -122,7 +132,9 @@ where
targets.remove(&rm); targets.remove(&rm);
} }
return Err(Error::Feasibility("Failed to pre-trim weight < T::MaxLength".to_string())); return Err(Error::Feasibility(
"Failed to pre-trim weight < T::MaxLength".to_string(),
));
} }
pub fn trim(&mut self, n: usize) -> Result<State, Error> { pub fn trim(&mut self, n: usize) -> Result<State, Error> {
@ -139,7 +151,10 @@ where
supports.retain(|a| a != &rm); supports.retain(|a| a != &rm);
} }
} }
Ok(State { voters, voters_by_stake }) Ok(State {
voters,
voters_by_stake,
})
} }
pub fn to_voters(&self) -> Voters { pub fn to_voters(&self) -> Voters {
@ -197,28 +212,37 @@ fn read_constant<'a, T: serde::Deserialize<'a>>(
.map_err(|e| Error::Subxt(e.into()))?; .map_err(|e| Error::Subxt(e.into()))?;
scale_value::serde::from_value::<_, T>(val).map_err(|e| { scale_value::serde::from_value::<_, T>(val).map_err(|e| {
Error::InvalidMetadata( Error::InvalidMetadata(format!(
format!("Decoding `{}` failed {}", std::any::type_name::<T>(), e) "Decoding `{}` failed {}",
) std::any::type_name::<T>(),
e
))
}) })
} }
pub(crate) fn set_emergency_result<A: Encode + TypeInfo + 'static>( pub(crate) fn set_emergency_result<A: Encode + TypeInfo + 'static>(
supports: frame_election_provider_support::Supports<A>, supports: frame_election_provider_support::Supports<A>,
) -> Result<DynamicPayload, Error> { ) -> Result<DynamicPayload, Error> {
let scale_result = to_scale_value(supports).map_err(|e| { let scale_result = to_scale_value(supports)
Error::DynamicTransaction(format!("Failed to encode `Supports`: {:?}", e)) .map_err(|e| Error::DynamicTransaction(format!("Failed to encode `Supports`: {:?}", e)))?;
})?; Ok(subxt::dynamic::tx(
Ok(subxt::dynamic::tx(EPM_PALLET_NAME, "set_emergency_election_result", vec![scale_result])) EPM_PALLET_NAME,
"set_emergency_election_result",
vec![scale_result],
))
} }
pub fn signed_solution<S: NposSolution + Encode + TypeInfo + 'static>( pub fn signed_solution<S: NposSolution + Encode + TypeInfo + 'static>(
solution: RawSolution<S>, solution: RawSolution<S>,
) -> Result<DynamicPayload, Error> { ) -> Result<DynamicPayload, Error> {
let scale_solution = to_scale_value(solution).map_err(|e| { let scale_solution = to_scale_value(solution).map_err(|e| {
Error::DynamicTransaction(format!("Failed to encode `RawSolution`: {:?}", e)) Error::DynamicTransaction(format!("Failed to encode `RawSolution`: {:?}", e))
})?; })?;
Ok(subxt::dynamic::tx(EPM_PALLET_NAME, "submit", vec![scale_solution])) Ok(subxt::dynamic::tx(
EPM_PALLET_NAME,
"submit",
vec![scale_solution],
))
} }
pub fn unsigned_solution<S: NposSolution + Encode + TypeInfo + 'static>( pub fn unsigned_solution<S: NposSolution + Encode + TypeInfo + 'static>(
@ -227,7 +251,11 @@ pub fn unsigned_solution<S: NposSolution + Encode + TypeInfo + 'static>(
) -> Result<DynamicPayload, Error> { ) -> Result<DynamicPayload, Error> {
let scale_solution = to_scale_value(solution)?; let scale_solution = to_scale_value(solution)?;
let scale_witness = to_scale_value(witness)?; let scale_witness = to_scale_value(witness)?;
Ok(subxt::dynamic::tx(EPM_PALLET_NAME, "submit_unsigned", vec![scale_solution, scale_witness])) Ok(subxt::dynamic::tx(
EPM_PALLET_NAME,
"submit_unsigned",
vec![scale_solution, scale_witness],
))
} }
pub async fn signed_submission<S: NposSolution + Decode + TypeInfo + 'static>( pub async fn signed_submission<S: NposSolution + Decode + TypeInfo + 'static>(
@ -244,7 +272,7 @@ pub async fn signed_submission<S: NposSolution + Decode + TypeInfo + 'static>(
Ok(Some(val)) => { Ok(Some(val)) => {
let submissions = Decode::decode(&mut val.encode())?; let submissions = Decode::decode(&mut val.encode())?;
Ok(Some(submissions)) Ok(Some(submissions))
}, }
Ok(None) => Ok(None), Ok(None) => Ok(None),
Err(err) => Err(err.into()), Err(err) => Err(err.into()),
} }
@ -263,7 +291,7 @@ pub async fn snapshot_at(
Ok(Some(val)) => { Ok(Some(val)) => {
let snapshot = Decode::decode(&mut val.encode())?; let snapshot = Decode::decode(&mut val.encode())?;
Ok(Some(snapshot)) Ok(Some(snapshot))
}, }
Ok(None) => Err(Error::EmptySnapshot), Ok(None) => Err(Error::EmptySnapshot),
Err(err) => Err(err.into()), Err(err) => Err(err.into()),
} }
@ -274,7 +302,15 @@ pub async fn mine_solution<T>(
targets: Vec<AccountId>, targets: Vec<AccountId>,
voters: Voters, voters: Voters,
desired_targets: u32, desired_targets: u32,
) -> Result<(SolutionOf<T>, ElectionScore, SolutionOrSnapshotSize, TrimmingStatus), Error> ) -> Result<
(
SolutionOf<T>,
ElectionScore,
SolutionOrSnapshotSize,
TrimmingStatus,
),
Error,
>
where where
T: MinerConfig<AccountId = AccountId, MaxVotesPerVoter = static_types::MaxVotesPerVoter> T: MinerConfig<AccountId = AccountId, MaxVotesPerVoter = static_types::MaxVotesPerVoter>
+ Send + Send
@ -288,14 +324,18 @@ where
Miner::<T>::mine_solution_with_snapshot::< Miner::<T>::mine_solution_with_snapshot::<
SequentialPhragmen<AccountId, Accuracy, Balancing>, SequentialPhragmen<AccountId, Accuracy, Balancing>,
>(voters, targets, desired_targets) >(voters, targets, desired_targets)
}, }
Solver::PhragMMS { iterations } => { Solver::PhragMMS { iterations } => {
BalanceIterations::set(iterations); BalanceIterations::set(iterations);
Miner::<T>::mine_solution_with_snapshot::< Miner::<T>::mine_solution_with_snapshot::<PhragMMS<AccountId, Accuracy, Balancing>>(
PhragMMS<AccountId, Accuracy, Balancing>, voters,
>(voters, targets, desired_targets) targets,
}, desired_targets,
}).await { )
}
})
.await
{
Ok(Ok(s)) => Ok(s), Ok(Ok(s)) => Ok(s),
Err(e) => Err(e.into()), Err(e) => Err(e.into()),
Ok(Err(e)) => Err(Error::Other(format!("{:?}", e))), Ok(Err(e)) => Err(Error::Other(format!("{:?}", e))),
@ -322,13 +362,21 @@ where
let desired_targets = match forced_desired_targets { let desired_targets = match forced_desired_targets {
Some(x) => x, Some(x) => x,
None => storage None => storage
.fetch(&runtime::storage()::election_provider_multi_phase().desired_targets()) .fetch(
&runtime::storage()
.election_provider_multi_phase()
.desired_targets(),
)
.await? .await?
.expect("Snapshot is non-empty; `desired_target` should exist; qed"), .expect("Snapshot is non-empty; `desired_target` should exist; qed"),
}; };
let minimum_untrusted_score = storage let minimum_untrusted_score = storage
.fetch(&runtime::storage().election_provider_multi_phase().minimum_untrusted_score()) .fetch(
&runtime::storage()
.election_provider_multi_phase()
.minimum_untrusted_score(),
)
.await? .await?
.map(|score| score.0); .map(|score| score.0);
@ -339,7 +387,8 @@ where
snapshot.targets.clone(), snapshot.targets.clone(),
voters.to_voters(), voters.to_voters(),
desired_targets, desired_targets,
).await?; )
.await?;
if !trim_status.is_trimmed() { if !trim_status.is_trimmed() {
return Ok(MinedSolution { return Ok(MinedSolution {
@ -368,14 +417,15 @@ where
snapshot.targets.clone(), snapshot.targets.clone(),
next_state.to_voters(), next_state.to_voters(),
desired_targets, desired_targets,
).await?; )
.await?;
if !trim_status.is_trimmed() { if !trim_status.is_trimmed() {
best_solution = Some((solution, score, solution_or_snapshot_size)); best_solution = Some((solution, score, solution_or_snapshot_size));
h = mid - 1; h = mid - 1;
} else { } else {
l = mid + 1; l = mid + 1;
} , }
} }
if let Some((solution, score, solution_or_snapshot_size)) = best_solution { if let Some((solution, score, solution_or_snapshot_size)) = best_solution {
@ -425,9 +475,13 @@ where
self.solution_or_snapshot_size self.solution_or_snapshot_size
} }
pub fn feasibility_check(&self) => Result<ReadySolution<AccountId, T::MaxWinners>, Error> { pub fn feasibility_check(&self) -> Result<ReadySolution<AccountId, T::MaxWinners>, Error> {
match Miner::<T>::feasibility_check( match Miner::<T>::feasibility_check(
RawSolution { solution: self.solution.clone(), score: self.score, round: self.round }, RawSolution {
solution: self.solution.clone(),
score: self.score,
round: self.round,
},
pallet_election_provider_multi_phase::ElectionCompute::Signed, pallet_election_provider_multi_phase::ElectionCompute::Signed,
self.desired_targets, self.desired_targets,
self.snapshot.clone(), self.snapshot.clone(),
@ -438,7 +492,7 @@ where
Err(e) => { Err(e) => {
log::error!(target: LOG_TARGET, "Solution feasibility error {:?}", e); log::error!(target: LOG_TARGET, "Solution feasibility error {:?}", e);
Err(Error::Feasibility(format!("{:?}", e))) Err(Error::Feasibility(format!("{:?}", e)))
}, }
} }
} }
} }
@ -483,7 +537,9 @@ pub async fn runtime_api_solution_weight<S: Encode + NposSolution + TypeInfo + '
witness: SolutionOrSnapshotSize, witness: SolutionOrSnapshotSize,
) -> Result<Weight, Error> { ) -> Result<Weight, Error> {
let tx = unsigned_solution(raw_solution, witness)?; let tx = unsigned_solution(raw_solution, witness)?;
let client = SHARED_CLIENT.get().expect("shared client is configured as start; qed"); let client = SHARED_CLIENT
.get()
.expect("shared client is configured as start; qed");
let call_data = { let call_data = {
let mut buffer = Vec::new(); let mut buffer = Vec::new();
@ -499,7 +555,11 @@ pub async fn runtime_api_solution_weight<S: Encode + NposSolution + TypeInfo + '
let bytes = client let bytes = client
.rpc() .rpc()
.state_call("TransactionPaymentCallApi_query_call_info", Some(&call_data), None) .state_call(
"TransactionPaymentCallApi_query_call_info",
Some(&call_data),
None,
)
.await?; .await?;
let info: RuntimeDispatchInfo = Decode::decode(&mut bytes.as_ref())?; let info: RuntimeDispatchInfo = Decode::decode(&mut bytes.as_ref())?;

View File

@ -41,14 +41,17 @@ where
Poll::Ready(v) => { Poll::Ready(v) => {
let elapsed = start.elapsed(); let elapsed = start.elapsed();
Poll::Ready((v, elapsed)) Poll::Ready((v, elapsed))
}, }
} }
} }
} }
pub trait TimedFuture: Sized + Future { pub trait TimedFuture: Sized + Future {
fn timed(self) -> Timed<Self> { fn timed(self) -> Timed<Self> {
Timed { inner: self, start: None } Timed {
inner: self,
start: None,
}
} }
} }
@ -59,15 +62,15 @@ pub struct RuntimeDispatchInfo {
pub weight: Weight, pub weight: Weight,
} }
pub fn kill_main_task_if_critical_err(tx: &tokio::sync::mpsc::UnboundedSender<Error>, err::Error) { pub fn kill_main_task_if_critical_err(tx: &tokio::sync::mpsc::UnboundedSender<Error>, err: Error) {
match err { match err {
Error::AlreadySubmitted | Error::AlreadySubmitted
Error::BetterScoreExist | | Error::BetterScoreExist
Error::IncorrectPhase | | Error::IncorrectPhase
Error::TransactionRejected | | Error::TransactionRejected
Error::JoinError | | Error::JoinError
Error::Feasibility | | Error::Feasibility
Error::EmptySnapshot => {}, | Error::EmptySnapshot => {}
Error::Subxt(SubxtError::Rpc(rpc_err)) => { Error::Subxt(SubxtError::Rpc(rpc_err)) => {
log::debug!(target: LOG_TARGET, "rpc error: {:?}", rpc_err); log::debug!(target: LOG_TARGET, "rpc error: {:?}", rpc_err);
@ -77,10 +80,11 @@ pub fn kill_main_task_if_critical_err(tx: &tokio::sync::mpsc::UnboundedSender<Er
Ok(e) => *e, Ok(e) => *e,
Err(_) => { Err(_) => {
let _ = tx.send(Error::Other( let _ = tx.send(Error::Other(
"Failed to downcast RPC error; this is a bug please file an issue".to_string() "Failed to downcast RPC error; this is a bug please file an issue"
.to_string(),
)); ));
return; return;
}, }
}; };
match jsonrpsee_err { match jsonrpsee_err {
@ -89,30 +93,30 @@ pub fn kill_main_task_if_critical_err(tx: &tokio::sync::mpsc::UnboundedSender<Er
const VERIFICATION_ERROR: i32 = 1002; const VERIFICATION_ERROR: i32 = 1002;
use jsonrpsee::types::error::ErrorCode; use jsonrpsee::types::error::ErrorCode;
if e.code() == BAD_EXTRINSIC_FORMAT || if e.code() == BAD_EXTRINSIC_FORMAT
e.code() == VERIFICATION_ERROR || || e.code() == VERIFICATION_ERROR
e.code() == ErrorCode::MethodNotFound.code() || e.code() == ErrorCode::MethodNotFound.code()
{ {
let _ = tx.send(Error::Subxt(SubxtError::Rpc( let _ = tx.send(Error::Subxt(SubxtError::Rpc(
RpcError::ClientError(Box::new(JsonRpseeError::Call(e))), RpcError::ClientError(Box::new(JsonRpseeError::Call(e))),
))); )));
} }
}, }
JsonRpseeError::RequestTimeout => {}, JsonRpseeError::RequestTimeout => {}
err => { err => {
let _ = tx.send(Error::Subxt(SubxtError::Rpc(RpcError::ClientError( let _ = tx.send(Error::Subxt(SubxtError::Rpc(RpcError::ClientError(
Box::new(err), Box::new(err),
)))); ))));
}, }
} }
}, }
RpcError::SubscriptionDropped => (), RpcError::SubscriptionDropped => (),
_ => (), _ => (),
} }
}, }
err => { err => {
let _ = tx.send(err); let _ = tx.send(err);
}, }
} }
} }

View File

@ -34,10 +34,7 @@ use std::str::FromStr;
use tokio::sync::oneshot; use tokio::sync::oneshot;
use tracing_subscriber::EnvFilter; use tracing_subscriber::EnvFilter;
use crate::{ use crate::{client::Client, opt::RuntimeVersion};
client::Client,
opt::RuntimeVersion,
};
#[derive(Debig, Clone, Parser)] #[derive(Debig, Clone, Parser)]
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
@ -96,7 +93,12 @@ macro_rules! any_runtime {
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Error> { async fn main() -> Result<(), Error> {
let Opt { uri, command, prometheus_port, log } = Opt::parse(); let Opt {
uri,
command,
prometheus_port,
log,
} = Opt::parse();
let filter = EnvFilter::from_default_env().add_directive(log.parse()?); let filter = EnvFilter::from_default_env().add_directive(log.parse()?);
tracing_subscriber::fmt().with_env_filter(filter).init(); tracing_subscriber::fmt().with_env_filter(filter).init();
@ -109,7 +111,9 @@ async fn main() -> Result<(), Error> {
log::info!(target: LOG_TARGET, "Connected to chain: {}", chain); log::info!(target: LOG_TARGET, "Connected to chain: {}", chain);
epm::update_metadata_constants(client.chain_api())?; epm::update_metadata_constants(client.chain_api())?;
SHARED_CLIENT.set(client.clone()).expect("shared client only set once; qed"); SHARED_CLIENT
.set(client.clone())
.expect("shared client only set once; qed");
// Start a new tokio tasl to perform the runtime updates in the backgound. // Start a new tokio tasl to perform the runtime updates in the backgound.
// If this fails then the miner will be stopped and has to be re-started. // If this fails then the miner will be stopped and has to be re-started.
@ -203,7 +207,7 @@ async fn runtime_upgrade_task(client: ChainClient, tx: oneshot::Sender<Error>) {
Err(e) => { Err(e) => {
let _ = tx.send(e.into()); let _ = tx.send(e.into());
return; return;
}, }
}; };
loop { loop {
@ -218,10 +222,10 @@ async fn runtime_upgrade_task(client: ChainClient, tx: oneshot::Sender<Error>) {
Err(e) => { Err(e) => {
let _ = tx.send(e.into()); let _ = tx.send(e.into());
return; return;
}, }
}; };
continue; continue;
}, }
}; };
let version = update.runtime_version().spec_version; let version = update.runtime_version().spec_version;
@ -233,10 +237,10 @@ async fn runtime_upgrade_task(client: ChainClient, tx: oneshot::Sender<Error>) {
} }
prometheus::on_runtime_upgrade(); prometheus::on_runtime_upgrade();
log::info!(target: LOG_TARGET, "upgrade to version: {} successful", version); log::info!(target: LOG_TARGET, "upgrade to version: {} successful", version);
}, }
Err(e) => { Err(e) => {
log::debug!(target: LOG_TARGET, "upgrade to version: {} failed: {:?}", version, e); log::debug!(target: LOG_TARGET, "upgrade to version: {} failed: {:?}", version, e);
}, }
} }
} }
} }
@ -262,7 +266,8 @@ mod tests {
"--delay", "--delay",
"12", "12",
"seq-phragmen", "seq-phragmen",
]).unwrap(); ])
.unwrap();
assert_eq!( assert_eq!(
opt, opt,
@ -293,7 +298,8 @@ mod tests {
"--seed-or-path", "--seed-or-path",
"//Alice", "//Alice",
"prag-mms", "prag-mms",
]).unwrap(); ])
.unwrap();
assert_eq!( assert_eq!(
opt, opt,
@ -323,7 +329,8 @@ mod tests {
"prag-mms", "prag-mms",
"--iterations", "--iterations",
"1337", "1337",
]).unwrap(); ])
.unwrap();
assert_eq!( assert_eq!(
opt, opt,

View File

@ -6,7 +6,7 @@ use sp_npos_elections::BalancingConfig;
use sp_runtime::DeserializeOwned; use sp_runtime::DeserializeOwned;
use std::{collections::HashMap, fmt, str::FromStr}; use std::{collections::HashMap, fmt, str::FromStr};
use subxt::backend::legacy::rpc_methods:: as subxt_rpc; use subxt::backend::legacy::rpc_methods as subxt_rpc;
#[derive(Debug, Clone, Parser)] #[derive(Debug, Clone, Parser)]
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
@ -18,7 +18,7 @@ pub enum Solver {
PhragMMS { PhragMMS {
#[clap(long, default_value = "10")] #[clap(long, default_value = "10")]
iterations: usize, iterations: usize,
} },
} }
frame_support::parameter_types! { frame_support::parameter_types! {
@ -30,7 +30,7 @@ frame_support::parameter_types! {
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub enum Chain { pub enum Chain {
Ghost, Ghost,
Casper Casper,
} }
impl fmt::Display for Chain { impl fmt::Display for Chain {
@ -64,8 +64,8 @@ impl TryFrom<subxt_rpc::RuntimeVersion> for Chain {
.get("specName") .get("specName")
.expect("RuntimeVersion must have specName; qed") .expect("RuntimeVersion must have specName; qed")
.clone(); .clone();
let mut chain = serde_json::from_value::<String>(json) let mut chain =
.expect("specName must be String; qed"); serde_json::from_value::<String>(json).expect("specName must be String; qed");
chain.make_ascii_lowercase(); chain.make_ascii_lowercase();
Chain::from_str(&chain) Chain::from_str(&chain)
} }
@ -96,8 +96,7 @@ impl From<subxt_rpc::RuntimeVersion> for RuntimeVersion {
} }
} }
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)] #[derive(Deserialize, Serialize, PartialEq, Debug, Clone, Debug)]
#[derive(Debug)]
pub struct RuntimeVersion { pub struct RuntimeVersion {
pub spec_name: String, pub spec_name: String,
pub impl_name: String, pub impl_name: String,

View File

@ -1,7 +1,7 @@
pub use pallet_election_provider_multi_phase::{Miner, MinerConfig}; pub use pallet_election_provider_multi_phase::{Miner, MinerConfig};
pub use subxt::ext::sp_core; pub use subxt::ext::sp_core;
pub use primitives::{AccountId, Header, Hash, Balance}; pub use primitives::{AccountId, Balance, Hash, Header};
// pub type AccountId = sp_runtime::AccountId32; // pub type AccountId = sp_runtime::AccountId32;
// pub type Header = subxt::config::substrate::SubstrateHeader<u32, subxt::config::substrate::BlakeTwo256>; // pub type Header = subxt::config::substrate::SubstrateHeader<u32, subxt::config::substrate::BlakeTwo256>;
@ -21,7 +21,8 @@ pub type RpcClient = subxt::backend::legacy::LegacyPrcMethods<subxt::SubstrateCo
pub type ChainClient = subxt::OnlineClient<subxt::SubstrateConfig>; pub type ChainClient = subxt::OnlineClient<subxt::SubstrateConfig>;
pub type Config = subxt::SubstrateConfig; pub type Config = subxt::SubstrateConfig;
pub type SignedSubmission<S> = pallet_election_provider_multi_phase::SignedSubmission<AccountId, Balance, S>; pub type SignedSubmission<S> =
pallet_election_provider_multi_phase::SignedSubmission<AccountId, Balance, S>;
#[subxt::subxt( #[subxt::subxt(
runtime_metadata_path = "artifacts/metadata.scale", runtime_metadata_path = "artifacts/metadata.scale",

View File

@ -21,9 +21,15 @@ async fn serve_req(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
.header(CONTENT_TYPE, encoder.format_type()) .header(CONTENT_TYPE, encoder.format_type())
.body(Body::from(buffer)) .body(Body::from(buffer))
.unwrap() .unwrap()
}, }
(&Method::GET, "/") => Response::builder().status(200).body(Body::from("")).unwrap(), (&Method::GET, "/") => Response::builder()
_ => Response::builder().status(404).body(Body::from("")).unwrap(), .status(200)
.body(Body::from(""))
.unwrap(),
_ => Response::builder()
.status(404)
.body(Body::from(""))
.unwrap(),
}; };
Ok(response) Ok(response)
@ -75,35 +81,40 @@ mod hidden {
register_counter!(opts!( register_counter!(opts!(
"staking_miner_trim_started", "staking_miner_trim_started",
"Number of started trimmed solutions", "Number of started trimmed solutions",
)).unwrap() ))
.unwrap()
}); });
static TRIMMED_SOLUTION_SUCCESS: Lazy<Counter> = Lazy::new(|| { static TRIMMED_SOLUTION_SUCCESS: Lazy<Counter> = Lazy::new(|| {
register_counter!(opts!( register_counter!(opts!(
"staking_miner_trim_success", "staking_miner_trim_success",
"Number of successful trimmed solutions", "Number of successful trimmed solutions",
)).unwrap() ))
.unwrap()
}); });
static SUBMISSIONS_STARTED: Lazy<Counter> = Lazy::new(|| { static SUBMISSIONS_STARTED: Lazy<Counter> = Lazy::new(|| {
register_counter!(opts!( register_counter!(opts!(
"staking_miner_submissions_started", "staking_miner_submissions_started",
"Number of submissions started", "Number of submissions started",
)).unwrap() ))
.unwrap()
}); });
static SUBMISSIONS_SUCCESS: Lazy<Counter> = Lazy::new(|| { static SUBMISSIONS_SUCCESS: Lazy<Counter> = Lazy::new(|| {
register_counter!(opts!( register_counter!(opts!(
"staking_miner_submissions_success", "staking_miner_submissions_success",
"Number of submissions finished successfully", "Number of submissions finished successfully",
)).unwrap() ))
.unwrap()
}); });
static MINED_SOLUTION_DURATION: Lazy<Gauge> = Lazy::new(|| { static MINED_SOLUTION_DURATION: Lazy<Gauge> = Lazy::new(|| {
register_counter!(opts!( register_counter!(opts!(
"staking_miner_mining_duration_ms", "staking_miner_mining_duration_ms",
"The mined solution time in milliseconds.", "The mined solution time in milliseconds.",
)).unwrap() ))
.unwrap()
}); });
static SUBMIT_SOLUTION_AND_WATCH_DURATION: Lazy<Gauge> = Lazy::new(|| { static SUBMIT_SOLUTION_AND_WATCH_DURATION: Lazy<Gauge> = Lazy::new(|| {
@ -117,49 +128,56 @@ mod hidden {
register_counter!(opts!( register_counter!(opts!(
"staking_miner_balance", "staking_miner_balance",
"The balance of the staking miner account", "The balance of the staking miner account",
)).unwrap() ))
.unwrap()
}); });
static SCORE_MINIMAL_STAKE: Lazy<Gauge> = Lazy::new(|| { static SCORE_MINIMAL_STAKE: Lazy<Gauge> = Lazy::new(|| {
register_counter!(opts!( register_counter!(opts!(
"staking_miner_score_minimal_stake", "staking_miner_score_minimal_stake",
"The minimal winner, in terms of total backing stake", "The minimal winner, in terms of total backing stake",
)).unwrap() ))
.unwrap()
}); });
static SCORE_SUM_STAKE: Lazy<Gauge> = Lazy::new(|| { static SCORE_SUM_STAKE: Lazy<Gauge> = Lazy::new(|| {
register_counter!(opts!( register_counter!(opts!(
"staking_miner_score_sum_stake", "staking_miner_score_sum_stake",
"The sum of the total backing of all winners", "The sum of the total backing of all winners",
)).unwrap() ))
.unwrap()
}); });
static SCORE_SUM_STAKE_SQUARED: Lazy<Gauge> = Lazy::new(|| { static SCORE_SUM_STAKE_SQUARED: Lazy<Gauge> = Lazy::new(|| {
register_counter!(opts!( register_counter!(opts!(
"staking_miner_score_sum_stake_squared", "staking_miner_score_sum_stake_squared",
"The sum of the total backing of all winners, aka. the variance.", "The sum of the total backing of all winners, aka. the variance.",
)).unwrap() ))
.unwrap()
}); });
static RUNTIME_UPGRADES: Lazy<Counter> = Lazy::new(|| { static RUNTIME_UPGRADES: Lazy<Counter> = Lazy::new(|| {
register_counter!(opts!( register_counter!(opts!(
"staking_miner_runtime", "staking_miner_runtime",
"Number of runtime upgrades performed", "Number of runtime upgrades performed",
)).unwrap() ))
.unwrap()
}); });
static SUBMISSION_LENGTH: Lazy<Gauge> = Lazy::new(|| { static SUBMISSION_LENGTH: Lazy<Gauge> = Lazy::new(|| {
register_counter!(opts!( register_counter!(opts!(
"staking_miner_solution_length_bytes", "staking_miner_solution_length_bytes",
"Number of bytes in the solution submitted", "Number of bytes in the solution submitted",
)).unwrap() ))
.unwrap()
}); });
static SUBMISSION_WEIGHT: Lazy<Gauge> = Lazy::new(|| { static SUBMISSION_WEIGHT: Lazy<Gauge> = Lazy::new(|| {
register_counter!(opts!( register_counter!(opts!(
"staking_miner_solution_weight", "staking_miner_solution_weight",
"Weight of the solution submitted", "Weight of the solution submitted",
)).unwrap() ))
.unwrap()
}); });
pub fn on_runtime_upgrade() { pub fn on_runtime_upgrade() {

View File

@ -16,7 +16,10 @@ impl std::fmt::Display for Signer {
impl Clone for Signer { impl Clone for Signer {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { pair: self.pair.clone(), signer: PairSigner::new(self.pair.clone()) } Self {
pair: self.pair.clone(),
signer: PairSigner::new(self.pair.clone()),
}
} }
} }

View File

@ -46,7 +46,10 @@ mod max_weight {
impl MaxWeight { impl MaxWeight {
pub fn get() -> Weight { pub fn get() -> Weight {
Weight::from_parts(REF_TIME.load(Ordering::SeqCst), PROOF_SIZE.load(Ordering::SeqCst)) Weight::from_parts(
REF_TIME.load(Ordering::SeqCst),
PROOF_SIZE.load(Ordering::SeqCst),
)
} }
} }
@ -84,7 +87,7 @@ pub mod ghost {
#[derive(Debug)] #[derive(Debug)]
pub struct MinerConfig; pub struct MinerConfig;
impla pallet_election_provider_multi_phase::unsigned::MinerConfig for MinerConfig { impl pallet_election_provider_multi_phase::unsigned::MinerConfig for MinerConfig {
type AccountId = AccountId; type AccountId = AccountId;
type MaxLength = MaxLength; type MaxLength = MaxLength;
type MaxWeight = MaxWeight; type MaxWeight = MaxWeight;
@ -100,18 +103,23 @@ pub mod ghost {
) -> Weight { ) -> Weight {
let Some(votes) = epm::mock_votes( let Some(votes) = epm::mock_votes(
active_voters, active_voters,
desired_targets.try_into().expect("Desired targets < u16::MAX"), desired_targets
.try_into()
.expect("Desired targets < u16::MAX"),
) else { ) else {
return Weight::MAX; return Weight::MAX;
}; };
let raw = RawSolution { let raw = RawSolution {
solution: NposSolution16 { votes1: votes, ..Default::default() }, solution: NposSolution16 {
votes1: votes,
..Default::default()
},
..Default::default() ..Default::default()
}; };
if raw.solution.voter_count() != active_voters as usize || if raw.solution.voter_count() != active_voters as usize
raw.solution.unique_targets().len() != desired_targets as usize || raw.solution.unique_targets().len() != desired_targets as usize
{ {
return Weight::MAX; return Weight::MAX;
} }
@ -119,7 +127,8 @@ pub mod ghost {
futures::executor::block_on(epm::runtime_api_solution_weight( futures::executor::block_on(epm::runtime_api_solution_weight(
raw, raw,
SolutionOrSnapshotSize { voters, targets }, SolutionOrSnapshotSize { voters, targets },
)).expect("solution_weight should work") ))
.expect("solution_weight should work")
} }
} }
} }
@ -139,7 +148,7 @@ pub mod casper {
#[derive(Debug)] #[derive(Debug)]
pub struct MinerConfig; pub struct MinerConfig;
impla pallet_election_provider_multi_phase::unsigned::MinerConfig for MinerConfig { impl pallet_election_provider_multi_phase::unsigned::MinerConfig for MinerConfig {
type AccountId = AccountId; type AccountId = AccountId;
type MaxLength = MaxLength; type MaxLength = MaxLength;
type MaxWeight = MaxWeight; type MaxWeight = MaxWeight;
@ -155,18 +164,23 @@ pub mod casper {
) -> Weight { ) -> Weight {
let Some(votes) = epm::mock_votes( let Some(votes) = epm::mock_votes(
active_voters, active_voters,
desired_targets.try_into().expect("Desired targets < u16::MAX"), desired_targets
.try_into()
.expect("Desired targets < u16::MAX"),
) else { ) else {
return Weight::MAX; return Weight::MAX;
}; };
let raw = RawSolution { let raw = RawSolution {
solution: NposSolution16 { votes1: votes, ..Default::default() }, solution: NposSolution16 {
votes1: votes,
..Default::default()
},
..Default::default() ..Default::default()
}; };
if raw.solution.voter_count() != active_voters as usize || if raw.solution.voter_count() != active_voters as usize
raw.solution.unique_targets().len() != desired_targets as usize || raw.solution.unique_targets().len() != desired_targets as usize
{ {
return Weight::MAX; return Weight::MAX;
} }
@ -174,7 +188,8 @@ pub mod casper {
futures::executor::block_on(epm::runtime_api_solution_weight( futures::executor::block_on(epm::runtime_api_solution_weight(
raw, raw,
SolutionOrSnapshotSize { voters, targets }, SolutionOrSnapshotSize { voters, targets },
)).expect("solution_weight should work") ))
.expect("solution_weight should work")
} }
} }
} }