Skeleton ruintime with new types

This commit is contained in:
Luke Parker
2025-02-26 14:16:04 -05:00
parent ed9cbdd8e0
commit 48f5ed71d7
8 changed files with 296 additions and 554 deletions

View File

@@ -69,7 +69,7 @@ jobs:
uses: ./.github/actions/build-dependencies
- name: Buld Rust docs
run: |
rustup toolchain install ${{ steps.nightly.outputs.version }} --profile minimal -t wasm32v1-none -c rust-docs
rustup toolchain install ${{ steps.nightly.outputs.version }} --profile minimal -t wasm32v1-none -c rust-docs -c rust-src
RUSTDOCFLAGS="--cfg docsrs" cargo +${{ steps.nightly.outputs.version }} doc --workspace --all-features
mv target/doc docs/_site/rust

View File

@@ -268,7 +268,7 @@ mod substrate {
>;
/// The implicit context to verify transactions with.
fn implicit_context() -> &'static ImplicitContext;
fn implicit_context() -> ImplicitContext;
/// If a block is present in the blockchain.
fn block_is_present_in_blockchain(&self, hash: &BlockHash) -> bool;
@@ -276,8 +276,8 @@ mod substrate {
///
/// Returns `None` if the time has yet to be set.
fn current_time(&self) -> Option<u64>;
/// The next nonce for an account.
fn next_nonce(&self, signer: &SeraiAddress) -> u32;
/// Get, and consume, the next nonce for an account.
fn get_and_consume_next_nonce(&self, signer: &SeraiAddress) -> u32;
/// If the signer can pay the SRI fee.
fn can_pay_fee(
&self,
@@ -339,7 +339,7 @@ mod substrate {
contextualized_signature: ContextualizedSignature { explicit_context, signature },
} => {
if !sp_core::sr25519::Signature::from(*signature).verify(
Transaction::signature_message(calls, Context::implicit_context(), explicit_context)
Transaction::signature_message(calls, &Context::implicit_context(), explicit_context)
.as_slice(),
&sp_core::sr25519::Public::from(explicit_context.signer),
) {
@@ -402,7 +402,7 @@ mod substrate {
Err(TransactionValidityError::Invalid(InvalidTransaction::Stale))?;
}
}
match self.1.next_nonce(signer).cmp(nonce) {
match self.1.get_and_consume_next_nonce(signer).cmp(nonce) {
core::cmp::Ordering::Less => {
Err(TransactionValidityError::Invalid(InvalidTransaction::Stale))?
}
@@ -454,6 +454,7 @@ mod substrate {
self.1.can_pay_fee(signer, *fee)?;
// Prioritize transactions by their fees
// TODO: Re-evaluate this
{
let fee = fee.0;
Weight::from_all(fee).checked_div_per_component(&info.call_weight).unwrap_or(0)

View File

@@ -27,6 +27,10 @@ const HUMAN_READABLE_PART: bech32::Hrp = bech32::Hrp::parse_unchecked("sri");
#[derive(scale::Encode, scale::Decode)] // This is safe as scale and borsh share an encoding here
pub struct SeraiAddress(pub [u8; 32]);
// These share encodings as 32-byte arrays
impl scale::EncodeLike<Public> for SeraiAddress {}
impl scale::EncodeLike<Public> for &SeraiAddress {}
impl SeraiAddress {
/// Generate an address for use by the system.
///

View File

@@ -48,9 +48,7 @@ pub mod instructions;
/// A block's number is its zero-indexed position on the list of blocks which form a blockchain.
/// For non-linear structures, this would presumably be the zero-indexed position within some
/// topological order.
#[derive(
Clone, Copy, Default, PartialEq, Eq, Hash, Debug, Zeroize, BorshSerialize, BorshDeserialize,
)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Zeroize, BorshSerialize, BorshDeserialize)]
pub struct BlockNumber(pub u64);
impl From<u64> for BlockNumber {
fn from(number: u64) -> BlockNumber {
@@ -66,6 +64,8 @@ impl From<u64> for BlockNumber {
hash it into a 32-byte hash or truncate it.
*/
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Zeroize, BorshSerialize, BorshDeserialize)]
#[rustfmt::skip]
#[derive(scale::Encode, scale::Decode)] // This is safe as scale and borsh share an encoding here
pub struct BlockHash(pub [u8; 32]);
impl From<[u8; 32]> for BlockHash {
fn from(hash: [u8; 32]) -> BlockHash {
@@ -77,3 +77,7 @@ impl From<sp_core::H256> for BlockHash {
BlockHash(hash.into())
}
}
// These share encodings as 32-byte arrays
impl scale::EncodeLike<sp_core::H256> for BlockHash {}
impl scale::EncodeLike<sp_core::H256> for &BlockHash {}

View File

@@ -1,7 +1,7 @@
[package]
name = "serai-runtime"
version = "0.1.0"
description = "Serai network node runtime, built over Substrate"
description = "Serai's on-chain logic"
license = "AGPL-3.0-only"
repository = "https://github.com/serai-dex/serai/tree/develop/substrate/runtime"
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
@@ -18,61 +18,19 @@ ignored = ["scale", "scale-info"]
workspace = true
[dependencies]
hashbrown = { version = "0.15", default-features = false, features = ["default-hasher", "inline-more"] }
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
scale-info = { version = "2", default-features = false, features = ["derive"] }
sp-core = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
sp-std = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
sp-offchain = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
sp-version = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
sp-inherents = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
sp-session = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
sp-consensus-babe = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
sp-consensus-grandpa = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
sp-authority-discovery = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
sp-transaction-pool = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
sp-block-builder = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
sp-runtime = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
sp-api = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
frame-system = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
frame-support = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
frame-executive = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
frame-benchmarking = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false, optional = true }
serai-primitives = { path = "../primitives", default-features = false }
serai-abi = { path = "../abi", default-features = false }
pallet-timestamp = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
pallet-authorship = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
pallet-transaction-payment = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
coins-pallet = { package = "serai-coins-pallet", path = "../coins/pallet", default-features = false }
dex-pallet = { package = "serai-dex-pallet", path = "../dex/pallet", default-features = false }
validator-sets-pallet = { package = "serai-validator-sets-pallet", path = "../validator-sets/pallet", default-features = false }
genesis-liquidity-pallet = { package = "serai-genesis-liquidity-pallet", path = "../genesis-liquidity/pallet", default-features = false }
emissions-pallet = { package = "serai-emissions-pallet", path = "../emissions/pallet", default-features = false }
economic-security-pallet = { package = "serai-economic-security-pallet", path = "../economic-security/pallet", default-features = false }
in-instructions-pallet = { package = "serai-in-instructions-pallet", path = "../in-instructions/pallet", default-features = false }
signals-pallet = { package = "serai-signals-pallet", path = "../signals/pallet", default-features = false }
pallet-babe = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
pallet-grandpa = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
frame-system-rpc-runtime-api = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next", default-features = false }
serai-abi = { path = "../abi", default-features = false, features = ["substrate"] }
[build-dependencies]
substrate-wasm-builder = { git = "https://github.com/serai-dex/polkadot-sdk", branch = "serai-next" }
@@ -83,21 +41,7 @@ std = [
"scale-info/std",
"sp-core/std",
"sp-std/std",
"sp-offchain/std",
"sp-version/std",
"sp-inherents/std",
"sp-session/std",
"sp-consensus-babe/std",
"sp-consensus-grandpa/std",
"sp-authority-discovery/std",
"sp-transaction-pool/std",
"sp-block-builder/std",
"sp-runtime/std",
"sp-api/std",
@@ -105,50 +49,12 @@ std = [
"frame-support/std",
"frame-executive/std",
"serai-primitives/std",
"serai-abi/std",
"pallet-timestamp/std",
"pallet-authorship/std",
"pallet-transaction-payment/std",
"coins-pallet/std",
"dex-pallet/std",
"validator-sets-pallet/std",
"genesis-liquidity-pallet/std",
"emissions-pallet/std",
"economic-security-pallet/std",
"in-instructions-pallet/std",
"signals-pallet/std",
"pallet-babe/std",
"pallet-grandpa/std",
"frame-system-rpc-runtime-api/std",
"pallet-transaction-payment-rpc-runtime-api/std",
]
fast-epoch = [
"genesis-liquidity-pallet/fast-epoch",
"emissions-pallet/fast-epoch",
]
fast-epoch = [] # TODO
runtime-benchmarks = [
"sp-runtime/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-benchmarking/runtime-benchmarks",
"pallet-timestamp/runtime-benchmarks",
"pallet-babe/runtime-benchmarks",
"pallet-grandpa/runtime-benchmarks",
]
try-runtime = ["sp-runtime/try-runtime", "frame-system/try-runtime", "frame-support/try-runtime", "frame-executive/try-runtime"]
runtime-benchmarks = ["sp-runtime/runtime-benchmarks", "frame-system/runtime-benchmarks", "frame-support/runtime-benchmarks"]
default = ["std"]

View File

@@ -1,365 +0,0 @@
use core::marker::PhantomData;
use scale::{Encode, Decode};
use serai_abi::Call;
use crate::{
timestamp, coins, dex, genesis_liquidity,
validator_sets::{self, MembershipProof},
in_instructions, signals, babe, grandpa, RuntimeCall,
};
impl From<Call> for RuntimeCall {
fn from(call: Call) -> RuntimeCall {
match call {
Call::Timestamp(serai_abi::timestamp::Call::set { now }) => {
RuntimeCall::Timestamp(timestamp::Call::set { now })
}
Call::Coins(coins) => match coins {
serai_abi::coins::Call::transfer { to, balance } => {
RuntimeCall::Coins(coins::Call::transfer { to: to.into(), balance })
}
serai_abi::coins::Call::burn { balance } => {
RuntimeCall::Coins(coins::Call::burn { balance })
}
serai_abi::coins::Call::burn_with_instruction { instruction } => {
RuntimeCall::Coins(coins::Call::burn_with_instruction { instruction })
}
},
Call::LiquidityTokens(lt) => match lt {
serai_abi::liquidity_tokens::Call::transfer { to, balance } => {
RuntimeCall::LiquidityTokens(coins::Call::transfer { to: to.into(), balance })
}
serai_abi::liquidity_tokens::Call::burn { balance } => {
RuntimeCall::LiquidityTokens(coins::Call::burn { balance })
}
},
Call::Dex(dex) => match dex {
serai_abi::dex::Call::add_liquidity {
coin,
coin_desired,
sri_desired,
coin_min,
sri_min,
mint_to,
} => RuntimeCall::Dex(dex::Call::add_liquidity {
coin,
coin_desired,
sri_desired,
coin_min,
sri_min,
mint_to: mint_to.into(),
}),
serai_abi::dex::Call::remove_liquidity {
coin,
lp_token_burn,
coin_min_receive,
sri_min_receive,
withdraw_to,
} => RuntimeCall::Dex(dex::Call::remove_liquidity {
coin,
lp_token_burn,
coin_min_receive,
sri_min_receive,
withdraw_to: withdraw_to.into(),
}),
serai_abi::dex::Call::swap_exact_tokens_for_tokens {
path,
amount_in,
amount_out_min,
send_to,
} => RuntimeCall::Dex(dex::Call::swap_exact_tokens_for_tokens {
path,
amount_in,
amount_out_min,
send_to: send_to.into(),
}),
serai_abi::dex::Call::swap_tokens_for_exact_tokens {
path,
amount_out,
amount_in_max,
send_to,
} => RuntimeCall::Dex(dex::Call::swap_tokens_for_exact_tokens {
path,
amount_out,
amount_in_max,
send_to: send_to.into(),
}),
},
Call::ValidatorSets(vs) => match vs {
serai_abi::validator_sets::Call::set_keys {
network,
key_pair,
signature_participants,
signature,
} => RuntimeCall::ValidatorSets(validator_sets::Call::set_keys {
network,
key_pair,
signature_participants,
signature,
}),
serai_abi::validator_sets::Call::set_embedded_elliptic_curve_key {
embedded_elliptic_curve,
key,
} => RuntimeCall::ValidatorSets(validator_sets::Call::set_embedded_elliptic_curve_key {
embedded_elliptic_curve,
key,
}),
serai_abi::validator_sets::Call::report_slashes { network, slashes, signature } => {
RuntimeCall::ValidatorSets(validator_sets::Call::report_slashes {
network,
slashes,
signature,
})
}
serai_abi::validator_sets::Call::allocate { network, amount } => {
RuntimeCall::ValidatorSets(validator_sets::Call::allocate { network, amount })
}
serai_abi::validator_sets::Call::deallocate { network, amount } => {
RuntimeCall::ValidatorSets(validator_sets::Call::deallocate { network, amount })
}
serai_abi::validator_sets::Call::claim_deallocation { network, session } => {
RuntimeCall::ValidatorSets(validator_sets::Call::claim_deallocation { network, session })
}
},
Call::GenesisLiquidity(gl) => match gl {
serai_abi::genesis_liquidity::Call::remove_coin_liquidity { balance } => {
RuntimeCall::GenesisLiquidity(genesis_liquidity::Call::remove_coin_liquidity { balance })
}
serai_abi::genesis_liquidity::Call::oraclize_values { values, signature } => {
RuntimeCall::GenesisLiquidity(genesis_liquidity::Call::oraclize_values {
values,
signature,
})
}
},
Call::InInstructions(ii) => match ii {
serai_abi::in_instructions::Call::execute_batch { batch } => {
RuntimeCall::InInstructions(in_instructions::Call::execute_batch { batch })
}
},
Call::Signals(signals) => match signals {
serai_abi::signals::Call::register_retirement_signal { in_favor_of } => {
RuntimeCall::Signals(signals::Call::register_retirement_signal { in_favor_of })
}
serai_abi::signals::Call::revoke_retirement_signal { retirement_signal_id } => {
RuntimeCall::Signals(signals::Call::revoke_retirement_signal { retirement_signal_id })
}
serai_abi::signals::Call::favor { signal_id, for_network } => {
RuntimeCall::Signals(signals::Call::favor { signal_id, for_network })
}
serai_abi::signals::Call::revoke_favor { signal_id, for_network } => {
RuntimeCall::Signals(signals::Call::revoke_favor { signal_id, for_network })
}
serai_abi::signals::Call::stand_against { signal_id, for_network } => {
RuntimeCall::Signals(signals::Call::stand_against { signal_id, for_network })
}
},
Call::Babe(babe) => match babe {
serai_abi::babe::Call::report_equivocation(report) => {
RuntimeCall::Babe(babe::Call::report_equivocation {
// TODO: Find a better way to go from Proof<[u8; 32]> to Proof<H256>
equivocation_proof: <_>::decode(&mut report.equivocation_proof.encode().as_slice())
.unwrap(),
key_owner_proof: MembershipProof(report.key_owner_proof.into(), PhantomData),
})
}
serai_abi::babe::Call::report_equivocation_unsigned(report) => {
RuntimeCall::Babe(babe::Call::report_equivocation_unsigned {
// TODO: Find a better way to go from Proof<[u8; 32]> to Proof<H256>
equivocation_proof: <_>::decode(&mut report.equivocation_proof.encode().as_slice())
.unwrap(),
key_owner_proof: MembershipProof(report.key_owner_proof.into(), PhantomData),
})
}
},
Call::Grandpa(grandpa) => match grandpa {
serai_abi::grandpa::Call::report_equivocation(report) => {
RuntimeCall::Grandpa(grandpa::Call::report_equivocation {
// TODO: Find a better way to go from Proof<[u8; 32]> to Proof<H256>
equivocation_proof: <_>::decode(&mut report.equivocation_proof.encode().as_slice())
.unwrap(),
key_owner_proof: MembershipProof(report.key_owner_proof.into(), PhantomData),
})
}
serai_abi::grandpa::Call::report_equivocation_unsigned(report) => {
RuntimeCall::Grandpa(grandpa::Call::report_equivocation_unsigned {
// TODO: Find a better way to go from Proof<[u8; 32]> to Proof<H256>
equivocation_proof: <_>::decode(&mut report.equivocation_proof.encode().as_slice())
.unwrap(),
key_owner_proof: MembershipProof(report.key_owner_proof.into(), PhantomData),
})
}
},
}
}
}
impl TryInto<Call> for RuntimeCall {
type Error = ();
fn try_into(self) -> Result<Call, ()> {
Ok(match self {
RuntimeCall::Timestamp(timestamp::Call::set { now }) => {
Call::Timestamp(serai_abi::timestamp::Call::set { now })
}
RuntimeCall::Coins(call) => Call::Coins(match call {
coins::Call::transfer { to, balance } => {
serai_abi::coins::Call::transfer { to: to.into(), balance }
}
coins::Call::burn { balance } => serai_abi::coins::Call::burn { balance },
coins::Call::burn_with_instruction { instruction } => {
serai_abi::coins::Call::burn_with_instruction { instruction }
}
}),
RuntimeCall::LiquidityTokens(call) => Call::LiquidityTokens(match call {
coins::Call::transfer { to, balance } => {
serai_abi::liquidity_tokens::Call::transfer { to: to.into(), balance }
}
coins::Call::burn { balance } => serai_abi::liquidity_tokens::Call::burn { balance },
_ => Err(())?,
}),
RuntimeCall::Dex(call) => Call::Dex(match call {
dex::Call::add_liquidity {
coin,
coin_desired,
sri_desired,
coin_min,
sri_min,
mint_to,
} => serai_abi::dex::Call::add_liquidity {
coin,
coin_desired,
sri_desired,
coin_min,
sri_min,
mint_to: mint_to.into(),
},
dex::Call::remove_liquidity {
coin,
lp_token_burn,
coin_min_receive,
sri_min_receive,
withdraw_to,
} => serai_abi::dex::Call::remove_liquidity {
coin,
lp_token_burn,
coin_min_receive,
sri_min_receive,
withdraw_to: withdraw_to.into(),
},
dex::Call::swap_exact_tokens_for_tokens { path, amount_in, amount_out_min, send_to } => {
serai_abi::dex::Call::swap_exact_tokens_for_tokens {
path,
amount_in,
amount_out_min,
send_to: send_to.into(),
}
}
dex::Call::swap_tokens_for_exact_tokens { path, amount_out, amount_in_max, send_to } => {
serai_abi::dex::Call::swap_tokens_for_exact_tokens {
path,
amount_out,
amount_in_max,
send_to: send_to.into(),
}
}
}),
RuntimeCall::GenesisLiquidity(call) => Call::GenesisLiquidity(match call {
genesis_liquidity::Call::remove_coin_liquidity { balance } => {
serai_abi::genesis_liquidity::Call::remove_coin_liquidity { balance }
}
genesis_liquidity::Call::oraclize_values { values, signature } => {
serai_abi::genesis_liquidity::Call::oraclize_values { values, signature }
}
}),
RuntimeCall::ValidatorSets(call) => Call::ValidatorSets(match call {
validator_sets::Call::set_keys { network, key_pair, signature_participants, signature } => {
serai_abi::validator_sets::Call::set_keys {
network,
key_pair,
signature_participants,
signature,
}
}
validator_sets::Call::set_embedded_elliptic_curve_key { embedded_elliptic_curve, key } => {
serai_abi::validator_sets::Call::set_embedded_elliptic_curve_key {
embedded_elliptic_curve,
key,
}
}
validator_sets::Call::report_slashes { network, slashes, signature } => {
serai_abi::validator_sets::Call::report_slashes { network, slashes, signature }
}
validator_sets::Call::allocate { network, amount } => {
serai_abi::validator_sets::Call::allocate { network, amount }
}
validator_sets::Call::deallocate { network, amount } => {
serai_abi::validator_sets::Call::deallocate { network, amount }
}
validator_sets::Call::claim_deallocation { network, session } => {
serai_abi::validator_sets::Call::claim_deallocation { network, session }
}
}),
RuntimeCall::InInstructions(call) => Call::InInstructions(match call {
in_instructions::Call::execute_batch { batch } => {
serai_abi::in_instructions::Call::execute_batch { batch }
}
}),
RuntimeCall::Signals(call) => Call::Signals(match call {
signals::Call::register_retirement_signal { in_favor_of } => {
serai_abi::signals::Call::register_retirement_signal { in_favor_of }
}
signals::Call::revoke_retirement_signal { retirement_signal_id } => {
serai_abi::signals::Call::revoke_retirement_signal { retirement_signal_id }
}
signals::Call::favor { signal_id, for_network } => {
serai_abi::signals::Call::favor { signal_id, for_network }
}
signals::Call::revoke_favor { signal_id, for_network } => {
serai_abi::signals::Call::revoke_favor { signal_id, for_network }
}
signals::Call::stand_against { signal_id, for_network } => {
serai_abi::signals::Call::stand_against { signal_id, for_network }
}
}),
RuntimeCall::Babe(call) => Call::Babe(match call {
babe::Call::report_equivocation { equivocation_proof, key_owner_proof } => {
serai_abi::babe::Call::report_equivocation(serai_abi::babe::ReportEquivocation {
// TODO: Find a better way to go from Proof<H256> to Proof<[u8; 32]>
equivocation_proof: <_>::decode(&mut equivocation_proof.encode().as_slice()).unwrap(),
key_owner_proof: key_owner_proof.0.into(),
})
}
babe::Call::report_equivocation_unsigned { equivocation_proof, key_owner_proof } => {
serai_abi::babe::Call::report_equivocation_unsigned(serai_abi::babe::ReportEquivocation {
// TODO: Find a better way to go from Proof<H256> to Proof<[u8; 32]>
equivocation_proof: <_>::decode(&mut equivocation_proof.encode().as_slice()).unwrap(),
key_owner_proof: key_owner_proof.0.into(),
})
}
_ => Err(())?,
}),
RuntimeCall::Grandpa(call) => Call::Grandpa(match call {
grandpa::Call::report_equivocation { equivocation_proof, key_owner_proof } => {
serai_abi::grandpa::Call::report_equivocation(serai_abi::grandpa::ReportEquivocation {
// TODO: Find a better way to go from Proof<H256> to Proof<[u8; 32]>
equivocation_proof: <_>::decode(&mut equivocation_proof.encode().as_slice()).unwrap(),
key_owner_proof: key_owner_proof.0.into(),
})
}
grandpa::Call::report_equivocation_unsigned { equivocation_proof, key_owner_proof } => {
serai_abi::grandpa::Call::report_equivocation_unsigned(
serai_abi::grandpa::ReportEquivocation {
// TODO: Find a better way to go from Proof<H256> to Proof<[u8; 32]>
equivocation_proof: <_>::decode(&mut equivocation_proof.encode().as_slice()).unwrap(),
key_owner_proof: key_owner_proof.0.into(),
},
)
}
_ => Err(())?,
}),
})
}
}

View File

@@ -0,0 +1,19 @@
#[frame_support::pallet]
mod core_pallet {
use ::alloc::*;
use frame_system::pallet_prelude::*;
use frame_support::pallet_prelude::*;
#[pallet::storage]
pub type NextNonce<T: Config> =
StorageMap<_, Blake2_128Concat, T::AccountId, T::Nonce, ValueQuery>;
#[pallet::storage]
pub type Blocks<T: Config> = StorageMap<_, Identity, T::Hash, (), OptionQuery>;
#[pallet::config]
pub trait Config: frame_system::Config {}
#[pallet::pallet]
pub struct Pallet<T>(_);
}
pub(super) use core_pallet::*;

View File

@@ -1,11 +1,261 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![cfg_attr(not(feature = "std"), no_std)]
#![recursion_limit = "256"]
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
extern crate alloc;
use ::alloc::{borrow::Cow, vec::Vec};
use sp_core::sr25519::Public;
use sp_runtime::{Perbill, Weight, traits::Header as _};
use sp_version::RuntimeVersion;
#[rustfmt::skip]
use serai_abi::{
primitives::address::SeraiAddress, SubstrateHeader as Header, SubstrateBlock,
};
mod core_pallet;
type Block = SubstrateBlock;
/// The lookup for a SeraiAddress -> Public.
pub struct Lookup;
impl sp_runtime::traits::StaticLookup for Lookup {
type Source = SeraiAddress;
type Target = Public;
fn lookup(source: SeraiAddress) -> Result<Public, sp_runtime::traits::LookupError> {
Ok(source.into())
}
fn unlookup(source: Public) -> SeraiAddress {
source.into()
}
}
// TODO: Remove
#[sp_version::runtime_version]
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: Cow::Borrowed("serai"),
impl_name: Cow::Borrowed("core"),
authoring_version: 0,
spec_version: 0,
impl_version: 0,
apis: RUNTIME_API_VERSIONS,
transaction_version: 0,
system_version: 0,
};
frame_support::parameter_types! {
pub const Version: RuntimeVersion = VERSION;
// TODO
pub BlockLength: frame_system::limits::BlockLength =
frame_system::limits::BlockLength::max_with_normal_ratio(0, Perbill::from_percent(0));
// TODO
pub BlockWeights: frame_system::limits::BlockWeights =
frame_system::limits::BlockWeights::with_sensible_defaults(
Weight::from_parts(0, 0),
Perbill::from_percent(0),
);
}
#[frame_support::runtime]
mod runtime {
use super::*;
#[runtime::runtime]
#[runtime::derive(RuntimeCall, RuntimeEvent, RuntimeError, RuntimeOrigin)]
pub struct Runtime;
#[runtime::pallet_index(0)]
pub type System = frame_system::Pallet<Runtime>;
#[runtime::pallet_index(1)]
pub type Core = core_pallet::Pallet<Runtime>;
}
impl frame_system::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type BaseCallFilter = frame_support::traits::Everything;
type BlockWeights = BlockWeights;
type BlockLength = BlockLength;
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
type RuntimeTask = ();
type Nonce = u32;
type Hash = <Self::Block as sp_runtime::traits::Block>::Hash;
type Hashing = sp_runtime::traits::BlakeTwo256;
type AccountId = sp_core::sr25519::Public;
type Lookup = Lookup;
type Block = Block;
// Don't track old block hashes within the System pallet
// We use not a number -> hash index, but a hash -> () index, in our own pallet
type BlockHashCount = sp_core::ConstU64<1>;
type DbWeight = frame_support::weights::constants::RocksDbWeight;
type Version = Version;
type PalletInfo = PalletInfo;
type AccountData = ();
type OnNewAccount = ();
type OnKilledAccount = ();
// We use the default weights as we never expose/call any of these methods
type SystemWeightInfo = ();
// We also don't use the provided extensions framework
type ExtensionsWeightInfo = ();
// We don't invoke any hooks on-set-code as we don't perform upgrades via the blockchain yet via
// nodes, ensuring everyone who upgrades consents to the rules they upgrade to
type OnSetCode = ();
type MaxConsumers = sp_core::ConstU32<{ u32::MAX }>;
// No migrations set
type SingleBlockMigrations = ();
type MultiBlockMigrator = ();
// We don't define any block-level hooks at this time
type PreInherents = ();
type PostInherents = ();
type PostTransactions = ();
}
impl core_pallet::Config for Runtime {}
impl From<Option<SeraiAddress>> for RuntimeOrigin {
fn from(signer: Option<SeraiAddress>) -> Self {
match signer {
None => RuntimeOrigin::none(),
Some(signer) => RuntimeOrigin::signed(signer.into()),
}
}
}
impl From<serai_abi::Call> for RuntimeCall {
fn from(call: serai_abi::Call) -> Self {
match call {
serai_abi::Call::Coins(call) => {
use serai_abi::coins::Call;
match call {
Call::transfer { .. } | Call::burn { .. } | Call::burn_with_instruction { .. } => {
todo!("TODO")
}
}
}
serai_abi::Call::ValidatorSets(call) => {
use serai_abi::validator_sets::Call;
match call {
Call::set_keys { .. } |
Call::report_slashes { .. } |
Call::set_embedded_elliptic_curve_keys { .. } |
Call::allocate { .. } |
Call::deallocate { .. } |
Call::claim_deallocation { .. } => todo!("TODO"),
}
}
serai_abi::Call::Signals(call) => {
use serai_abi::signals::Call;
match call {
Call::register_retirement_signal { .. } |
Call::revoke_retirement_signal { .. } |
Call::favor { .. } |
Call::revoke_favor { .. } |
Call::stand_against { .. } => todo!("TODO"),
}
}
serai_abi::Call::Dex(call) => {
use serai_abi::dex::Call;
match call {
Call::add_liquidity { .. } |
Call::transfer_liquidity { .. } |
Call::remove_liquidity { .. } |
Call::swap_exact { .. } |
Call::swap_for_exact { .. } => todo!("TODO"),
}
}
serai_abi::Call::GenesisLiquidity(call) => {
use serai_abi::genesis_liquidity::Call;
match call {
Call::oraclize_values { .. } | Call::remove_liquidity { .. } => todo!("TODO"),
}
}
serai_abi::Call::InInstructions(call) => {
use serai_abi::in_instructions::Call;
match call {
Call::execute_batch { .. } => todo!("TODO"),
}
}
}
}
}
type Executive = frame_executive::Executive<Runtime, Block, Context, Runtime, AllPalletsWithSystem>;
sp_api::impl_runtime_apis! {
impl sp_api::Core<Block> for Runtime {
fn version() -> RuntimeVersion {
VERSION
}
fn initialize_block(header: &Header) -> sp_runtime::ExtrinsicInclusionMode {
core_pallet::Blocks::<Runtime>::set(header.parent_hash(), Some(()));
Executive::initialize_block(header)
}
fn execute_block(block: Block) {
Executive::execute_block(block);
}
}
}
#[derive(Clone, Default, PartialEq, Eq, Debug)]
struct Context;
impl serai_abi::TransactionContext for Context {
// TODO
const SIGNED_WEIGHT: Weight = Weight::zero();
type RuntimeCall = RuntimeCall;
/// The implicit context to verify transactions with.
fn implicit_context() -> serai_abi::ImplicitContext {
serai_abi::ImplicitContext {
genesis: System::block_hash(0).into(),
protocol_id: [0; 32], // TODO via build script
}
}
/// If a block is present in the blockchain.
fn block_is_present_in_blockchain(&self, hash: &serai_abi::primitives::BlockHash) -> bool {
core_pallet::Blocks::<Runtime>::get(hash).is_some()
}
/// The time embedded into the current block.
fn current_time(&self) -> Option<u64> {
todo!("TODO")
}
/// Get, and consume, the next nonce for an account.
fn get_and_consume_next_nonce(&self, signer: &SeraiAddress) -> u32 {
core_pallet::NextNonce::<Runtime>::mutate(signer, |value| {
// Copy the current value for the next nonce
let next_nonce = *value;
// Increment the next nonce in the DB, consuming the current value
*value += 1;
// Return the existing value
next_nonce
})
}
/// If the signer can pay the SRI fee.
fn can_pay_fee(
&self,
signer: &SeraiAddress,
fee: serai_abi::primitives::balance::Amount,
) -> Result<(), sp_runtime::transaction_validity::TransactionValidityError> {
todo!("TODO")
}
/// Have the transaction pay its SRI fee.
fn pay_fee(
&self,
signer: &SeraiAddress,
fee: serai_abi::primitives::balance::Amount,
) -> Result<(), sp_runtime::transaction_validity::TransactionValidityError> {
todo!("TODO")
}
}
/*
use core::marker::PhantomData;
// Re-export all components
@@ -73,29 +323,14 @@ use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
use babe::AuthorityId as BabeId;
use grandpa::AuthorityId as GrandpaId;
mod abi;
/// Nonce of a transaction in the chain, for a given account.
pub type Nonce = u32;
/// A hash of some data used by the chain.
pub type Hash = sp_core::H256;
pub type SignedExtra = (
system::CheckNonZeroSender<Runtime>,
system::CheckSpecVersion<Runtime>,
system::CheckTxVersion<Runtime>,
system::CheckGenesis<Runtime>,
system::CheckEra<Runtime>,
system::CheckNonce<Runtime>,
system::CheckWeight<Runtime>,
transaction_payment::ChargeTransactionPayment<Runtime>,
system::CheckWeight<Runtime>, TODO
);
pub type Transaction = serai_abi::tx::Transaction<RuntimeCall, SignedExtra>;
pub type Block = generic::Block<Header, Transaction>;
pub type BlockId = generic::BlockId<Block>;
pub mod opaque {
use super::*;
@@ -107,22 +342,6 @@ pub mod opaque {
}
}
#[sp_version::runtime_version]
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("serai"),
impl_name: create_runtime_str!("core"),
spec_version: 1,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
state_version: 1,
};
#[cfg(feature = "std")]
pub fn native_version() -> NativeVersion {
NativeVersion { runtime_version: VERSION, can_author_with: Default::default() }
}
pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4);
pub const BABE_GENESIS_EPOCH_CONFIG: sp_consensus_babe::BabeEpochConfiguration =
sp_consensus_babe::BabeEpochConfiguration {
@@ -133,7 +352,6 @@ pub const BABE_GENESIS_EPOCH_CONFIG: sp_consensus_babe::BabeEpochConfiguration =
const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
parameter_types! {
pub const BlockHashCount: BlockNumber = 2400;
pub const Version: RuntimeVersion = VERSION;
pub const SS58Prefix: u8 = 42; // TODO: Remove for Bech32m
@@ -148,44 +366,6 @@ parameter_types! {
);
}
pub struct CallFilter;
impl Contains<RuntimeCall> for CallFilter {
fn contains(call: &RuntimeCall) -> bool {
// If the call is defined in our ABI, it's allowed
let call: Result<serai_abi::Call, ()> = call.clone().try_into();
call.is_ok()
}
}
impl system::Config for Runtime {
type BaseCallFilter = CallFilter;
type BlockWeights = BlockWeights;
type BlockLength = BlockLength;
type AccountId = PublicKey;
type RuntimeCall = RuntimeCall;
type Lookup = AccountLookup;
type Hash = Hash;
type Hashing = BlakeTwo256;
type Nonce = Nonce;
type Block = Block;
type RuntimeOrigin = RuntimeOrigin;
type RuntimeEvent = RuntimeEvent;
type BlockHashCount = BlockHashCount;
type DbWeight = RocksDbWeight;
type Version = Version;
type PalletInfo = PalletInfo;
type OnNewAccount = ();
type OnKilledAccount = ();
type OnSetCode = ();
type AccountData = ();
type SystemWeightInfo = ();
type SS58Prefix = SS58Prefix; // TODO: Remove for Bech32m
type MaxConsumers = support::traits::ConstU32<16>;
}
impl timestamp::Config for Runtime {
type Moment = u64;
type OnTimestampSet = Babe;
@@ -319,14 +499,6 @@ impl grandpa::Config for Runtime {
grandpa::EquivocationReportSystem<Self, ValidatorSets, ValidatorSets, ReportLongevity>;
}
pub type Executive = frame_executive::Executive<
Runtime,
Block,
system::ChainContext<Runtime>,
Runtime,
AllPalletsWithSystem,
>;
construct_runtime!(
pub enum Runtime {
System: system exclude_parts { Call },
@@ -627,3 +799,4 @@ sp_api::impl_runtime_apis! {
}
}
}
*/