feat(operator): Multi-runtime support (#38)

Add support for multiple runtimes: `stagenet`, `testnet` & `mainnet`.

- Moved common types to `datahaven-runtime-common` crate.
- Made the node's command & service code generic over different
runtimes. Each runtime has a `dev` & `local` genesis config preset.
- More types / constants can be moved to the `datahaven-runtime-common`
crate ... this will be done in subsequent PRs.

---------

Co-authored-by: Gonza Montiel <gon.montiel@gmail.com>
Co-authored-by: Gonza Montiel <gonzamontiel@users.noreply.github.com>
Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
This commit is contained in:
Steve Degosserie 2025-05-08 16:14:30 +03:00 committed by GitHub
parent e161accac2
commit d6f76f7fa3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
42 changed files with 6185 additions and 569 deletions

View file

@ -33,6 +33,14 @@ jobs:
- uses: ./.github/workflows/actions/setup-env
with:
cache-key: "TEST"
- name: Free up disk space
# Remove some pre-installed tooling that we don't use to free space
run: |
echo "Disk space before cleanup:"
df -h /
sudo rm -rf /usr/share/dotnet /opt/ghc /opt/hostedtoolcache/CodeQL
echo "Disk space after cleanup:"
df -h /
- name: Install nextest
uses: taiki-e/install-action@nextest
- name: Build and archive tests

730
operator/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -9,15 +9,9 @@ edition = "2021"
members = [
"node",
"pallets/outbound-commitment-store",
"pallets/ethereum-client",
"pallets/inbound-queue-v2",
"pallets/outbound-queue-v2",
"pallets/system",
"pallets/system-v2",
"pallets/validator-set",
"pallets/*",
"primitives/bridge",
"runtime",
"runtime/common",
"runtime/*",
]
resolver = "2"
@ -25,8 +19,10 @@ resolver = "2"
[workspace.dependencies]
# Local
datahaven-runtime = { path = "./runtime", default-features = false }
datahaven-mainnet-runtime = { path = "./runtime/mainnet", default-features = false }
datahaven-runtime-common = { path = "./runtime/common", default-features = false }
datahaven-stagenet-runtime = { path = "./runtime/stagenet", default-features = false }
datahaven-testnet-runtime = { path = "./runtime/testnet", default-features = false }
dhp-bridge = { path = "./primitives/bridge", default-features = false }
pallet-outbound-commitment-store = { path = "./pallets/outbound-commitment-store", default-features = false }
pallet-validator-set = { path = "./pallets/validator-set", default-features = false }
@ -135,12 +131,14 @@ sp-consensus = { git = "https://github.com/paritytech/polkadot-sdk", branch = "s
sp-consensus-babe = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2412", default-features = false }
sp-consensus-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2412", default-features = false }
sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2412", default-features = false }
sp-consensus-slots = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2412", default-features = false }
sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2412", default-features = false }
sp-crypto-hashing = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2412", default-features = false }
sp-genesis-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2412", default-features = false }
sp-inherents = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2412", default-features = false }
sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2412", default-features = false }
sp-keyring = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2412", default-features = false }
sp-keystore = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2412", default-features = false }
sp-offchain = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2412", default-features = false }
sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2412", default-features = false }
sp-runtime-interface = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2412", default-features = false }

View file

@ -16,7 +16,10 @@ targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
# Local
datahaven-runtime = { workspace = true }
datahaven-mainnet-runtime = { workspace = true }
datahaven-runtime-common = { workspace = true }
datahaven-stagenet-runtime = { workspace = true }
datahaven-testnet-runtime = { workspace = true }
# Crates.io
clap = { features = ["derive"], workspace = true }
@ -29,12 +32,16 @@ log = { workspace = true }
serde_json = { workspace = true, default-features = true }
url = { workspace = true }
#MMR
mmr-rpc = { workspace = true, default-features = true }
pallet-beefy-mmr = { workspace = true, default-features = true }
pallet-mmr = { workspace = true, default-features = true }
# Polkadot SDK
frame-benchmarking-cli = { workspace = true, default-features = true }
frame-metadata-hash-extension = { workspace = true, default-features = true }
frame-system = { workspace = true, default-features = true }
frame-system-rpc-runtime-api = { workspace = true }
mmr-rpc = { workspace = true, default-features = true }
pallet-im-online = { workspace = true }
pallet-transaction-payment = { workspace = true, default-features = true }
pallet-transaction-payment-rpc = { workspace = true, default-features = true }
@ -68,11 +75,11 @@ sp-genesis-builder = { workspace = true, default-features = true }
sp-inherents = { workspace = true, default-features = true }
sp-io = { workspace = true, default-features = true }
sp-keyring = { workspace = true, default-features = true }
sp-offchain = { workspace = true, features = ["default"] }
sp-offchain = { workspace = true, default-features = true }
sp-runtime = { workspace = true, default-features = true }
sp-session = { workspace = true, features = ["default"] }
sp-session = { workspace = true, default-features = true }
sp-timestamp = { workspace = true, default-features = true }
sp-transaction-pool = { workspace = true, features = ["default"] }
sp-transaction-pool = { workspace = true, default-features = true }
substrate-frame-rpc-system = { workspace = true, default-features = true }
# Frontier
@ -95,22 +102,30 @@ substrate-build-script-utils = { workspace = true, default-features = true }
[features]
default = ["std"]
std = [
"datahaven-runtime/std",
"datahaven-runtime-common/std",
"datahaven-stagenet-runtime/std",
"datahaven-mainnet-runtime/std",
"datahaven-testnet-runtime/std",
]
# Dependencies that are only required if runtime benchmarking should be build.
runtime-benchmarks = [
"datahaven-runtime/runtime-benchmarks",
"frame-benchmarking-cli/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"sc-service/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"frame-benchmarking-cli/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"sc-service/runtime-benchmarks",
"datahaven-runtime-common/runtime-benchmarks",
"datahaven-stagenet-runtime/runtime-benchmarks",
"datahaven-mainnet-runtime/runtime-benchmarks",
"datahaven-testnet-runtime/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
]
# Enable features that allow the runtime to be tried and debugged. Name might be subject to change
# in the near future.
try-runtime = [
"datahaven-runtime/try-runtime",
"frame-system/try-runtime",
"pallet-transaction-payment/try-runtime",
"sp-runtime/try-runtime",
"frame-system/try-runtime",
"pallet-transaction-payment/try-runtime",
"datahaven-stagenet-runtime/try-runtime",
"datahaven-mainnet-runtime/try-runtime",
"datahaven-testnet-runtime/try-runtime",
"sp-runtime/try-runtime",
]

View file

@ -4,7 +4,7 @@
use crate::service::FullClient;
use datahaven_runtime as runtime;
use datahaven_mainnet_runtime as runtime;
use fp_account::EthereumSignature;
use runtime::{AccountId, Balance, BalancesCall, SystemCall};
use sc_cli::Result;
@ -18,18 +18,18 @@ use std::{sync::Arc, time::Duration};
/// Generates extrinsics for the `benchmark overhead` command.
///
/// Note: Should only be used for benchmarking.
pub struct RemarkBuilder {
client: Arc<FullClient>,
pub struct RemarkBuilder<RuntimeApi> {
client: Arc<FullClient<RuntimeApi>>,
}
impl RemarkBuilder {
impl<RuntimeApi> RemarkBuilder<RuntimeApi> {
/// Creates a new [`Self`] from the given client.
pub fn new(client: Arc<FullClient>) -> Self {
pub fn new(client: Arc<FullClient<RuntimeApi>>) -> Self {
Self { client }
}
}
impl frame_benchmarking_cli::ExtrinsicBuilder for RemarkBuilder {
impl<RuntimeApi> frame_benchmarking_cli::ExtrinsicBuilder for RemarkBuilder<RuntimeApi> {
fn pallet(&self) -> &str {
"system"
}
@ -54,15 +54,15 @@ impl frame_benchmarking_cli::ExtrinsicBuilder for RemarkBuilder {
/// Generates `Balances::TransferKeepAlive` extrinsics for the benchmarks.
///
/// Note: Should only be used for benchmarking.
pub struct TransferKeepAliveBuilder {
client: Arc<FullClient>,
pub struct TransferKeepAliveBuilder<RuntimeApi> {
client: Arc<FullClient<RuntimeApi>>,
dest: AccountId,
value: Balance,
}
impl TransferKeepAliveBuilder {
impl<RuntimeApi> TransferKeepAliveBuilder<RuntimeApi> {
/// Creates a new [`Self`] from the given client.
pub fn new(client: Arc<FullClient>, dest: AccountId, value: Balance) -> Self {
pub fn new(client: Arc<FullClient<RuntimeApi>>, dest: AccountId, value: Balance) -> Self {
Self {
client,
dest,
@ -71,7 +71,7 @@ impl TransferKeepAliveBuilder {
}
}
impl frame_benchmarking_cli::ExtrinsicBuilder for TransferKeepAliveBuilder {
impl<RuntimeApi> frame_benchmarking_cli::ExtrinsicBuilder for TransferKeepAliveBuilder<RuntimeApi> {
fn pallet(&self) -> &str {
"balances"
}
@ -100,8 +100,8 @@ impl frame_benchmarking_cli::ExtrinsicBuilder for TransferKeepAliveBuilder {
/// Create a transaction using the given `call`.
///
/// Note: Should only be used for benchmarking.
pub fn create_benchmark_extrinsic(
client: &FullClient,
pub fn create_benchmark_extrinsic<RuntimeApi>(
client: &FullClient<RuntimeApi>,
sender: ecdsa::Pair,
call: runtime::RuntimeCall,
nonce: u32,

View file

@ -1,14 +1,13 @@
use datahaven_runtime::WASM_BINARY;
use datahaven_mainnet_runtime::WASM_BINARY;
use sc_service::ChainType;
use super::ChainSpec;
const EVM_CHAIN_ID: u64 = 1289;
const SS58_FORMAT: u16 = EVM_CHAIN_ID as u16;
const TOKEN_DECIMALS: u8 = 18;
const TOKEN_SYMBOL: &str = "HAVE";
/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.
pub type ChainSpec = sc_service::GenericChainSpec;
pub fn development_chain_spec() -> Result<ChainSpec, String> {
// Give the token a unit name and decimal places
let mut properties = sc_service::Properties::new();
@ -21,8 +20,8 @@ pub fn development_chain_spec() -> Result<ChainSpec, String> {
WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?,
None,
)
.with_name("Development")
.with_id("dev")
.with_name("DataHaven Mainnet Dev")
.with_id("datahaven_mainnet_dev")
.with_chain_type(ChainType::Development)
.with_genesis_config_preset_name(sp_genesis_builder::DEV_RUNTIME_PRESET)
.with_properties(properties)
@ -40,8 +39,8 @@ pub fn local_chain_spec() -> Result<ChainSpec, String> {
WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?,
None,
)
.with_name("Local Testnet")
.with_id("local")
.with_name("DataHaven Mainnet Local")
.with_id("datahaven_mainnet_local")
.with_chain_type(ChainType::Local)
.with_genesis_config_preset_name(sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET)
.with_properties(properties)

View file

@ -0,0 +1,40 @@
pub mod mainnet;
pub mod stagenet;
pub mod testnet;
/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.
pub type ChainSpec = sc_service::GenericChainSpec;
/// Can be called for a chain spec `Configuration` to determine the network type.
#[allow(unused)]
pub trait NetworkType {
/// Returns `true` if this is a configuration for the `Stagenet` network.
fn is_stagenet(&self) -> bool;
/// Returns `true` if this is a configuration for the `Testnet` network.
fn is_testnet(&self) -> bool;
/// Returns `true` if this is a configuration for the `Mainnet` network.
fn is_mainnet(&self) -> bool;
/// Returns `true` if this is a configuration for a dev network.
fn is_dev(&self) -> bool;
}
impl NetworkType for Box<dyn sc_service::ChainSpec> {
fn is_dev(&self) -> bool {
self.chain_type() == sc_service::ChainType::Development
}
fn is_stagenet(&self) -> bool {
self.id().starts_with("datahaven_stagenet")
}
fn is_testnet(&self) -> bool {
self.id().starts_with("datahaven_testnet")
}
fn is_mainnet(&self) -> bool {
self.id().starts_with("datahaven_mainnet")
}
}

View file

@ -0,0 +1,48 @@
use datahaven_stagenet_runtime::WASM_BINARY;
use sc_service::ChainType;
use super::ChainSpec;
const EVM_CHAIN_ID: u64 = 1283;
const SS58_FORMAT: u16 = EVM_CHAIN_ID as u16;
const TOKEN_DECIMALS: u8 = 18;
const TOKEN_SYMBOL: &str = "HAVE";
pub fn development_chain_spec() -> Result<ChainSpec, String> {
// Give the token a unit name and decimal places
let mut properties = sc_service::Properties::new();
properties.insert("tokenSymbol".into(), TOKEN_SYMBOL.into());
properties.insert("tokenDecimals".into(), TOKEN_DECIMALS.into());
properties.insert("ss58Format".into(), SS58_FORMAT.into());
properties.insert("isEthereum".into(), true.into());
Ok(ChainSpec::builder(
WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?,
None,
)
.with_name("DataHaven Stagenet Dev")
.with_id("datahaven_stagenet_dev")
.with_chain_type(ChainType::Development)
.with_genesis_config_preset_name(sp_genesis_builder::DEV_RUNTIME_PRESET)
.with_properties(properties)
.build())
}
pub fn local_chain_spec() -> Result<ChainSpec, String> {
let mut properties = sc_service::Properties::new();
properties.insert("tokenSymbol".into(), TOKEN_SYMBOL.into());
properties.insert("tokenDecimals".into(), TOKEN_DECIMALS.into());
properties.insert("ss58Format".into(), SS58_FORMAT.into());
properties.insert("isEthereum".into(), true.into());
Ok(ChainSpec::builder(
WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?,
None,
)
.with_name("DataHaven Stagenet Local")
.with_id("datahaven_stagenet_local")
.with_chain_type(ChainType::Local)
.with_genesis_config_preset_name(sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET)
.with_properties(properties)
.build())
}

View file

@ -0,0 +1,48 @@
use datahaven_testnet_runtime::WASM_BINARY;
use sc_service::ChainType;
use super::ChainSpec;
const EVM_CHAIN_ID: u64 = 1288;
const SS58_FORMAT: u16 = EVM_CHAIN_ID as u16;
const TOKEN_DECIMALS: u8 = 18;
const TOKEN_SYMBOL: &str = "HAVE";
pub fn development_chain_spec() -> Result<ChainSpec, String> {
// Give the token a unit name and decimal places
let mut properties = sc_service::Properties::new();
properties.insert("tokenSymbol".into(), TOKEN_SYMBOL.into());
properties.insert("tokenDecimals".into(), TOKEN_DECIMALS.into());
properties.insert("ss58Format".into(), SS58_FORMAT.into());
properties.insert("isEthereum".into(), true.into());
Ok(ChainSpec::builder(
WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?,
None,
)
.with_name("DataHaven Testnet Dev")
.with_id("datahaven_testnet_dev")
.with_chain_type(ChainType::Development)
.with_genesis_config_preset_name(sp_genesis_builder::DEV_RUNTIME_PRESET)
.with_properties(properties)
.build())
}
pub fn local_chain_spec() -> Result<ChainSpec, String> {
let mut properties = sc_service::Properties::new();
properties.insert("tokenSymbol".into(), TOKEN_SYMBOL.into());
properties.insert("tokenDecimals".into(), TOKEN_DECIMALS.into());
properties.insert("ss58Format".into(), SS58_FORMAT.into());
properties.insert("isEthereum".into(), true.into());
Ok(ChainSpec::builder(
WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?,
None,
)
.with_name("DataHaven Testnet Local")
.with_id("datahaven_testnet_local")
.with_chain_type(ChainType::Local)
.with_genesis_config_preset_name(sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET)
.with_properties(properties)
.build())
}

View file

@ -1,7 +1,7 @@
use crate::eth::EthCompatRuntimeApiCollection;
use codec::Codec;
// Substrate
use datahaven_runtime::{AccountId, Nonce};
use datahaven_runtime_common::{AccountId, Nonce};
use sc_executor::WasmExecutor;
use sp_runtime::traits::{Block as BlockT, MaybeDisplay};

View file

@ -3,14 +3,14 @@ use std::sync::Arc;
use crate::service::frontier_database_dir;
use crate::{
benchmarking::{inherent_benchmark_data, RemarkBuilder, TransferKeepAliveBuilder},
chain_spec,
chain_spec::{self, NetworkType},
cli::{Cli, Subcommand},
service,
};
use datahaven_runtime::{genesis_config_presets::alith, Block, EXISTENTIAL_DEPOSIT};
use datahaven_runtime_common::Block;
use frame_benchmarking_cli::{BenchmarkCmd, ExtrinsicFactory, SUBSTRATE_REFERENCE_HARDWARE};
use sc_cli::SubstrateCli;
use sc_service::{DatabaseSource, PartialComponents};
use sc_service::DatabaseSource;
impl SubstrateCli for Cli {
fn impl_name() -> String {
@ -39,8 +39,12 @@ impl SubstrateCli for Cli {
fn load_spec(&self, id: &str) -> Result<Box<dyn sc_service::ChainSpec>, String> {
Ok(match id {
"dev" => Box::new(chain_spec::development_chain_spec()?),
"" | "local" => Box::new(chain_spec::local_chain_spec()?),
"dev" | "stagenet-dev" => Box::new(chain_spec::stagenet::development_chain_spec()?),
"" | "local" | "stagenet-local" => Box::new(chain_spec::stagenet::local_chain_spec()?),
"testnet-dev" => Box::new(chain_spec::testnet::development_chain_spec()?),
"testnet-local" => Box::new(chain_spec::testnet::local_chain_spec()?),
"mainnet-dev" => Box::new(chain_spec::mainnet::development_chain_spec()?),
"mainnet-local" => Box::new(chain_spec::mainnet::local_chain_spec()?),
path => Box::new(chain_spec::ChainSpec::from_json_file(
std::path::PathBuf::from(path),
)?),
@ -48,6 +52,66 @@ impl SubstrateCli for Cli {
}
}
macro_rules! construct_async_run {
(|$components:ident, $cli:ident, $cmd:ident, $config:ident| $( $code:tt )* ) => {{
let runner = $cli.create_runner($cmd)?;
match runner.config().chain_spec {
ref spec if spec.is_mainnet() => {
runner.async_run(|$config| {
let $components = service::new_partial::<datahaven_mainnet_runtime::apis::RuntimeApi>(
&$config,
&mut $cli.eth.clone()
)?;
let task_manager = $components.task_manager;
{ $( $code )* }.map(|v| (v, task_manager))
})
}
ref spec if spec.is_testnet() => {
runner.async_run(|$config| {
let $components = service::new_partial::<datahaven_testnet_runtime::apis::RuntimeApi>(
&$config,
&mut $cli.eth.clone()
)?;
let task_manager = $components.task_manager;
{ $( $code )* }.map(|v| (v, task_manager))
})
}
_ => {
runner.async_run(|$config| {
let $components = service::new_partial::<datahaven_stagenet_runtime::apis::RuntimeApi>(
&$config,
&mut $cli.eth.clone()
)?;
let task_manager = $components.task_manager;
{ $( $code )* }.map(|v| (v, task_manager))
})
}
}
}}
}
macro_rules! construct_benchmark_partials {
($cli:expr, $config:expr, |$partials:ident| $code:expr) => {
match $config.chain_spec {
ref spec if spec.is_mainnet() => {
let $partials =
service::new_partial::<datahaven_mainnet_runtime::apis::RuntimeApi>(&$config, &mut $cli.eth.clone())?;
$code
}
ref spec if spec.is_testnet() => {
let $partials =
service::new_partial::<datahaven_testnet_runtime::apis::RuntimeApi>(&$config, &mut $cli.eth.clone())?;
$code
}
_ => {
let $partials =
service::new_partial::<datahaven_stagenet_runtime::apis::RuntimeApi>(&$config, &mut $cli.eth.clone())?;
$code
}
}
};
}
/// Parse and run command line arguments
pub fn run() -> sc_cli::Result<()> {
let cli = Cli::from_args();
@ -59,49 +123,23 @@ pub fn run() -> sc_cli::Result<()> {
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, &mut cli.eth.clone())?;
Ok((cmd.run(client, import_queue), task_manager))
construct_async_run!(|components, cli, cmd, config| {
Ok(cmd.run(components.client, components.import_queue))
})
}
Some(Subcommand::ExportBlocks(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents {
client,
task_manager,
..
} = service::new_partial(&config, &mut cli.eth.clone())?;
Ok((cmd.run(client, config.database), task_manager))
construct_async_run!(|components, cli, cmd, config| {
Ok(cmd.run(components.client, config.database))
})
}
Some(Subcommand::ExportState(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents {
client,
task_manager,
..
} = service::new_partial(&config, &mut cli.eth.clone())?;
Ok((cmd.run(client, config.chain_spec), task_manager))
construct_async_run!(|components, cli, cmd, config| {
Ok(cmd.run(components.client, config.chain_spec))
})
}
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, &mut cli.eth.clone())?;
Ok((cmd.run(client, import_queue), task_manager))
construct_async_run!(|components, cli, cmd, config| {
Ok(cmd.run(components.client, components.import_queue))
})
}
Some(Subcommand::PurgeChain(cmd)) => {
@ -124,20 +162,14 @@ pub fn run() -> sc_cli::Result<()> {
})
}
Some(Subcommand::Revert(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents {
client,
task_manager,
backend,
..
} = service::new_partial(&config, &mut cli.eth.clone())?;
let aux_revert = Box::new(|client: Arc<service::FullClient>, backend, blocks| {
sc_consensus_babe::revert(client.clone(), backend, blocks)?;
sc_consensus_grandpa::revert(client, blocks)?;
Ok(())
});
Ok((cmd.run(client, backend, Some(aux_revert)), task_manager))
construct_async_run!(|components, cli, cmd, config| {
let aux_revert =
Box::new(|client: Arc<service::FullClient<_>>, backend, blocks| {
sc_consensus_babe::revert(client.clone(), backend, blocks)?;
sc_consensus_grandpa::revert(client, blocks)?;
Ok(())
});
Ok(cmd.run(components.client, components.backend, Some(aux_revert)))
})
}
Some(Subcommand::Benchmark(cmd)) => {
@ -151,7 +183,7 @@ pub fn run() -> sc_cli::Result<()> {
if !cfg!(feature = "runtime-benchmarks") {
return Err(
"Runtime benchmarking wasn't enabled when building the node. \
You can enable it with `--features runtime-benchmarks`."
You can enable it with `--features runtime-benchmarks`."
.into(),
);
}
@ -161,9 +193,8 @@ pub fn run() -> sc_cli::Result<()> {
))
}
BenchmarkCmd::Block(cmd) => {
let PartialComponents { client, .. } =
service::new_partial(&config, &mut cli.eth.clone())?;
cmd.run(client)
construct_benchmark_partials!(cli, config, |partials| cmd
.run(partials.client))
}
#[cfg(not(feature = "runtime-benchmarks"))]
BenchmarkCmd::Storage(_) => Err(
@ -172,42 +203,46 @@ pub fn run() -> sc_cli::Result<()> {
),
#[cfg(feature = "runtime-benchmarks")]
BenchmarkCmd::Storage(cmd) => {
let PartialComponents {
client, backend, ..
} = service::new_partial(&config, &mut cli.eth.clone())?;
let db = backend.expose_db();
let storage = backend.expose_storage();
construct_benchmark_partials!(cli, config, |partials| {
let db = partials.backend.expose_db();
let storage = partials.backend.expose_storage();
cmd.run(config, client, db, storage)
cmd.run(config, partials.client.clone(), db, storage)
})
}
BenchmarkCmd::Overhead(cmd) => {
let PartialComponents { client, .. } =
service::new_partial(&config, &mut cli.eth.clone())?;
let ext_builder = RemarkBuilder::new(client.clone());
cmd.run(
config.chain_spec.name().to_string(),
client,
inherent_benchmark_data()?,
Vec::new(),
&ext_builder,
false,
)
construct_benchmark_partials!(cli, config, |partials| {
let ext_builder = RemarkBuilder::new(partials.client.clone());
cmd.run(
config.chain_spec.name().to_string(),
partials.client,
inherent_benchmark_data()?,
Vec::new(),
&ext_builder,
false,
)
})
}
BenchmarkCmd::Extrinsic(cmd) => {
let PartialComponents { client, .. } =
service::new_partial(&config, &mut cli.eth.clone())?;
// Register the *Remark* and *TKA* builders.
let ext_factory = ExtrinsicFactory(vec![
Box::new(RemarkBuilder::new(client.clone())),
Box::new(TransferKeepAliveBuilder::new(
client.clone(),
alith(),
EXISTENTIAL_DEPOSIT,
)),
]);
construct_benchmark_partials!(cli, config, |partials| {
// Register the *Remark* and *TKA* builders.
let ext_factory = ExtrinsicFactory(vec![
Box::new(RemarkBuilder::new(partials.client.clone())),
Box::new(TransferKeepAliveBuilder::new(
partials.client.clone(),
datahaven_stagenet_runtime::genesis_config_presets::alith(),
// Assume the existential deposit is the same for all runtimes
datahaven_stagenet_runtime::EXISTENTIAL_DEPOSIT,
)),
]);
cmd.run(client, inherent_benchmark_data()?, Vec::new(), &ext_factory)
cmd.run(
partials.client,
inherent_benchmark_data()?,
Vec::new(),
&ext_factory,
)
})
}
BenchmarkCmd::Machine(cmd) => {
cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone())
@ -223,22 +258,54 @@ pub fn run() -> sc_cli::Result<()> {
let runner = cli.create_runner(&cli.run)?;
runner.run_node_until_exit(|config| async move {
match config.network.network_backend.unwrap_or_default() {
sc_network::config::NetworkBackendType::Libp2p => service::new_full::<
sc_network::NetworkWorker<
datahaven_runtime::opaque::Block,
<datahaven_runtime::opaque::Block as sp_runtime::traits::Block>::Hash,
>,
>(
config, cli.eth
)
.await
.map_err(sc_cli::Error::Service),
sc_network::config::NetworkBackendType::Litep2p => {
service::new_full::<sc_network::Litep2pNetworkBackend>(config, cli.eth)
sc_network::config::NetworkBackendType::Libp2p => match config.chain_spec {
ref spec if spec.is_mainnet() => {
service::new_full::<
datahaven_mainnet_runtime::apis::RuntimeApi,
sc_network::NetworkWorker<_, _>,
>(config, cli.eth)
.await
.map_err(sc_cli::Error::Service)
}
ref spec if spec.is_testnet() => {
service::new_full::<
datahaven_testnet_runtime::apis::RuntimeApi,
sc_network::NetworkWorker<_, _>,
>(config, cli.eth)
.await
}
_ => {
service::new_full::<
datahaven_stagenet_runtime::apis::RuntimeApi,
sc_network::NetworkWorker<_, _>,
>(config, cli.eth)
.await
}
}
.map_err(sc_cli::Error::Service),
sc_network::config::NetworkBackendType::Litep2p => match config.chain_spec {
ref spec if spec.is_mainnet() => {
service::new_full::<
datahaven_mainnet_runtime::apis::RuntimeApi,
sc_network::Litep2pNetworkBackend,
>(config, cli.eth)
.await
}
ref spec if spec.is_testnet() => {
service::new_full::<
datahaven_testnet_runtime::apis::RuntimeApi,
sc_network::Litep2pNetworkBackend,
>(config, cli.eth)
.await
}
_ => {
service::new_full::<
datahaven_stagenet_runtime::apis::RuntimeApi,
sc_network::Litep2pNetworkBackend,
>(config, cli.eth)
.await
}
}
.map_err(sc_cli::Error::Service),
}
})
}

View file

@ -1,6 +1,6 @@
// Substrate
use crate::client::{FullBackend, FullClient};
use datahaven_runtime::opaque::Block;
use datahaven_runtime_common::Block;
pub use fc_db::Backend as FrontierBackend;
use fc_rpc::EthTask;
pub use fc_rpc_core::types::{FeeHistoryCache, FeeHistoryCacheLimit, FilterPool};

View file

@ -7,8 +7,8 @@
use crate::consensus::BabeConsensusDataProvider;
use crate::eth::DefaultEthConfig;
use datahaven_runtime::{
opaque::Block, AccountId, Balance, BlockNumber, Hash, Nonce, SLOT_DURATION,
use datahaven_runtime_common::{
time::SLOT_DURATION, AccountId, Balance, Block, BlockNumber, Hash, Nonce,
};
use fc_rpc::TxPool;
use fc_rpc::{Eth, EthBlockDataCacheTask, EthFilter, Net, Web3};
@ -241,6 +241,8 @@ where
let tx_pool = TxPool::new(client.clone(), graph.clone());
module.merge(tx_pool.into_rpc())?;
// module.merge(FrontierFinality::new(client.clone(), frontier_backend.clone()).into_rpc())?;
// Extend this RPC with a custom API by using the following syntax.
// `YourRpcStruct` should have a reference to a client, which is needed
// to call into the runtime.

View file

@ -6,7 +6,7 @@ use crate::eth::{
};
use crate::eth::{EthConfiguration, StorageOverrideHandler};
use crate::rpc::BeefyDeps;
use datahaven_runtime::{self, apis::RuntimeApi, opaque::Block};
use datahaven_runtime_common::{AccountId, Balance, Block, BlockNumber, Hash, Nonce};
use fc_consensus::FrontierBlockImport;
use fc_db::DatabaseSource;
use fc_storage::StorageOverride;
@ -15,42 +15,115 @@ use sc_client_api::{AuxStore, Backend, BlockBackend, StateBackend, StorageProvid
use sc_consensus_babe::ImportQueueParams;
use sc_consensus_grandpa::SharedVoterState;
use sc_executor::{HeapAllocStrategy, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY};
use sc_network_sync::WarpSyncConfig;
use sc_service::{error::Error as ServiceError, Configuration, TFullClient, TaskManager};
use sc_service::{error::Error as ServiceError, Configuration, TaskManager, WarpSyncConfig};
use sc_telemetry::{Telemetry, TelemetryWorker};
use sc_transaction_pool::{BasicPool, FullChainApi};
use sc_transaction_pool_api::OffchainTransactionPoolFactory;
use sp_api::ProvideRuntimeApi;
use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};
use sp_consensus_beefy::ecdsa_crypto;
use sp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId;
use sp_runtime::traits::BlakeTwo256;
use std::default::Default;
use std::time::Duration;
use std::{path::Path, sync::Arc};
use std::{default::Default, path::Path, sync::Arc, time::Duration};
pub type HostFunctions = sp_io::SubstrateHostFunctions;
pub(crate) type FullClient = TFullClient<Block, RuntimeApi, WasmExecutor<HostFunctions>>;
pub(crate) type FullClient<RuntimeApi> = sc_service::TFullClient<
Block,
RuntimeApi,
sc_executor::WasmExecutor<sp_io::SubstrateHostFunctions>,
>;
type FullBackend = sc_service::TFullBackend<Block>;
type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;
type FullGrandpaBlockImport =
sc_consensus_grandpa::GrandpaBlockImport<FullBackend, Block, FullClient, FullSelectChain>;
type FullBeefyBlockImport<InnerBlockImport, AuthorityId> =
type FullGrandpaBlockImport<RuntimeApi> = sc_consensus_grandpa::GrandpaBlockImport<
FullBackend,
Block,
FullClient<RuntimeApi>,
FullSelectChain,
>;
type FullBeefyBlockImport<InnerBlockImport, AuthorityId, RuntimeApi> =
sc_consensus_beefy::import::BeefyBlockImport<
Block,
FullBackend,
FullClient,
FullClient<RuntimeApi>,
InnerBlockImport,
AuthorityId,
>;
type SingleStatePool = BasicPool<FullChainApi<FullClient, Block>, Block>;
type SingleStatePool<RuntimeApi> = BasicPool<FullChainApi<FullClient<RuntimeApi>, Block>, Block>;
/// The minimum period of blocks on which justifications will be
/// imported and generated.
const GRANDPA_JUSTIFICATION_PERIOD: u32 = 512;
pub(crate) trait FullRuntimeApi:
sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
+ sp_api::Metadata<Block>
+ crate::eth::EthCompatRuntimeApiCollection<Block>
+ frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce>
+ sp_session::SessionKeys<Block>
+ sp_api::ApiExt<Block>
+ pallet_mmr::primitives::MmrApi<Block, Hash, BlockNumber>
+ pallet_beefy_mmr::BeefyMmrApi<Block, Hash>
+ sp_consensus_beefy::BeefyApi<Block, BeefyId>
+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
+ sp_offchain::OffchainWorkerApi<Block>
+ sp_block_builder::BlockBuilder<Block>
+ sp_consensus_babe::BabeApi<Block>
+ sp_consensus_grandpa::GrandpaApi<Block>
+ fp_rpc::ConvertTransactionRuntimeApi<Block>
+ fp_rpc::EthereumRuntimeRPCApi<Block>
{
}
impl<T> FullRuntimeApi for T where
T: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
+ sp_api::Metadata<Block>
+ crate::eth::EthCompatRuntimeApiCollection<Block>
+ frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce>
+ sp_session::SessionKeys<Block>
+ sp_api::ApiExt<Block>
+ pallet_mmr::primitives::MmrApi<Block, Hash, BlockNumber>
+ pallet_beefy_mmr::BeefyMmrApi<Block, Hash>
+ sp_consensus_beefy::BeefyApi<Block, BeefyId>
+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
+ sp_offchain::OffchainWorkerApi<Block>
+ sp_block_builder::BlockBuilder<Block>
+ sp_consensus_babe::BabeApi<Block>
+ sp_consensus_grandpa::GrandpaApi<Block>
+ fp_rpc::ConvertTransactionRuntimeApi<Block>
+ fp_rpc::EthereumRuntimeRPCApi<Block>
{
}
pub type Service<RuntimeApi> = sc_service::PartialComponents<
FullClient<RuntimeApi>,
FullBackend,
FullSelectChain,
sc_consensus::DefaultImportQueue<Block>,
SingleStatePool<RuntimeApi>,
(
sc_consensus_babe::BabeBlockImport<
Block,
FullClient<RuntimeApi>,
FullBeefyBlockImport<
FrontierBlockImport<
Block,
FullGrandpaBlockImport<RuntimeApi>,
FullClient<RuntimeApi>,
>,
BeefyId,
RuntimeApi,
>,
>,
sc_consensus_grandpa::LinkHalf<Block, FullClient<RuntimeApi>, FullSelectChain>,
sc_consensus_babe::BabeLink<Block>,
sc_consensus_beefy::BeefyVoterLinks<Block, BeefyId>,
sc_consensus_beefy::BeefyRPCLinks<Block, BeefyId>,
Arc<fc_db::Backend<Block, FullClient<RuntimeApi>>>,
Arc<dyn StorageOverride<Block>>,
Option<Telemetry>,
),
>;
pub fn frontier_database_dir(config: &Configuration, path: &str) -> std::path::PathBuf {
config
.base_path
@ -58,6 +131,7 @@ pub fn frontier_database_dir(config: &Configuration, path: &str) -> std::path::P
.join("frontier")
.join(path)
}
pub fn open_frontier_backend<C, BE>(
client: Arc<C>,
config: &Configuration,
@ -124,35 +198,15 @@ where
Ok(frontier_backend)
}
pub type Service = sc_service::PartialComponents<
FullClient,
FullBackend,
FullSelectChain,
sc_consensus::DefaultImportQueue<Block>,
SingleStatePool,
(
sc_consensus_babe::BabeBlockImport<
Block,
FullClient,
FullBeefyBlockImport<
FrontierBlockImport<Block, FullGrandpaBlockImport, FullClient>,
ecdsa_crypto::AuthorityId,
>,
>,
sc_consensus_grandpa::LinkHalf<Block, FullClient, FullSelectChain>,
sc_consensus_babe::BabeLink<Block>,
sc_consensus_beefy::BeefyVoterLinks<Block, ecdsa_crypto::AuthorityId>,
sc_consensus_beefy::BeefyRPCLinks<Block, ecdsa_crypto::AuthorityId>,
Arc<fc_db::Backend<Block, FullClient>>,
Arc<dyn StorageOverride<Block>>,
Option<Telemetry>,
),
>;
pub fn new_partial(
pub fn new_partial<RuntimeApi>(
config: &Configuration,
eth_config: &mut EthConfiguration,
) -> Result<Service, ServiceError> {
) -> Result<Service<RuntimeApi>, ServiceError>
where
RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi>> + Send + Sync + 'static,
RuntimeApi::RuntimeApi: FullRuntimeApi,
{
let telemetry = config
.telemetry_endpoints
.clone()
@ -182,7 +236,7 @@ pub fn new_partial(
let executor = wasm_builder.build();
let (client, backend, keystore_container, task_manager) =
sc_service::new_full_parts::<Block, datahaven_runtime::apis::RuntimeApi, _>(
sc_service::new_full_parts::<Block, RuntimeApi, _>(
config,
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
executor,
@ -285,13 +339,18 @@ pub fn new_partial(
})
}
// Builds a new service for a full client.
/// Builds a new service for a full client.
pub async fn new_full<
RuntimeApi,
N: sc_network::NetworkBackend<Block, <Block as sp_runtime::traits::Block>::Hash>,
>(
config: Configuration,
mut eth_config: EthConfiguration,
) -> Result<TaskManager, ServiceError> {
) -> Result<TaskManager, ServiceError>
where
RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi>> + Send + Sync + 'static,
RuntimeApi::RuntimeApi: FullRuntimeApi,
{
let sc_service::PartialComponents {
client,
backend,
@ -311,7 +370,7 @@ pub async fn new_full<
storage_override,
mut telemetry,
),
} = new_partial(&config, &mut eth_config)?;
} = new_partial::<RuntimeApi>(&config, &mut eth_config)?;
let FrontierPartialComponents {
filter_pool,
@ -472,7 +531,7 @@ pub async fn new_full<
client: client.clone(),
pool: pool.clone(),
graph: pool.pool().clone(),
beefy: BeefyDeps::<ecdsa_crypto::AuthorityId> {
beefy: BeefyDeps::<BeefyId> {
beefy_finality_proof_stream: beefy_rpc_links.from_voter_justif_stream.clone(),
beefy_best_block_stream: beefy_rpc_links.from_voter_best_beefy_stream.clone(),
subscription_executor,
@ -638,16 +697,8 @@ pub async fn new_full<
is_authority: role.is_authority(),
};
let gadget = sc_consensus_beefy::start_beefy_gadget::<
_,
_,
_,
_,
_,
_,
_,
ecdsa_crypto::AuthorityId,
>(beefy_params);
let gadget =
sc_consensus_beefy::start_beefy_gadget::<_, _, _, _, _, _, _, BeefyId>(beefy_params);
// BEEFY is part of consensus, if it fails we'll bring the node down with it to make sure it
// is noticed.

View file

@ -3,8 +3,8 @@ name = "snowbridge-pallet-system-v2"
description = "Snowbridge System Pallet V2"
version = "0.2.0"
authors = ["Snowfork <contact@snowfork.com>"]
edition.workspace = true
repository.workspace = true
edition = { workspace = true }
repository = { workspace = true }
license = "Apache-2.0"
categories = ["cryptography::cryptocurrencies"]
@ -15,30 +15,30 @@ targets = ["x86_64-unknown-linux-gnu"]
exclude-from-umbrella = true
[dependencies]
codec = { features = ["derive"], workspace = true }
frame-benchmarking = { optional = true, workspace = true }
frame-support.workspace = true
frame-system.workspace = true
codec = { workspace = true, features = ["derive"] }
frame-benchmarking = { workspace = true, optional = true }
frame-support = { workspace = true }
frame-system = { workspace = true }
log = { workspace = true }
pallet-xcm.workspace = true
scale-info = { features = ["derive"], workspace = true }
snowbridge-core.workspace = true
snowbridge-outbound-queue-primitives.workspace = true
snowbridge-pallet-system.workspace = true
sp-core.workspace = true
sp-io.workspace = true
sp-runtime.workspace = true
sp-std.workspace = true
xcm-executor.workspace = true
xcm.workspace = true
pallet-xcm = { workspace = true }
scale-info = { workspace = true, features = ["derive"] }
snowbridge-core = { workspace = true }
snowbridge-outbound-queue-primitives = { workspace = true }
snowbridge-pallet-system = { workspace = true }
sp-core = { workspace = true }
sp-io = { workspace = true }
sp-runtime = { workspace = true }
sp-std = { workspace = true }
xcm = { workspace = true }
xcm-executor = { workspace = true }
[dev-dependencies]
hex-literal = { workspace = true, default-features = true }
pallet-balances = { default-features = true, workspace = true }
polkadot-primitives = { default-features = true, workspace = true }
snowbridge-pallet-outbound-queue-v2 = { default-features = true, workspace = true }
pallet-balances = { workspace = true, default-features = true }
polkadot-primitives = { workspace = true, default-features = true }
snowbridge-pallet-outbound-queue-v2 = { workspace = true, default-features = true }
snowbridge-test-utils = { workspace = true }
sp-keyring = { default-features = true, workspace = true }
sp-keyring = { workspace = true, default-features = true }
[features]
default = ["std"]

View file

@ -6,19 +6,17 @@ edition = '2021'
license = 'Apache-2.0'
[dependencies]
codec = { features = [ "derive" ], workspace = true }
frame-benchmarking.optional = true
frame-benchmarking.workspace = true
frame-support.workspace = true
frame-system.workspace = true
log.workspace = true
scale-info = { features = [ "derive", "serde" ], workspace = true }
sp-core.workspace = true
sp-io.workspace = true
sp-runtime.workspace = true
sp-staking.workspace = true
codec = { workspace = true, features = ["derive"] }
frame-benchmarking = { workspace = true, optional = true }
frame-support = { workspace = true }
frame-system = { workspace = true }
log = { workspace = true }
pallet-session = { workspace = true, features = ['historical'] }
scale-info = { workspace = true, features = ["derive", "serde"] }
sp-core = { workspace = true }
sp-io = { workspace = true }
sp-runtime = { workspace = true }
sp-staking = { workspace = true }
[features]
default = ['std']

View file

@ -2,26 +2,33 @@
name = "datahaven-runtime-common"
description = "Common code used through the Datahaven network"
version = "0.1.0"
edition.workspace = true
edition = { workspace = true }
[dependencies]
frame-support.workspace = true
polkadot-primitives.workspace = true
polkadot-runtime-common.workspace = true
fp-account = { workspace = true }
frame-support = { workspace = true }
polkadot-primitives = { workspace = true }
polkadot-runtime-common = { workspace = true }
sp-core = { workspace = true, features = ["serde"] }
sp-runtime = { workspace = true, features = ["serde"] }
xcm = { workspace = true }
[features]
default = ["std"]
std = [
"frame-support/std",
"polkadot-primitives/std",
"polkadot-runtime-common/std",
"xcm/std"
"xcm/std",
"sp-core/std",
"sp-runtime/std",
]
runtime-benchmarks = [
"frame-support/runtime-benchmarks",
"polkadot-primitives/runtime-benchmarks",
"polkadot-runtime-common/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
]
# Set timing constants (e.g. session period) to faster versions to speed up testing.

View file

@ -19,3 +19,43 @@
pub mod constants;
pub use constants::*;
pub mod impl_on_charge_evm_transaction;
use fp_account::EthereumSignature;
pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
use sp_runtime::{
generic,
traits::{BlakeTwo256, IdentifyAccount, Verify},
};
/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
pub type Signature = EthereumSignature;
/// Some way of identifying an account on the chain. We intentionally make it equivalent
/// to the public key of our transaction signing scheme.
pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
/// Balance of an account.
pub type Balance = u128;
/// Index of a transaction in the chain.
pub type Nonce = u32;
/// A hash of some data used by the chain.
pub type Hash = sp_core::H256;
/// An index to a block.
pub type BlockNumber = u32;
/// The address format for describing accounts.
pub type Address = AccountId;
/// Block header type as expected by this runtime.
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
/// Block type as expected by this runtime.
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
/// A Block signed with a Justification
pub type SignedBlock = generic::SignedBlock<Block>;
/// BlockId type as expected by this runtime.
pub type BlockId = generic::BlockId<Block>;

View file

@ -1,6 +1,6 @@
[package]
name = "datahaven-runtime"
description = "datahaven runtime template built with polkadot-sdk."
name = "datahaven-mainnet-runtime"
description = "DataHaven Mainnet runtime"
version = "0.1.0"
license = "Unlicense"
authors = { workspace = true }
@ -14,21 +14,21 @@ targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
bridge-hub-common = { workspace = true, optional = true }
codec = { features = ["derive"], workspace = true }
codec = { workspace = true, features = ["derive"] }
datahaven-runtime-common = { workspace = true }
dhp-bridge = { workspace = true }
fp-account = { workspace = true, features = ["serde"] }
fp-evm = { workspace = true, features = ["serde"] }
fp-rpc = { workspace = true }
fp-self-contained = { workspace = true, features = ["serde", "try-runtime"] }
frame-benchmarking = { optional = true, workspace = true }
frame-benchmarking = { workspace = true, optional = true }
frame-executive = { workspace = true }
frame-metadata-hash-extension = { workspace = true }
frame-support = { features = ["experimental"], workspace = true }
frame-support = { workspace = true, features = ["experimental"] }
frame-system = { workspace = true }
frame-system-benchmarking = { optional = true, workspace = true }
frame-system-benchmarking = { workspace = true, optional = true }
frame-system-rpc-runtime-api = { workspace = true }
frame-try-runtime = { optional = true, workspace = true }
frame-try-runtime = { workspace = true, optional = true }
hex = { workspace = true }
hex-literal = { workspace = true }
pallet-authorship = { workspace = true }
@ -59,7 +59,7 @@ pallet-utility = { workspace = true }
pallet-validator-set = { workspace = true }
polkadot-primitives = { workspace = true }
polkadot-runtime-common = { workspace = true }
scale-info = { features = ["derive", "serde"], workspace = true }
scale-info = { workspace = true, features = ["derive", "serde"] }
serde_json = { workspace = true, default-features = false, features = ["alloc"] }
snowbridge-beacon-primitives = { workspace = true }
snowbridge-core = { workspace = true }
@ -76,27 +76,27 @@ snowbridge-system-v2-runtime-api = { workspace = true }
snowbridge-verification-primitives = { workspace = true }
sp-api = { workspace = true }
sp-block-builder = { workspace = true }
sp-consensus-babe = { features = ["serde"], workspace = true }
sp-consensus-beefy = { features = ["serde"], workspace = true }
sp-consensus-grandpa = { features = ["serde"], workspace = true }
sp-core = { features = ["serde"], workspace = true }
sp-consensus-babe = { workspace = true, features = ["serde"] }
sp-consensus-beefy = { workspace = true, features = ["serde"] }
sp-consensus-grandpa = { workspace = true, features = ["serde"] }
sp-core = { workspace = true, features = ["serde"] }
sp-genesis-builder = { workspace = true }
sp-inherents = { workspace = true }
sp-keyring = { workspace = true }
sp-offchain = { workspace = true }
sp-runtime = { features = ["serde"], workspace = true }
sp-runtime = { workspace = true, features = ["serde"] }
sp-session = { workspace = true }
sp-staking = { workspace = true }
sp-std = { workspace = true }
sp-storage = { workspace = true }
sp-transaction-pool = { workspace = true }
sp-version = { features = ["serde"], workspace = true }
sp-version = { workspace = true, features = ["serde"] }
xcm = { workspace = true }
xcm-builder = { workspace = true }
xcm-executor = { workspace = true }
[build-dependencies]
substrate-wasm-builder = { optional = true, workspace = true, default-features = true }
substrate-wasm-builder = { workspace = true, optional = true, default-features = true }
[features]
default = ["std"]

View file

@ -0,0 +1,220 @@
use crate::{
configs::BABE_GENESIS_EPOCH_CONFIG, AccountId, BalancesConfig, RuntimeGenesisConfig,
SessionKeys, Signature, SudoConfig,
};
use alloc::{format, vec, vec::Vec};
use hex_literal::hex;
use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
use serde_json::Value;
use sp_consensus_babe::AuthorityId as BabeId;
use sp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId;
use sp_consensus_grandpa::AuthorityId as GrandpaId;
use sp_core::{ecdsa, Pair, Public};
use sp_genesis_builder::{self, PresetId};
use sp_runtime::traits::{IdentifyAccount, Verify};
const MAINNET_EVM_CHAIN_ID: u64 = 1289;
// Returns the genesis config presets populated with given parameters.
fn testnet_genesis(
initial_authorities: Vec<(AccountId, BabeId, GrandpaId, ImOnlineId, BeefyId)>,
root_key: AccountId,
endowed_accounts: Vec<AccountId>,
evm_chain_id: u64,
) -> Value {
let config = RuntimeGenesisConfig {
balances: BalancesConfig {
balances: endowed_accounts
.iter()
.cloned()
.map(|k| (k, 1u128 << 110))
.collect::<Vec<_>>(),
},
babe: pallet_babe::GenesisConfig {
epoch_config: BABE_GENESIS_EPOCH_CONFIG,
..Default::default()
},
evm_chain_id: pallet_evm_chain_id::GenesisConfig {
chain_id: evm_chain_id,
..Default::default()
},
session: pallet_session::GenesisConfig {
keys: initial_authorities
.iter()
.map(|(account, babe, grandpa, im_online, beefy)| {
(
*account,
*account,
session_keys(
babe.clone(),
grandpa.clone(),
im_online.clone(),
beefy.clone(),
),
)
})
.collect::<Vec<_>>(),
..Default::default()
},
sudo: SudoConfig {
key: Some(root_key),
},
validator_set: pallet_validator_set::GenesisConfig {
initial_validators: initial_authorities
.iter()
.map(|(account, ..)| *account)
.collect::<Vec<_>>()
.try_into()
.expect("Too many initial authorities"),
},
..Default::default()
};
serde_json::to_value(config).expect("Could not build genesis config.")
}
/// Return the development genesis config.
pub fn development_config_genesis() -> Value {
let mut endowed_accounts = pre_funded_accounts();
endowed_accounts.sort();
testnet_genesis(
vec![authority_keys_from_seed("Alice")],
alith(),
endowed_accounts,
MAINNET_EVM_CHAIN_ID,
)
}
/// Return the local genesis config preset.
pub fn local_config_genesis() -> Value {
let mut endowed_accounts = pre_funded_accounts();
endowed_accounts.sort();
testnet_genesis(
vec![
authority_keys_from_seed("Alice"),
authority_keys_from_seed("Bob"),
authority_keys_from_seed("Charlie"),
authority_keys_from_seed("Dave"),
authority_keys_from_seed("Eve"),
authority_keys_from_seed("Ferdie"),
],
alith(),
endowed_accounts,
MAINNET_EVM_CHAIN_ID,
)
}
/// Provides the JSON representation of predefined genesis config for given `id`.
pub fn get_preset(id: &PresetId) -> Option<Vec<u8>> {
let patch = match id.as_str() {
sp_genesis_builder::DEV_RUNTIME_PRESET => development_config_genesis(),
sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET => local_config_genesis(),
_ => return None,
};
Some(
serde_json::to_string(&patch)
.expect("serialization to json is expected to work. qed.")
.into_bytes(),
)
}
/// List of supported presets.
pub fn preset_names() -> Vec<PresetId> {
vec![
PresetId::from(sp_genesis_builder::DEV_RUNTIME_PRESET),
PresetId::from(sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET),
]
}
/// 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()
}
fn session_keys(
babe: BabeId,
grandpa: GrandpaId,
im_online: ImOnlineId,
beefy: BeefyId,
) -> SessionKeys {
SessionKeys {
babe,
grandpa,
im_online,
beefy,
}
}
type AccountPublic = <Signature as Verify>::Signer;
/// Generate an account ID 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 a Babe authority key.
pub fn authority_keys_from_seed(s: &str) -> (AccountId, BabeId, GrandpaId, ImOnlineId, BeefyId) {
(
get_account_id_from_seed::<ecdsa::Public>(s),
get_from_seed::<BabeId>(s),
get_from_seed::<GrandpaId>(s),
get_from_seed::<ImOnlineId>(s),
get_from_seed::<BeefyId>(s),
)
}
pub fn alith() -> AccountId {
AccountId::from(hex!("f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"))
}
pub fn baltathar() -> AccountId {
AccountId::from(hex!("3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"))
}
pub fn charleth() -> AccountId {
AccountId::from(hex!("798d4Ba9baf0064Ec19eB4F0a1a45785ae9D6DFc"))
}
pub fn dorothy() -> AccountId {
AccountId::from(hex!("773539d4Ac0e786233D90A233654ccEE26a613D9"))
}
pub fn ethan() -> AccountId {
AccountId::from(hex!("Ff64d3F6efE2317EE2807d2235B1ac2AA69d9E87"))
}
pub fn frank() -> AccountId {
AccountId::from(hex!("C0F0f4ab324C46e55D02D0033343B4Be8A55532d"))
}
pub fn beacon_relayer() -> AccountId {
AccountId::from(hex!("c46e141b5083721ad5f5056ba1cded69dce4a65f"))
}
/// Get pre-funded accounts
pub fn pre_funded_accounts() -> Vec<AccountId> {
// These addresses are derived from Substrate's canonical mnemonic:
// bottom drive obey lake curtain smoke basket hold race lonely fit walk
vec![
get_account_id_from_seed::<ecdsa::Public>("Alice"),
get_account_id_from_seed::<ecdsa::Public>("Bob"),
get_account_id_from_seed::<ecdsa::Public>("Charlie"),
get_account_id_from_seed::<ecdsa::Public>("Dave"),
get_account_id_from_seed::<ecdsa::Public>("Eve"),
get_account_id_from_seed::<ecdsa::Public>("Ferdie"),
alith(),
baltathar(),
charleth(),
dorothy(),
ethan(),
frank(),
beacon_relayer(),
]
}

View file

@ -0,0 +1,322 @@
#![cfg_attr(not(feature = "std"), no_std)]
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
#![recursion_limit = "256"]
extern crate alloc;
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
pub mod apis;
#[cfg(feature = "runtime-benchmarks")]
mod benchmarks;
pub mod configs;
use alloc::{borrow::Cow, vec::Vec};
use sp_runtime::{generic, impl_opaque_keys};
#[cfg(feature = "std")]
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
pub use frame_system::Call as SystemCall;
pub use pallet_balances::Call as BalancesCall;
pub use pallet_timestamp::Call as TimestampCall;
use sp_core::H160;
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
pub use datahaven_runtime_common::{
AccountId, Address, Balance, BlockNumber, Hash, Header, Nonce, Signature,
};
pub mod genesis_config_presets;
/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
/// the specifics of the runtime. They can then be made to be agnostic over specific formats
/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
/// to even the core data structures.
pub mod opaque {
use super::*;
use sp_runtime::{
generic,
traits::{BlakeTwo256, Hash as HashT},
};
pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
/// Opaque block header type.
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
/// Opaque block type.
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
/// Opaque block identifier type.
pub type BlockId = generic::BlockId<Block>;
/// Opaque block hash type.
pub type Hash = <BlakeTwo256 as HashT>::Output;
}
impl_opaque_keys! {
pub struct SessionKeys {
pub babe: Babe,
pub grandpa: Grandpa,
pub im_online: ImOnline,
pub beefy: Beefy,
}
}
// To learn more about runtime versioning, see:
// https://docs.substrate.io/main-docs/build/upgrade#runtime-versioning
#[sp_version::runtime_version]
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: Cow::Borrowed("datahaven-mainnet"),
impl_name: Cow::Borrowed("datahaven-mainnet"),
authoring_version: 1,
// The version of the runtime specification. A full node will not attempt to use its native
// runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`,
// `spec_version`, and `authoring_version` are the same between Wasm and native.
// This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
// the compatible custom types.
spec_version: 100,
impl_version: 1,
apis: apis::RUNTIME_API_VERSIONS,
transaction_version: 1,
system_version: 1,
};
mod block_times {
/// This determines the average expected block time that we are targeting. Blocks will be
/// produced at a minimum duration defined by `SLOT_DURATION`. `SLOT_DURATION` is picked up by
/// `pallet_timestamp` which is in turn picked up by `pallet_babe` to implement `fn
/// slot_duration()`.
///
/// Change this to adjust the block time.
pub const MILLI_SECS_PER_BLOCK: u64 = 6000;
// NOTE: Currently it is not possible to change the slot duration after the chain has started.
// Attempting to do so will brick block production.
pub const SLOT_DURATION: u64 = MILLI_SECS_PER_BLOCK;
}
pub use block_times::*;
// Time is measured by number of blocks.
pub const MINUTES: BlockNumber = 60_000 / (MILLI_SECS_PER_BLOCK as BlockNumber);
pub const HOURS: BlockNumber = MINUTES * 60;
pub const DAYS: BlockNumber = HOURS * 24;
pub const BLOCK_HASH_COUNT: BlockNumber = 2400;
// Provide a common factor between runtimes based on a supply of 10_000_000 tokens.
pub const SUPPLY_FACTOR: Balance = 1;
// Unit = the base number of indivisible units for balances
pub const UNIT: Balance = 1_000_000_000_000;
pub const MILLI_UNIT: Balance = 1_000_000_000;
pub const MICRO_UNIT: Balance = 1_000_000;
pub const STORAGE_BYTE_FEE: Balance = 100 * MICRO_UNIT * SUPPLY_FACTOR;
/// Existential deposit.
pub const EXISTENTIAL_DEPOSIT: Balance = MILLI_UNIT;
pub const fn deposit(items: u32, bytes: u32) -> Balance {
items as Balance * UNIT * SUPPLY_FACTOR + (bytes as Balance) * STORAGE_BYTE_FEE
}
/// The version information used to identify this runtime when compiled natively.
#[cfg(feature = "std")]
pub fn native_version() -> NativeVersion {
NativeVersion {
runtime_version: VERSION,
can_author_with: Default::default(),
}
}
/// Block type as expected by this runtime.
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
/// The SignedExtension to the basic transaction logic.
pub type SignedExtra = (
frame_system::CheckNonZeroSender<Runtime>,
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>,
frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
);
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic =
fp_self_contained::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
pub type CheckedExtrinsic =
fp_self_contained::CheckedExtrinsic<AccountId, RuntimeCall, SignedExtra, H160>;
/// The payload being signed in transactions.
pub type SignedPayload = generic::SignedPayload<RuntimeCall, SignedExtra>;
/// All migrations of the runtime, aside from the ones declared in the pallets.
///
/// This can be a tuple of types, each implementing `OnRuntimeUpgrade`.
#[allow(unused_parens)]
type Migrations = ();
/// Executive: handles dispatch to the various modules.
pub type Executive = frame_executive::Executive<
Runtime,
Block,
frame_system::ChainContext<Runtime>,
Runtime,
AllPalletsWithSystem,
Migrations,
>;
impl<C> frame_system::offchain::CreateTransactionBase<C> for Runtime
where
RuntimeCall: From<C>,
{
type Extrinsic = UncheckedExtrinsic;
type RuntimeCall = RuntimeCall;
}
impl<C> frame_system::offchain::CreateInherent<C> for Runtime
where
RuntimeCall: From<C>,
{
fn create_inherent(call: RuntimeCall) -> UncheckedExtrinsic {
UncheckedExtrinsic::new_bare(call)
}
}
// Create the runtime by composing the FRAME pallets that were previously configured.
#[frame_support::runtime]
mod runtime {
#[runtime::runtime]
#[runtime::derive(
RuntimeCall,
RuntimeEvent,
RuntimeError,
RuntimeOrigin,
RuntimeFreezeReason,
RuntimeHoldReason,
RuntimeSlashReason,
RuntimeLockId,
RuntimeTask
)]
pub struct Runtime;
// ╔══════════════════ System and Consensus Pallets ═════════════════╗
#[runtime::pallet_index(0)]
pub type System = frame_system;
// Babe must be before session.
#[runtime::pallet_index(1)]
pub type Babe = pallet_babe;
#[runtime::pallet_index(2)]
pub type Timestamp = pallet_timestamp;
#[runtime::pallet_index(3)]
pub type Balances = pallet_balances;
// Consensus support.
// Authorship must be before session in order to note author in the correct session and era.
#[runtime::pallet_index(4)]
pub type Authorship = pallet_authorship;
#[runtime::pallet_index(5)]
pub type Offences = pallet_offences;
#[runtime::pallet_index(6)]
pub type Historical = pallet_session::historical;
// Validator set must be before Session.
#[runtime::pallet_index(7)]
pub type ValidatorSet = pallet_validator_set;
#[runtime::pallet_index(8)]
pub type Session = pallet_session;
#[runtime::pallet_index(9)]
pub type ImOnline = pallet_im_online;
#[runtime::pallet_index(10)]
pub type Grandpa = pallet_grandpa;
#[runtime::pallet_index(11)]
pub type TransactionPayment = pallet_transaction_payment;
#[runtime::pallet_index(12)]
pub type Beefy = pallet_beefy;
#[runtime::pallet_index(13)]
pub type Mmr = pallet_mmr;
#[runtime::pallet_index(14)]
pub type BeefyMmrLeaf = pallet_beefy_mmr;
// ╚═════════════════ System and Consensus Pallets ══════════════════╝
// ╔═════════════════ Polkadot SDK Utility Pallets ══════════════════╗
#[runtime::pallet_index(30)]
pub type Utility = pallet_utility;
#[runtime::pallet_index(31)]
pub type Scheduler = pallet_scheduler;
#[runtime::pallet_index(32)]
pub type Preimage = pallet_preimage;
#[runtime::pallet_index(33)]
pub type Identity = pallet_identity;
#[runtime::pallet_index(34)]
pub type Multisig = pallet_multisig;
#[runtime::pallet_index(35)]
pub type Parameters = pallet_parameters;
#[runtime::pallet_index(36)]
pub type Sudo = pallet_sudo;
#[runtime::pallet_index(37)]
pub type MessageQueue = pallet_message_queue;
// ╚═════════════════ Polkadot SDK Utility Pallets ══════════════════╝
// ╔════════════════════ Frontier (EVM) Pallets ═════════════════════╗
#[runtime::pallet_index(50)]
pub type Ethereum = pallet_ethereum;
#[runtime::pallet_index(51)]
pub type Evm = pallet_evm;
#[runtime::pallet_index(52)]
pub type EvmChainId = pallet_evm_chain_id;
// ╚════════════════════ Frontier (EVM) Pallets ═════════════════════╝
// ╔══════════════════════ Snowbridge Pallets ═══════════════════════╗
#[runtime::pallet_index(60)]
pub type EthereumBeaconClient = snowbridge_pallet_ethereum_client;
#[runtime::pallet_index(61)]
pub type InboundQueueV2 = snowbridge_pallet_inbound_queue_v2;
#[runtime::pallet_index(62)]
pub type OutboundQueueV2 = snowbridge_pallet_outbound_queue_v2;
#[runtime::pallet_index(63)]
pub type SnowbridgeSystem = snowbridge_pallet_system;
#[runtime::pallet_index(64)]
pub type SnowbridgeSystemV2 = snowbridge_pallet_system_v2;
// ╚══════════════════════ Snowbridge Pallets ═══════════════════════╝
// ╔══════════════════════ StorageHub Pallets ═══════════════════════╗
// Start with index 70
// ╚══════════════════════ StorageHub Pallets ═══════════════════════╝
// ╔═══════════════════ DataHaven-specific Pallets ══════════════════╗
// Start with index 100
#[runtime::pallet_index(100)]
pub type OutboundCommitmentStore = pallet_outbound_commitment_store;
// ╚═══════════════════ DataHaven-specific Pallets ══════════════════╝
}

View file

@ -0,0 +1,267 @@
[package]
name = "datahaven-stagenet-runtime"
description = "DataHaven Stagenet runtime"
version = "0.1.0"
license = "Unlicense"
authors = { workspace = true }
homepage = { workspace = true }
repository = { workspace = true }
edition = { workspace = true }
publish = false
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
bridge-hub-common = { workspace = true, optional = true }
codec = { workspace = true, features = ["derive"] }
datahaven-runtime-common = { workspace = true }
dhp-bridge = { workspace = true }
fp-account = { workspace = true, features = ["serde"] }
fp-evm = { workspace = true, features = ["serde"] }
fp-rpc = { workspace = true }
fp-self-contained = { workspace = true, features = ["serde", "try-runtime"] }
frame-benchmarking = { workspace = true, optional = true }
frame-executive = { workspace = true }
frame-metadata-hash-extension = { workspace = true }
frame-support = { workspace = true, features = ["experimental"] }
frame-system = { workspace = true }
frame-system-benchmarking = { workspace = true, optional = true }
frame-system-rpc-runtime-api = { workspace = true }
frame-try-runtime = { workspace = true, optional = true }
hex = { workspace = true }
hex-literal = { workspace = true }
pallet-authorship = { workspace = true }
pallet-babe = { workspace = true }
pallet-balances = { workspace = true }
pallet-beefy = { workspace = true }
pallet-beefy-mmr = { workspace = true }
pallet-ethereum = { workspace = true }
pallet-evm = { workspace = true }
pallet-evm-chain-id = { workspace = true }
pallet-grandpa = { workspace = true }
pallet-identity = { workspace = true }
pallet-im-online = { workspace = true }
pallet-message-queue = { workspace = true }
pallet-mmr = { workspace = true }
pallet-multisig = { workspace = true }
pallet-offences = { workspace = true }
pallet-outbound-commitment-store = { workspace = true }
pallet-parameters = { workspace = true }
pallet-preimage = { workspace = true }
pallet-scheduler = { workspace = true }
pallet-session = { workspace = true }
pallet-sudo = { workspace = true }
pallet-timestamp = { workspace = true }
pallet-transaction-payment = { workspace = true }
pallet-transaction-payment-rpc-runtime-api = { workspace = true }
pallet-utility = { workspace = true }
pallet-validator-set = { workspace = true }
polkadot-primitives = { workspace = true }
polkadot-runtime-common = { workspace = true }
scale-info = { workspace = true, features = ["derive", "serde"] }
serde_json = { workspace = true, default-features = false, features = ["alloc"] }
snowbridge-beacon-primitives = { workspace = true }
snowbridge-core = { workspace = true }
snowbridge-inbound-queue-primitives = { workspace = true }
snowbridge-merkle-tree = { workspace = true }
snowbridge-outbound-queue-primitives = { workspace = true }
snowbridge-outbound-queue-v2-runtime-api = { workspace = true }
snowbridge-pallet-ethereum-client = { workspace = true }
snowbridge-pallet-inbound-queue-v2 = { workspace = true }
snowbridge-pallet-outbound-queue-v2 = { workspace = true }
snowbridge-pallet-system = { workspace = true }
snowbridge-pallet-system-v2 = { workspace = true }
snowbridge-system-v2-runtime-api = { workspace = true }
snowbridge-verification-primitives = { workspace = true }
sp-api = { workspace = true }
sp-block-builder = { workspace = true }
sp-consensus-babe = { workspace = true, features = ["serde"] }
sp-consensus-beefy = { workspace = true, features = ["serde"] }
sp-consensus-grandpa = { workspace = true, features = ["serde"] }
sp-core = { workspace = true, features = ["serde"] }
sp-genesis-builder = { workspace = true }
sp-inherents = { workspace = true }
sp-keyring = { workspace = true }
sp-offchain = { workspace = true }
sp-runtime = { workspace = true, features = ["serde"] }
sp-session = { workspace = true }
sp-staking = { workspace = true }
sp-std = { workspace = true }
sp-storage = { workspace = true }
sp-transaction-pool = { workspace = true }
sp-version = { workspace = true, features = ["serde"] }
xcm = { workspace = true }
xcm-builder = { workspace = true }
xcm-executor = { workspace = true }
[build-dependencies]
substrate-wasm-builder = { workspace = true, optional = true, default-features = true }
[features]
default = ["std"]
std = [
"codec/std",
"datahaven-runtime-common/std",
"fp-account/std",
"frame-benchmarking?/std",
"frame-executive/std",
"frame-metadata-hash-extension/std",
"frame-support/std",
"frame-system-benchmarking?/std",
"frame-system-rpc-runtime-api/std",
"frame-system/std",
"frame-try-runtime?/std",
"pallet-authorship/std",
"pallet-babe/std",
"pallet-balances/std",
"pallet-beefy-mmr/std",
"pallet-beefy/std",
"pallet-ethereum/std",
"pallet-evm-chain-id/std",
"pallet-evm/std",
"pallet-grandpa/std",
"pallet-identity/std",
"pallet-im-online/std",
"pallet-message-queue/std",
"pallet-mmr/std",
"pallet-multisig/std",
"pallet-offences/std",
"pallet-parameters/std",
"pallet-preimage/std",
"pallet-scheduler/std",
"pallet-session/std",
"pallet-sudo/std",
"pallet-timestamp/std",
"pallet-transaction-payment-rpc-runtime-api/std",
"pallet-transaction-payment/std",
"pallet-utility/std",
"pallet-validator-set/std",
"polkadot-primitives/std",
"polkadot-runtime-common/std",
"scale-info/std",
"serde_json/std",
"snowbridge-beacon-primitives/std",
"snowbridge-inbound-queue-primitives/std",
"snowbridge-outbound-queue-primitives/std",
"snowbridge-pallet-ethereum-client/std",
"snowbridge-pallet-inbound-queue-v2/std",
"snowbridge-pallet-outbound-queue-v2/std",
"snowbridge-merkle-tree/std",
"snowbridge-outbound-queue-v2-runtime-api/std",
"snowbridge-pallet-system/std",
"snowbridge-pallet-system-v2/std",
"snowbridge-system-v2-runtime-api/std",
"dhp-bridge/std",
"snowbridge-verification-primitives/std",
"sp-api/std",
"sp-block-builder/std",
"sp-consensus-babe/std",
"sp-consensus-beefy/std",
"sp-consensus-grandpa/std",
"sp-core/std",
"sp-genesis-builder/std",
"sp-inherents/std",
"sp-keyring/std",
"sp-offchain/std",
"sp-runtime/std",
"sp-session/std",
"sp-staking/std",
"sp-std/std",
"sp-storage/std",
"sp-transaction-pool/std",
"sp-version/std",
"substrate-wasm-builder",
"pallet-outbound-commitment-store/std",
]
runtime-benchmarks = [
"bridge-hub-common",
"datahaven-runtime-common/runtime-benchmarks",
"frame-benchmarking/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-system-benchmarking/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-beefy-mmr/runtime-benchmarks",
"pallet-ethereum/runtime-benchmarks",
"pallet-evm/runtime-benchmarks",
"pallet-grandpa/runtime-benchmarks",
"pallet-identity/runtime-benchmarks",
"pallet-im-online/runtime-benchmarks",
"pallet-message-queue/runtime-benchmarks",
"pallet-mmr/runtime-benchmarks",
"pallet-multisig/runtime-benchmarks",
"pallet-offences/runtime-benchmarks",
"pallet-parameters/runtime-benchmarks",
"pallet-preimage/runtime-benchmarks",
"pallet-scheduler/runtime-benchmarks",
"pallet-sudo/runtime-benchmarks",
"pallet-timestamp/runtime-benchmarks",
"pallet-utility/runtime-benchmarks",
"polkadot-primitives/runtime-benchmarks",
"polkadot-runtime-common/runtime-benchmarks",
"snowbridge-inbound-queue-primitives/runtime-benchmarks",
"snowbridge-pallet-ethereum-client/runtime-benchmarks",
"snowbridge-pallet-inbound-queue-v2/runtime-benchmarks",
"snowbridge-pallet-system-v2/runtime-benchmarks",
"snowbridge-pallet-outbound-queue-v2/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"snowbridge-pallet-system/runtime-benchmarks",
"pallet-outbound-commitment-store/runtime-benchmarks",
]
try-runtime = [
"fp-self-contained/try-runtime",
"frame-executive/try-runtime",
"frame-support/try-runtime",
"frame-system/try-runtime",
"frame-try-runtime/try-runtime",
"pallet-authorship/try-runtime",
"pallet-babe/try-runtime",
"pallet-balances/try-runtime",
"pallet-beefy-mmr/try-runtime",
"pallet-beefy/try-runtime",
"pallet-ethereum/try-runtime",
"pallet-evm/try-runtime",
"pallet-grandpa/try-runtime",
"pallet-identity/try-runtime",
"pallet-im-online/try-runtime",
"pallet-message-queue/try-runtime",
"pallet-mmr/try-runtime",
"pallet-multisig/try-runtime",
"pallet-offences/try-runtime",
"pallet-parameters/try-runtime",
"pallet-preimage/try-runtime",
"pallet-scheduler/try-runtime",
"pallet-session/try-runtime",
"pallet-sudo/try-runtime",
"pallet-timestamp/try-runtime",
"pallet-transaction-payment/try-runtime",
"pallet-utility/try-runtime",
"polkadot-runtime-common/try-runtime",
"snowbridge-pallet-ethereum-client/try-runtime",
"snowbridge-pallet-inbound-queue-v2/try-runtime",
"snowbridge-pallet-system-v2/try-runtime",
"snowbridge-pallet-outbound-queue-v2/try-runtime",
"sp-runtime/try-runtime",
"snowbridge-pallet-system/try-runtime",
"pallet-outbound-commitment-store/try-runtime",
]
fast-runtime = [
"datahaven-runtime-common/fast-runtime",
]
# Enable the metadata hash generation.
#
# This is hidden behind a feature because it increases the compile time.
# The wasm binary needs to be compiled twice, once to fetch the metadata,
# generate the metadata hash and then a second time with the
# `RUNTIME_METADATA_HASH` environment variable set for the `CheckMetadataHash`
# extension.
metadata-hash = ["substrate-wasm-builder/metadata-hash"]
# A convenience feature for enabling things when doing a build
# for an on-chain release.
on-chain-release-build = ["metadata-hash", "sp-api/disable-logging"]

View file

@ -0,0 +1,16 @@
#[cfg(all(feature = "std", feature = "metadata-hash"))]
fn main() {
substrate_wasm_builder::WasmBuilder::init_with_defaults()
.enable_metadata_hash("UNIT", 12)
.build();
}
#[cfg(all(feature = "std", not(feature = "metadata-hash")))]
fn main() {
substrate_wasm_builder::WasmBuilder::build_using_defaults();
}
/// The wasm builder is deactivated when compiling
/// this crate for wasm to speed up the compilation.
#[cfg(not(feature = "std"))]
fn main() {}

View file

@ -0,0 +1,800 @@
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// For more information, please refer to <http://unlicense.org>
// Local module imports
use super::{
AccountId, Babe, Balance, Beefy, BeefyMmrLeaf, Block, BlockNumber, Ethereum, Executive,
Grandpa, Historical, InherentDataExt, Mmr, Nonce, Runtime, RuntimeCall, RuntimeGenesisConfig,
RuntimeOrigin, SessionKeys, System, TransactionPayment, UncheckedExtrinsic, VERSION,
};
// External crates imports
use crate::configs::BABE_GENESIS_EPOCH_CONFIG;
use alloc::vec::Vec;
use codec::Encode;
use datahaven_runtime_common::time::EpochDurationInBlocks;
use fp_rpc::TransactionStatus;
use frame_support::traits::OnFinalize;
use pallet_ethereum::Transaction as EthereumTransaction;
use pallet_evm::GasWeightMapping;
use frame_support::traits::KeyOwnerProofSystem;
use frame_support::{
genesis_builder_helper::{build_state, get_preset},
weights::Weight,
};
use pallet_ethereum::Call::transact;
use pallet_evm::Account as EVMAccount;
use pallet_evm::FeeCalculator;
use pallet_evm::Runner;
use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId};
use polkadot_primitives::Hash;
use snowbridge_core::AgentId;
use sp_api::impl_runtime_apis;
use sp_consensus_beefy::{
ecdsa_crypto::{AuthorityId as BeefyId, Signature as BeefySignature},
AncestryHelper,
};
use sp_core::{Get, H256, U256};
use sp_core::{OpaqueMetadata, H160};
use sp_runtime::traits::{DispatchInfoOf, Dispatchable, PostDispatchInfoOf};
use sp_runtime::transaction_validity::TransactionValidityError;
use sp_runtime::{
traits::Block as BlockT,
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult, Permill,
};
use sp_version::RuntimeVersion;
use xcm::VersionedLocation;
/// MMR helper types.
mod mmr {
use super::Runtime;
pub use pallet_mmr::primitives::*;
pub type Leaf = <<Runtime as pallet_mmr::Config>::LeafData as LeafDataProvider>::LeafData;
pub type Hashing = <Runtime as pallet_mmr::Config>::Hashing;
pub type Hash = <Hashing as sp_runtime::traits::Hash>::Output;
}
#[derive(Clone)]
pub struct TransactionConverter;
impl fp_self_contained::SelfContainedCall for RuntimeCall {
type SignedInfo = H160;
fn is_self_contained(&self) -> bool {
match self {
RuntimeCall::Ethereum(call) => call.is_self_contained(),
_ => false,
}
}
fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {
match self {
RuntimeCall::Ethereum(call) => call.check_self_contained(),
_ => None,
}
}
fn validate_self_contained(
&self,
signed_info: &Self::SignedInfo,
dispatch_info: &DispatchInfoOf<RuntimeCall>,
len: usize,
) -> Option<TransactionValidity> {
match self {
RuntimeCall::Ethereum(call) => {
call.validate_self_contained(signed_info, dispatch_info, len)
}
_ => None,
}
}
fn pre_dispatch_self_contained(
&self,
info: &Self::SignedInfo,
dispatch_info: &DispatchInfoOf<RuntimeCall>,
len: usize,
) -> Option<Result<(), TransactionValidityError>> {
match self {
RuntimeCall::Ethereum(call) => {
call.pre_dispatch_self_contained(info, dispatch_info, len)
}
_ => None,
}
}
fn apply_self_contained(
self,
info: Self::SignedInfo,
) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {
match self {
call @ RuntimeCall::Ethereum(pallet_ethereum::Call::transact { .. }) => {
Some(call.dispatch(RuntimeOrigin::from(
pallet_ethereum::RawOrigin::EthereumTransaction(info),
)))
}
_ => None,
}
}
}
impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {
fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {
UncheckedExtrinsic::new_bare(
pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
)
}
}
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) -> sp_runtime::ExtrinsicInclusionMode {
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() -> 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: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
data.create_extrinsics()
}
fn check_inherents(
block: Block,
data: sp_inherents::InherentData,
) -> sp_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_session::SessionKeys<Block> for Runtime {
fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
SessionKeys::generate(seed)
}
fn decode_session_keys(
encoded: Vec<u8>,
) -> Option<Vec<(Vec<u8>, sp_core::crypto::KeyTypeId)>> {
SessionKeys::decode_into_raw_public_keys(&encoded)
}
}
impl sp_consensus_babe::BabeApi<Block> for Runtime {
fn configuration() -> sp_consensus_babe::BabeConfiguration {
let epoch_config = Babe::epoch_config().unwrap_or(BABE_GENESIS_EPOCH_CONFIG);
sp_consensus_babe::BabeConfiguration {
slot_duration: Babe::slot_duration(),
epoch_length: EpochDurationInBlocks::get().into(),
c: epoch_config.c,
authorities: Babe::authorities().to_vec(),
randomness: Babe::randomness(),
allowed_slots: epoch_config.allowed_slots,
}
}
fn current_epoch_start() -> sp_consensus_babe::Slot {
Babe::current_epoch_start()
}
fn current_epoch() -> sp_consensus_babe::Epoch {
Babe::current_epoch()
}
fn next_epoch() -> sp_consensus_babe::Epoch {
Babe::next_epoch()
}
fn generate_key_ownership_proof(
_slot: sp_consensus_babe::Slot,
authority_id: sp_consensus_babe::AuthorityId,
) -> Option<sp_consensus_babe::OpaqueKeyOwnershipProof> {
use codec::Encode;
Historical::prove((sp_consensus_babe::KEY_TYPE, authority_id))
.map(|p| p.encode())
.map(sp_consensus_babe::OpaqueKeyOwnershipProof::new)
}
fn submit_report_equivocation_unsigned_extrinsic(
equivocation_proof: sp_consensus_babe::EquivocationProof<<Block as BlockT>::Header>,
key_owner_proof: sp_consensus_babe::OpaqueKeyOwnershipProof,
) -> Option<()> {
let key_owner_proof = key_owner_proof.decode()?;
Babe::submit_unsigned_equivocation_report(
equivocation_proof,
key_owner_proof,
)
}
}
impl sp_consensus_grandpa::GrandpaApi<Block> for Runtime {
fn grandpa_authorities() -> Vec<(GrandpaId, u64)> {
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,
sp_runtime::traits::NumberFor<Block>,
>,
key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof,
) -> Option<()> {
let key_owner_proof = key_owner_proof.decode()?;
Grandpa::submit_unsigned_equivocation_report(
equivocation_proof,
key_owner_proof,
)
}
fn generate_key_ownership_proof(
_set_id: fg_primitives::SetId,
authority_id: fg_primitives::AuthorityId,
) -> Option<fg_primitives::OpaqueKeyOwnershipProof> {
Historical::prove((fg_primitives::KEY_TYPE, authority_id))
.map(|p| p.encode())
.map(fg_primitives::OpaqueKeyOwnershipProof::new)
}
}
#[api_version(2)]
impl mmr::MmrApi<Block, mmr::Hash, BlockNumber> for Runtime {
fn mmr_root() -> Result<mmr::Hash, mmr::Error> {
Ok(pallet_mmr::RootHash::<Runtime>::get())
}
fn mmr_leaf_count() -> Result<mmr::LeafIndex, mmr::Error> {
Ok(pallet_mmr::NumberOfLeaves::<Runtime>::get())
}
fn generate_proof(
block_numbers: Vec<BlockNumber>,
best_known_block_number: Option<BlockNumber>,
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::LeafProof<mmr::Hash>), mmr::Error> {
Mmr::generate_proof(block_numbers, best_known_block_number).map(
|(leaves, proof)| {
(
leaves
.into_iter()
.map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf))
.collect(),
proof,
)
},
)
}
fn verify_proof(leaves: Vec<mmr::EncodableOpaqueLeaf>, proof: mmr::LeafProof<mmr::Hash>)
-> Result<(), mmr::Error>
{
let leaves = leaves.into_iter().map(|leaf|
leaf.into_opaque_leaf()
.try_decode()
.ok_or(mmr::Error::Verify)).collect::<Result<Vec<mmr::Leaf>, mmr::Error>>()?;
Mmr::verify_leaves(leaves, proof)
}
fn verify_proof_stateless(
root: mmr::Hash,
leaves: Vec<mmr::EncodableOpaqueLeaf>,
proof: mmr::LeafProof<mmr::Hash>
) -> Result<(), mmr::Error> {
let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect();
pallet_mmr::verify_leaves_proof::<mmr::Hashing, _>(root, nodes, proof)
}
}
impl pallet_beefy_mmr::BeefyMmrApi<Block, Hash> for RuntimeApi {
fn authority_set_proof() -> sp_consensus_beefy::mmr::BeefyAuthoritySet<Hash> {
BeefyMmrLeaf::authority_set_proof()
}
fn next_authority_set_proof() -> sp_consensus_beefy::mmr::BeefyNextAuthoritySet<Hash> {
BeefyMmrLeaf::next_authority_set_proof()
}
}
#[api_version(5)]
impl sp_consensus_beefy::BeefyApi<Block, BeefyId> for Runtime {
fn beefy_genesis() -> Option<BlockNumber> {
pallet_beefy::GenesisBlock::<Runtime>::get()
}
fn validator_set() -> Option<sp_consensus_beefy::ValidatorSet<BeefyId>> {
Beefy::validator_set()
}
fn submit_report_double_voting_unsigned_extrinsic(
equivocation_proof: sp_consensus_beefy::DoubleVotingProof<
BlockNumber,
BeefyId,
BeefySignature,
>,
key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof,
) -> Option<()> {
let key_owner_proof = key_owner_proof.decode()?;
Beefy::submit_unsigned_double_voting_report(
equivocation_proof,
key_owner_proof,
)
}
fn submit_report_fork_voting_unsigned_extrinsic(
equivocation_proof:
sp_consensus_beefy::ForkVotingProof<
<Block as BlockT>::Header,
BeefyId,
sp_runtime::OpaqueValue
>,
key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof,
) -> Option<()> {
Beefy::submit_unsigned_fork_voting_report(
equivocation_proof.try_into()?,
key_owner_proof.decode()?,
)
}
fn submit_report_future_block_voting_unsigned_extrinsic(
equivocation_proof: sp_consensus_beefy::FutureBlockVotingProof<BlockNumber, BeefyId>,
key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof,
) -> Option<()> {
Beefy::submit_unsigned_future_block_voting_report(
equivocation_proof,
key_owner_proof.decode()?,
)
}
fn generate_key_ownership_proof(
_set_id: sp_consensus_beefy::ValidatorSetId,
authority_id: BeefyId,
) -> Option<sp_consensus_beefy::OpaqueKeyOwnershipProof> {
Historical::prove((sp_consensus_beefy::KEY_TYPE, authority_id))
.map(|p| p.encode())
.map(sp_consensus_beefy::OpaqueKeyOwnershipProof::new)
}
fn generate_ancestry_proof(
prev_block_number: BlockNumber,
best_known_block_number: Option<BlockNumber>,
) -> Option<sp_runtime::OpaqueValue> {
use codec::Encode;
BeefyMmrLeaf::generate_proof(prev_block_number, best_known_block_number)
.map(|p| p.encode())
.map(sp_runtime::OpaqueValue::new)
}
}
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::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 snowbridge_outbound_queue_v2_runtime_api::OutboundQueueV2Api<Block, Balance> for Runtime {
fn prove_message(leaf_index: u64) -> Option<snowbridge_merkle_tree::MerkleProof> {
snowbridge_pallet_outbound_queue_v2::api::prove_message::<Runtime>(leaf_index)
}
}
impl snowbridge_system_v2_runtime_api::ControlV2Api<Block> for Runtime {
fn agent_id(location: VersionedLocation) -> Option<AgentId> {
snowbridge_pallet_system_v2::api::agent_id::<Runtime>(location)
}
}
#[cfg(feature = "runtime-benchmarks")]
impl frame_benchmarking::Benchmark<Block> for Runtime {
fn benchmark_metadata(extra: bool) -> (
Vec<frame_benchmarking::BenchmarkList>,
Vec<frame_support::traits::StorageInfo>,
) {
use frame_benchmarking::{baseline, Benchmarking, BenchmarkList};
use frame_support::traits::StorageInfoTrait;
use frame_system_benchmarking::Pallet as SystemBench;
use baseline::Pallet as BaselineBench;
use super::*;
let mut list = Vec::<BenchmarkList>::new();
list_benchmarks!(list, extra);
let storage_info = AllPalletsWithSystem::storage_info();
(list, storage_info)
}
#[expect(non_local_definitions)]
fn dispatch_benchmark(
config: frame_benchmarking::BenchmarkConfig
) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch};
use sp_storage::TrackedStorageKey;
use frame_system_benchmarking::Pallet as SystemBench;
use baseline::Pallet as BaselineBench;
use super::*;
impl frame_system_benchmarking::Config for Runtime {}
impl baseline::Config for Runtime {}
use frame_support::traits::WhitelistedStorageKeys;
let whitelist: Vec<TrackedStorageKey> = AllPalletsWithSystem::whitelisted_storage_keys();
let mut batches = Vec::<BenchmarkBatch>::new();
let params = (&config, &whitelist);
add_benchmarks!(params, batches);
Ok(batches)
}
}
#[cfg(feature = "try-runtime")]
impl frame_try_runtime::TryRuntime<Block> for Runtime {
fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
// NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to
// have a backtrace here. If any of the pre/post migration checks fail, we shall stop
// right here and right now.
let weight = Executive::try_runtime_upgrade(checks).unwrap();
(weight, super::configs::RuntimeBlockWeights::get().max_block)
}
fn execute_block(
block: Block,
state_root_check: bool,
signature_check: bool,
select: frame_try_runtime::TryStateSelect
) -> Weight {
// NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to
// have a backtrace here.
Executive::try_execute_block(block, state_root_check, signature_check, select).expect("execute-block failed")
}
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, crate::genesis_config_presets::get_preset)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
crate::genesis_config_presets::preset_names()
}
}
impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {
fn chain_id() -> u64 {
<Runtime as pallet_evm::Config>::ChainId::get()
}
fn account_basic(address: H160) -> EVMAccount {
let (account, _) = pallet_evm::Pallet::<Runtime>::account_basic(&address);
account
}
fn gas_price() -> U256 {
let (gas_price, _) = <Runtime as pallet_evm::Config>::FeeCalculator::min_gas_price();
gas_price
}
fn account_code_at(address: H160) -> Vec<u8> {
pallet_evm::AccountCodes::<Runtime>::get(address)
}
fn author() -> H160 {
<pallet_evm::Pallet<Runtime>>::find_author()
}
fn storage_at(address: H160, index: U256) -> H256 {
let tmp = index.to_big_endian();
pallet_evm::AccountStorages::<Runtime>::get(address, H256::from_slice(&tmp[..]))
}
fn call(
from: H160,
to: H160,
data: Vec<u8>,
value: U256,
gas_limit: U256,
max_fee_per_gas: Option<U256>,
max_priority_fee_per_gas: Option<U256>,
nonce: Option<U256>,
estimate: bool,
access_list: Option<Vec<(H160, Vec<H256>)>>,
) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {
let config = if estimate {
let mut config = <Runtime as pallet_evm::Config>::config().clone();
config.estimate = true;
Some(config)
} else {
None
};
let is_transactional = false;
let validate = true;
// Estimated encoded transaction size must be based on the heaviest transaction
// type (EIP1559Transaction) to be compatible with all transaction types.
let mut estimated_transaction_len = data.len() +
// pallet ethereum index: 1
// transact call index: 1
// Transaction enum variant: 1
// chain_id 8 bytes
// nonce: 32
// max_priority_fee_per_gas: 32
// max_fee_per_gas: 32
// gas_limit: 32
// action: 21 (enum varianrt + call address)
// value: 32
// access_list: 1 (empty vec size)
// 65 bytes signature
258;
if access_list.is_some() {
estimated_transaction_len += access_list.encoded_size();
}
let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
let without_base_extrinsic_weight = true;
let (weight_limit, proof_size_base_cost) =
match <Runtime as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
gas_limit,
without_base_extrinsic_weight
) {
weight_limit if weight_limit.proof_size() > 0 => {
(Some(weight_limit), Some(estimated_transaction_len as u64))
}
_ => (None, None),
};
<Runtime as pallet_evm::Config>::Runner::call(
from,
to,
data,
value,
gas_limit,
max_fee_per_gas,
max_priority_fee_per_gas,
nonce,
access_list.unwrap_or_default(),
is_transactional,
validate,
weight_limit,
proof_size_base_cost,
config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config()),
).map_err(|err| err.error.into())
}
fn create(
from: H160,
data: Vec<u8>,
value: U256,
gas_limit: U256,
max_fee_per_gas: Option<U256>,
max_priority_fee_per_gas: Option<U256>,
nonce: Option<U256>,
estimate: bool,
access_list: Option<Vec<(H160, Vec<H256>)>>,
) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {
let config = if estimate {
let mut config = <Runtime as pallet_evm::Config>::config().clone();
config.estimate = true;
Some(config)
} else {
None
};
let is_transactional = false;
let validate = true;
let gas_limit = if gas_limit > U256::from(u64::MAX) {
u64::MAX
} else {
gas_limit.low_u64()
};
let (weight_limit, proof_size_base_cost) = (None, None);
#[allow(clippy::or_fun_call)]
<Runtime as pallet_evm::Config>::Runner::create(
from,
data,
value,
gas_limit,
max_fee_per_gas,
max_priority_fee_per_gas,
nonce,
access_list.unwrap_or_default(),
is_transactional,
validate,
weight_limit,
proof_size_base_cost,
config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config()),
).map_err(|err| err.error.into())
}
fn current_transaction_statuses() -> Option<Vec<TransactionStatus>> {
pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
}
fn current_block() -> Option<pallet_ethereum::Block> {
pallet_ethereum::CurrentBlock::<Runtime>::get()
}
fn current_receipts() -> Option<Vec<pallet_ethereum::Receipt>> {
pallet_ethereum::CurrentReceipts::<Runtime>::get()
}
fn current_all() -> (
Option<pallet_ethereum::Block>,
Option<Vec<pallet_ethereum::Receipt>>,
Option<Vec<TransactionStatus>>,
) {
(
pallet_ethereum::CurrentBlock::<Runtime>::get(),
pallet_ethereum::CurrentReceipts::<Runtime>::get(),
pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
)
}
fn extrinsic_filter(
xts: Vec<<Block as BlockT>::Extrinsic>,
) -> Vec<EthereumTransaction> {
xts.into_iter().filter_map(|xt| match xt.0.function {
RuntimeCall::Ethereum(transact { transaction }) => Some(transaction),
_ => None
}).collect::<Vec<EthereumTransaction>>()
}
fn elasticity() -> Option<Permill> {
None
}
fn gas_limit_multiplier_support() {}
fn pending_block(
xts: Vec<<Block as BlockT>::Extrinsic>,
) -> (Option<pallet_ethereum::Block>, Option<Vec<TransactionStatus>>) {
for ext in xts.into_iter() {
let _ = Executive::apply_extrinsic(ext);
}
Ethereum::on_finalize(System::block_number() + 1);
(
pallet_ethereum::CurrentBlock::<Runtime>::get(),
pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
)
}
fn initialize_pending_block(header: &<Block as BlockT>::Header) {
Executive::initialize_block(header);
}
}
impl fp_rpc::ConvertTransactionRuntimeApi<Block> for Runtime {
fn convert_transaction(transaction: EthereumTransaction) -> <Block as BlockT>::Extrinsic {
UncheckedExtrinsic::new_bare(
pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
)
}
}
}

View file

@ -0,0 +1,38 @@
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// For more information, please refer to <http://unlicense.org>
frame_benchmarking::define_benchmarks!(
[frame_benchmarking, BaselineBench::<Runtime>]
[frame_system, SystemBench::<Runtime>]
[pallet_balances, Balances]
[pallet_identity, Identity]
[pallet_im_online, ImOnline]
[pallet_multisig, Multisig]
[pallet_preimage, Preimage]
[pallet_scheduler, Scheduler]
[pallet_timestamp, Timestamp]
[pallet_utility, Utility]
[pallet_sudo, Sudo]
);

View file

@ -0,0 +1,874 @@
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// For more information, please refer to <http://unlicense.org>
mod runtime_params;
use super::{
deposit, AccountId, Babe, Balance, Balances, BeefyMmrLeaf, Block, BlockNumber,
EthereumBeaconClient, EvmChainId, Hash, Historical, ImOnline, MessageQueue, Nonce, Offences,
OriginCaller, OutboundCommitmentStore, OutboundQueueV2, PalletInfo, Preimage, Runtime,
RuntimeCall, RuntimeEvent, RuntimeFreezeReason, RuntimeHoldReason, RuntimeOrigin, RuntimeTask,
Session, SessionKeys, Signature, System, Timestamp, ValidatorSet, EXISTENTIAL_DEPOSIT,
SLOT_DURATION, STORAGE_BYTE_FEE, SUPPLY_FACTOR, UNIT, VERSION,
};
use codec::{Decode, Encode};
use datahaven_runtime_common::{
gas::WEIGHT_PER_GAS,
time::{EpochDurationInBlocks, DAYS, MILLISECS_PER_BLOCK, MINUTES},
};
use dhp_bridge::EigenLayerMessageProcessor;
use frame_support::{
derive_impl,
pallet_prelude::TransactionPriority,
parameter_types,
traits::{
fungible::{Balanced, Credit, HoldConsideration, Inspect},
ConstU128, ConstU32, ConstU64, ConstU8, EqualPrivilegeOnly, FindAuthor,
KeyOwnerProofSystem, LinearStoragePrice, OnUnbalanced, VariantCountOf,
},
weights::{
constants::{RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND},
IdentityFee, RuntimeDbWeight, Weight,
},
};
use frame_system::{
limits::{BlockLength, BlockWeights},
EnsureRoot, EnsureRootWithSuccess,
};
use pallet_ethereum::PostLogContent;
use pallet_evm::{
EVMFungibleAdapter, EnsureAddressNever, EnsureAddressRoot, FeeCalculator,
FrameSystemAccountProvider, IdentityAddressMapping,
OnChargeEVMTransaction as OnChargeEVMTransactionT,
};
use pallet_grandpa::AuthorityId as GrandpaId;
use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
use pallet_transaction_payment::{
ConstFeeMultiplier, FungibleAdapter, Multiplier, Pallet as TransactionPayment,
};
use polkadot_primitives::Moment;
use runtime_params::RuntimeParameters;
use snowbridge_beacon_primitives::{Fork, ForkVersions};
use snowbridge_core::{gwei, meth, AgentIdOf, PricingParameters, Rewards};
use snowbridge_inbound_queue_primitives::RewardLedger;
use snowbridge_outbound_queue_primitives::{
v1::{Fee, Message, SendMessage},
v2::ConstantGasMeter,
SendError, SendMessageFeeProvider,
};
use snowbridge_pallet_outbound_queue_v2::OnNewCommitment;
use snowbridge_pallet_system::BalanceOf;
use sp_consensus_beefy::{
ecdsa_crypto::AuthorityId as BeefyId,
mmr::{BeefyDataProvider, MmrLeafVersion},
};
use sp_core::{crypto::KeyTypeId, Get, H160, H256, U256};
use sp_runtime::FixedU128;
use sp_runtime::{
traits::{ConvertInto, IdentityLookup, Keccak256, One, OpaqueKeys, UniqueSaturatedInto},
FixedPointNumber, Perbill,
};
use sp_staking::{EraIndex, SessionIndex};
use sp_std::{
convert::{From, Into},
prelude::*,
};
use sp_version::RuntimeVersion;
use xcm::latest::NetworkId;
use xcm::prelude::*;
#[cfg(feature = "runtime-benchmarks")]
use bridge_hub_common::AggregateMessageOrigin;
const EVM_CHAIN_ID: u64 = 1283;
const SS58_FORMAT: u16 = EVM_CHAIN_ID as u16;
// TODO: We need to define what do we want here as max PoV size
pub const MAX_POV_SIZE: u64 = 5 * 1024 * 1024;
// Todo: import all currency constants from moonbeam
pub const WEIGHT_FEE: Balance = 50_000 / 4;
pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND, u64::MAX)
.saturating_mul(2)
.set_proof_size(MAX_POV_SIZE);
const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
//╔═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
//║ COMMON PARAMETERS ║
//╚═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
parameter_types! {
pub const MaxAuthorities: u32 = 32;
pub const BondingDuration: EraIndex = polkadot_runtime_common::prod_or_fast!(28, 3);
pub const SessionsPerEra: SessionIndex = polkadot_runtime_common::prod_or_fast!(6, 1);
}
//╔═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
//║ SYSTEM AND CONSENSUS PALLETS ║
//╚═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
parameter_types! {
pub const BlockHashCount: BlockNumber = 2400;
pub const Version: RuntimeVersion = VERSION;
/// We allow for 2 seconds of compute with a 6 second average block time.
pub RuntimeBlockWeights: BlockWeights = BlockWeights::with_sensible_defaults(
Weight::from_parts(2u64 * WEIGHT_REF_TIME_PER_SECOND, u64::MAX),
NORMAL_DISPATCH_RATIO,
);
pub RuntimeBlockLength: BlockLength = BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
pub const SS58Prefix: u16 = SS58_FORMAT;
}
/// The default types are being injected by [`derive_impl`](`frame_support::derive_impl`) from
/// [`SoloChainDefaultConfig`](`struct@frame_system::config_preludes::SolochainDefaultConfig`),
/// but overridden as needed.
#[derive_impl(frame_system::config_preludes::SolochainDefaultConfig)]
impl frame_system::Config for Runtime {
/// The block type for the runtime.
type Block = Block;
/// Block & extrinsics weights: base values and limits.
type BlockWeights = RuntimeBlockWeights;
/// The maximum length of a block (in bytes).
type BlockLength = RuntimeBlockLength;
/// The identifier used to distinguish between accounts.
type AccountId = AccountId;
/// The lookup mechanism to get account ID from whatever is passed in dispatchers.
type Lookup = IdentityLookup<AccountId>;
/// The type for storing how many extrinsics an account has signed.
type Nonce = Nonce;
/// The type for hashing blocks and tries.
type Hash = Hash;
/// Maximum number of block number to block hash mappings to keep (oldest pruned first).
type BlockHashCount = BlockHashCount;
/// The weight of database operations that the runtime can invoke.
type DbWeight = RocksDbWeight;
/// Version of the runtime.
type Version = Version;
/// The data to be stored in an account.
type AccountData = pallet_balances::AccountData<Balance>;
/// This is used as an identifier of the chain. 42 is the generic substrate prefix.
type SS58Prefix = SS58Prefix;
type MaxConsumers = frame_support::traits::ConstU32<16>;
}
// 1 in 4 blocks (on average, not counting collisions) will be primary babe blocks.
pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4);
/// The BABE epoch configuration at genesis.
pub const BABE_GENESIS_EPOCH_CONFIG: sp_consensus_babe::BabeEpochConfiguration =
sp_consensus_babe::BabeEpochConfiguration {
c: PRIMARY_PROBABILITY,
allowed_slots: sp_consensus_babe::AllowedSlots::PrimaryAndSecondaryVRFSlots,
};
parameter_types! {
pub const ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK;
pub ReportLongevity: u64 =
BondingDuration::get() as u64 * SessionsPerEra::get() as u64 * (EpochDurationInBlocks::get() as u64);
}
impl pallet_babe::Config for Runtime {
type EpochDuration = EpochDurationInBlocks;
type ExpectedBlockTime = ExpectedBlockTime;
type EpochChangeTrigger = pallet_babe::ExternalTrigger;
type DisabledValidators = Session;
type WeightInfo = ();
type MaxAuthorities = MaxAuthorities;
type MaxNominators = ConstU32<0>;
type KeyOwnerProof =
<Historical as KeyOwnerProofSystem<(KeyTypeId, pallet_babe::AuthorityId)>>::Proof;
type EquivocationReportSystem =
pallet_babe::EquivocationReportSystem<Self, Offences, Historical, ReportLongevity>;
}
impl pallet_timestamp::Config for Runtime {
/// A timestamp: milliseconds since the unix epoch.
type Moment = u64;
type OnTimestampSet = Babe;
type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>;
type WeightInfo = ();
}
impl pallet_balances::Config for Runtime {
type MaxLocks = ConstU32<50>;
type MaxReserves = ();
type ReserveIdentifier = [u8; 8];
/// The type for recording an account's balance.
type Balance = Balance;
/// The ubiquitous event type.
type RuntimeEvent = RuntimeEvent;
type DustRemoval = ();
type ExistentialDeposit = ConstU128<EXISTENTIAL_DEPOSIT>;
type AccountStore = System;
type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
type FreezeIdentifier = RuntimeFreezeReason;
type MaxFreezes = VariantCountOf<RuntimeFreezeReason>;
type RuntimeHoldReason = RuntimeHoldReason;
type RuntimeFreezeReason = RuntimeFreezeReason;
type DoneSlashHandler = ();
}
impl pallet_authorship::Config for Runtime {
type FindAuthor = pallet_session::FindAccountFromAuthorIndex<Self, Babe>;
type EventHandler = ImOnline;
}
impl pallet_offences::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type IdentificationTuple = pallet_session::historical::IdentificationTuple<Self>;
type OnOffenceHandler = ValidatorSet;
}
impl pallet_session::historical::Config for Runtime {
type FullIdentification = Self::ValidatorId;
type FullIdentificationOf = Self::ValidatorIdOf;
}
impl pallet_session::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type ValidatorId = AccountId;
type ValidatorIdOf = ConvertInto;
type ShouldEndSession = Babe;
type NextSessionRotation = Babe;
type SessionManager = pallet_session::historical::NoteHistoricalRoot<Self, ValidatorSet>;
type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
type Keys = SessionKeys;
type WeightInfo = pallet_session::weights::SubstrateWeight<Runtime>;
}
parameter_types! {
pub const SetKeysCooldownBlocks: BlockNumber = 5 * MINUTES;
}
impl pallet_validator_set::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type AddRemoveOrigin = EnsureRoot<AccountId>;
type MaxAuthorities = MaxAuthorities;
type SetKeysCooldownBlocks = SetKeysCooldownBlocks;
type WeightInfo = pallet_validator_set::weights::SubstrateWeight<Runtime>;
}
parameter_types! {
pub const ImOnlineUnsignedPriority: TransactionPriority = TransactionPriority::MAX;
}
impl pallet_im_online::Config for Runtime {
type AuthorityId = ImOnlineId;
type MaxKeys = MaxAuthorities;
type MaxPeerInHeartbeats = ConstU32<0>; // Not used any more
type RuntimeEvent = RuntimeEvent;
type ValidatorSet = Historical;
type NextSessionRotation = Babe;
type ReportUnresponsiveness = Offences;
type UnsignedPriority = ImOnlineUnsignedPriority;
type WeightInfo = ();
}
parameter_types! {
pub const EquivocationReportPeriodInEpochs: u64 = 168;
pub const EquivocationReportPeriodInBlocks: u64 =
EquivocationReportPeriodInEpochs::get() * (EpochDurationInBlocks::get() as u64);
pub const MaxSetIdSessionEntries: u32 = BondingDuration::get() * SessionsPerEra::get();
}
impl pallet_grandpa::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type WeightInfo = ();
type MaxAuthorities = MaxAuthorities;
type MaxNominators = ConstU32<0>;
type MaxSetIdSessionEntries = MaxSetIdSessionEntries;
type KeyOwnerProof = <Historical as KeyOwnerProofSystem<(KeyTypeId, GrandpaId)>>::Proof;
type EquivocationReportSystem = pallet_grandpa::EquivocationReportSystem<
Self,
Offences,
Historical,
EquivocationReportPeriodInBlocks,
>;
}
parameter_types! {
pub FeeMultiplier: Multiplier = Multiplier::one();
}
impl pallet_transaction_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type OnChargeTransaction = FungibleAdapter<Balances, ()>;
type OperationalFeeMultiplier = ConstU8<5>;
type WeightToFee = IdentityFee<Balance>;
type LengthToFee = IdentityFee<Balance>;
type FeeMultiplierUpdate = ConstFeeMultiplier<FeeMultiplier>;
type WeightInfo = ();
}
parameter_types! {
pub const BeefySetIdSessionEntries: u32 = BondingDuration::get() * SessionsPerEra::get();
}
impl pallet_beefy::Config for Runtime {
type BeefyId = BeefyId;
type MaxAuthorities = ConstU32<32>;
type MaxNominators = ConstU32<0>;
type MaxSetIdSessionEntries = BeefySetIdSessionEntries;
type OnNewValidatorSet = BeefyMmrLeaf;
type AncestryHelper = BeefyMmrLeaf;
type WeightInfo = ();
type KeyOwnerProof = <Historical as KeyOwnerProofSystem<(KeyTypeId, BeefyId)>>::Proof;
type EquivocationReportSystem = ();
}
parameter_types! {
pub LeafVersion: MmrLeafVersion = MmrLeafVersion::new(0, 0);
}
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct LeafExtraData {
extra: H256,
}
pub struct LeafExtraDataProvider;
impl BeefyDataProvider<LeafExtraData> for LeafExtraDataProvider {
fn extra_data() -> LeafExtraData {
LeafExtraData {
extra: OutboundCommitmentStore::get_latest_commitment().unwrap_or_default(),
}
}
}
impl pallet_mmr::Config for Runtime {
const INDEXING_PREFIX: &'static [u8] = pallet_mmr::primitives::INDEXING_PREFIX;
type Hashing = Keccak256;
type LeafData = pallet_beefy_mmr::Pallet<Runtime>;
type OnNewRoot = pallet_beefy_mmr::DepositBeefyDigest<Runtime>;
type WeightInfo = ();
type BlockHashProvider = pallet_mmr::DefaultBlockHashProvider<Runtime>;
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = ();
}
impl pallet_beefy_mmr::Config for Runtime {
type LeafVersion = LeafVersion;
type BeefyAuthorityToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum;
type LeafExtra = LeafExtraData;
type BeefyDataProvider = LeafExtraDataProvider;
type WeightInfo = ();
}
//╔═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
//║ POLKADOT SDK UTILITY PALLETS ║
//╚═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
impl pallet_utility::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type RuntimeCall = RuntimeCall;
type PalletsOrigin = OriginCaller;
type WeightInfo = ();
}
parameter_types! {
pub MaximumSchedulerWeight: Weight = NORMAL_DISPATCH_RATIO * RuntimeBlockWeights::get().max_block;
pub const NoPreimagePostponement: Option<u32> = Some(10);
}
impl pallet_scheduler::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type RuntimeOrigin = RuntimeOrigin;
type PalletsOrigin = OriginCaller;
type RuntimeCall = RuntimeCall;
type MaximumWeight = MaximumSchedulerWeight;
type ScheduleOrigin = EnsureRoot<AccountId>;
type MaxScheduledPerBlock = ConstU32<50>;
type OriginPrivilegeCmp = EqualPrivilegeOnly;
type Preimages = Preimage;
type WeightInfo = ();
}
parameter_types! {
pub const PreimageBaseDeposit: Balance = 5 * UNIT * SUPPLY_FACTOR ;
pub const PreimageByteDeposit: Balance = STORAGE_BYTE_FEE;
pub const PreimageHoldReason: RuntimeHoldReason =
RuntimeHoldReason::Preimage(pallet_preimage::HoldReason::Preimage);
}
impl pallet_preimage::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type ManagerOrigin = EnsureRoot<AccountId>;
type Consideration = HoldConsideration<
AccountId,
Balances,
PreimageHoldReason,
LinearStoragePrice<PreimageBaseDeposit, PreimageByteDeposit, Balance>,
>;
type WeightInfo = ();
}
parameter_types! {
pub const MaxSubAccounts: u32 = 100;
pub const MaxAdditionalFields: u32 = 100;
pub const MaxRegistrars: u32 = 20;
pub const PendingUsernameExpiration: u32 = 7 * DAYS;
pub const MaxSuffixLength: u32 = 7;
pub const MaxUsernameLength: u32 = 32;
}
type IdentityForceOrigin = EnsureRoot<AccountId>;
type IdentityRegistrarOrigin = EnsureRoot<AccountId>;
// TODO: Add governance origin when available
// type IdentityForceOrigin =
// EitherOfDiverse<EnsureRoot<AccountId>, governance::custom_origins::GeneralAdmin>;
// type IdentityRegistrarOrigin =
// EitherOfDiverse<EnsureRoot<AccountId>, governance::custom_origins::GeneralAdmin>;
impl pallet_identity::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
// Add one item in storage and take 258 bytes
type BasicDeposit = ConstU128<{ deposit(1, 258) }>;
// Does not add any item to the storage but takes 1 bytes
type ByteDeposit = ConstU128<{ deposit(0, 1) }>;
// Add one item in storage and take 53 bytes
type SubAccountDeposit = ConstU128<{ deposit(1, 53) }>;
type MaxSubAccounts = MaxSubAccounts;
type IdentityInformation = pallet_identity::legacy::IdentityInfo<MaxAdditionalFields>;
type MaxRegistrars = MaxRegistrars;
type Slashed = ();
// TODO: Slashed funds should be sent to the treasury (when added to the runtime)
// type Slashed = Treasury;
type ForceOrigin = IdentityForceOrigin;
type RegistrarOrigin = IdentityRegistrarOrigin;
type OffchainSignature = Signature;
type SigningPublicKey = <Signature as sp_runtime::traits::Verify>::Signer;
type UsernameAuthorityOrigin = EnsureRoot<AccountId>;
type PendingUsernameExpiration = PendingUsernameExpiration;
type MaxSuffixLength = MaxSuffixLength;
type MaxUsernameLength = MaxUsernameLength;
type WeightInfo = ();
type UsernameDeposit = ();
type UsernameGracePeriod = ();
}
parameter_types! {
// One storage item; key size is 32 + 20; value is size 4+4+16+20 bytes = 44 bytes.
pub const DepositBase: Balance = deposit(1, 96);
// Additional storage item size of 20 bytes.
pub const DepositFactor: Balance = deposit(0, 20);
pub const MaxSignatories: u32 = 100;
}
impl pallet_multisig::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type RuntimeCall = RuntimeCall;
type Currency = Balances;
type DepositBase = DepositBase;
type DepositFactor = DepositFactor;
type MaxSignatories = MaxSignatories;
type WeightInfo = ();
}
impl pallet_parameters::Config for Runtime {
type AdminOrigin = EnsureRoot<AccountId>;
type RuntimeEvent = RuntimeEvent;
type RuntimeParameters = RuntimeParameters;
type WeightInfo = ();
}
impl pallet_sudo::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type RuntimeCall = RuntimeCall;
type WeightInfo = pallet_sudo::weights::SubstrateWeight<Runtime>;
}
parameter_types! {
/// Amount of weight that can be spent per block to service messages.
///
/// # WARNING
///
/// This is not a good value for para-chains since the `Scheduler` already uses up to 80% block weight.
pub MessageQueueServiceWeight: Weight = Perbill::from_percent(20) * RuntimeBlockWeights::get().max_block;
pub const MessageQueueHeapSize: u32 = 32 * 1024;
pub const MessageQueueMaxStale: u32 = 96;
}
impl pallet_message_queue::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
#[cfg(not(feature = "runtime-benchmarks"))]
type MessageProcessor = OutboundQueueV2;
#[cfg(feature = "runtime-benchmarks")]
type MessageProcessor =
pallet_message_queue::mock_helpers::NoopMessageProcessor<AggregateMessageOrigin>;
type Size = u32;
type QueueChangeHandler = ();
type QueuePausedQuery = ();
type HeapSize = MessageQueueHeapSize;
type MaxStale = MessageQueueMaxStale;
type ServiceWeight = MessageQueueServiceWeight;
type IdleMaxServiceWeight = MessageQueueServiceWeight;
type WeightInfo = ();
}
//╔═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
//║ FRONTIER (EVM) PALLETS ║
//╚═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
parameter_types! {
pub const PostBlockAndTxnHashes: PostLogContent = PostLogContent::BlockAndTxnHashes;
}
impl pallet_ethereum::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type StateRoot = pallet_ethereum::IntermediateStateRoot<Self::Version>;
type PostLogContent = PostBlockAndTxnHashes;
type ExtraDataLength = ConstU32<30>;
}
// Ported from Moonbeam, please check for reference: https://github.com/moonbeam-foundation/moonbeam/pull/1765
pub struct TransactionPaymentAsGasPrice;
impl FeeCalculator for TransactionPaymentAsGasPrice {
fn min_gas_price() -> (U256, Weight) {
// note: transaction-payment differs from EIP-1559 in that its tip and length fees are not
// scaled by the multiplier, which means its multiplier will be overstated when
// applied to an ethereum transaction
// note: transaction-payment uses both a congestion modifier (next_fee_multiplier, which is
// updated once per block in on_finalize) and a 'WeightToFee' implementation. Our
// runtime implements this as a 'ConstantModifier', so we can get away with a simple
// multiplication here.
let min_gas_price: u128 = TransactionPayment::<Runtime>::next_fee_multiplier()
.saturating_mul_int((WEIGHT_FEE).saturating_mul(WEIGHT_PER_GAS as u128));
(
min_gas_price.into(),
<<Runtime as frame_system::Config>::DbWeight as Get<RuntimeDbWeight>>::get().reads(1),
)
}
}
pub struct FindAuthorAdapter<T>(core::marker::PhantomData<T>);
impl<T> FindAuthor<H160> for FindAuthorAdapter<T>
where
T: frame_system::Config + pallet_session::Config,
<T as pallet_session::Config>::ValidatorId: Into<H160>,
{
fn find_author<'a, I>(digests: I) -> Option<H160>
where
I: 'a + IntoIterator<Item = (sp_runtime::ConsensusEngineId, &'a [u8])>,
{
pallet_session::FindAccountFromAuthorIndex::<T, Babe>::find_author(digests)
.map(|author| author.into())
}
}
datahaven_runtime_common::impl_on_charge_evm_transaction!();
parameter_types! {
pub BlockGasLimit: U256
= U256::from(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT.ref_time() / WEIGHT_PER_GAS);
// pub PrecompilesValue: TemplatePrecompiles<Runtime> = TemplatePrecompiles::<_>::new();
pub WeightPerGas: Weight = Weight::from_parts(WEIGHT_PER_GAS, 0);
pub SuicideQuickClearLimit: u32 = 0;
pub GasLimitPovSizeRatio: u32 = 16;
pub GasLimitStorageGrowthRatio: u64 = 366;
}
impl pallet_evm::Config for Runtime {
type AccountProvider = FrameSystemAccountProvider<Runtime>;
type FeeCalculator = TransactionPaymentAsGasPrice;
type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
type WeightPerGas = WeightPerGas;
type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;
type CallOrigin = EnsureAddressRoot<AccountId>;
type WithdrawOrigin = EnsureAddressNever<AccountId>;
type AddressMapping = IdentityAddressMapping;
type Currency = Balances;
type RuntimeEvent = RuntimeEvent;
type PrecompilesType = ();
type PrecompilesValue = ();
type ChainId = EvmChainId;
type BlockGasLimit = BlockGasLimit;
type Runner = pallet_evm::runner::stack::Runner<Self>;
type OnChargeTransaction = OnChargeEVMTransaction<()>;
type OnCreate = ();
type FindAuthor = FindAuthorAdapter<Self>;
type GasLimitPovSizeRatio = GasLimitPovSizeRatio;
type GasLimitStorageGrowthRatio = ();
type Timestamp = Timestamp;
type WeightInfo = ();
}
impl pallet_evm_chain_id::Config for Runtime {}
//╔═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
//║ SNOWBRIDGE PALLETS ║
//╚═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
// --- Snowbridge Config Constants & Parameter Types ---
parameter_types! {
pub UniversalLocation: InteriorLocation = Here.into();
pub InboundDeliveryCost: BalanceOf<Runtime> = 0;
pub RootLocation: Location = Location::here();
pub Parameters: PricingParameters<u128> = PricingParameters {
exchange_rate: FixedU128::from_rational(1, 400),
fee_per_gas: gwei(20),
rewards: Rewards { local: 1 * UNIT, remote: meth(1) },
multiplier: FixedU128::from_rational(1, 1),
};
pub EthereumLocation: Location = Location::new(1, EthereumNetwork::get());
pub TreasuryAccountId: AccountId = AccountId::from([0u8; 20]);
}
pub struct DoNothingOutboundQueue;
impl SendMessage for DoNothingOutboundQueue {
type Ticket = ();
fn validate(
_: &Message,
) -> Result<(Self::Ticket, Fee<<Self as SendMessageFeeProvider>::Balance>), SendError> {
Ok(((), Fee::from((0, 0))))
}
fn deliver(_: Self::Ticket) -> Result<H256, snowbridge_outbound_queue_primitives::SendError> {
Ok(H256::zero())
}
}
impl SendMessageFeeProvider for DoNothingOutboundQueue {
type Balance = u128;
fn local_fee() -> Self::Balance {
1
}
}
// Implement the Snowbridge System V1 config trait
impl snowbridge_pallet_system::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type OutboundQueue = DoNothingOutboundQueue;
type SiblingOrigin = EnsureRootWithSuccess<AccountId, RootLocation>;
type AgentIdOf = AgentIdOf;
type Token = Balances;
type TreasuryAccount = TreasuryAccountId;
type DefaultPricingParameters = Parameters;
type InboundDeliveryCost = InboundDeliveryCost;
type WeightInfo = ();
type UniversalLocation = UniversalLocation;
type EthereumLocation = EthereumLocation;
#[cfg(feature = "runtime-benchmarks")]
type Helper = ();
}
// Implement the Snowbridge System v2 config trait
impl snowbridge_pallet_system_v2::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type OutboundQueue = OutboundQueueV2;
type FrontendOrigin = EnsureRootWithSuccess<AccountId, RootLocation>;
type GovernanceOrigin = EnsureRootWithSuccess<AccountId, RootLocation>;
type WeightInfo = ();
#[cfg(feature = "runtime-benchmarks")]
type Helper = ();
}
// For tests, benchmarks and fast-runtime configurations we use the mocked fork versions
#[cfg(any(
feature = "std",
feature = "fast-runtime",
feature = "runtime-benchmarks",
test
))]
parameter_types! {
pub const ChainForkVersions: ForkVersions = ForkVersions {
genesis: Fork {
version: [0, 0, 0, 0], // 0x00000000
epoch: 0,
},
altair: Fork {
version: [1, 0, 0, 0], // 0x01000000
epoch: 0,
},
bellatrix: Fork {
version: [2, 0, 0, 0], // 0x02000000
epoch: 0,
},
capella: Fork {
version: [3, 0, 0, 0], // 0x03000000
epoch: 0,
},
deneb: Fork {
version: [4, 0, 0, 0], // 0x04000000
epoch: 0,
},
electra: Fork {
version: [5, 0, 0, 0], // 0x05000000
epoch: 0,
},
};
}
// Holesky: https://github.com/eth-clients/holesky
// Fork versions: https://github.com/eth-clients/holesky/blob/main/metadata/config.yaml
#[cfg(not(any(
feature = "std",
feature = "fast-runtime",
feature = "runtime-benchmarks",
test
)))]
parameter_types! {
pub const ChainForkVersions: ForkVersions = ForkVersions {
genesis: Fork {
version: hex_literal::hex!("01017000"), // 0x01017000
epoch: 0,
},
altair: Fork {
version: hex_literal::hex!("02017000"), // 0x02017000
epoch: 0,
},
bellatrix: Fork {
version: hex_literal::hex!("03017000"), // 0x03017000
epoch: 0,
},
capella: Fork {
version: hex_literal::hex!("04017000"), // 0x04017000
epoch: 256,
},
deneb: Fork {
version: hex_literal::hex!("05017000"), // 0x05017000
epoch: 29696,
},
electra: Fork {
version: hex_literal::hex!("06017000"), // 0x06017000
epoch: 115968,
},
};
}
impl snowbridge_pallet_ethereum_client::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type ForkVersions = ChainForkVersions;
type FreeHeadersInterval = ();
type WeightInfo = ();
}
parameter_types! {
pub DefaultRewardKind: () = ();
}
// Dummy RewardPayment implementation
pub struct DummyRewardPayment;
impl RewardLedger<AccountId, (), u128> for DummyRewardPayment {
fn register_reward(_who: &AccountId, _reward: (), _amount: u128) {
// Empty implementation for dummy struct
}
}
impl snowbridge_pallet_inbound_queue_v2::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Verifier = EthereumBeaconClient;
type GatewayAddress = runtime_params::dynamic_params::runtime_config::EthereumGatewayAddress;
type MessageProcessor = EigenLayerMessageProcessor<Runtime>;
type RewardKind = ();
type DefaultRewardKind = DefaultRewardKind;
type RewardPayment = DummyRewardPayment;
type WeightInfo = ();
#[cfg(feature = "runtime-benchmarks")]
type Helper = Runtime;
}
parameter_types! {
/// Network and location for the Ethereum chain.
/// Using the Sepolia Ethereum testnet, with chain ID 11155111.
/// <https://chainlist.org/chain/11155111>
/// <https://ethereum.org/en/developers/docs/apis/json-rpc/#net_version>
pub EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 11155111 };
}
pub struct CommitmentHandler;
impl OnNewCommitment for CommitmentHandler {
fn on_new_commitment(commitment: H256) {
OutboundCommitmentStore::store_commitment(commitment);
}
}
impl snowbridge_pallet_outbound_queue_v2::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Hashing = Keccak256;
type MessageQueue = MessageQueue;
type GasMeter = ConstantGasMeter;
type Balance = Balance;
type MaxMessagePayloadSize = ConstU32<2048>;
type MaxMessagesPerBlock = ConstU32<32>;
type OnNewCommitment = CommitmentHandler;
type WeightToFee = IdentityFee<Balance>;
type WeightInfo = ();
type Verifier = EthereumBeaconClient;
type GatewayAddress = runtime_params::dynamic_params::runtime_config::EthereumGatewayAddress;
type RewardKind = ();
type DefaultRewardKind = DefaultRewardKind;
type RewardPayment = DummyRewardPayment;
type EthereumNetwork = EthereumNetwork;
type ConvertAssetId = ();
}
//╔═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
//║ STORAGEHUB PALLETS ║
//╚═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
//╔═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
//║ DATAHAVEN-SPECIFIC PALLETS ║
//╚═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
#[cfg(feature = "runtime-benchmarks")]
pub mod benchmark_helpers {
use crate::RuntimeOrigin;
use crate::{EthereumBeaconClient, Runtime};
use snowbridge_beacon_primitives::BeaconHeader;
use snowbridge_pallet_inbound_queue_v2::BenchmarkHelper as InboundQueueBenchmarkHelperV2;
use sp_core::H256;
use xcm::opaque::latest::Location;
impl<T: snowbridge_pallet_inbound_queue_v2::Config> InboundQueueBenchmarkHelperV2<T> for Runtime {
fn initialize_storage(beacon_header: BeaconHeader, block_roots_root: H256) {
EthereumBeaconClient::store_finalized_header(beacon_header, block_roots_root).unwrap();
}
}
impl snowbridge_pallet_system::BenchmarkHelper<RuntimeOrigin> for () {
fn make_xcm_origin(_location: Location) -> RuntimeOrigin {
RuntimeOrigin::root()
}
}
impl snowbridge_pallet_system_v2::BenchmarkHelper<RuntimeOrigin> for () {
fn make_xcm_origin(_location: Location) -> RuntimeOrigin {
RuntimeOrigin::root()
}
}
}
impl pallet_outbound_commitment_store::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
}

View file

@ -0,0 +1,34 @@
use frame_support::dynamic_params::{dynamic_pallet_params, dynamic_params};
use sp_core::H160;
use crate::Runtime;
#[dynamic_params(RuntimeParameters, pallet_parameters::Parameters::<Runtime>)]
pub mod dynamic_params {
use super::*;
#[dynamic_pallet_params]
#[codec(index = 0)]
pub mod runtime_config {
use super::*;
#[codec(index = 0)]
#[allow(non_upper_case_globals)]
/// Set the initial address of the Snowbridge Gateway contract on Ethereum.
/// The fact that this is a parameter means that we can set it initially to the zero address,
/// and then change it later via governance, to the actual address of the deployed contract.
pub static EthereumGatewayAddress: H160 = H160::repeat_byte(0x0);
}
}
#[cfg(feature = "runtime-benchmarks")]
impl Default for RuntimeParameters {
fn default() -> Self {
RuntimeParameters::RuntimeConfig(
dynamic_params::runtime_config::Parameters::EthereumGatewayAddress(
dynamic_params::runtime_config::EthereumGatewayAddress,
Some(H160::repeat_byte(0x0)),
),
)
}
}

View file

@ -0,0 +1,220 @@
use crate::{
configs::BABE_GENESIS_EPOCH_CONFIG, AccountId, BalancesConfig, RuntimeGenesisConfig,
SessionKeys, Signature, SudoConfig,
};
use alloc::{format, vec, vec::Vec};
use hex_literal::hex;
use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
use serde_json::Value;
use sp_consensus_babe::AuthorityId as BabeId;
use sp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId;
use sp_consensus_grandpa::AuthorityId as GrandpaId;
use sp_core::{ecdsa, Pair, Public};
use sp_genesis_builder::{self, PresetId};
use sp_runtime::traits::{IdentifyAccount, Verify};
const STAGENET_EVM_CHAIN_ID: u64 = 1283;
// Returns the genesis config presets populated with given parameters.
fn testnet_genesis(
initial_authorities: Vec<(AccountId, BabeId, GrandpaId, ImOnlineId, BeefyId)>,
root_key: AccountId,
endowed_accounts: Vec<AccountId>,
evm_chain_id: u64,
) -> Value {
let config = RuntimeGenesisConfig {
balances: BalancesConfig {
balances: endowed_accounts
.iter()
.cloned()
.map(|k| (k, 1u128 << 110))
.collect::<Vec<_>>(),
},
babe: pallet_babe::GenesisConfig {
epoch_config: BABE_GENESIS_EPOCH_CONFIG,
..Default::default()
},
evm_chain_id: pallet_evm_chain_id::GenesisConfig {
chain_id: evm_chain_id,
..Default::default()
},
session: pallet_session::GenesisConfig {
keys: initial_authorities
.iter()
.map(|(account, babe, grandpa, im_online, beefy)| {
(
*account,
*account,
session_keys(
babe.clone(),
grandpa.clone(),
im_online.clone(),
beefy.clone(),
),
)
})
.collect::<Vec<_>>(),
..Default::default()
},
sudo: SudoConfig {
key: Some(root_key),
},
validator_set: pallet_validator_set::GenesisConfig {
initial_validators: initial_authorities
.iter()
.map(|(account, ..)| *account)
.collect::<Vec<_>>()
.try_into()
.expect("Too many initial authorities"),
},
..Default::default()
};
serde_json::to_value(config).expect("Could not build genesis config.")
}
/// Return the development genesis config.
pub fn development_config_genesis() -> Value {
let mut endowed_accounts = pre_funded_accounts();
endowed_accounts.sort();
testnet_genesis(
vec![authority_keys_from_seed("Alice")],
alith(),
endowed_accounts,
STAGENET_EVM_CHAIN_ID,
)
}
/// Return the local genesis config preset.
pub fn local_config_genesis() -> Value {
let mut endowed_accounts = pre_funded_accounts();
endowed_accounts.sort();
testnet_genesis(
vec![
authority_keys_from_seed("Alice"),
authority_keys_from_seed("Bob"),
authority_keys_from_seed("Charlie"),
authority_keys_from_seed("Dave"),
authority_keys_from_seed("Eve"),
authority_keys_from_seed("Ferdie"),
],
alith(),
endowed_accounts,
STAGENET_EVM_CHAIN_ID,
)
}
/// Provides the JSON representation of predefined genesis config for given `id`.
pub fn get_preset(id: &PresetId) -> Option<Vec<u8>> {
let patch = match id.as_str() {
sp_genesis_builder::DEV_RUNTIME_PRESET => development_config_genesis(),
sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET => local_config_genesis(),
_ => return None,
};
Some(
serde_json::to_string(&patch)
.expect("serialization to json is expected to work. qed.")
.into_bytes(),
)
}
/// List of supported presets.
pub fn preset_names() -> Vec<PresetId> {
vec![
PresetId::from(sp_genesis_builder::DEV_RUNTIME_PRESET),
PresetId::from(sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET),
]
}
/// 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()
}
fn session_keys(
babe: BabeId,
grandpa: GrandpaId,
im_online: ImOnlineId,
beefy: BeefyId,
) -> SessionKeys {
SessionKeys {
babe,
grandpa,
im_online,
beefy,
}
}
type AccountPublic = <Signature as Verify>::Signer;
/// Generate an account ID 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 a Babe authority key.
pub fn authority_keys_from_seed(s: &str) -> (AccountId, BabeId, GrandpaId, ImOnlineId, BeefyId) {
(
get_account_id_from_seed::<ecdsa::Public>(s),
get_from_seed::<BabeId>(s),
get_from_seed::<GrandpaId>(s),
get_from_seed::<ImOnlineId>(s),
get_from_seed::<BeefyId>(s),
)
}
pub fn alith() -> AccountId {
AccountId::from(hex!("f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"))
}
pub fn baltathar() -> AccountId {
AccountId::from(hex!("3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"))
}
pub fn charleth() -> AccountId {
AccountId::from(hex!("798d4Ba9baf0064Ec19eB4F0a1a45785ae9D6DFc"))
}
pub fn dorothy() -> AccountId {
AccountId::from(hex!("773539d4Ac0e786233D90A233654ccEE26a613D9"))
}
pub fn ethan() -> AccountId {
AccountId::from(hex!("Ff64d3F6efE2317EE2807d2235B1ac2AA69d9E87"))
}
pub fn frank() -> AccountId {
AccountId::from(hex!("C0F0f4ab324C46e55D02D0033343B4Be8A55532d"))
}
pub fn beacon_relayer() -> AccountId {
AccountId::from(hex!("c46e141b5083721ad5f5056ba1cded69dce4a65f"))
}
/// Get pre-funded accounts
pub fn pre_funded_accounts() -> Vec<AccountId> {
// These addresses are derived from Substrate's canonical mnemonic:
// bottom drive obey lake curtain smoke basket hold race lonely fit walk
vec![
get_account_id_from_seed::<ecdsa::Public>("Alice"),
get_account_id_from_seed::<ecdsa::Public>("Bob"),
get_account_id_from_seed::<ecdsa::Public>("Charlie"),
get_account_id_from_seed::<ecdsa::Public>("Dave"),
get_account_id_from_seed::<ecdsa::Public>("Eve"),
get_account_id_from_seed::<ecdsa::Public>("Ferdie"),
alith(),
baltathar(),
charleth(),
dorothy(),
ethan(),
frank(),
beacon_relayer(),
]
}

View file

@ -12,15 +12,11 @@ mod benchmarks;
pub mod configs;
use alloc::{borrow::Cow, vec::Vec};
use sp_runtime::{
generic, impl_opaque_keys,
traits::{BlakeTwo256, IdentifyAccount, Verify},
};
use sp_runtime::{generic, impl_opaque_keys};
#[cfg(feature = "std")]
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
use fp_account::EthereumSignature;
pub use frame_system::Call as SystemCall;
pub use pallet_balances::Call as BalancesCall;
pub use pallet_timestamp::Call as TimestampCall;
@ -28,6 +24,10 @@ use sp_core::H160;
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
pub use datahaven_runtime_common::{
AccountId, Address, Balance, BlockNumber, Hash, Header, Nonce, Signature,
};
pub mod genesis_config_presets;
/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
@ -129,40 +129,9 @@ pub fn native_version() -> NativeVersion {
}
}
/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
pub type Signature = EthereumSignature;
/// Some way of identifying an account on the chain. We intentionally make it equivalent
/// to the public key of our transaction signing scheme.
pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
/// Balance of an account.
pub type Balance = u128;
/// Index of a transaction in the chain.
pub type Nonce = u32;
/// A hash of some data used by the chain.
pub type Hash = sp_core::H256;
/// An index to a block.
pub type BlockNumber = u32;
/// The address format for describing accounts.
pub type Address = AccountId;
/// Block header type as expected by this runtime.
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
/// Block type as expected by this runtime.
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
/// A Block signed with a Justification
pub type SignedBlock = generic::SignedBlock<Block>;
/// BlockId type as expected by this runtime.
pub type BlockId = generic::BlockId<Block>;
/// The SignedExtension to the basic transaction logic.
pub type SignedExtra = (
frame_system::CheckNonZeroSender<Runtime>,

View file

@ -0,0 +1,267 @@
[package]
name = "datahaven-testnet-runtime"
description = "DataHaven Testnet runtime"
version = "0.1.0"
license = "Unlicense"
authors = { workspace = true }
homepage = { workspace = true }
repository = { workspace = true }
edition = { workspace = true }
publish = false
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
bridge-hub-common = { workspace = true, optional = true }
codec = { workspace = true, features = ["derive"] }
datahaven-runtime-common = { workspace = true }
dhp-bridge = { workspace = true }
fp-account = { workspace = true, features = ["serde"] }
fp-evm = { workspace = true, features = ["serde"] }
fp-rpc = { workspace = true }
fp-self-contained = { workspace = true, features = ["serde", "try-runtime"] }
frame-benchmarking = { workspace = true, optional = true }
frame-executive = { workspace = true }
frame-metadata-hash-extension = { workspace = true }
frame-support = { workspace = true, features = ["experimental"] }
frame-system = { workspace = true }
frame-system-benchmarking = { workspace = true, optional = true }
frame-system-rpc-runtime-api = { workspace = true }
frame-try-runtime = { workspace = true, optional = true }
hex = { workspace = true }
hex-literal = { workspace = true }
pallet-authorship = { workspace = true }
pallet-babe = { workspace = true }
pallet-balances = { workspace = true }
pallet-beefy = { workspace = true }
pallet-beefy-mmr = { workspace = true }
pallet-ethereum = { workspace = true }
pallet-evm = { workspace = true }
pallet-evm-chain-id = { workspace = true }
pallet-grandpa = { workspace = true }
pallet-identity = { workspace = true }
pallet-im-online = { workspace = true }
pallet-message-queue = { workspace = true }
pallet-mmr = { workspace = true }
pallet-multisig = { workspace = true }
pallet-offences = { workspace = true }
pallet-outbound-commitment-store = { workspace = true }
pallet-parameters = { workspace = true }
pallet-preimage = { workspace = true }
pallet-scheduler = { workspace = true }
pallet-session = { workspace = true }
pallet-sudo = { workspace = true }
pallet-timestamp = { workspace = true }
pallet-transaction-payment = { workspace = true }
pallet-transaction-payment-rpc-runtime-api = { workspace = true }
pallet-utility = { workspace = true }
pallet-validator-set = { workspace = true }
polkadot-primitives = { workspace = true }
polkadot-runtime-common = { workspace = true }
scale-info = { workspace = true, features = ["derive", "serde"] }
serde_json = { workspace = true, default-features = false, features = ["alloc"] }
snowbridge-beacon-primitives = { workspace = true }
snowbridge-core = { workspace = true }
snowbridge-inbound-queue-primitives = { workspace = true }
snowbridge-merkle-tree = { workspace = true }
snowbridge-outbound-queue-primitives = { workspace = true }
snowbridge-outbound-queue-v2-runtime-api = { workspace = true }
snowbridge-pallet-ethereum-client = { workspace = true }
snowbridge-pallet-inbound-queue-v2 = { workspace = true }
snowbridge-pallet-outbound-queue-v2 = { workspace = true }
snowbridge-pallet-system = { workspace = true }
snowbridge-pallet-system-v2 = { workspace = true }
snowbridge-system-v2-runtime-api = { workspace = true }
snowbridge-verification-primitives = { workspace = true }
sp-api = { workspace = true }
sp-block-builder = { workspace = true }
sp-consensus-babe = { workspace = true, features = ["serde"] }
sp-consensus-beefy = { workspace = true, features = ["serde"] }
sp-consensus-grandpa = { workspace = true, features = ["serde"] }
sp-core = { workspace = true, features = ["serde"] }
sp-genesis-builder = { workspace = true }
sp-inherents = { workspace = true }
sp-keyring = { workspace = true }
sp-offchain = { workspace = true }
sp-runtime = { workspace = true, features = ["serde"] }
sp-session = { workspace = true }
sp-staking = { workspace = true }
sp-std = { workspace = true }
sp-storage = { workspace = true }
sp-transaction-pool = { workspace = true }
sp-version = { workspace = true, features = ["serde"] }
xcm = { workspace = true }
xcm-builder = { workspace = true }
xcm-executor = { workspace = true }
[build-dependencies]
substrate-wasm-builder = { workspace = true, optional = true, default-features = true }
[features]
default = ["std"]
std = [
"codec/std",
"datahaven-runtime-common/std",
"fp-account/std",
"frame-benchmarking?/std",
"frame-executive/std",
"frame-metadata-hash-extension/std",
"frame-support/std",
"frame-system-benchmarking?/std",
"frame-system-rpc-runtime-api/std",
"frame-system/std",
"frame-try-runtime?/std",
"pallet-authorship/std",
"pallet-babe/std",
"pallet-balances/std",
"pallet-beefy-mmr/std",
"pallet-beefy/std",
"pallet-ethereum/std",
"pallet-evm-chain-id/std",
"pallet-evm/std",
"pallet-grandpa/std",
"pallet-identity/std",
"pallet-im-online/std",
"pallet-message-queue/std",
"pallet-mmr/std",
"pallet-multisig/std",
"pallet-offences/std",
"pallet-parameters/std",
"pallet-preimage/std",
"pallet-scheduler/std",
"pallet-session/std",
"pallet-sudo/std",
"pallet-timestamp/std",
"pallet-transaction-payment-rpc-runtime-api/std",
"pallet-transaction-payment/std",
"pallet-utility/std",
"pallet-validator-set/std",
"polkadot-primitives/std",
"polkadot-runtime-common/std",
"scale-info/std",
"serde_json/std",
"snowbridge-beacon-primitives/std",
"snowbridge-inbound-queue-primitives/std",
"snowbridge-outbound-queue-primitives/std",
"snowbridge-pallet-ethereum-client/std",
"snowbridge-pallet-inbound-queue-v2/std",
"snowbridge-pallet-outbound-queue-v2/std",
"snowbridge-merkle-tree/std",
"snowbridge-outbound-queue-v2-runtime-api/std",
"snowbridge-pallet-system/std",
"snowbridge-pallet-system-v2/std",
"snowbridge-system-v2-runtime-api/std",
"dhp-bridge/std",
"snowbridge-verification-primitives/std",
"sp-api/std",
"sp-block-builder/std",
"sp-consensus-babe/std",
"sp-consensus-beefy/std",
"sp-consensus-grandpa/std",
"sp-core/std",
"sp-genesis-builder/std",
"sp-inherents/std",
"sp-keyring/std",
"sp-offchain/std",
"sp-runtime/std",
"sp-session/std",
"sp-staking/std",
"sp-std/std",
"sp-storage/std",
"sp-transaction-pool/std",
"sp-version/std",
"substrate-wasm-builder",
"pallet-outbound-commitment-store/std",
]
runtime-benchmarks = [
"bridge-hub-common",
"datahaven-runtime-common/runtime-benchmarks",
"frame-benchmarking/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-system-benchmarking/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-beefy-mmr/runtime-benchmarks",
"pallet-ethereum/runtime-benchmarks",
"pallet-evm/runtime-benchmarks",
"pallet-grandpa/runtime-benchmarks",
"pallet-identity/runtime-benchmarks",
"pallet-im-online/runtime-benchmarks",
"pallet-message-queue/runtime-benchmarks",
"pallet-mmr/runtime-benchmarks",
"pallet-multisig/runtime-benchmarks",
"pallet-offences/runtime-benchmarks",
"pallet-parameters/runtime-benchmarks",
"pallet-preimage/runtime-benchmarks",
"pallet-scheduler/runtime-benchmarks",
"pallet-sudo/runtime-benchmarks",
"pallet-timestamp/runtime-benchmarks",
"pallet-utility/runtime-benchmarks",
"polkadot-primitives/runtime-benchmarks",
"polkadot-runtime-common/runtime-benchmarks",
"snowbridge-inbound-queue-primitives/runtime-benchmarks",
"snowbridge-pallet-ethereum-client/runtime-benchmarks",
"snowbridge-pallet-inbound-queue-v2/runtime-benchmarks",
"snowbridge-pallet-system-v2/runtime-benchmarks",
"snowbridge-pallet-outbound-queue-v2/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"snowbridge-pallet-system/runtime-benchmarks",
"pallet-outbound-commitment-store/runtime-benchmarks",
]
try-runtime = [
"fp-self-contained/try-runtime",
"frame-executive/try-runtime",
"frame-support/try-runtime",
"frame-system/try-runtime",
"frame-try-runtime/try-runtime",
"pallet-authorship/try-runtime",
"pallet-babe/try-runtime",
"pallet-balances/try-runtime",
"pallet-beefy-mmr/try-runtime",
"pallet-beefy/try-runtime",
"pallet-ethereum/try-runtime",
"pallet-evm/try-runtime",
"pallet-grandpa/try-runtime",
"pallet-identity/try-runtime",
"pallet-im-online/try-runtime",
"pallet-message-queue/try-runtime",
"pallet-mmr/try-runtime",
"pallet-multisig/try-runtime",
"pallet-offences/try-runtime",
"pallet-parameters/try-runtime",
"pallet-preimage/try-runtime",
"pallet-scheduler/try-runtime",
"pallet-session/try-runtime",
"pallet-sudo/try-runtime",
"pallet-timestamp/try-runtime",
"pallet-transaction-payment/try-runtime",
"pallet-utility/try-runtime",
"polkadot-runtime-common/try-runtime",
"snowbridge-pallet-ethereum-client/try-runtime",
"snowbridge-pallet-inbound-queue-v2/try-runtime",
"snowbridge-pallet-system-v2/try-runtime",
"snowbridge-pallet-outbound-queue-v2/try-runtime",
"sp-runtime/try-runtime",
"snowbridge-pallet-system/try-runtime",
"pallet-outbound-commitment-store/try-runtime",
]
fast-runtime = [
"datahaven-runtime-common/fast-runtime",
]
# Enable the metadata hash generation.
#
# This is hidden behind a feature because it increases the compile time.
# The wasm binary needs to be compiled twice, once to fetch the metadata,
# generate the metadata hash and then a second time with the
# `RUNTIME_METADATA_HASH` environment variable set for the `CheckMetadataHash`
# extension.
metadata-hash = ["substrate-wasm-builder/metadata-hash"]
# A convenience feature for enabling things when doing a build
# for an on-chain release.
on-chain-release-build = ["metadata-hash", "sp-api/disable-logging"]

View file

@ -0,0 +1,16 @@
#[cfg(all(feature = "std", feature = "metadata-hash"))]
fn main() {
substrate_wasm_builder::WasmBuilder::init_with_defaults()
.enable_metadata_hash("UNIT", 12)
.build();
}
#[cfg(all(feature = "std", not(feature = "metadata-hash")))]
fn main() {
substrate_wasm_builder::WasmBuilder::build_using_defaults();
}
/// The wasm builder is deactivated when compiling
/// this crate for wasm to speed up the compilation.
#[cfg(not(feature = "std"))]
fn main() {}

View file

@ -0,0 +1,800 @@
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// For more information, please refer to <http://unlicense.org>
// Local module imports
use super::{
AccountId, Babe, Balance, Beefy, BeefyMmrLeaf, Block, BlockNumber, Ethereum, Executive,
Grandpa, Historical, InherentDataExt, Mmr, Nonce, Runtime, RuntimeCall, RuntimeGenesisConfig,
RuntimeOrigin, SessionKeys, System, TransactionPayment, UncheckedExtrinsic, VERSION,
};
// External crates imports
use crate::configs::BABE_GENESIS_EPOCH_CONFIG;
use alloc::vec::Vec;
use codec::Encode;
use datahaven_runtime_common::time::EpochDurationInBlocks;
use fp_rpc::TransactionStatus;
use frame_support::traits::OnFinalize;
use pallet_ethereum::Transaction as EthereumTransaction;
use pallet_evm::GasWeightMapping;
use frame_support::traits::KeyOwnerProofSystem;
use frame_support::{
genesis_builder_helper::{build_state, get_preset},
weights::Weight,
};
use pallet_ethereum::Call::transact;
use pallet_evm::Account as EVMAccount;
use pallet_evm::FeeCalculator;
use pallet_evm::Runner;
use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId};
use polkadot_primitives::Hash;
use snowbridge_core::AgentId;
use sp_api::impl_runtime_apis;
use sp_consensus_beefy::{
ecdsa_crypto::{AuthorityId as BeefyId, Signature as BeefySignature},
AncestryHelper,
};
use sp_core::{Get, H256, U256};
use sp_core::{OpaqueMetadata, H160};
use sp_runtime::traits::{DispatchInfoOf, Dispatchable, PostDispatchInfoOf};
use sp_runtime::transaction_validity::TransactionValidityError;
use sp_runtime::{
traits::Block as BlockT,
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult, Permill,
};
use sp_version::RuntimeVersion;
use xcm::VersionedLocation;
/// MMR helper types.
mod mmr {
use super::Runtime;
pub use pallet_mmr::primitives::*;
pub type Leaf = <<Runtime as pallet_mmr::Config>::LeafData as LeafDataProvider>::LeafData;
pub type Hashing = <Runtime as pallet_mmr::Config>::Hashing;
pub type Hash = <Hashing as sp_runtime::traits::Hash>::Output;
}
#[derive(Clone)]
pub struct TransactionConverter;
impl fp_self_contained::SelfContainedCall for RuntimeCall {
type SignedInfo = H160;
fn is_self_contained(&self) -> bool {
match self {
RuntimeCall::Ethereum(call) => call.is_self_contained(),
_ => false,
}
}
fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {
match self {
RuntimeCall::Ethereum(call) => call.check_self_contained(),
_ => None,
}
}
fn validate_self_contained(
&self,
signed_info: &Self::SignedInfo,
dispatch_info: &DispatchInfoOf<RuntimeCall>,
len: usize,
) -> Option<TransactionValidity> {
match self {
RuntimeCall::Ethereum(call) => {
call.validate_self_contained(signed_info, dispatch_info, len)
}
_ => None,
}
}
fn pre_dispatch_self_contained(
&self,
info: &Self::SignedInfo,
dispatch_info: &DispatchInfoOf<RuntimeCall>,
len: usize,
) -> Option<Result<(), TransactionValidityError>> {
match self {
RuntimeCall::Ethereum(call) => {
call.pre_dispatch_self_contained(info, dispatch_info, len)
}
_ => None,
}
}
fn apply_self_contained(
self,
info: Self::SignedInfo,
) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {
match self {
call @ RuntimeCall::Ethereum(pallet_ethereum::Call::transact { .. }) => {
Some(call.dispatch(RuntimeOrigin::from(
pallet_ethereum::RawOrigin::EthereumTransaction(info),
)))
}
_ => None,
}
}
}
impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {
fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {
UncheckedExtrinsic::new_bare(
pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
)
}
}
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) -> sp_runtime::ExtrinsicInclusionMode {
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() -> 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: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
data.create_extrinsics()
}
fn check_inherents(
block: Block,
data: sp_inherents::InherentData,
) -> sp_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_session::SessionKeys<Block> for Runtime {
fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
SessionKeys::generate(seed)
}
fn decode_session_keys(
encoded: Vec<u8>,
) -> Option<Vec<(Vec<u8>, sp_core::crypto::KeyTypeId)>> {
SessionKeys::decode_into_raw_public_keys(&encoded)
}
}
impl sp_consensus_babe::BabeApi<Block> for Runtime {
fn configuration() -> sp_consensus_babe::BabeConfiguration {
let epoch_config = Babe::epoch_config().unwrap_or(BABE_GENESIS_EPOCH_CONFIG);
sp_consensus_babe::BabeConfiguration {
slot_duration: Babe::slot_duration(),
epoch_length: EpochDurationInBlocks::get().into(),
c: epoch_config.c,
authorities: Babe::authorities().to_vec(),
randomness: Babe::randomness(),
allowed_slots: epoch_config.allowed_slots,
}
}
fn current_epoch_start() -> sp_consensus_babe::Slot {
Babe::current_epoch_start()
}
fn current_epoch() -> sp_consensus_babe::Epoch {
Babe::current_epoch()
}
fn next_epoch() -> sp_consensus_babe::Epoch {
Babe::next_epoch()
}
fn generate_key_ownership_proof(
_slot: sp_consensus_babe::Slot,
authority_id: sp_consensus_babe::AuthorityId,
) -> Option<sp_consensus_babe::OpaqueKeyOwnershipProof> {
use codec::Encode;
Historical::prove((sp_consensus_babe::KEY_TYPE, authority_id))
.map(|p| p.encode())
.map(sp_consensus_babe::OpaqueKeyOwnershipProof::new)
}
fn submit_report_equivocation_unsigned_extrinsic(
equivocation_proof: sp_consensus_babe::EquivocationProof<<Block as BlockT>::Header>,
key_owner_proof: sp_consensus_babe::OpaqueKeyOwnershipProof,
) -> Option<()> {
let key_owner_proof = key_owner_proof.decode()?;
Babe::submit_unsigned_equivocation_report(
equivocation_proof,
key_owner_proof,
)
}
}
impl sp_consensus_grandpa::GrandpaApi<Block> for Runtime {
fn grandpa_authorities() -> Vec<(GrandpaId, u64)> {
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,
sp_runtime::traits::NumberFor<Block>,
>,
key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof,
) -> Option<()> {
let key_owner_proof = key_owner_proof.decode()?;
Grandpa::submit_unsigned_equivocation_report(
equivocation_proof,
key_owner_proof,
)
}
fn generate_key_ownership_proof(
_set_id: fg_primitives::SetId,
authority_id: fg_primitives::AuthorityId,
) -> Option<fg_primitives::OpaqueKeyOwnershipProof> {
Historical::prove((fg_primitives::KEY_TYPE, authority_id))
.map(|p| p.encode())
.map(fg_primitives::OpaqueKeyOwnershipProof::new)
}
}
#[api_version(2)]
impl mmr::MmrApi<Block, mmr::Hash, BlockNumber> for Runtime {
fn mmr_root() -> Result<mmr::Hash, mmr::Error> {
Ok(pallet_mmr::RootHash::<Runtime>::get())
}
fn mmr_leaf_count() -> Result<mmr::LeafIndex, mmr::Error> {
Ok(pallet_mmr::NumberOfLeaves::<Runtime>::get())
}
fn generate_proof(
block_numbers: Vec<BlockNumber>,
best_known_block_number: Option<BlockNumber>,
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::LeafProof<mmr::Hash>), mmr::Error> {
Mmr::generate_proof(block_numbers, best_known_block_number).map(
|(leaves, proof)| {
(
leaves
.into_iter()
.map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf))
.collect(),
proof,
)
},
)
}
fn verify_proof(leaves: Vec<mmr::EncodableOpaqueLeaf>, proof: mmr::LeafProof<mmr::Hash>)
-> Result<(), mmr::Error>
{
let leaves = leaves.into_iter().map(|leaf|
leaf.into_opaque_leaf()
.try_decode()
.ok_or(mmr::Error::Verify)).collect::<Result<Vec<mmr::Leaf>, mmr::Error>>()?;
Mmr::verify_leaves(leaves, proof)
}
fn verify_proof_stateless(
root: mmr::Hash,
leaves: Vec<mmr::EncodableOpaqueLeaf>,
proof: mmr::LeafProof<mmr::Hash>
) -> Result<(), mmr::Error> {
let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect();
pallet_mmr::verify_leaves_proof::<mmr::Hashing, _>(root, nodes, proof)
}
}
impl pallet_beefy_mmr::BeefyMmrApi<Block, Hash> for RuntimeApi {
fn authority_set_proof() -> sp_consensus_beefy::mmr::BeefyAuthoritySet<Hash> {
BeefyMmrLeaf::authority_set_proof()
}
fn next_authority_set_proof() -> sp_consensus_beefy::mmr::BeefyNextAuthoritySet<Hash> {
BeefyMmrLeaf::next_authority_set_proof()
}
}
#[api_version(5)]
impl sp_consensus_beefy::BeefyApi<Block, BeefyId> for Runtime {
fn beefy_genesis() -> Option<BlockNumber> {
pallet_beefy::GenesisBlock::<Runtime>::get()
}
fn validator_set() -> Option<sp_consensus_beefy::ValidatorSet<BeefyId>> {
Beefy::validator_set()
}
fn submit_report_double_voting_unsigned_extrinsic(
equivocation_proof: sp_consensus_beefy::DoubleVotingProof<
BlockNumber,
BeefyId,
BeefySignature,
>,
key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof,
) -> Option<()> {
let key_owner_proof = key_owner_proof.decode()?;
Beefy::submit_unsigned_double_voting_report(
equivocation_proof,
key_owner_proof,
)
}
fn submit_report_fork_voting_unsigned_extrinsic(
equivocation_proof:
sp_consensus_beefy::ForkVotingProof<
<Block as BlockT>::Header,
BeefyId,
sp_runtime::OpaqueValue
>,
key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof,
) -> Option<()> {
Beefy::submit_unsigned_fork_voting_report(
equivocation_proof.try_into()?,
key_owner_proof.decode()?,
)
}
fn submit_report_future_block_voting_unsigned_extrinsic(
equivocation_proof: sp_consensus_beefy::FutureBlockVotingProof<BlockNumber, BeefyId>,
key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof,
) -> Option<()> {
Beefy::submit_unsigned_future_block_voting_report(
equivocation_proof,
key_owner_proof.decode()?,
)
}
fn generate_key_ownership_proof(
_set_id: sp_consensus_beefy::ValidatorSetId,
authority_id: BeefyId,
) -> Option<sp_consensus_beefy::OpaqueKeyOwnershipProof> {
Historical::prove((sp_consensus_beefy::KEY_TYPE, authority_id))
.map(|p| p.encode())
.map(sp_consensus_beefy::OpaqueKeyOwnershipProof::new)
}
fn generate_ancestry_proof(
prev_block_number: BlockNumber,
best_known_block_number: Option<BlockNumber>,
) -> Option<sp_runtime::OpaqueValue> {
use codec::Encode;
BeefyMmrLeaf::generate_proof(prev_block_number, best_known_block_number)
.map(|p| p.encode())
.map(sp_runtime::OpaqueValue::new)
}
}
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::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 snowbridge_outbound_queue_v2_runtime_api::OutboundQueueV2Api<Block, Balance> for Runtime {
fn prove_message(leaf_index: u64) -> Option<snowbridge_merkle_tree::MerkleProof> {
snowbridge_pallet_outbound_queue_v2::api::prove_message::<Runtime>(leaf_index)
}
}
impl snowbridge_system_v2_runtime_api::ControlV2Api<Block> for Runtime {
fn agent_id(location: VersionedLocation) -> Option<AgentId> {
snowbridge_pallet_system_v2::api::agent_id::<Runtime>(location)
}
}
#[cfg(feature = "runtime-benchmarks")]
impl frame_benchmarking::Benchmark<Block> for Runtime {
fn benchmark_metadata(extra: bool) -> (
Vec<frame_benchmarking::BenchmarkList>,
Vec<frame_support::traits::StorageInfo>,
) {
use frame_benchmarking::{baseline, Benchmarking, BenchmarkList};
use frame_support::traits::StorageInfoTrait;
use frame_system_benchmarking::Pallet as SystemBench;
use baseline::Pallet as BaselineBench;
use super::*;
let mut list = Vec::<BenchmarkList>::new();
list_benchmarks!(list, extra);
let storage_info = AllPalletsWithSystem::storage_info();
(list, storage_info)
}
#[expect(non_local_definitions)]
fn dispatch_benchmark(
config: frame_benchmarking::BenchmarkConfig
) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch};
use sp_storage::TrackedStorageKey;
use frame_system_benchmarking::Pallet as SystemBench;
use baseline::Pallet as BaselineBench;
use super::*;
impl frame_system_benchmarking::Config for Runtime {}
impl baseline::Config for Runtime {}
use frame_support::traits::WhitelistedStorageKeys;
let whitelist: Vec<TrackedStorageKey> = AllPalletsWithSystem::whitelisted_storage_keys();
let mut batches = Vec::<BenchmarkBatch>::new();
let params = (&config, &whitelist);
add_benchmarks!(params, batches);
Ok(batches)
}
}
#[cfg(feature = "try-runtime")]
impl frame_try_runtime::TryRuntime<Block> for Runtime {
fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
// NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to
// have a backtrace here. If any of the pre/post migration checks fail, we shall stop
// right here and right now.
let weight = Executive::try_runtime_upgrade(checks).unwrap();
(weight, super::configs::RuntimeBlockWeights::get().max_block)
}
fn execute_block(
block: Block,
state_root_check: bool,
signature_check: bool,
select: frame_try_runtime::TryStateSelect
) -> Weight {
// NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to
// have a backtrace here.
Executive::try_execute_block(block, state_root_check, signature_check, select).expect("execute-block failed")
}
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, crate::genesis_config_presets::get_preset)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
crate::genesis_config_presets::preset_names()
}
}
impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {
fn chain_id() -> u64 {
<Runtime as pallet_evm::Config>::ChainId::get()
}
fn account_basic(address: H160) -> EVMAccount {
let (account, _) = pallet_evm::Pallet::<Runtime>::account_basic(&address);
account
}
fn gas_price() -> U256 {
let (gas_price, _) = <Runtime as pallet_evm::Config>::FeeCalculator::min_gas_price();
gas_price
}
fn account_code_at(address: H160) -> Vec<u8> {
pallet_evm::AccountCodes::<Runtime>::get(address)
}
fn author() -> H160 {
<pallet_evm::Pallet<Runtime>>::find_author()
}
fn storage_at(address: H160, index: U256) -> H256 {
let tmp = index.to_big_endian();
pallet_evm::AccountStorages::<Runtime>::get(address, H256::from_slice(&tmp[..]))
}
fn call(
from: H160,
to: H160,
data: Vec<u8>,
value: U256,
gas_limit: U256,
max_fee_per_gas: Option<U256>,
max_priority_fee_per_gas: Option<U256>,
nonce: Option<U256>,
estimate: bool,
access_list: Option<Vec<(H160, Vec<H256>)>>,
) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {
let config = if estimate {
let mut config = <Runtime as pallet_evm::Config>::config().clone();
config.estimate = true;
Some(config)
} else {
None
};
let is_transactional = false;
let validate = true;
// Estimated encoded transaction size must be based on the heaviest transaction
// type (EIP1559Transaction) to be compatible with all transaction types.
let mut estimated_transaction_len = data.len() +
// pallet ethereum index: 1
// transact call index: 1
// Transaction enum variant: 1
// chain_id 8 bytes
// nonce: 32
// max_priority_fee_per_gas: 32
// max_fee_per_gas: 32
// gas_limit: 32
// action: 21 (enum varianrt + call address)
// value: 32
// access_list: 1 (empty vec size)
// 65 bytes signature
258;
if access_list.is_some() {
estimated_transaction_len += access_list.encoded_size();
}
let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
let without_base_extrinsic_weight = true;
let (weight_limit, proof_size_base_cost) =
match <Runtime as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
gas_limit,
without_base_extrinsic_weight
) {
weight_limit if weight_limit.proof_size() > 0 => {
(Some(weight_limit), Some(estimated_transaction_len as u64))
}
_ => (None, None),
};
<Runtime as pallet_evm::Config>::Runner::call(
from,
to,
data,
value,
gas_limit,
max_fee_per_gas,
max_priority_fee_per_gas,
nonce,
access_list.unwrap_or_default(),
is_transactional,
validate,
weight_limit,
proof_size_base_cost,
config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config()),
).map_err(|err| err.error.into())
}
fn create(
from: H160,
data: Vec<u8>,
value: U256,
gas_limit: U256,
max_fee_per_gas: Option<U256>,
max_priority_fee_per_gas: Option<U256>,
nonce: Option<U256>,
estimate: bool,
access_list: Option<Vec<(H160, Vec<H256>)>>,
) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {
let config = if estimate {
let mut config = <Runtime as pallet_evm::Config>::config().clone();
config.estimate = true;
Some(config)
} else {
None
};
let is_transactional = false;
let validate = true;
let gas_limit = if gas_limit > U256::from(u64::MAX) {
u64::MAX
} else {
gas_limit.low_u64()
};
let (weight_limit, proof_size_base_cost) = (None, None);
#[allow(clippy::or_fun_call)]
<Runtime as pallet_evm::Config>::Runner::create(
from,
data,
value,
gas_limit,
max_fee_per_gas,
max_priority_fee_per_gas,
nonce,
access_list.unwrap_or_default(),
is_transactional,
validate,
weight_limit,
proof_size_base_cost,
config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config()),
).map_err(|err| err.error.into())
}
fn current_transaction_statuses() -> Option<Vec<TransactionStatus>> {
pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
}
fn current_block() -> Option<pallet_ethereum::Block> {
pallet_ethereum::CurrentBlock::<Runtime>::get()
}
fn current_receipts() -> Option<Vec<pallet_ethereum::Receipt>> {
pallet_ethereum::CurrentReceipts::<Runtime>::get()
}
fn current_all() -> (
Option<pallet_ethereum::Block>,
Option<Vec<pallet_ethereum::Receipt>>,
Option<Vec<TransactionStatus>>,
) {
(
pallet_ethereum::CurrentBlock::<Runtime>::get(),
pallet_ethereum::CurrentReceipts::<Runtime>::get(),
pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
)
}
fn extrinsic_filter(
xts: Vec<<Block as BlockT>::Extrinsic>,
) -> Vec<EthereumTransaction> {
xts.into_iter().filter_map(|xt| match xt.0.function {
RuntimeCall::Ethereum(transact { transaction }) => Some(transaction),
_ => None
}).collect::<Vec<EthereumTransaction>>()
}
fn elasticity() -> Option<Permill> {
None
}
fn gas_limit_multiplier_support() {}
fn pending_block(
xts: Vec<<Block as BlockT>::Extrinsic>,
) -> (Option<pallet_ethereum::Block>, Option<Vec<TransactionStatus>>) {
for ext in xts.into_iter() {
let _ = Executive::apply_extrinsic(ext);
}
Ethereum::on_finalize(System::block_number() + 1);
(
pallet_ethereum::CurrentBlock::<Runtime>::get(),
pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
)
}
fn initialize_pending_block(header: &<Block as BlockT>::Header) {
Executive::initialize_block(header);
}
}
impl fp_rpc::ConvertTransactionRuntimeApi<Block> for Runtime {
fn convert_transaction(transaction: EthereumTransaction) -> <Block as BlockT>::Extrinsic {
UncheckedExtrinsic::new_bare(
pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
)
}
}
}

View file

@ -0,0 +1,38 @@
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// For more information, please refer to <http://unlicense.org>
frame_benchmarking::define_benchmarks!(
[frame_benchmarking, BaselineBench::<Runtime>]
[frame_system, SystemBench::<Runtime>]
[pallet_balances, Balances]
[pallet_identity, Identity]
[pallet_im_online, ImOnline]
[pallet_multisig, Multisig]
[pallet_preimage, Preimage]
[pallet_scheduler, Scheduler]
[pallet_timestamp, Timestamp]
[pallet_utility, Utility]
[pallet_sudo, Sudo]
);

View file

@ -0,0 +1,874 @@
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// For more information, please refer to <http://unlicense.org>
mod runtime_params;
use super::{
deposit, AccountId, Babe, Balance, Balances, BeefyMmrLeaf, Block, BlockNumber,
EthereumBeaconClient, EvmChainId, Hash, Historical, ImOnline, MessageQueue, Nonce, Offences,
OriginCaller, OutboundCommitmentStore, OutboundQueueV2, PalletInfo, Preimage, Runtime,
RuntimeCall, RuntimeEvent, RuntimeFreezeReason, RuntimeHoldReason, RuntimeOrigin, RuntimeTask,
Session, SessionKeys, Signature, System, Timestamp, ValidatorSet, EXISTENTIAL_DEPOSIT,
SLOT_DURATION, STORAGE_BYTE_FEE, SUPPLY_FACTOR, UNIT, VERSION,
};
use codec::{Decode, Encode};
use datahaven_runtime_common::{
gas::WEIGHT_PER_GAS,
time::{EpochDurationInBlocks, DAYS, MILLISECS_PER_BLOCK, MINUTES},
};
use dhp_bridge::EigenLayerMessageProcessor;
use frame_support::{
derive_impl,
pallet_prelude::TransactionPriority,
parameter_types,
traits::{
fungible::{Balanced, Credit, HoldConsideration, Inspect},
ConstU128, ConstU32, ConstU64, ConstU8, EqualPrivilegeOnly, FindAuthor,
KeyOwnerProofSystem, LinearStoragePrice, OnUnbalanced, VariantCountOf,
},
weights::{
constants::{RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND},
IdentityFee, RuntimeDbWeight, Weight,
},
};
use frame_system::{
limits::{BlockLength, BlockWeights},
EnsureRoot, EnsureRootWithSuccess,
};
use pallet_ethereum::PostLogContent;
use pallet_evm::{
EVMFungibleAdapter, EnsureAddressNever, EnsureAddressRoot, FeeCalculator,
FrameSystemAccountProvider, IdentityAddressMapping,
OnChargeEVMTransaction as OnChargeEVMTransactionT,
};
use pallet_grandpa::AuthorityId as GrandpaId;
use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
use pallet_transaction_payment::{
ConstFeeMultiplier, FungibleAdapter, Multiplier, Pallet as TransactionPayment,
};
use polkadot_primitives::Moment;
use runtime_params::RuntimeParameters;
use snowbridge_beacon_primitives::{Fork, ForkVersions};
use snowbridge_core::{gwei, meth, AgentIdOf, PricingParameters, Rewards};
use snowbridge_inbound_queue_primitives::RewardLedger;
use snowbridge_outbound_queue_primitives::{
v1::{Fee, Message, SendMessage},
v2::ConstantGasMeter,
SendError, SendMessageFeeProvider,
};
use snowbridge_pallet_outbound_queue_v2::OnNewCommitment;
use snowbridge_pallet_system::BalanceOf;
use sp_consensus_beefy::{
ecdsa_crypto::AuthorityId as BeefyId,
mmr::{BeefyDataProvider, MmrLeafVersion},
};
use sp_core::{crypto::KeyTypeId, Get, H160, H256, U256};
use sp_runtime::FixedU128;
use sp_runtime::{
traits::{ConvertInto, IdentityLookup, Keccak256, One, OpaqueKeys, UniqueSaturatedInto},
FixedPointNumber, Perbill,
};
use sp_staking::{EraIndex, SessionIndex};
use sp_std::{
convert::{From, Into},
prelude::*,
};
use sp_version::RuntimeVersion;
use xcm::latest::NetworkId;
use xcm::prelude::*;
#[cfg(feature = "runtime-benchmarks")]
use bridge_hub_common::AggregateMessageOrigin;
const EVM_CHAIN_ID: u64 = 1288;
const SS58_FORMAT: u16 = EVM_CHAIN_ID as u16;
// TODO: We need to define what do we want here as max PoV size
pub const MAX_POV_SIZE: u64 = 5 * 1024 * 1024;
// Todo: import all currency constants from moonbeam
pub const WEIGHT_FEE: Balance = 50_000 / 4;
pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND, u64::MAX)
.saturating_mul(2)
.set_proof_size(MAX_POV_SIZE);
const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
//╔═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
//║ COMMON PARAMETERS ║
//╚═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
parameter_types! {
pub const MaxAuthorities: u32 = 32;
pub const BondingDuration: EraIndex = polkadot_runtime_common::prod_or_fast!(28, 3);
pub const SessionsPerEra: SessionIndex = polkadot_runtime_common::prod_or_fast!(6, 1);
}
//╔═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
//║ SYSTEM AND CONSENSUS PALLETS ║
//╚═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
parameter_types! {
pub const BlockHashCount: BlockNumber = 2400;
pub const Version: RuntimeVersion = VERSION;
/// We allow for 2 seconds of compute with a 6 second average block time.
pub RuntimeBlockWeights: BlockWeights = BlockWeights::with_sensible_defaults(
Weight::from_parts(2u64 * WEIGHT_REF_TIME_PER_SECOND, u64::MAX),
NORMAL_DISPATCH_RATIO,
);
pub RuntimeBlockLength: BlockLength = BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
pub const SS58Prefix: u16 = SS58_FORMAT;
}
/// The default types are being injected by [`derive_impl`](`frame_support::derive_impl`) from
/// [`SoloChainDefaultConfig`](`struct@frame_system::config_preludes::SolochainDefaultConfig`),
/// but overridden as needed.
#[derive_impl(frame_system::config_preludes::SolochainDefaultConfig)]
impl frame_system::Config for Runtime {
/// The block type for the runtime.
type Block = Block;
/// Block & extrinsics weights: base values and limits.
type BlockWeights = RuntimeBlockWeights;
/// The maximum length of a block (in bytes).
type BlockLength = RuntimeBlockLength;
/// The identifier used to distinguish between accounts.
type AccountId = AccountId;
/// The lookup mechanism to get account ID from whatever is passed in dispatchers.
type Lookup = IdentityLookup<AccountId>;
/// The type for storing how many extrinsics an account has signed.
type Nonce = Nonce;
/// The type for hashing blocks and tries.
type Hash = Hash;
/// Maximum number of block number to block hash mappings to keep (oldest pruned first).
type BlockHashCount = BlockHashCount;
/// The weight of database operations that the runtime can invoke.
type DbWeight = RocksDbWeight;
/// Version of the runtime.
type Version = Version;
/// The data to be stored in an account.
type AccountData = pallet_balances::AccountData<Balance>;
/// This is used as an identifier of the chain. 42 is the generic substrate prefix.
type SS58Prefix = SS58Prefix;
type MaxConsumers = frame_support::traits::ConstU32<16>;
}
// 1 in 4 blocks (on average, not counting collisions) will be primary babe blocks.
pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4);
/// The BABE epoch configuration at genesis.
pub const BABE_GENESIS_EPOCH_CONFIG: sp_consensus_babe::BabeEpochConfiguration =
sp_consensus_babe::BabeEpochConfiguration {
c: PRIMARY_PROBABILITY,
allowed_slots: sp_consensus_babe::AllowedSlots::PrimaryAndSecondaryVRFSlots,
};
parameter_types! {
pub const ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK;
pub ReportLongevity: u64 =
BondingDuration::get() as u64 * SessionsPerEra::get() as u64 * (EpochDurationInBlocks::get() as u64);
}
impl pallet_babe::Config for Runtime {
type EpochDuration = EpochDurationInBlocks;
type ExpectedBlockTime = ExpectedBlockTime;
type EpochChangeTrigger = pallet_babe::ExternalTrigger;
type DisabledValidators = Session;
type WeightInfo = ();
type MaxAuthorities = MaxAuthorities;
type MaxNominators = ConstU32<0>;
type KeyOwnerProof =
<Historical as KeyOwnerProofSystem<(KeyTypeId, pallet_babe::AuthorityId)>>::Proof;
type EquivocationReportSystem =
pallet_babe::EquivocationReportSystem<Self, Offences, Historical, ReportLongevity>;
}
impl pallet_timestamp::Config for Runtime {
/// A timestamp: milliseconds since the unix epoch.
type Moment = u64;
type OnTimestampSet = Babe;
type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>;
type WeightInfo = ();
}
impl pallet_balances::Config for Runtime {
type MaxLocks = ConstU32<50>;
type MaxReserves = ();
type ReserveIdentifier = [u8; 8];
/// The type for recording an account's balance.
type Balance = Balance;
/// The ubiquitous event type.
type RuntimeEvent = RuntimeEvent;
type DustRemoval = ();
type ExistentialDeposit = ConstU128<EXISTENTIAL_DEPOSIT>;
type AccountStore = System;
type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
type FreezeIdentifier = RuntimeFreezeReason;
type MaxFreezes = VariantCountOf<RuntimeFreezeReason>;
type RuntimeHoldReason = RuntimeHoldReason;
type RuntimeFreezeReason = RuntimeFreezeReason;
type DoneSlashHandler = ();
}
impl pallet_authorship::Config for Runtime {
type FindAuthor = pallet_session::FindAccountFromAuthorIndex<Self, Babe>;
type EventHandler = ImOnline;
}
impl pallet_offences::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type IdentificationTuple = pallet_session::historical::IdentificationTuple<Self>;
type OnOffenceHandler = ValidatorSet;
}
impl pallet_session::historical::Config for Runtime {
type FullIdentification = Self::ValidatorId;
type FullIdentificationOf = Self::ValidatorIdOf;
}
impl pallet_session::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type ValidatorId = AccountId;
type ValidatorIdOf = ConvertInto;
type ShouldEndSession = Babe;
type NextSessionRotation = Babe;
type SessionManager = pallet_session::historical::NoteHistoricalRoot<Self, ValidatorSet>;
type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
type Keys = SessionKeys;
type WeightInfo = pallet_session::weights::SubstrateWeight<Runtime>;
}
parameter_types! {
pub const SetKeysCooldownBlocks: BlockNumber = 5 * MINUTES;
}
impl pallet_validator_set::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type AddRemoveOrigin = EnsureRoot<AccountId>;
type MaxAuthorities = MaxAuthorities;
type SetKeysCooldownBlocks = SetKeysCooldownBlocks;
type WeightInfo = pallet_validator_set::weights::SubstrateWeight<Runtime>;
}
parameter_types! {
pub const ImOnlineUnsignedPriority: TransactionPriority = TransactionPriority::MAX;
}
impl pallet_im_online::Config for Runtime {
type AuthorityId = ImOnlineId;
type MaxKeys = MaxAuthorities;
type MaxPeerInHeartbeats = ConstU32<0>; // Not used any more
type RuntimeEvent = RuntimeEvent;
type ValidatorSet = Historical;
type NextSessionRotation = Babe;
type ReportUnresponsiveness = Offences;
type UnsignedPriority = ImOnlineUnsignedPriority;
type WeightInfo = ();
}
parameter_types! {
pub const EquivocationReportPeriodInEpochs: u64 = 168;
pub const EquivocationReportPeriodInBlocks: u64 =
EquivocationReportPeriodInEpochs::get() * (EpochDurationInBlocks::get() as u64);
pub const MaxSetIdSessionEntries: u32 = BondingDuration::get() * SessionsPerEra::get();
}
impl pallet_grandpa::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type WeightInfo = ();
type MaxAuthorities = MaxAuthorities;
type MaxNominators = ConstU32<0>;
type MaxSetIdSessionEntries = MaxSetIdSessionEntries;
type KeyOwnerProof = <Historical as KeyOwnerProofSystem<(KeyTypeId, GrandpaId)>>::Proof;
type EquivocationReportSystem = pallet_grandpa::EquivocationReportSystem<
Self,
Offences,
Historical,
EquivocationReportPeriodInBlocks,
>;
}
parameter_types! {
pub FeeMultiplier: Multiplier = Multiplier::one();
}
impl pallet_transaction_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type OnChargeTransaction = FungibleAdapter<Balances, ()>;
type OperationalFeeMultiplier = ConstU8<5>;
type WeightToFee = IdentityFee<Balance>;
type LengthToFee = IdentityFee<Balance>;
type FeeMultiplierUpdate = ConstFeeMultiplier<FeeMultiplier>;
type WeightInfo = ();
}
parameter_types! {
pub const BeefySetIdSessionEntries: u32 = BondingDuration::get() * SessionsPerEra::get();
}
impl pallet_beefy::Config for Runtime {
type BeefyId = BeefyId;
type MaxAuthorities = ConstU32<32>;
type MaxNominators = ConstU32<0>;
type MaxSetIdSessionEntries = BeefySetIdSessionEntries;
type OnNewValidatorSet = BeefyMmrLeaf;
type AncestryHelper = BeefyMmrLeaf;
type WeightInfo = ();
type KeyOwnerProof = <Historical as KeyOwnerProofSystem<(KeyTypeId, BeefyId)>>::Proof;
type EquivocationReportSystem = ();
}
parameter_types! {
pub LeafVersion: MmrLeafVersion = MmrLeafVersion::new(0, 0);
}
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct LeafExtraData {
extra: H256,
}
pub struct LeafExtraDataProvider;
impl BeefyDataProvider<LeafExtraData> for LeafExtraDataProvider {
fn extra_data() -> LeafExtraData {
LeafExtraData {
extra: OutboundCommitmentStore::get_latest_commitment().unwrap_or_default(),
}
}
}
impl pallet_mmr::Config for Runtime {
const INDEXING_PREFIX: &'static [u8] = pallet_mmr::primitives::INDEXING_PREFIX;
type Hashing = Keccak256;
type LeafData = pallet_beefy_mmr::Pallet<Runtime>;
type OnNewRoot = pallet_beefy_mmr::DepositBeefyDigest<Runtime>;
type WeightInfo = ();
type BlockHashProvider = pallet_mmr::DefaultBlockHashProvider<Runtime>;
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = ();
}
impl pallet_beefy_mmr::Config for Runtime {
type LeafVersion = LeafVersion;
type BeefyAuthorityToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum;
type LeafExtra = LeafExtraData;
type BeefyDataProvider = LeafExtraDataProvider;
type WeightInfo = ();
}
//╔═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
//║ POLKADOT SDK UTILITY PALLETS ║
//╚═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
impl pallet_utility::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type RuntimeCall = RuntimeCall;
type PalletsOrigin = OriginCaller;
type WeightInfo = ();
}
parameter_types! {
pub MaximumSchedulerWeight: Weight = NORMAL_DISPATCH_RATIO * RuntimeBlockWeights::get().max_block;
pub const NoPreimagePostponement: Option<u32> = Some(10);
}
impl pallet_scheduler::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type RuntimeOrigin = RuntimeOrigin;
type PalletsOrigin = OriginCaller;
type RuntimeCall = RuntimeCall;
type MaximumWeight = MaximumSchedulerWeight;
type ScheduleOrigin = EnsureRoot<AccountId>;
type MaxScheduledPerBlock = ConstU32<50>;
type OriginPrivilegeCmp = EqualPrivilegeOnly;
type Preimages = Preimage;
type WeightInfo = ();
}
parameter_types! {
pub const PreimageBaseDeposit: Balance = 5 * UNIT * SUPPLY_FACTOR ;
pub const PreimageByteDeposit: Balance = STORAGE_BYTE_FEE;
pub const PreimageHoldReason: RuntimeHoldReason =
RuntimeHoldReason::Preimage(pallet_preimage::HoldReason::Preimage);
}
impl pallet_preimage::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type ManagerOrigin = EnsureRoot<AccountId>;
type Consideration = HoldConsideration<
AccountId,
Balances,
PreimageHoldReason,
LinearStoragePrice<PreimageBaseDeposit, PreimageByteDeposit, Balance>,
>;
type WeightInfo = ();
}
parameter_types! {
pub const MaxSubAccounts: u32 = 100;
pub const MaxAdditionalFields: u32 = 100;
pub const MaxRegistrars: u32 = 20;
pub const PendingUsernameExpiration: u32 = 7 * DAYS;
pub const MaxSuffixLength: u32 = 7;
pub const MaxUsernameLength: u32 = 32;
}
type IdentityForceOrigin = EnsureRoot<AccountId>;
type IdentityRegistrarOrigin = EnsureRoot<AccountId>;
// TODO: Add governance origin when available
// type IdentityForceOrigin =
// EitherOfDiverse<EnsureRoot<AccountId>, governance::custom_origins::GeneralAdmin>;
// type IdentityRegistrarOrigin =
// EitherOfDiverse<EnsureRoot<AccountId>, governance::custom_origins::GeneralAdmin>;
impl pallet_identity::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
// Add one item in storage and take 258 bytes
type BasicDeposit = ConstU128<{ deposit(1, 258) }>;
// Does not add any item to the storage but takes 1 bytes
type ByteDeposit = ConstU128<{ deposit(0, 1) }>;
// Add one item in storage and take 53 bytes
type SubAccountDeposit = ConstU128<{ deposit(1, 53) }>;
type MaxSubAccounts = MaxSubAccounts;
type IdentityInformation = pallet_identity::legacy::IdentityInfo<MaxAdditionalFields>;
type MaxRegistrars = MaxRegistrars;
type Slashed = ();
// TODO: Slashed funds should be sent to the treasury (when added to the runtime)
// type Slashed = Treasury;
type ForceOrigin = IdentityForceOrigin;
type RegistrarOrigin = IdentityRegistrarOrigin;
type OffchainSignature = Signature;
type SigningPublicKey = <Signature as sp_runtime::traits::Verify>::Signer;
type UsernameAuthorityOrigin = EnsureRoot<AccountId>;
type PendingUsernameExpiration = PendingUsernameExpiration;
type MaxSuffixLength = MaxSuffixLength;
type MaxUsernameLength = MaxUsernameLength;
type WeightInfo = ();
type UsernameDeposit = ();
type UsernameGracePeriod = ();
}
parameter_types! {
// One storage item; key size is 32 + 20; value is size 4+4+16+20 bytes = 44 bytes.
pub const DepositBase: Balance = deposit(1, 96);
// Additional storage item size of 20 bytes.
pub const DepositFactor: Balance = deposit(0, 20);
pub const MaxSignatories: u32 = 100;
}
impl pallet_multisig::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type RuntimeCall = RuntimeCall;
type Currency = Balances;
type DepositBase = DepositBase;
type DepositFactor = DepositFactor;
type MaxSignatories = MaxSignatories;
type WeightInfo = ();
}
impl pallet_parameters::Config for Runtime {
type AdminOrigin = EnsureRoot<AccountId>;
type RuntimeEvent = RuntimeEvent;
type RuntimeParameters = RuntimeParameters;
type WeightInfo = ();
}
impl pallet_sudo::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type RuntimeCall = RuntimeCall;
type WeightInfo = pallet_sudo::weights::SubstrateWeight<Runtime>;
}
parameter_types! {
/// Amount of weight that can be spent per block to service messages.
///
/// # WARNING
///
/// This is not a good value for para-chains since the `Scheduler` already uses up to 80% block weight.
pub MessageQueueServiceWeight: Weight = Perbill::from_percent(20) * RuntimeBlockWeights::get().max_block;
pub const MessageQueueHeapSize: u32 = 32 * 1024;
pub const MessageQueueMaxStale: u32 = 96;
}
impl pallet_message_queue::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
#[cfg(not(feature = "runtime-benchmarks"))]
type MessageProcessor = OutboundQueueV2;
#[cfg(feature = "runtime-benchmarks")]
type MessageProcessor =
pallet_message_queue::mock_helpers::NoopMessageProcessor<AggregateMessageOrigin>;
type Size = u32;
type QueueChangeHandler = ();
type QueuePausedQuery = ();
type HeapSize = MessageQueueHeapSize;
type MaxStale = MessageQueueMaxStale;
type ServiceWeight = MessageQueueServiceWeight;
type IdleMaxServiceWeight = MessageQueueServiceWeight;
type WeightInfo = ();
}
//╔═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
//║ FRONTIER (EVM) PALLETS ║
//╚═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
parameter_types! {
pub const PostBlockAndTxnHashes: PostLogContent = PostLogContent::BlockAndTxnHashes;
}
impl pallet_ethereum::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type StateRoot = pallet_ethereum::IntermediateStateRoot<Self::Version>;
type PostLogContent = PostBlockAndTxnHashes;
type ExtraDataLength = ConstU32<30>;
}
// Ported from Moonbeam, please check for reference: https://github.com/moonbeam-foundation/moonbeam/pull/1765
pub struct TransactionPaymentAsGasPrice;
impl FeeCalculator for TransactionPaymentAsGasPrice {
fn min_gas_price() -> (U256, Weight) {
// note: transaction-payment differs from EIP-1559 in that its tip and length fees are not
// scaled by the multiplier, which means its multiplier will be overstated when
// applied to an ethereum transaction
// note: transaction-payment uses both a congestion modifier (next_fee_multiplier, which is
// updated once per block in on_finalize) and a 'WeightToFee' implementation. Our
// runtime implements this as a 'ConstantModifier', so we can get away with a simple
// multiplication here.
let min_gas_price: u128 = TransactionPayment::<Runtime>::next_fee_multiplier()
.saturating_mul_int((WEIGHT_FEE).saturating_mul(WEIGHT_PER_GAS as u128));
(
min_gas_price.into(),
<<Runtime as frame_system::Config>::DbWeight as Get<RuntimeDbWeight>>::get().reads(1),
)
}
}
pub struct FindAuthorAdapter<T>(core::marker::PhantomData<T>);
impl<T> FindAuthor<H160> for FindAuthorAdapter<T>
where
T: frame_system::Config + pallet_session::Config,
<T as pallet_session::Config>::ValidatorId: Into<H160>,
{
fn find_author<'a, I>(digests: I) -> Option<H160>
where
I: 'a + IntoIterator<Item = (sp_runtime::ConsensusEngineId, &'a [u8])>,
{
pallet_session::FindAccountFromAuthorIndex::<T, Babe>::find_author(digests)
.map(|author| author.into())
}
}
datahaven_runtime_common::impl_on_charge_evm_transaction!();
parameter_types! {
pub BlockGasLimit: U256
= U256::from(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT.ref_time() / WEIGHT_PER_GAS);
// pub PrecompilesValue: TemplatePrecompiles<Runtime> = TemplatePrecompiles::<_>::new();
pub WeightPerGas: Weight = Weight::from_parts(WEIGHT_PER_GAS, 0);
pub SuicideQuickClearLimit: u32 = 0;
pub GasLimitPovSizeRatio: u32 = 16;
pub GasLimitStorageGrowthRatio: u64 = 366;
}
impl pallet_evm::Config for Runtime {
type AccountProvider = FrameSystemAccountProvider<Runtime>;
type FeeCalculator = TransactionPaymentAsGasPrice;
type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
type WeightPerGas = WeightPerGas;
type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;
type CallOrigin = EnsureAddressRoot<AccountId>;
type WithdrawOrigin = EnsureAddressNever<AccountId>;
type AddressMapping = IdentityAddressMapping;
type Currency = Balances;
type RuntimeEvent = RuntimeEvent;
type PrecompilesType = ();
type PrecompilesValue = ();
type ChainId = EvmChainId;
type BlockGasLimit = BlockGasLimit;
type Runner = pallet_evm::runner::stack::Runner<Self>;
type OnChargeTransaction = OnChargeEVMTransaction<()>;
type OnCreate = ();
type FindAuthor = FindAuthorAdapter<Self>;
type GasLimitPovSizeRatio = GasLimitPovSizeRatio;
type GasLimitStorageGrowthRatio = ();
type Timestamp = Timestamp;
type WeightInfo = ();
}
impl pallet_evm_chain_id::Config for Runtime {}
//╔═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
//║ SNOWBRIDGE PALLETS ║
//╚═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
// --- Snowbridge Config Constants & Parameter Types ---
parameter_types! {
pub UniversalLocation: InteriorLocation = Here.into();
pub InboundDeliveryCost: BalanceOf<Runtime> = 0;
pub RootLocation: Location = Location::here();
pub Parameters: PricingParameters<u128> = PricingParameters {
exchange_rate: FixedU128::from_rational(1, 400),
fee_per_gas: gwei(20),
rewards: Rewards { local: 1 * UNIT, remote: meth(1) },
multiplier: FixedU128::from_rational(1, 1),
};
pub EthereumLocation: Location = Location::new(1, EthereumNetwork::get());
pub TreasuryAccountId: AccountId = AccountId::from([0u8; 20]);
}
pub struct DoNothingOutboundQueue;
impl SendMessage for DoNothingOutboundQueue {
type Ticket = ();
fn validate(
_: &Message,
) -> Result<(Self::Ticket, Fee<<Self as SendMessageFeeProvider>::Balance>), SendError> {
Ok(((), Fee::from((0, 0))))
}
fn deliver(_: Self::Ticket) -> Result<H256, snowbridge_outbound_queue_primitives::SendError> {
Ok(H256::zero())
}
}
impl SendMessageFeeProvider for DoNothingOutboundQueue {
type Balance = u128;
fn local_fee() -> Self::Balance {
1
}
}
// Implement the Snowbridge System V1 config trait
impl snowbridge_pallet_system::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type OutboundQueue = DoNothingOutboundQueue;
type SiblingOrigin = EnsureRootWithSuccess<AccountId, RootLocation>;
type AgentIdOf = AgentIdOf;
type Token = Balances;
type TreasuryAccount = TreasuryAccountId;
type DefaultPricingParameters = Parameters;
type InboundDeliveryCost = InboundDeliveryCost;
type WeightInfo = ();
type UniversalLocation = UniversalLocation;
type EthereumLocation = EthereumLocation;
#[cfg(feature = "runtime-benchmarks")]
type Helper = ();
}
// Implement the Snowbridge System v2 config trait
impl snowbridge_pallet_system_v2::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type OutboundQueue = OutboundQueueV2;
type FrontendOrigin = EnsureRootWithSuccess<AccountId, RootLocation>;
type GovernanceOrigin = EnsureRootWithSuccess<AccountId, RootLocation>;
type WeightInfo = ();
#[cfg(feature = "runtime-benchmarks")]
type Helper = ();
}
// For tests, benchmarks and fast-runtime configurations we use the mocked fork versions
#[cfg(any(
feature = "std",
feature = "fast-runtime",
feature = "runtime-benchmarks",
test
))]
parameter_types! {
pub const ChainForkVersions: ForkVersions = ForkVersions {
genesis: Fork {
version: [0, 0, 0, 0], // 0x00000000
epoch: 0,
},
altair: Fork {
version: [1, 0, 0, 0], // 0x01000000
epoch: 0,
},
bellatrix: Fork {
version: [2, 0, 0, 0], // 0x02000000
epoch: 0,
},
capella: Fork {
version: [3, 0, 0, 0], // 0x03000000
epoch: 0,
},
deneb: Fork {
version: [4, 0, 0, 0], // 0x04000000
epoch: 0,
},
electra: Fork {
version: [5, 0, 0, 0], // 0x05000000
epoch: 0,
},
};
}
// Holesky: https://github.com/eth-clients/holesky
// Fork versions: https://github.com/eth-clients/holesky/blob/main/metadata/config.yaml
#[cfg(not(any(
feature = "std",
feature = "fast-runtime",
feature = "runtime-benchmarks",
test
)))]
parameter_types! {
pub const ChainForkVersions: ForkVersions = ForkVersions {
genesis: Fork {
version: hex_literal::hex!("01017000"), // 0x01017000
epoch: 0,
},
altair: Fork {
version: hex_literal::hex!("02017000"), // 0x02017000
epoch: 0,
},
bellatrix: Fork {
version: hex_literal::hex!("03017000"), // 0x03017000
epoch: 0,
},
capella: Fork {
version: hex_literal::hex!("04017000"), // 0x04017000
epoch: 256,
},
deneb: Fork {
version: hex_literal::hex!("05017000"), // 0x05017000
epoch: 29696,
},
electra: Fork {
version: hex_literal::hex!("06017000"), // 0x06017000
epoch: 115968,
},
};
}
impl snowbridge_pallet_ethereum_client::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type ForkVersions = ChainForkVersions;
type FreeHeadersInterval = ();
type WeightInfo = ();
}
parameter_types! {
pub DefaultRewardKind: () = ();
}
// Dummy RewardPayment implementation
pub struct DummyRewardPayment;
impl RewardLedger<AccountId, (), u128> for DummyRewardPayment {
fn register_reward(_who: &AccountId, _reward: (), _amount: u128) {
// Empty implementation for dummy struct
}
}
impl snowbridge_pallet_inbound_queue_v2::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Verifier = EthereumBeaconClient;
type GatewayAddress = runtime_params::dynamic_params::runtime_config::EthereumGatewayAddress;
type MessageProcessor = EigenLayerMessageProcessor<Runtime>;
type RewardKind = ();
type DefaultRewardKind = DefaultRewardKind;
type RewardPayment = DummyRewardPayment;
type WeightInfo = ();
#[cfg(feature = "runtime-benchmarks")]
type Helper = Runtime;
}
parameter_types! {
/// Network and location for the Ethereum chain.
/// Using the Sepolia Ethereum testnet, with chain ID 11155111.
/// <https://chainlist.org/chain/11155111>
/// <https://ethereum.org/en/developers/docs/apis/json-rpc/#net_version>
pub EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 11155111 };
}
pub struct CommitmentHandler;
impl OnNewCommitment for CommitmentHandler {
fn on_new_commitment(commitment: H256) {
OutboundCommitmentStore::store_commitment(commitment);
}
}
impl snowbridge_pallet_outbound_queue_v2::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Hashing = Keccak256;
type MessageQueue = MessageQueue;
type GasMeter = ConstantGasMeter;
type Balance = Balance;
type MaxMessagePayloadSize = ConstU32<2048>;
type MaxMessagesPerBlock = ConstU32<32>;
type OnNewCommitment = CommitmentHandler;
type WeightToFee = IdentityFee<Balance>;
type WeightInfo = ();
type Verifier = EthereumBeaconClient;
type GatewayAddress = runtime_params::dynamic_params::runtime_config::EthereumGatewayAddress;
type RewardKind = ();
type DefaultRewardKind = DefaultRewardKind;
type RewardPayment = DummyRewardPayment;
type EthereumNetwork = EthereumNetwork;
type ConvertAssetId = ();
}
//╔═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
//║ STORAGEHUB PALLETS ║
//╚═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
//╔═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
//║ DATAHAVEN-SPECIFIC PALLETS ║
//╚═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
#[cfg(feature = "runtime-benchmarks")]
pub mod benchmark_helpers {
use crate::RuntimeOrigin;
use crate::{EthereumBeaconClient, Runtime};
use snowbridge_beacon_primitives::BeaconHeader;
use snowbridge_pallet_inbound_queue_v2::BenchmarkHelper as InboundQueueBenchmarkHelperV2;
use sp_core::H256;
use xcm::opaque::latest::Location;
impl<T: snowbridge_pallet_inbound_queue_v2::Config> InboundQueueBenchmarkHelperV2<T> for Runtime {
fn initialize_storage(beacon_header: BeaconHeader, block_roots_root: H256) {
EthereumBeaconClient::store_finalized_header(beacon_header, block_roots_root).unwrap();
}
}
impl snowbridge_pallet_system::BenchmarkHelper<RuntimeOrigin> for () {
fn make_xcm_origin(_location: Location) -> RuntimeOrigin {
RuntimeOrigin::root()
}
}
impl snowbridge_pallet_system_v2::BenchmarkHelper<RuntimeOrigin> for () {
fn make_xcm_origin(_location: Location) -> RuntimeOrigin {
RuntimeOrigin::root()
}
}
}
impl pallet_outbound_commitment_store::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
}

View file

@ -0,0 +1,34 @@
use frame_support::dynamic_params::{dynamic_pallet_params, dynamic_params};
use sp_core::H160;
use crate::Runtime;
#[dynamic_params(RuntimeParameters, pallet_parameters::Parameters::<Runtime>)]
pub mod dynamic_params {
use super::*;
#[dynamic_pallet_params]
#[codec(index = 0)]
pub mod runtime_config {
use super::*;
#[codec(index = 0)]
#[allow(non_upper_case_globals)]
/// Set the initial address of the Snowbridge Gateway contract on Ethereum.
/// The fact that this is a parameter means that we can set it initially to the zero address,
/// and then change it later via governance, to the actual address of the deployed contract.
pub static EthereumGatewayAddress: H160 = H160::repeat_byte(0x0);
}
}
#[cfg(feature = "runtime-benchmarks")]
impl Default for RuntimeParameters {
fn default() -> Self {
RuntimeParameters::RuntimeConfig(
dynamic_params::runtime_config::Parameters::EthereumGatewayAddress(
dynamic_params::runtime_config::EthereumGatewayAddress,
Some(H160::repeat_byte(0x0)),
),
)
}
}

View file

@ -13,7 +13,7 @@ use sp_core::{ecdsa, Pair, Public};
use sp_genesis_builder::{self, PresetId};
use sp_runtime::traits::{IdentifyAccount, Verify};
const TESTNET_EVM_CHAIN_ID: u64 = 1283;
const TESTNET_EVM_CHAIN_ID: u64 = 1288;
// Returns the genesis config presets populated with given parameters.
fn testnet_genesis(

View file

@ -0,0 +1,322 @@
#![cfg_attr(not(feature = "std"), no_std)]
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
#![recursion_limit = "256"]
extern crate alloc;
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
pub mod apis;
#[cfg(feature = "runtime-benchmarks")]
mod benchmarks;
pub mod configs;
use alloc::{borrow::Cow, vec::Vec};
use sp_runtime::{generic, impl_opaque_keys};
#[cfg(feature = "std")]
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
pub use frame_system::Call as SystemCall;
pub use pallet_balances::Call as BalancesCall;
pub use pallet_timestamp::Call as TimestampCall;
use sp_core::H160;
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
pub use datahaven_runtime_common::{
AccountId, Address, Balance, BlockNumber, Hash, Header, Nonce, Signature,
};
pub mod genesis_config_presets;
/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
/// the specifics of the runtime. They can then be made to be agnostic over specific formats
/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
/// to even the core data structures.
pub mod opaque {
use super::*;
use sp_runtime::{
generic,
traits::{BlakeTwo256, Hash as HashT},
};
pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
/// Opaque block header type.
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
/// Opaque block type.
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
/// Opaque block identifier type.
pub type BlockId = generic::BlockId<Block>;
/// Opaque block hash type.
pub type Hash = <BlakeTwo256 as HashT>::Output;
}
impl_opaque_keys! {
pub struct SessionKeys {
pub babe: Babe,
pub grandpa: Grandpa,
pub im_online: ImOnline,
pub beefy: Beefy,
}
}
// To learn more about runtime versioning, see:
// https://docs.substrate.io/main-docs/build/upgrade#runtime-versioning
#[sp_version::runtime_version]
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: Cow::Borrowed("datahaven-testnet"),
impl_name: Cow::Borrowed("datahaven-testnet"),
authoring_version: 1,
// The version of the runtime specification. A full node will not attempt to use its native
// runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`,
// `spec_version`, and `authoring_version` are the same between Wasm and native.
// This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
// the compatible custom types.
spec_version: 100,
impl_version: 1,
apis: apis::RUNTIME_API_VERSIONS,
transaction_version: 1,
system_version: 1,
};
mod block_times {
/// This determines the average expected block time that we are targeting. Blocks will be
/// produced at a minimum duration defined by `SLOT_DURATION`. `SLOT_DURATION` is picked up by
/// `pallet_timestamp` which is in turn picked up by `pallet_babe` to implement `fn
/// slot_duration()`.
///
/// Change this to adjust the block time.
pub const MILLI_SECS_PER_BLOCK: u64 = 6000;
// NOTE: Currently it is not possible to change the slot duration after the chain has started.
// Attempting to do so will brick block production.
pub const SLOT_DURATION: u64 = MILLI_SECS_PER_BLOCK;
}
pub use block_times::*;
// Time is measured by number of blocks.
pub const MINUTES: BlockNumber = 60_000 / (MILLI_SECS_PER_BLOCK as BlockNumber);
pub const HOURS: BlockNumber = MINUTES * 60;
pub const DAYS: BlockNumber = HOURS * 24;
pub const BLOCK_HASH_COUNT: BlockNumber = 2400;
// Provide a common factor between runtimes based on a supply of 10_000_000 tokens.
pub const SUPPLY_FACTOR: Balance = 1;
// Unit = the base number of indivisible units for balances
pub const UNIT: Balance = 1_000_000_000_000;
pub const MILLI_UNIT: Balance = 1_000_000_000;
pub const MICRO_UNIT: Balance = 1_000_000;
pub const STORAGE_BYTE_FEE: Balance = 100 * MICRO_UNIT * SUPPLY_FACTOR;
/// Existential deposit.
pub const EXISTENTIAL_DEPOSIT: Balance = MILLI_UNIT;
pub const fn deposit(items: u32, bytes: u32) -> Balance {
items as Balance * UNIT * SUPPLY_FACTOR + (bytes as Balance) * STORAGE_BYTE_FEE
}
/// The version information used to identify this runtime when compiled natively.
#[cfg(feature = "std")]
pub fn native_version() -> NativeVersion {
NativeVersion {
runtime_version: VERSION,
can_author_with: Default::default(),
}
}
/// Block type as expected by this runtime.
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
/// The SignedExtension to the basic transaction logic.
pub type SignedExtra = (
frame_system::CheckNonZeroSender<Runtime>,
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>,
frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
);
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic =
fp_self_contained::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
pub type CheckedExtrinsic =
fp_self_contained::CheckedExtrinsic<AccountId, RuntimeCall, SignedExtra, H160>;
/// The payload being signed in transactions.
pub type SignedPayload = generic::SignedPayload<RuntimeCall, SignedExtra>;
/// All migrations of the runtime, aside from the ones declared in the pallets.
///
/// This can be a tuple of types, each implementing `OnRuntimeUpgrade`.
#[allow(unused_parens)]
type Migrations = ();
/// Executive: handles dispatch to the various modules.
pub type Executive = frame_executive::Executive<
Runtime,
Block,
frame_system::ChainContext<Runtime>,
Runtime,
AllPalletsWithSystem,
Migrations,
>;
impl<C> frame_system::offchain::CreateTransactionBase<C> for Runtime
where
RuntimeCall: From<C>,
{
type Extrinsic = UncheckedExtrinsic;
type RuntimeCall = RuntimeCall;
}
impl<C> frame_system::offchain::CreateInherent<C> for Runtime
where
RuntimeCall: From<C>,
{
fn create_inherent(call: RuntimeCall) -> UncheckedExtrinsic {
UncheckedExtrinsic::new_bare(call)
}
}
// Create the runtime by composing the FRAME pallets that were previously configured.
#[frame_support::runtime]
mod runtime {
#[runtime::runtime]
#[runtime::derive(
RuntimeCall,
RuntimeEvent,
RuntimeError,
RuntimeOrigin,
RuntimeFreezeReason,
RuntimeHoldReason,
RuntimeSlashReason,
RuntimeLockId,
RuntimeTask
)]
pub struct Runtime;
// ╔══════════════════ System and Consensus Pallets ═════════════════╗
#[runtime::pallet_index(0)]
pub type System = frame_system;
// Babe must be before session.
#[runtime::pallet_index(1)]
pub type Babe = pallet_babe;
#[runtime::pallet_index(2)]
pub type Timestamp = pallet_timestamp;
#[runtime::pallet_index(3)]
pub type Balances = pallet_balances;
// Consensus support.
// Authorship must be before session in order to note author in the correct session and era.
#[runtime::pallet_index(4)]
pub type Authorship = pallet_authorship;
#[runtime::pallet_index(5)]
pub type Offences = pallet_offences;
#[runtime::pallet_index(6)]
pub type Historical = pallet_session::historical;
// Validator set must be before Session.
#[runtime::pallet_index(7)]
pub type ValidatorSet = pallet_validator_set;
#[runtime::pallet_index(8)]
pub type Session = pallet_session;
#[runtime::pallet_index(9)]
pub type ImOnline = pallet_im_online;
#[runtime::pallet_index(10)]
pub type Grandpa = pallet_grandpa;
#[runtime::pallet_index(11)]
pub type TransactionPayment = pallet_transaction_payment;
#[runtime::pallet_index(12)]
pub type Beefy = pallet_beefy;
#[runtime::pallet_index(13)]
pub type Mmr = pallet_mmr;
#[runtime::pallet_index(14)]
pub type BeefyMmrLeaf = pallet_beefy_mmr;
// ╚═════════════════ System and Consensus Pallets ══════════════════╝
// ╔═════════════════ Polkadot SDK Utility Pallets ══════════════════╗
#[runtime::pallet_index(30)]
pub type Utility = pallet_utility;
#[runtime::pallet_index(31)]
pub type Scheduler = pallet_scheduler;
#[runtime::pallet_index(32)]
pub type Preimage = pallet_preimage;
#[runtime::pallet_index(33)]
pub type Identity = pallet_identity;
#[runtime::pallet_index(34)]
pub type Multisig = pallet_multisig;
#[runtime::pallet_index(35)]
pub type Parameters = pallet_parameters;
#[runtime::pallet_index(36)]
pub type Sudo = pallet_sudo;
#[runtime::pallet_index(37)]
pub type MessageQueue = pallet_message_queue;
// ╚═════════════════ Polkadot SDK Utility Pallets ══════════════════╝
// ╔════════════════════ Frontier (EVM) Pallets ═════════════════════╗
#[runtime::pallet_index(50)]
pub type Ethereum = pallet_ethereum;
#[runtime::pallet_index(51)]
pub type Evm = pallet_evm;
#[runtime::pallet_index(52)]
pub type EvmChainId = pallet_evm_chain_id;
// ╚════════════════════ Frontier (EVM) Pallets ═════════════════════╝
// ╔══════════════════════ Snowbridge Pallets ═══════════════════════╗
#[runtime::pallet_index(60)]
pub type EthereumBeaconClient = snowbridge_pallet_ethereum_client;
#[runtime::pallet_index(61)]
pub type InboundQueueV2 = snowbridge_pallet_inbound_queue_v2;
#[runtime::pallet_index(62)]
pub type OutboundQueueV2 = snowbridge_pallet_outbound_queue_v2;
#[runtime::pallet_index(63)]
pub type SnowbridgeSystem = snowbridge_pallet_system;
#[runtime::pallet_index(64)]
pub type SnowbridgeSystemV2 = snowbridge_pallet_system_v2;
// ╚══════════════════════ Snowbridge Pallets ═══════════════════════╝
// ╔══════════════════════ StorageHub Pallets ═══════════════════════╗
// Start with index 70
// ╚══════════════════════ StorageHub Pallets ═══════════════════════╝
// ╔═══════════════════ DataHaven-specific Pallets ══════════════════╗
// Start with index 100
#[runtime::pallet_index(100)]
pub type OutboundCommitmentStore = pallet_outbound_commitment_store;
// ╚═══════════════════ DataHaven-specific Pallets ══════════════════╝
}