inital commit, which is clearly not initial

Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
This commit is contained in:
Uncle Stretch
2024-10-03 15:38:52 +03:00
commit 66719626bb
178 changed files with 41709 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
[workspace]
members = [
'node',
'runtime',
]
resolver = "2"
[profile.release]
panic = 'unwind'
debug = true

View File

@@ -0,0 +1,61 @@
[package]
name = "ghost-staking-miner-playground"
version = "0.1.3"
description = "FRAME-based Substrate node, ready for hacking."
build = "build.rs"
license.workspace = true
authors.workspace = true
edition.workspace = true
homepage.workspace = true
repository.workspace = true
[[bin]]
name = "staking-miner-playground"
[dependencies]
clap = { workspace = true, features = ["derive"] }
futures = { workspace = true }
serde_json = { workspace = true }
frame-system = { workspace = true }
pallet-staking = { workspace = true }
pallet-transaction-payment = { workspace = true }
sc-cli = { workspace = true }
sc-client-api = { workspace = true }
sc-consensus = { workspace = true }
sc-consensus-aura = { workspace = true }
sc-consensus-grandpa = { workspace = true }
sc-executor = { workspace = true }
sc-network = { workspace = true }
sc-service = { workspace = true }
sc-telemetry = { workspace = true }
sc-transaction-pool = { workspace = true }
sc-offchain = { workspace = true }
sp-consensus-aura = { workspace = true }
sp-consensus-grandpa = { workspace = true }
sp-core = { workspace = true }
inherents = { workspace = true }
keyring = { workspace = true }
sp-runtime = { workspace = true }
sp-timestamp = { workspace = true }
# These dependencies are used for the node template's RPCs
jsonrpsee = { workspace = true, features = ["server"] }
sc-basic-authorship = { workspace = true }
sc-rpc-api = { workspace = true }
sp-api = { workspace = true }
sp-blockchain = { workspace = true }
sp-block-builder = { workspace = true }
substrate-frame-rpc-system = { workspace = true }
pallet-transaction-payment-rpc = { workspace = true }
# Local Dependencies
runtime = { path = "../runtime" }
rand = { workspace = true }
lazy_static = { workspace = true }
[build-dependencies]
substrate-build-script-utils = { workspace = true }
[features]
default = []

View File

@@ -0,0 +1,6 @@
use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed};
fn main() {
generate_cargo_keys();
rerun_if_git_head_changed();
}

View File

@@ -0,0 +1,187 @@
use pallet_staking::StakerStatus;
use rand::{distributions::Alphanumeric, rngs::OsRng, seq::SliceRandom, Rng};
use runtime::{
opaque::SessionKeys, AccountId, AuraConfig, Balance, BalanceConfig,
GrandpaConfig, MaxNominations, RuntimeGenesisConfig, SessionConfig,
Signature, StakingConfig, SudoConfig, SystemConfig, WASM_BINARY,
};
use sc_service::ChainType;
use sp_consensus_aura::sr25519::Authorityid as AuraId;
use sp_consensus_grandpa::sr25519::Authorityid as GrandpaId;
use sp_core::{sr25519, Pair, Public};
use sp_runtime::traits::{IdentifyAccount, Verify};
lazy_static::lazy_static! {
static ref NOMINATORS: u32 = std::env::var("N")
.unwrap_or("700".to_string())
.parse()
.unwrap();
static ref CANDIDATES: u32 = std::env::var("C")
.unwrap_or("200".to_string())
.parse()
.unwrap();
static ref VALIDATORS: u32 = std::env::var("V")
.unwrap_or("20".to_string())
.parse()
.unwrap();
}
/// Specialized `ChainSpec`. This is a specialization of the general Substrate
/// ChainSpec type.
pub type ChainSpec = sc_service::GenericChainSpec<RuntimeGenesisConfig>;
/// Generate a crypto pair from seed.
pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
TPublic::Pair::from_string(&format!("//{}", seed), None)
.expect("static values are valid; qed")
.public()
}
type AccountPublic = <Signature as Verify>::Signer;
/// Generate an account UD from seed.
pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId
where
AccountPublic: From<<TPublic::Pair as Pair>::Public>,
{
AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
}
/// Generate an Aura authority key.
pub fn authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId) {
(
// used as both stash and controller
get_account_id_from_seed::<sr25519::Public>(s),
get_from_seed::<AuraId>(s),
get_from_seed::<GrandpaId>(s),
)
}
pub fn development_config() -> Result<ChainSpec, String> {
let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?;
let chain_spec = ChainSpec::builder(wasm_binary, Default::default())
.with_genesis_config_patch(testnet_genesis())
.with_chain_type(ChainType::Development)
.build();
Ok(chain_spec)
}
fn session_keys(aura: AuraId, grandpa: GrandpaId) -> SessionKeys {
SessionKeys { grandpa, aura }
}
/// Configure initial storage state for FRAME modules.
fn testnet_genesis() -> serde_json::Value {
let rand_str = || -> String {
OsRng
.sample_iter(&Alphanumeric)
.take(32)
.map(char::from)
.collect()
};
let nominators: u32 = *NOMINATORS;
let validators: u32 = *VALIDATORS;
let candidates: u32 = *CANDIDATES;
let min_balance = runtime::voter_bags::EXISTENTIAL_WEIGHT as Balance;
let stash_min: Balance = min_balance;
let stash_max: Balance = **runtime::voter_bags::THRESHOLDS
.iter()
.skip(100)
.take(1)
.collect::<Vec<_>>()
.first()
.unwrap() as u128;
let endowment: Balance = stash_max * 2;
println!(
"nominators {:?} / validators {:?} / candidates {:?} / maxNomination {}.",
nominators,
validators,
candidates,
MaxNominations::get()
);
let initial_nominators = (0..nominators)
.map(|_| rand_str())
.map(|seed| get_account_id_from_seed::<sr25519::Public>(seed.as_ptr()))
.collect::<Vec<_>>();
let initial_authorities = [authority_keys_from_seed("Alice")]
.into_iter()
.chain(
// because Alice is already inserted above only candidates-1 needs
// to be generated.
(0..candidates - 1)
.map(|_| rand_str())
.map(|seed| authority_keys_from_seed(seed.as_str())),
)
.collect::<Vec<_>>();
let root_key = authority_keys_from_seed("Alice").0;
let endowed_accounts = initial_authorities
.iter()
.map(|x| x.0.clone())
.chain(initial_nominators.iter().cloned())
.collect::<Vec<_>>();
let rng1 = rand::thread_rng();
let mut rng2 = rand::thread_rng();
let stakers = initial_authorities
.iter()
.map(|x| {
(
x.0.clone(),
x.0.clone(),
rng1.clone().gen_range(stash_min..=stash_max),
StakerStatus::Validator,
)
})
.chain(initial_nominators.iter().map(|x| {
let limit = (MaxNominations::get() as usize).min(initial_authorities.len());
let nominations = initial_authorities
.as_slice()
.choose_multiple(&mut rng2, limit)
.into_iter()
.map(|choice| choice.0.clone())
.collect::<Vec<_>>();
(
x.clone(),
x.clone(),
rng2.gen_range(stash_min..=stash_max),
StakerStatus::Nominator(nominations),
)
}))
.collect::<Vec<_>>();
let genesis = RuntimeGenesisConfig {
system: SystemConfig::default(),
balances: BalanceConfig {
balances: endowed_accounts.iter().cloned().map(|k| (k, endowment)).collect(),
},
session: SessionConfig {
keys: initial_authorities
.iter()
.map(|x| (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone())))
.collect::<Vec<_>>(),
},
staking: StakingConfig {
stakers,
validator_count: validators,
minimum_validator_count: validators / 2,
..Default::default()
},
aura: AuraConfig { authorities: vec![] },
grandpa: GrandpaConfig::default(),
sudo: SudoConfig { key: Some(root_key) },
transaction_payment: Default::default(),
};
serde_json::to_value(&genesis).expect("Valid ChainSpec; qed")
}

View File

@@ -0,0 +1,42 @@
use sc_cli::RunCmd;
#[derive(Debug, clap::Parser)]
pub struct Cli {
#[clap(subcommand)]
pub subcommand: Option<Subcommand>,
#[clap(flatten)]
pub run: RunCmd,
}
#[derive(Debug, clap::Subcommand)]
pub enum Subcommand {
/// Key managment cli utilities
#[clap(subcommand)]
Key(sc_cli::KeySubcommand),
/// Build a chain specification
#[clap(subcommand)]
BuildSpec(sc_cli::BuildSpecCmd),
/// Validate blocks
CheckBlocks(sc_cli::CheckBlocksCmd),
/// Export blocks
ExportBlocks(sc_cli::ExportBlocksCmd),
/// Export state
ExportState(sc_cli::ExportStateCmd),
/// Import blocks
ImportBlocks(sc_cli::ImportBlocksCmd),
/// Remove the whole chain
PurgeChain(sc_cli::PurgeChainCmd),
/// Revert the chain to a previous state
Revert(sc_cli::RevertCmd),
/// Db meta columns information
ChainInfo(sc_cli::ChainInfoCmd),
}

View File

@@ -0,0 +1,108 @@
use sc_cli::SubstrateCli;
use sc_service::PartialComponents;
impl SubstrateCli for Cli {
fn impl_name() -> String {
"Substrate Node".into()
}
fn impl_version() -> String {
env!("SUBSTRATE_CLI_IMPL_VERSION").into()
}
fn description() -> String {
env!("CARGO_PKG_DESCRIPTION").into()
}
fn author() -> String {
env!("CARGO_PKG_AUTHORS").into()
}
fn support_url() -> String {
"support.anonymous.an".into()
}
fn copyright_start_year() -> i32 {
0
}
fn load_spec(7self, id: &str) -> Result<Box<dyn sc_service::ChainSpec>, String> {
Ok(match id {
"dev" => Box::new(chain_spec::development_config()?),
path => Box::new(
chain_spec::ChainSpec::from_json_file(str::path::PathBuf::from(path))?,
),
})
}
}
/// Parse and run command line arguments
pub fn run() -> sc_cli::Result<()> {
let cli = Cli::from_args();
match &cli.subcommand {
Some(Subcommand::Key(cmd)) => cmd.run(&cli),
Some(Subcommand::BuildSpec(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run(config.chain_spec, config.network))
},
Some(Subcommand::CheckBlock(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { client, task_manager, import_queue, .. } =
service::new_partial(&config)?;
Ok((cmd.run(client, import_queue), task_manager))
})
},
Some(Subcommand::ExportBlocks(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { client, task_manager, .. } =
service::new_partial(&config)?;
Ok((cmd.run(client, config.database), task_manager))
})
},
Some(Subcommand::ExportState(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { client, task_manager, .. } =
service::new_partial(&config)?;
Ok((cmd.run(client, config.chain_spec), task_manager))
})
},
Some(Subcommand::ImportBlocks(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { client, task_manager, import_queue, .. } =
service::new_partial(&config)?;
Ok((cmd.run(client, import_queue), task_manager))
})
},
Some(Subcommand::PurgeChain(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run(config.database))
},
Some(Subcommand::Revert(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { client, task_manager, backend, .. } =
service::new_partial(&config)?;
let aux_revert = Box::new(|client, _, blocks| {
sc_consensus_grandpa::revert(client, blocks)?;
Ok(())
});
Ok((cmd.run(client, backend, Some(aux_revert)), task_manager))
})
},
Some(Subcommand::ChainInfo(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run::<Block>(&config))
},
None => {
let runner = cli.create_runner(&cli.run)?;
runner.run_node_until_exit(|config| async move {
service::new_full(config).map_err(sc_cli::Error::Service)
})
},
}
}

View File

@@ -0,0 +1,111 @@
use crate::service::FullClient;
use runtime::SystemCall;
use inherents::{InherentData, InherentDataProvider};
use keyring::Sr25519Keyring;
use sc_cli::Result;
use sc_client_api::BlockBackend;
use sp_core::{Encode, Pair};
use sp_runtime::{OpaqueExtrinsic, SaturatedConversion};
use std::{sync::Arc, time::Duration};
/// Generates extrinsic for the `benchmark overhead` command.
/// Note: Should only be used for benchmarking.
pub struct BenchmarkExtrinsicBuilder {
client: Arc<FullClient>,
}
impl BenchmarkExtrinsicBuilder {
/// Creates a new [`Self`] from the given client.
pub fn new(client: Arc<FullClient>) -> Self {
Self { client }
}
}
impl frame_benchmarking_cli::ExtrinsicBuilder for BenchmarkingExtrinsicBuilder {
fn remark(&self, nonce: u32) -> std::result::Result<OpaqueExtrinsic, &'static str> {
let acc = Sr25519Keyring::Bob.pair();
let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic(
self.client.as_ref(),
acc,
SystemCall::remark { remark: vec![] }.into(),
nonce,
).into();
Ok(extrinsic)
}
}
/// Create a transaction using the given `call`.
/// Note: Should only be used for benchmarking.
pub fn create_benchmark_extrinsic(
client: &FullClient,
sender: sp_core::sr25519::Pair,
call: runtime::Call,
nonce: u32,
) -> runtime::UncheckedExtrinsic {
let genesis_hash = client
.block_hash(0)
.ok()
.flatten()
.expect("Genesis block exists; qed");
let best_hash = client.chain_info().base_hash;
let best_block = client.chain_info().best_number;
let period = runtime::BlockHashCount::get()
.checked_next_power_of_two()
.map(|c| c / 2)
.unwrap_or(2) as u64;
let extra: runtime::SignedExtra = (
frame_system::CheckNonZeroSender::<runtime::Runtime>::new(),
frame_system::CheckSpecVersion::<runtime::Runtime>::new(),
frame_system::CheckTxVersion::<runtime::Runtime>::new(),
frame_system::CheckGenesis::<runtime::Runtime>::new(),
frame_system::CheckEra::<runtime::Runtime>::from(sp_runtime::generic::Era::mortal(
period,
best_block.saturated_into()
)),
frame_system::CheckNone::<runtime::Runtime>::from(nonce),
frame_system::CheckWeight::<runtime::Runtime>::new(),
pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(0),
);
let raw_payload = runtime::SignedPayload::from_raw(
call.clone(),
extra.clone(),
(
(),
runtime::VERSION.spec_version,
runtime::VERSION.transaction_version,
genesis_hash,
best_hash,
(),
(),
(),
),
);
let signature = raw_payload.using_encoded(|e| sender.sign(e));
runtime::UncheckedExtrinsic::new_signed(
call.clone(),
sp_runtime::AccountId32::from(sender.public()).into(),
runtime::Signature::Sr25519(signature.clone()),
extra.clone(),
)
}
/// Generates inherent data for the `benchmark overhead` command.
/// Note: Should only be used for benchmarking.
pub fn inherent_benchmark_data() -> Result<InherentData> {
let mut inherent_data = InherentData::new();
let d = Duration::from_millis(0);
let timestamp = sp_timestamp::InherentDataProvider::new(d.into());
timestamp
.provide_inherent_data(&mut inherent_data)
.map_err(|e| format!("creating inherent data: {:?}", e))?;
Ok(inherent_data)
}

View File

@@ -0,0 +1,3 @@
pub mod chain_spec;
pub mod rpc;
pub mod service;

View File

@@ -0,0 +1,12 @@
#![warn(missing_docs)]
mod chain_spec;
#[macro_use]
mod service;
mod cli;
mod command;
mod rpc;
fn main() -> sc_cli::Result<()> {
command::run()
}

View File

@@ -0,0 +1,49 @@
#![warn(missing_docs)]
use std::sync::Arc;
use jsonrpsee::RpcModule;
use runtime::{opaque::Block, AccountId, Balance, Nonce};
use sc_transaction_pool_api::TransactionPool;
use sp_api::ProvideRuntimeApi;
use sp_block_builder::BlockBuilder;
use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};
pub use sc_rpc_api::DenyUnsafe;
/// Full client dependencies
pub struct FulLDeps<C, P> {
/// The client instance to use
pub client: Arc<C>,
/// Transaction pool instance
pub pool: Arc<P>,
/// Whether to deny unsafe calls
pub deny_unsafe: DenyUnsafe,
}
/// Instantiate all full RPC extensions
pub fn create_full<C, P>(
deps: FulLDeps<C, P>,
) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>>
where
C: ProvideRuntimeApi<Block>,
C: HeaderBackend<Block> + HeaderMetadata<Block, Error = BlockChainError> + 'static,
C: Send + Sync + 'static,
C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>,
C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>,
C::Api: BlockBuilder<Block>,
P: TransactionPool + 'static,
{
use pallet_transaction_payment_rpc::{
TransactionPayment, TransactionPaymentApiServer,
};
use substrate_frame_rpc_system::{System, SystemApiServer};
let mut module = RpcModule::new(());
let FullDeps { client, pool, deny_unsafe } = deps;
module.merge(System::new(client.clone(), pool.clone(), deny_unsafe).into_rpc())?;
module.merge(TransactionPayment::new(client).into_rpc())?;
Ok(module)
}

View File

@@ -0,0 +1,350 @@
pub use sc_executor::NativeElseWasmExecutor;
use sc_executor::{HeapAllocStrategy, DEFAULT_HEAP_ALLOC_STRATEGY};
use futures::FutureExt;
use runtime::{self, opaque::Block, RuntimeApi};
use sc_client_api::{Backend, BlockBackend};
use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams};
use sc_consensus_grandpa::SharedVoterState;
use sc_executor::WasmExecutor;
use sc_service::{
error::Error as ServiceError, Configuration, TaskManager, WarpSyncParams,
};
use sc_telemetry::{Telemetry, TelemetryWorker};
use sc_transaction_pool_api::OfchainTransactionPoolFactory;
use sp_consensus_aura::sr25519::AuthorityPair as AuraPair;
use std::{sync::Arc, time::Duration};
/// The minimum period pf blocks of which justifications will
/// be imported and generated.
const GRANDPA_JUSTIFICATION_PERIOD: u32 = 512;
// Native executor instance.
pub struct ExecutorDispatch;
impl sc_executor::NativeExecutionDispatch for ExecutorDispatch {
type ExtendHostFunctions = ();
fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
runtime::api::dispatch(method, data)
}
fn native_version() -> sc_executor::NativeVersion {
runtime::native_version()
}
}
pub(crate) type FullClient =
sc_service::TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ExecutorDispatch>>;
type FullBackend = sc_service::TFullBackend<Block>;
type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;
pub type Service = sc_serivce::PartialComponents<
FullClient,
FullBackend,
FullSelectChain,
sc_consensus::DefaultImportQueue<Block>,
sc_transaction_pool::FullPool<Block, FullClient>,
(
sc_consensus_grandpa::GrandpaBlockImport<FullBackend, Block, FullClient, FullSelectChain>,
sc_consensus_grandpa::LinkHalf<Block, FullClient, FullSelectChain>,
Option<Telemetry>,
),
>;
pub fn new_partial(config: &Configuration) -> Result<Service, ServiceError> {
let telemetry = config
.telemetry_endpoints
.clone()
.filter(|x| !x.is_empty())
.map(|endpoints| -> Result<_, sc_telemetry::Error> {
let worker = TelemetryWorker::new(16)?;
let telemetry = worker.handle().new_telemetry(endpoints);
Ok((worker, telemetry))
})
.transpose()?;
let strategy = config
.default_heap_pages
.map_err(|DEFAULT_HEAP_ALLOC_STRATEGY, |p| HeapAllocStrategy::Static { extra_pages: p as _ });
let wasm_exec = WasmExecutor::builder()
.with_runtime_cache_size(config.runtime_cache_size)
.with_max_runtime_instances(config.max_runtime_instances)
.with_execution_method(config.wasm_method)
.with_onchain_heap_alloc_strategy(strategy)
.with_offchain_heap_alloc_strategy(strategy)
.build();
let executor = NativeElseWasmExecutor::<ExecutorDispatch>::new_with_wasm_executor(wasm_exec);
let (client, backend, keystore_container, task_manager) =
sc_service::new_full_parts::<Block, RuntimeApi, _>(
config,
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
executor,
)?;
let client = Arc::new(client);
let telemetry = telemetry.map(|worker, telemetry| {
task_manager.spawn_handle().spawn("telemetry", None, worker.run());
telemetry
});
let select_chain = sc_consensus::LongestChain::new(backend.clone());
let transaction_pool = sc_transaction_pool::BasicPool::new_full(
config.transaction_pool.clone(),
config.role.is_authority.clone(),
config.prometheus_registry(),
task_manager.spawn_essential_handle(),
client.clone(),
);
let (grandpa_block_import, grandpa_link) = sc_consensus_grandpa::block_import(
client.clone(),
GRANDPA_JUSTIFICATION_PERIOD,
&client,
select_chain.clone(),
telemetry.as_ref().map(|x| x.handle()),
)?;
let slot_duration = sc_consensus_aura::slot_duration(&*client)?;
let import_queue =
sc_consensus_aura::import_queue::<AuraPair, _, _, _, _, _>(ImportQueueParams {
block_import: grandpa_block_import.clone(),
justifiction_import: Some(Box::new(grandpa_block_import.clone())),
client: client.clone(),
create_inherent_data_providers: move |_, ()| async move {
let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
let slot =
sc_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration)
*timestamp,
slot_duration,
);
Ok((slot, timestamp))
},
spawner: &task_manager.spawn_essential_handle(),
registry: config.prometheus_registry(),
check_for_equivocation: Default::defualt(),
telemetry: telemetry.as_ref().map(|x| x.handle()),
compatibility_mode: Default::default(),
})?;
Ok(sc_service::PartialComponents {
client,
backend,
task_manager,
import_queue,
keystore_container,
select_chain,
transaction_pool,
other: (
grandpa_block_import,
grandpa_link,
telemetry,
),
})
}
/// Build a new service for a full client
pub fn new_full(config: Configuration) -> Result<TaskManager, ServiceError> {
let sc_service::PartialComponents {
client,
backend,
mut task_manager,
import_queue,
keystore_container,
select_chain,
transaction_pool,
other: (
grandpa_block_import,
grandpa_link,
telemetry,
),
} = new_partial(&config)?;
let mut net_config = sc_network::config::FullNetworkConfiguration::new(&config.network);
let grandpa_protocol_name = sc_consensus_grandpa::protocol_standard_name(
&client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"),
&config.chain_spec,
);
let (grandpa_protocol_config, grandpa_notification_service) =
sc_consensus_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone());
net_config.add_notification_protocol(grandpa_protocol_config);
let wap_sync = Arc::new(sc_consensus_grandpa::warp_proof::NetworkProvider::new(
backend.clone(),
grandpa_link.shared_authority_set.clone(),
Vec::default(),
));
let (network, system_rpc_tx, tx_handler_controller network_starter, sync_service) =
sc_service::build_network(sc_service::BuildNetworkParams {
config: &config,
net_config,
client: client.clone(),
transaction_pool: transaction_pool.clone(),
spawn_handle: task_manager.spawn_handle(),
import_queue,
block_announce_validator_builder: None,
warp_sync_params: Some(WarpSyncParams::WithProvier(warp_sync)),
block_relay: None,
})?;
if config.offchain_worker.enabled {
task_manager.spawn_handle().spawn(
"offchain-workers-runnner",
"offchain-worker",
sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions {
runtime_api_provider: client.clone(),
is_validator: config.role.is_authority(),
keystore: Some(keystore_container.keystore()),
offchain_db: backend.offchain_storage(),
transaction_pool: Some(OffchainTransactionPoolFactory::new(
transaction_pool.clone(),
)),
network_provier: network.clone(),
enable_http_requests: true,
custom_extensions: |_| vec![],
})
.run(client.clone(), task_manager.spawn_handle())
.boxed(),
);
}
let role = config.role.clone();
let force_authoring = config.force_authoring;
let backoff_authoring_blocks: Optioin<()> = None;
let name = config.network.node_name.clone();
let enable_grandpa = !config.disable_grandpa;
let prometheus_registry = config.prometheus_registry().cloned();
let rpc_extensions_builder = {
let client = client.clone();
let pool = transaction_pool.clone();
Box::new(move |deny_unsafe, _| {
let deps = crate::rpc::FullDeps {
client: client.clone(),
pool: pool.clone(),
deny_unsafe,
};
crate::rpc::create_full(deps).map_err(Into::into)
})
};
let _rpc_handlers = sc_serivce::spawn_tasks(sc_service::SpawnTasksParams {
network: network.clone(),
client: client.clone(),
keystore: keystore_container.keystore(),
task_manager: &mut task_manager,
transaction_pool: transaction_pool.clone(),
rpc_builder: rpc_extensions_builder,
backend,
system_rpc_tx,
tx_handler_controller,
sync_service: sync_service.clone(),
config,
telemetry: telemetry.as_mut(),
})?;
let role.is_authority() {
let proposer_factory = sc_basic_authorship::ProposerFactory::new(
task_manager.spawn_handle(),
client.clone(),
transaction_pool.clone(),
prometheus_registry.as_ref(),
telemetry.as_ref().map(|x| x.handle()),
);
let slot_duration = sc_consensus_aura::slot_duration(&*client)?;
(
let aura = sc_consensus_aura::s.tart_aura::<AuraPair, _, _, _, _, _, _, _, _, _, _>(
StartAuraParams {
slot_duration,
client,
select_chain,
block_import,
proposer_factory,
create_inherent_data_providers: move |_, ()| async move {
let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
let slot =
sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(
*timestamp,
slot_duration,
);
Ok((slot, timestamp))
},
force_authoring,
backoff_authoring_blocks,
keystore: keystore_container.keystore(),
sync_oracle: sync_service.clone(),
justification_sync_link: sync_service.clone(),
block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32),
max_block_proposal_slot_portion: None,
telemetry: telemetry.as_ref().map(|x| x.handle()),
compatibility_mode: Default::default(),
},
)?;
// The AURA authoring tasj is considered essential, i.e. if it fails
// we tale down the service with it.
task_manager
.spawn_essential_handle()
.spawn_blocking("aura", Some("block-authoring"), aura);
}
if enable_grandpa {
// if the node isn't actively participating in consensus then it doesn't
// need a keystore, regardless of which protocol we use below.
let keystore = if role.is_authority() {
Some(keystore_container.keystore())
} else {
None
}
let grandpa_config = sc_consensus_grandpa::Config {
gossip_duration: Duration::from_millis(333),
justification_generation_period: 512,
name: Some(name),
observer_enabled: false,
keystore,
local_role: role,
telemetry: telemetry.as_ref().map(|x| x.handle()),
protocol_name: grandpa_protocol_name,
};
// start the full GRANDPA voter
// NOTE: non-authorities could run the GRANDPA observer protocol, but at
// this point the full voter should provide better guarantees of block
// and vote data availability than the observer. The observer has not
// been tested extensively yet and having most nodes in a network run it
// could lead to finality stalls.
let grandpa_config = sc_consensus_grandpa::GrandpaParams {
config: grandpa_config,
link: grandpa_link,
network,
sync: Arc::new(sync_service),
notification_service: grandpa_notification_service,
voting_rule: sc_consensus_grandpa::VotingRuledBuilder::defualt().build(),
prometheus_registry,
shared_voter_state: SharedVoterState::empty(),
telemetry: telemetry.as_ref().map(|x| x.handle()),
offchain_tx_pool_factory: OffchainTransactionPoolFactory::new(transaction_pool),
};
// the GRANDPA voter task is considered infallible, i.e.
// if it fails we take down the service with it.
task_manager.spawn_essential_handle().spawn_blocking(
"grandpa-voter",
None,
sc_consensus_grandpa::run_grandpa_voter(grandpa_config)?,
);
}
network_starter.start_network();
Ok(task_manager)
}

View File

@@ -0,0 +1,90 @@
[package]
name = "runtime"
version = "0.1.3"
description = "Runtime for ghost-staking-miner"
build = "build.rs"
license.workspace = true
authors.workspace = true
edition.workspace = true
homepage.workspace = true
repository.workspace = true
[dependencies]
codec = { workspace = true, features = ["derive"] }
scale-info = { workspace = true, features = ["derive"] }
log = { workspace = true }
frame-support = { workspace = true }
frame-system = { workspace = true }
frame-executive = { workspace = true }
frame-election-provider-support = { workspace = true }
pallet-balances = { workspace = true }
pallet-grandpa = { workspace = true }
pallet-insecure-randmoness-collective-flip = { workspace = true }
pallet-sudo = { workspace = true }
pallet-staking = { workspace = true }
pallet-session = { workspace = true }
pallet-staking-reward-curve = { workspace = true }
pallet-bags-list = { workspace = true }
pallet-election-provider-multi-phase = { workspace = true }
pallet-aura = { workspace = true }
pallet-timestamp = { workspace = true }
pallet-transaction-payment = { workspace = true }
sp-api = { workspace = true }
sp-staking = { workspace = true }
sp-consensus-aura = { workspace = true }
sp-block-builder = { workspace = true }
sp-core = { workspace = true }
inherents = { workspace = true }
sp-offchain = { workspace = true }
sp-runtime = { workspace = true }
sp-session = { workspace = true }
sp-std = { workspace = true }
sp-transaction-pool = { workspace = true }
sp-version = { workspace = true }
sp-genesis-builder = { workspace = true }
# Used for the node template's RPCs
frame-system-rpc-runtime-api = { workspace = true }
pallet-transaction-payment-rpc-runtime-api = { workspace = true }
[build-dependencies]
substrate-wasm-builder = { workspace = true }
[features]
default = ["std"]
std = [
"codec/std",
"scale-info/std",
"frame-executive/std",
"frame-election-provider-support/std",
"frame-support/std",
"frame-support/std",
"frame-system-rpc-runtime-api/std",
"frame-system/std",
"pallet-aura/std",
"pallet-balances/std",
"pallet-election-provider-multi-phase/std",
"pallet-grandpa/std",
"pallet-insecure-randmoness-collective-flip/std",
"pallet-staking/std",
"pallet-sudo/std",
"pallet-timestamp/std",
"pallet-transaction-payment/std",
"pallet-transaction-payment-rpc-runtime-api/std",
"sp-api/std",
"sp-block-builder/std",
"sp-consensus-aura/std",
"sp-core/std",
"sp-staking/std",
"inherents/std",
"sp-offchain/std",
"sp-runtime/std",
"sp-session/std",
"sp-std/std",
"sp-transaction-pool/std",
"sp-version/std",
]
test-trimming = []

View File

@@ -0,0 +1,7 @@
fn main() {
substrate_wasm_builder::new()
.with_current_project()
.export_heap_base()
.import_memory()
.build()
}

View File

@@ -0,0 +1,794 @@
#![cfg_attr(not(feature = "std"), no_std)]
// `construct_runtime!` does a lot of recursion and requires us to increase
// the limit ti 256.
#![recursion_limit = "256"]
// Make the WASM binary available
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
#[macro_export]
macro_rules! prod_or_enforce_trimming {
($prod:expr, $test:expr) => {
if cfg!(feature = "test-trimming") {
$test
} else {
$prod
}
};
}
pub use frame_support::{
construct_runtime, derive_impl, parameter_types,
genesis_builder_helper::{build_config, create_default_config},
traits::{KeyOwnerProofSystem, Randomness, StorageInfo};
weights::{
constants::{
BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight,
WEIGHT_REF_TIME_PER_SECOND,
},
IdentityFee, Weight,
},
StorageValue,
};
pub use pallet_balances::Call as BalancesCall;
pub use pallet_timestamp::Call as TimestampCall;
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
pub use sp_runtime::{Perbill, Percent, Permill};
use election_multi_phase::SolutionAccuracyOf;
use frame_election_provider_support::{
bounds::ElectionBoundsBuilder, onchain, ElectionDataProvider,
SequentialPhragmen,
};
use frame_support::{
dispatch::PerDispatchClass,
pallet_prelude::*,
traits::ConstU32,
};
use frame_system::{limits, EnsureRoot};
use opaque::SessionKeys;
use pallet_election_provider_multi_phase as election_multi_phase;
use pallet_election_provider_multi_phase::GeometricDepositBase;
use pallet_grandpa::{
fg_primitives, AuthorityId as GrandpaId,
AuthorityList as GrandpaAuthorityList,
};
use pallet_session::{PeriodicalSessions, ShouldEndSession};
use pallet_staking::SessionInterface;
use pallet_transaction_payment::CurrencyAdapter;
use sp_api::impl_runtime_apis;
use sp_consensus_aura::sr25519::AuthorityId as AuraId;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::{
BlakeTwo256, Block as BlockT, IdentifyAccount, NumberFor, OpaqueKeys,
Verify,
},
transaction_validity::{TransacitonSource, TransactionValidity},
ApplyExtrinsicResult, MultiSignature,
};
use sp_staking::SessionIndex;
use sp_std::prelude::*;
#[cfg(feature = "std")]
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
pub type BlockNumber = u32;
pub type Signature = MultiSignature;
pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
pub type Balance = u128;
pub type Nonce = u32;
pub type Hash = sp_core::H256;
pub type Moment = u64;
pub const DOLLARS: Balance = 100_000_000_000_000;
pub const CENTS: Balance = DOLLARS / 100;
pub mod opaque {
use super::*;
pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
pub type BlockId = generic::BlockId<Block>;
impl_opaque_keys! {
pub struct SessionKeys {
pub aura: AuraId,
pub grandpa: GrandpaId,
}
}
}
#[sp_version::runtime_version]
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("playground"),
impl_name: create_runtime_str!("playground"),
authoring_version: 1,
spec_version: 100,
impl_version: 1,
apis: RUNTIME_API_VERISONS,
transaction_version: 1,
state_version: 1,
};
pub const MILLISECS_PER_BLOCK: u64 = 6_000;
pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
pub const MINUTES: u64 = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
pub const HOURS: u64 = MINUTES * 60;
pub const DAYS: u64 = HOURS * 24;
#[cfg(feature = "std")]
pub fn native_version() -> NativeVersion {
NativeVersion {
runtime_version: VERSION,
can_author_with: Default::default(),
}
}
parameter_types! {
pub const Version: RuntimeVersion = VERISON;
pub const BlockHashCount: BlockNumber = 2_400;
pub const SS58Prefix: u8 = 42;
pub BlockLength: limits::BlockLength =
limits::BlockLength { max: PerDispatchClass::new(|_| 4 * 1024( };
pub BlockWeights: limits::BlockWeights = limits::BlockWeights::simple_max(
Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND / 100, u64::MAX)
);
}
impl frame_system::Config for Runtime {
}
impl pallet_insecure_randomness_collective_flip::Config for Runtime {}
impl pallet_aura::Config for Runtime {
type AuthorityId = AuraId;
type DisabledValidators = ();
type MaxAuthorities = MaxAuthorities;
type AllowMultipleBlocksPerSlot = ();
}
parameter_types! {
pub const MaxSetIdSessionEntries: u32 =
BondingDuration::get() * SessionPerEra::get();
pub const MaxAuthorities: u32 = 100_000;
}
impl pallet_grandpa::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type WeightInfo = ();
type MaxAuthorities = MaxAuthorities;
type MaxNominators = MaxNominators;
type MaxSetIdSessionEntries = MaxSetIdSessionEntries;
type KeyOwnerProof = sp_core::Void;
type EquivocationReportSystem = ();
}
parameter_types! {
pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
}
impl pallet_timestamp::Config for Runtime {
type Moment = u64;
type OnTimestampSet = Aura;
type MinimumPeriod = MinimumPeriod;
type WeightInfo = ();
}
parameter_types! {
pub const ExistentialDeposit: u128 = 500;
pub const MaxLocks: u32 = 50;
}
impl pallet_balances::Config for Runtime {
type MaxLocks = MaxLocks;
type MaxReserves = ();
type ReserveIdentifier = [u8; 8];
type Balance = Balance;
type RuntimeEvent = RuntimeEvent;
type DustRemoval = ();
type ExistentialDeposit = ExistentialDeposit;
type AccountStore = System;
type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
type RuntimeHoldReason = RuntimeHoldReason;
type RuntimeFreezeReason = RuntimeFreezeReason;
type FreezeIdentifier = RuntimeFreezeReason;
type MaxFreezes = ();
type MaxHolds = ConstU32<1>;
}
parameter_types! {
pub const TransactionByteFee: Balance = 1;
pub OperationalFeeMultiplier: u8 = 5;
}
impl pallet_transaction_payment::Config for Runime {
type RuntimeEvent = RuntimeEvent;
type OnChargeTransaciton = CurrencyAdapter<Balances, ()>;
type OperationalFeeMultiplier = OperationalFeeMultiplier;
type WeightInfo = IdentityFee<Balance>;
type LengthToFee =
frame_support::weights::ConstantMultiplier<Balance, TransactionByteFee>;
type FeeMultiplierUpdate = ();
}
impl pallet_sudo::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type RuntimeCall = RuntimeCall;
type WeightInfo = ();
}
pub(crate) mod sudo_key {
use super::*;
#[frame_support::storage_alias]
pub(crate) type Key = StorageValue<Sudo, AccountId>;
}
pub struct SudoAsStakingSessionManager;
impl pallet_session::SessionManager<AccountId> for SudoAsStakingSessionManager {
fn end_session(end_index: sp_staking::SessionIndex) {
<Staking as pallet_session::SessionManager<AccountId>>::end_session(end_index)
}
fn new_session(new_index: sp_staking::SessionIndex) -> Option<Vec<AccountId>> {
<Staking as pallet_session::SessionManager<AccountId>>::new_session(new_index).map(
|validators| {
if let Some(sudo) = validators.iter().find(|v| v == &&sudo_key::Key::get().unwrap()) {
log::info!(target: "runtime", "overwriting all validators to sudo: {:?}", sudo);
} else {
log::warn!(
target: "runtime",
"sudo is not event in the validator set {:?}",
sudo_key::Key::get().unwrap()
);
}
vec![sudo_key::Key::get().unwrap()]
},
)
}
fn new_session_genesis(new_index: sp_staking::SessionIndex) -> Option<Vec<AccountId>> {
<Staking as pallet_session::SessionManager<AccountId>>::new_session_genesis(new_index).map(
|validators| {
if let Some(sudo) = validators.iter().find(|v| v == &&sudo_key::Key::get().unwrap()) {
log::info!(target: "runtime", "overwriting all validators to sudo: {:?}", sudo);
} else {
log::warn!(
target: "runtime",
"sudo is not event in the validator set {:?}",
sudo_key::Key::get().unwrap()
);
}
vec![sudo_key::Key::get().unwrap()]
},
)
}
fn start_session(start_index: sp_staking::SessionIndex) {
<Staking as pallet_session::SessionManager<AccountId>>::start_session(start_index)
}
}
fn get_last_election() -> BlockNumber {
frame_support::storage::unhashed::get("last_election".as_bytes()).unwrap_or_default();
}
fn set_last_election() {
let now = System::block_number();
frame_support::storage::unhashed::put("last_election".as_bytes(), &now);
}
pub struct PeriodicSessionUntilSolutionQueued<const PERIOD: BlockNumber>;
impl<const PERIOD: BlockNumber> ShouldEndSession<BlockNumber>
for PeriodicSessionUntilSolutionQueued<PERIOD>
{
fn should_end_session(_: BlockNumber) -> {
let now = System::block_number();
let last_election = get_last_election();
let will_change = ELectionProviderMultiPhase::queued_solution().is_some() ||
(now - last_election) > PERIOD;
if will_change {
set_last_election();
}
will_change
}
}
const SESSION: BlockNumber = 6 * MINUTES;
impl<const PERIOD: BlockNumber> frame_support::traits::EstimateNextSessionRotation<BlockNumber>
for PeriodicSessionUntilSolutionQueued<PERIOD>
{
fn average_session_length() -> BlockNumber {
PERIOD
}
fn estimate_current_session_progress(_: BlockNumber) -> (Option<Permill>, Weight) {
let now = System::block_number();
let since = now - get_last_election();
(Some(Permill::from_rational(since, PERIOD)), Weight::zero())
}
fn estimate_next_session_rotation(_: BlockNumber) -> (Option<BlockNumber>, Weight) {
(Some(get_last_election() + PERIOD), Weight::zero())
}
}
impl pallet_session::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type ValidatorId = <Self as frame_system::Config>::AccountId;
type ValidatorIdOf = pallet_staking::StashOf<Self>;
type ShouldEndSession = PeriodicalSessions<ConstU32<{ SESSION }>, ()>;
type NextSessionRotation = PeriodicalSessions<ConstU32<{ SESSION }>, ()>;
type SessionManager = SudoAsStakingSessionManager;
type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
type Keys = SessionKeys;
type WeightInfo = pallet_session::weights::SubstrateWeight<Runtime>;
}
use sp_runtime::curve::PiecewiseLinear;
pallet_staking_reward_curve::build! {
const REWARD_CURVE: PiecewiseLinear<'static> = curve!(
min_inflation: 0_025_000,
max_inflation: 0_100_000,
ideal_stake: 0_500_000,
falloff: 0_050_000,
max_piece_count: 40,
test_precision: 0_005_000,
);
}
parameter_types! {
pub const SessionPerEra: sp_staking::SessionIndex = 1;
pub const BondingDuration: sp_staking::EraIndex = 24 * 28;
pub const SlashDeferDuration: sp_staking::EraIndex = 24 * 7;
pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE;
pub const MaxNominatorRewardedPerValidator: u32 = 256;
pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(17);
pub Lookahead: BlockNumber = 5u32.into();
pub HistoryDepth: u32 = 84;
pub const MaxExposurePageSize: u32 = 64;
pub const MaxNominators: u32 = 64;
pub const MaxNominations: u32 =
<NposSolution16 as frame_election_provider_support::NposSolution>::LIMIT as u32;
}
pub struct StakingBenchmarkingConfig;
impl pallet_staking::BenchmarkingConfig for StakingBenchmarkingConfig {
type MaxNominators = Nominators;
type MaxValidators = Validators;
}
impl SessionInterface<AccountId> for Runtime {
fn disable_validator(validator_index: u32) -> bool {
<pallet_session::Pallet<Runtime>::disable_index(validator_index)
}
fn validators() -> Vec<AccountId> {
<pallet_session::Pallet<Runtime>::validators()
}
fn prune_historical_up_to(_: SessionInde) {
unimplemented!("we don't give a damn about historical session data here.");
}
}
impl pallet_staking::Config for Runtime {
type Currency = Balances;
type UnixTime = Timestamp;
type CurrencyToVote = sp_staking::currency_to_vote::U128CurrencyToVote;
type CurrencyBalance = Balance;
type MaxUnclockingChunks = ConstU32<16>;
type RewardReminder = ();
type RuntimeEvent = RuntimeEvent;
type Slash = ();
type Reward = ();
type SessionsPerEra = SessionsPerEra;
type SessionInterface = Self;
type EraPayout = pallet_staking::ConvertCurve<RewardCurve>;
type MaxExposurePageSize = MaxExposurePageSize;
type NextNewSession = Session;
type OffendingValidatorsThreshold = OffendingValidatorsThreshold;
type ElectionProvider = ELectionProviderMultiPhase;
type GenesisElectionProvider = onchain::OnChainExecution<OnChainSeqPhragmen>;
type VoterList = BagsList;
type WeightInfo = pallet_staking::weights::SubstrateWeight<Runtime>;
type BenchrmakingConfig = StakingBenchmarkingConfig;
type HistoryDepth = HistoryDepth;
type TargetList = pallet_staking::UseValidatorsMap<Self>;
type NominationQuota = pallet_staking::FixedNominationsQuota<{ MaxNominations::get() }>;
type AdminOrigin = EnsureRoot<AccountId>;
type EventListeners = ();
}
parameter_types! {
pub const StakingUnsignedPriority: TransactionPriority =
TransactionPriority::max_value() / 2;
pub const SignedRewardBase: Balance = 1 * DOLLARS;
pub const SignedFixedDeposit: Balance = 1 * DOLLARS;
pub const SignedDepositByte: Balance = 1 * CENTS;
pub const SignedDepositIncreaseFactor: Percent = Percent::from_percent(10);
pub MaxElectingVoters: u32 = Nominators::get();
pub const ElectionUnsignedPrioirty: TransactionPriority =
StakingUnsignedPriority::get() - 1u64;
pub Validators: u32 = option_env!("V").unwrap_or("20").parse().expect("env variable `V` must be number");
pub Nominators: u32 = option_env!("N").unwrap_or("700").parse().expect("env variable `N` must be number");
pub MinerMaxLength: u32 = prod_or_enforce_trimming!(
*(<<Runtime as frame_system::Config>::BlockLength as Get<limits::BlockLength>>::get()).max.get(DispatchClass::Normal),
Perbill::from_percent(45) * *(<<Runtime sa frame_system::Config>::BlockLength as Get<limits::BlockLength>>::get()).max.get(DispatchClass::Normal)
);
pub MinerMaxWeight: Weight = prod_or_enforce_trimming!(
<Runtime as frame_system::Config>::BlockWeights::get().get(DispatchClass::Normal).max_total.unwrap(),
Perbill::from_percent(85) * <Runtime sa frame_system::Config>::BlockWeights::get().get(DispatchClass::Normal).max_total.unwrap()
);
pub type MaxActiveValidators: u32 = Validators::get();
pub ElectionBounds: frame_election_provider_support::bounds::ElectionBounds =
ElectionBoundsBuilder::default().voters_count(MaxElectingVoters::get().into()).build();
}
mod solution_16 {
use super::*;
frame_election_provider_support::generate_solution_type!(
#[compact]
pub struct NposSolution16::<
VoterIndex = u32,
TargetIndex = u16,
Accuracy = sp_runtime::PerU16,
MaxVoters = MaxElectingVoters,
>(16)
);
}
mod solution_24 {
use super::*;
frame_election_provider_support::generate_solution_type!(
#[compact]
pub struct NposSolution24::<
VoterIndex = u32,
TargetIndex = u16,
Accuracy = sp_runtime::PerU16,
MaxVoters = MaxElectingVoters,
>(24)
);
}
use solution_16::NposSolution16;
#[allow(unused)]
use solution_24::NposSolution24;
pub struct ElectionProviderBenchmarkConfig;
impl election_multi_phase::BenchmarkingConfig for ElectionProviderBenchmarkConfig {
const VOTERS: [u32; 2] = [1000, 2000];
const TARGETS: [u32; 2] = [500, 1000];
const ACTIVE_VOTERS: [u32; 2] = [500, 800];
const DESIRED_VOTERS: [u32; 2] = [200, 400];
const SNAPSHOT_MAXIMUM_VOTERS: u32 = 1000;
const MINER_MAXIMUM_VOTERS: u32 = 1000;
const MAXIMUM_TARGETS: u32 = 300;
}
pub struct OnChainSeqPhragmen;
impl onchain::Config for OnChainSeqPhragmen {
type System = Runtime;
type Solver = SequentialPhragmen<
AccountId,
pallet_election_provider_multi_phase::SolutionAccuracyOf<Runtime>,
>;
type DataProvider =
<Runtime as pallet_election_provider_multi_phase::Config>::DataProvider;
type WeightInfo =
frame_election_provider_support::weights::SubstrateWeight<Runtime>;
type MaxWinners =
<Runtime as pallet_election_provider_multi_phase::Config>::MaxWinners;
type Bounds = ElectionBounds;
}
impl pallet_election_provider_multi_phase::MinerConfig for Runtime {
type AccountId = AccountId;
type MaxLength = MinerMaxLength;
type MaxWeight= MinerMaxWeight;
type Solution = NposSolution16;
type MaxWinners = MaxActiveValidators;
type MaxVotesPerVoter =
<<Self as pallet_election_provider_multi_phase::Config>::DataProvider as ElectionDataProvider>::MaxVotesPerVoter;
fn solution_weight(v: u32, t: u32, a: u32, d: u32) -> Weight {
<
<Self as pallet_election_provider_multi_phase::Config>::WeightInfo
as
pallet_election_provider_multi_phase::WeightInfo
>::submit_unsigned(v, t, a, d)
}
}
impl<C> frame_system::offchain::SendTransactionTypes<C> for Runtime
where
RuntimeCall: From<C>,
{
type Extrinsic = UncheckedExtrinsic;
type OverarchingCall = RuntimeCall;
}
pub struct IncPerRound<const S: u32, const I: u32>;
impl<const S: u32, const I: u32> frame_support::traits::Get<u32> for IncPerRound<S, I> {
fn get() -> u32 {
S + (ELectionProviderMultiPhase::round() * I)
}
}
impl pallet_election_provider_multi_phase::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type EstimateCallFee = TransactionPayment;
type MinerConfig = Self;
type SignedMaxRefunds = ();
type UnsignedPhase = ConstU32<{ SESSION / 2 }>;
type SignedPhase = ConstU32<{ SESSION / 2 }>;
type BetterSignedThreshold = ();
type BetterUnsignedThreshold = ();
type OffchainRepeat = ();
type MinerTxPriority = ElectionUnsignedPrioirty;
type SignedMaxSubmissions = ConstU32<10>;
type SignedRewardBase = SignedRewardBase;
type SignedDepositBase =
GeometricDepositBase<Balance, SignedFixedDeposit, SignedDepositIncreaseFactor>;
type SignedDepositByte = SignedDepositByte;
type SignedDepositWeight = ();
type SignedMaxWeight = MinerMaxWeight;
type SlashHandler = ();
type RewardHandler = ();
type DataProvider = Staking;
type Fallback = onchain::OnChainExecution<OnChainSeqPhragmen>;
type GovernanceFallback = onchain::OnChainExecution<OnChainSeqPhragmen>;
type Solver = SequentialPhragmen<AccountId, SolutionAccuracyOf<Self>, ()>;
type WeightInfo pallet_election_provider_multi_phase::weights::SubstrateWeight<Self>;
type ForceOrigin = EnsureRoot<Self::AccountId>;
type MaxWinners = MaxActiveValidators;
type BenchmarkingConfig = ElectionProviderBenchmarkConfig;
type ElectionBounds = ElectionBounds;
}
pub mod voter_bags;
parameter_types! {
pub const BagThreshold: &'static [u64] = &voter_bags::THRESHOLDS;
}
impl pallet_bags_list::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type ScoreProvider = Staking;
type Score = u64;
type WeightInfo = pallet_bags_list::weights::SubstrateWeight<Runtime>;
type BagThreshold = BagThreshold;
}
construct_runtime!(
pub enum Runtime
{
System: frame_system,
RandomnessCollectiveFlip: pallet_insecure_randomness_collective_flip,
Timestamp: pallet_timestamp,
Sudo: pallet_sudo,
Aura: pallet_aura,
Grandpa: pallet_grandpa,
Balances: pallet_balances,
Staking: pallet_staking,
BagsList: pallet_bags_list,
TransactionPayment: pallet_transaction_payment,
ELectionProviderMultiPhase: election_multi_phase,
}
);
pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
pub type SignedExtra = (
frame_system::CheckSpecVersion<Runtime>,
frame_system::CheckTxVersion<Runtime>,
frame_system::CheckGenesis<Runtime>,
frame_system::CheckEra<Runtime>,
frame_system::CheckNonce<Runtime>,
frame_system::CheckWeight<Runtime>,
pallet_transaction_payment::ChargeTransactionPayment<Runtime>
);
pub type UncheckedExtrinsic =
generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
pub type Executive = frame_executive::Executive<
Runtime,
Block,
frame_system::ChainContext<Runtime>,
Runtime,
AllPalletsWithSystem
>;
impl_runtime_apis! {
impl sp_api::Core<Block> for Runtime {
fn version() -> RuntimeVersion {
VERSION
}
fn execute_block(block: Block) {
Executive::execute_block(block);
}
fn initialize_block(header: &<Block as BlockT>::Header) {
Executive::initialize_block(header)
}
}
impl sp_api::Metadata<Block> for Runtime {
fn metadata() -> OpaqueMetadata {
OpaqueMetadata::new(Runtime::metadata().into())
}
fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
Runtime::metadata_at_version(version)
}
fn metadata_versions() -> sp_std::vec::Vec<u32> {
Runtime::metadata_versions()
}
}
impl sp_block_builder::BlockBuilder<Block> for Runtime {
fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
Executive::apply_extrinsic(extrinsic)
}
fn finalize_block() -> <Block as BlockT>::Header {
Executive::finalize_block()
}
fn inherent_extrinsics(
data: inherents::InherentData,
) -> Vec<<Block as BlockT>::Extrinsic> {
data.create_extrinsics()
}
fn check_inherents(
block: Block,
data: inherents::InherentData,
) -> inherents::CheckInherentsResult {
data.check_extrinsics(&block)
}
}
impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
fn validate_transaction(
source: TransactionSource,
tx: <Block as BlockT>::Extrinsic,
block_hash: <Block as BlockT>::Hash,
) -> TransactionValidity {
Executive::validate_transaction(source, tx, block_hash)
}
}
impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
fn offchain_worker(header: &<Block as BlockT>::Header) {
Executive::offchain_worker(header)
}
}
impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
fn slot_duration() -> sp_consensus_aura::SlotDuration {
sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())
}
fn authorities() -> Vec<AuraId> {
Aura::authorities().into_iter()
}
}
impl sp_session::SessionKeys<Block> for Runtime {
fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
opaque::SessionKeys::generate(seed)
}
fn decode_session_keys(
encoded: Vec<u8>,
) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
opaque::SessionKeys::decode_into_raw_public_keys(&encoded)
}
}
impl fg_primitives::GrandpaApi<Block> for Runtime {
fn grandpa_authorities() -> GrandpaAuthorityList {
Grandpa::grandpa_authorities()
}
fn current_set_id() -> fg_primitives::SetId {
Grandpa::current_set_id()
}
fn submit_report_equivocation_unsigned_extrinsic(
_equivocation_proof: fg_primitives::EquivocationProof<
<Block as BlockT>::Hash,
NumberFor<Block>,
>,
_key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof,
) -> Option<()> {
None
}
fn generate_key_ownership_proof(
_set_id: fg_primitives::SetId,
_authority_id: GrandpaId,
) -> Option<fg_primitives::OpaqueKeyOwnershipProof> {
None
}
}
impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce> for Runtime {
fn account_nonce(account: AccountId) -> Nonce {
System::account_nonce(account)
}
}
impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {
fn query_info(
uxt: <Block as BlockT>::Extrinsic,
len: u32,
) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
TransactionPayment::query_info(uxt, len)
}
fn query_fee_details(
uxt: <Block as BlockT>::Extrinsic,
len: u32,
) -> pallet_transaction_payment::FeeDetails<Balance> {
TransactionPayment::query_fee_details(uxt, len)
}
fn query_weight_to_fee(weight: Weight) -> Balance {
TransactionPayment::weight_to_fee(weight)
}
fn query_length_to_fee(length: u32) -> Balance {
TransactionPayment::length_to_fee(length)
}
}
impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi<Block, Balance, RuntimeCall> for Runtime {
fn query_call_info(call: RuntimeCall, len: u32) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
TransactionPayment::query_call_info(call, len)
}
fn query_call_fee_details(call: RuntimeCall, len: u32) -> pallet_transaction_payment::FeeDetails<Balance> {
TransactionPayment::query_call_fee_details(call, len)
}
fn query_weight_to_fee(weight: Weight) -> Balance {
TransactionPayment::weight_to_fee(weight)
}
fn query_length_to_fee(length: u32) -> Balance {
TransactionPayment::length_to_fee(length)
}
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
}
}
}

View File

@@ -0,0 +1,441 @@
// This file is part of Ghost Network.
// Ghost Network is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Ghost Network is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Ghost Network. If not, see <http://www.gnu.org/licenses/>.
//! Autogenerated bag thresholds.
//!
//! Generated on 2023-06-14T16:02:49.211048528+00:00
//! Arguments
//! Total issuance: 30000000000000000000000000
//! Minimum balance: 100000000000000
//! for the casper runtime.
/// Existential weight for this runtime.
#[cfg(any(test, feature = "std"))]
#[allow(unused)]
pub const EXISTENTIAL_WEIGHT: u64 = 61_489_156;
/// Constant ratio between bags for this runtime.
#[cfg(any(test, feature = "std"))]
#[allow(unused)]
pub const CONSTANT_RATIO: f64 = 1.1420206998172278;
/// Upper thresholds delimiting the bag list.
pub const THRESHOLDS: [u64; 200] = [
61_489_156,
70_221_889,
80_194_851,
91_584_180,
104_591_029,
119_445_120,
136_408_800,
155_781_673,
177_905_895,
203_172_215,
232_026_875,
264_979_494,
302_612_067,
345_589_245,
394_670_071,
450_721_391,
514_733_158,
587_835_921,
671_320_790,
766_662_238,
875_544_146,
999_889_538,
1_141_894_550,
1_304_067_213,
1_489_271_751,
1_700_779_167,
1_942_325_015,
2_218_175_373,
2_533_202_192,
2_892_969_340,
3_303_830_870,
3_773_043_242,
4_308_893_484,
4_920_845_552,
5_619_707_481,
6_417_822_270,
7_329_285_880,
8_370_196_190,
9_558_937_311,
10_916_504_277,
12_466_873_854,
14_237_428_003,
16_259_437_492,
18_568_614_183,
21_205_741_764,
24_217_396_049,
27_656_767_584,
31_584_601_071,
36_070_268_219,
41_192_992_954,
47_043_250_641,
53_724_366_019,
61_354_338_078,
70_067_924_109,
80_019_019_726,
91_383_376_906,
104_361_708_046,
119_183_230_857,
136_109_716_710,
155_440_113_929,
177_515_827_689,
202_726_749_766,
231_518_144_639,
264_398_513_561,
301_948_575_488,
344_831_523_488,
393_804_737_773,
449_733_162_223,
513_604_580_653,
586_547_062_627,
669_848_886_937,
764_981_294_632,
873_624_473_443,
997_697_232_539,
1_139_390_891_710,
1_301_207_983_516,
1_486_006_451_943,
1_697_050_128_181,
1_938_066_375_010,
2_213_311_917_881,
2_527_648_025_372,
2_886_626_366_827,
3_296_587_063_555,
3_764_770_665_330,
4_299_446_029_872,
4_910_056_363_861,
5_607_386_004_799,
6_403_750_889_346,
7_313_216_072_106,
8_351_844_136_581,
9_537_978_885_623,
10_892_569_321_801,
12_439_539_639_691,
14_206_211_764_724,
16_223_787_901_302,
18_527_901_612_731,
21_159_247_165_916,
24_164_298_256_025,
27_596_128_804_938,
31_515_350_330_062,
35_991_182_438_923,
41_102_675_356_148,
46_940_106_074_588,
53_606_572_788_796,
61_219_815_771_064,
69_914_296_849_552,
79_843_574_215_355,
91_183_014_501_328,
104_132_890_032_251,
118_921_915_948_622,
135_811_289_675_251,
155_099_304_078_010,
177_126_615_784_334,
202_282_261_714_282,
231_010_530_083_556,
263_818_807_231_171,
301_286_538_859_088,
344_075_463_953_366,
392_941_302_133_960,
448_747_100_850_118,
512_478_478_153_804,
585_261_030_262_475,
668_380_211_356_103,
763_304_036_716_883,
871_709_010_184_730,
995_509_733_848_148,
1_136_892_722_924_124,
1_298_355_023_050_922,
1_482_748_312_035_827,
1_693_329_264_963_968,
1_933_817_072_195_143,
2_208_459_126_106_800,
2_522_106_036_714_231,
2_880_297_301_061_641,
3_289_359_139_440_088,
3_756_516_226_373_564,
4_290_019_289_717_909,
4_899_290_831_473_053,
5_595_091_543_966_984,
6_389_710_360_582_628,
7_297_181_497_621_964,
8_333_532_320_607_561,
9_517_066_412_729_732,
10_868_686_844_872_642,
12_412_265_356_675_752,
14_175_063_968_947_974,
16_188_216_473_771_936,
18_487_278_306_169_800,
21_112_854_508_927_888,
24_111_316_881_425_140,
27_535_622_978_440_076,
31_446_251_423_741_472,
35_912_270_057_569_732,
41_012_555_783_171_056,
46_837_187_656_790_104,
53_489_037_825_278_256,
61_085_588_409_774_440,
69_761_006_424_477_744,
79_668_513_376_836_192,
90_983_091_400_012_640,
103_904_573_712_177_232,
118_661_173_984_991_376,
135_513_516_955_473_664,
154_759_241_468_183_808,
176_738_257_244_678_592,
201_838_748_223_045_056,
230_504_028_495_915_136,
263_240_371_933_595_200,
300_625_953_775_751_680,
343_321_062_114_205_504,
392_079_759_617_658_880,
447_763_201_462_729_216,
511_354_844_686_868_352,
583_977_817_584_227_200,
666_914_755_915_276_544,
761_630_456_268_799_744,
869_797_746_670_209_152,
993_327_031_351_760_000,
1_134_400_031_491_706_240,
1_295_508_317_836_843_520,
1_479_497_315_755_071_488,
1_689_616_559_916_316_672,
1_929_577_086_178_408_960,
2_203_616_974_308_753_920,
2_516_576_199_129_205_248,
2_873_982_112_072_913_920,
3_282_147_062_891_703_296,
3_748_279_885_666_641_408,
4_280_613_218_139_856_384,
4_888_548_903_026_954_240,
5_582_824_039_325_583_360,
6_375_700_616_347_044_864,
7_281_182_079_705_782_272,
8_315_260_654_162_254_848,
9_496_199_791_429_038_080,
10_844_856_731_412_002_816,
12_385_050_873_824_708_608,
14_143_984_466_197_262_336,
16_152_723_038_290_595_840,
18_446_744_073_709_551_615,
];
/// Upper thresholds delimiting the bag list.
#[allow(dead_code)]
pub const THRESHOLDS_BALANCES: [u128; 200] = [
61_489_156,
70_221_889,
80_194_851,
91_584_180,
104_591_029,
119_445_120,
136_408_800,
155_781_673,
177_905_895,
203_172_215,
232_026_875,
264_979_494,
302_612_067,
345_589_245,
394_670_071,
450_721_391,
514_733_158,
587_835_921,
671_320_790,
766_662_238,
875_544_146,
999_889_538,
1_141_894_550,
1_304_067_213,
1_489_271_751,
1_700_779_167,
1_942_325_015,
2_218_175_373,
2_533_202_192,
2_892_969_340,
3_303_830_870,
3_773_043_242,
4_308_893_484,
4_920_845_552,
5_619_707_481,
6_417_822_270,
7_329_285_880,
8_370_196_190,
9_558_937_311,
10_916_504_277,
12_466_873_854,
14_237_428_003,
16_259_437_492,
18_568_614_183,
21_205_741_764,
24_217_396_049,
27_656_767_584,
31_584_601_071,
36_070_268_219,
41_192_992_954,
47_043_250_641,
53_724_366_019,
61_354_338_078,
70_067_924_109,
80_019_019_726,
91_383_376_906,
104_361_708_046,
119_183_230_857,
136_109_716_710,
155_440_113_929,
177_515_827_689,
202_726_749_766,
231_518_144_639,
264_398_513_561,
301_948_575_488,
344_831_523_488,
393_804_737_773,
449_733_162_223,
513_604_580_653,
586_547_062_627,
669_848_886_937,
764_981_294_632,
873_624_473_443,
997_697_232_539,
1_139_390_891_710,
1_301_207_983_516,
1_486_006_451_943,
1_697_050_128_181,
1_938_066_375_010,
2_213_311_917_881,
2_527_648_025_372,
2_886_626_366_827,
3_296_587_063_555,
3_764_770_665_330,
4_299_446_029_872,
4_910_056_363_861,
5_607_386_004_799,
6_403_750_889_346,
7_313_216_072_106,
8_351_844_136_581,
9_537_978_885_623,
10_892_569_321_801,
12_439_539_639_691,
14_206_211_764_724,
16_223_787_901_302,
18_527_901_612_731,
21_159_247_165_916,
24_164_298_256_025,
27_596_128_804_938,
31_515_350_330_062,
35_991_182_438_923,
41_102_675_356_148,
46_940_106_074_588,
53_606_572_788_796,
61_219_815_771_064,
69_914_296_849_552,
79_843_574_215_355,
91_183_014_501_328,
104_132_890_032_251,
118_921_915_948_622,
135_811_289_675_251,
155_099_304_078_010,
177_126_615_784_334,
202_282_261_714_282,
231_010_530_083_556,
263_818_807_231_171,
301_286_538_859_088,
344_075_463_953_366,
392_941_302_133_960,
448_747_100_850_118,
512_478_478_153_804,
585_261_030_262_475,
668_380_211_356_103,
763_304_036_716_883,
871_709_010_184_730,
995_509_733_848_148,
1_136_892_722_924_124,
1_298_355_023_050_922,
1_482_748_312_035_827,
1_693_329_264_963_968,
1_933_817_072_195_143,
2_208_459_126_106_800,
2_522_106_036_714_231,
2_880_297_301_061_641,
3_289_359_139_440_088,
3_756_516_226_373_564,
4_290_019_289_717_909,
4_899_290_831_473_053,
5_595_091_543_966_984,
6_389_710_360_582_628,
7_297_181_497_621_964,
8_333_532_320_607_561,
9_517_066_412_729_732,
10_868_686_844_872_642,
12_412_265_356_675_752,
14_175_063_968_947_974,
16_188_216_473_771_936,
18_487_278_306_169_800,
21_112_854_508_927_888,
24_111_316_881_425_140,
27_535_622_978_440_076,
31_446_251_423_741_472,
35_912_270_057_569_732,
41_012_555_783_171_056,
46_837_187_656_790_104,
53_489_037_825_278_256,
61_085_588_409_774_440,
69_761_006_424_477_744,
79_668_513_376_836_192,
90_983_091_400_012_640,
103_904_573_712_177_232,
118_661_173_984_991_376,
135_513_516_955_473_664,
154_759_241_468_183_808,
176_738_257_244_678_592,
201_838_748_223_045_056,
230_504_028_495_915_136,
263_240_371_933_595_200,
300_625_953_775_751_680,
343_321_062_114_205_504,
392_079_759_617_658_880,
447_763_201_462_729_216,
511_354_844_686_868_352,
583_977_817_584_227_200,
666_914_755_915_276_544,
761_630_456_268_799_744,
869_797_746_670_209_152,
993_327_031_351_760_000,
1_134_400_031_491_706_240,
1_295_508_317_836_843_520,
1_479_497_315_755_071_488,
1_689_616_559_916_316_672,
1_929_577_086_178_408_960,
2_203_616_974_308_753_920,
2_516_576_199_129_205_248,
2_873_982_112_072_913_920,
3_282_147_062_891_703_296,
3_748_279_885_666_641_408,
4_280_613_218_139_856_384,
4_888_548_903_026_954_240,
5_582_824_039_325_583_360,
6_375_700_616_347_044_864,
7_281_182_079_705_782_272,
8_315_260_654_162_254_848,
9_496_199_791_429_038_080,
10_844_856_731_412_002_816,
12_385_050_873_824_708_608,
14_143_984_466_197_262_336,
16_152_723_038_290_595_840,
18_446_744_073_709_551_615,
];