mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-12 14:09:25 +00:00
Compare commits
6 Commits
ffae6753ec
...
ea66cd0d1a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea66cd0d1a | ||
|
|
8b32fba458 | ||
|
|
e63acf3f67 | ||
|
|
d373d2a4c9 | ||
|
|
cbf998ff30 | ||
|
|
ef07253a27 |
@@ -7,6 +7,10 @@ runs:
|
|||||||
- name: Remove unused packages
|
- name: Remove unused packages
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
# Ensure the repositories are synced
|
||||||
|
sudo apt update -y
|
||||||
|
|
||||||
|
# Actually perform the removals
|
||||||
sudo apt remove -y "*powershell*" "*nuget*" "*bazel*" "*ansible*" "*terraform*" "*heroku*" "*aws*" azure-cli
|
sudo apt remove -y "*powershell*" "*nuget*" "*bazel*" "*ansible*" "*terraform*" "*heroku*" "*aws*" azure-cli
|
||||||
sudo apt remove -y "*nodejs*" "*npm*" "*yarn*" "*java*" "*kotlin*" "*golang*" "*swift*" "*julia*" "*fortran*" "*android*"
|
sudo apt remove -y "*nodejs*" "*npm*" "*yarn*" "*java*" "*kotlin*" "*golang*" "*swift*" "*julia*" "*fortran*" "*android*"
|
||||||
sudo apt remove -y "*apache2*" "*nginx*" "*firefox*" "*chromium*" "*chrome*" "*edge*"
|
sudo apt remove -y "*apache2*" "*nginx*" "*firefox*" "*chromium*" "*chrome*" "*edge*"
|
||||||
@@ -14,8 +18,9 @@ runs:
|
|||||||
sudo apt remove -y --allow-remove-essential -f shim-signed *python3*
|
sudo apt remove -y --allow-remove-essential -f shim-signed *python3*
|
||||||
# This removal command requires the prior removals due to unmet dependencies otherwise
|
# This removal command requires the prior removals due to unmet dependencies otherwise
|
||||||
sudo apt remove -y "*qemu*" "*sql*" "*texinfo*" "*imagemagick*"
|
sudo apt remove -y "*qemu*" "*sql*" "*texinfo*" "*imagemagick*"
|
||||||
|
|
||||||
# Reinstall python3 as a general dependency of a functional operating system
|
# Reinstall python3 as a general dependency of a functional operating system
|
||||||
sudo apt install python3
|
sudo apt install -y python3 --fix-missing
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
|
|
||||||
- name: Remove unused packages
|
- name: Remove unused packages
|
||||||
|
|||||||
447
Cargo.lock
generated
447
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -22,12 +22,12 @@ workspace = true
|
|||||||
borsh = { version = "1", default-features = false, features = ["derive", "de_strict_order"] }
|
borsh = { version = "1", default-features = false, features = ["derive", "de_strict_order"] }
|
||||||
|
|
||||||
bitvec = { version = "1", default-features = false, features = ["alloc"] }
|
bitvec = { version = "1", default-features = false, features = ["alloc"] }
|
||||||
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
serde = { version = "1", default-features = false, features = ["derive"], optional = true }
|
serde = { version = "1", default-features = false, features = ["derive"], optional = true }
|
||||||
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"], optional = true }
|
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"], optional = true }
|
||||||
sp-runtime = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false, features = ["serde"], optional = true }
|
sp-runtime = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false, features = ["serde"], optional = true }
|
||||||
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false, optional = true }
|
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false, optional = true }
|
||||||
|
|
||||||
serai-primitives = { path = "../primitives", version = "0.1", default-features = false }
|
serai-primitives = { path = "../primitives", version = "0.1", default-features = false }
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
use borsh::{BorshSerialize, BorshDeserialize};
|
use borsh::{BorshSerialize, BorshDeserialize};
|
||||||
|
|
||||||
use serai_primitives::network_id::ExternalNetworkId;
|
use serai_primitives::{
|
||||||
|
network_id::ExternalNetworkId,
|
||||||
|
balance::{Amount, ExternalBalance},
|
||||||
|
};
|
||||||
|
|
||||||
/// An event from economic security.
|
/// An event from economic security.
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)]
|
#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)]
|
||||||
@@ -14,7 +17,10 @@ pub enum Event {
|
|||||||
|
|
||||||
/// A trait representing access to the information on economic security.
|
/// A trait representing access to the information on economic security.
|
||||||
pub trait EconomicSecurity {
|
pub trait EconomicSecurity {
|
||||||
/// If am external network has _ever_ achieved economic security.
|
/// If an external network has _ever_ achieved economic security.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn achieved_economic_security(network: ExternalNetworkId) -> bool;
|
fn achieved_economic_security(network: ExternalNetworkId) -> bool;
|
||||||
|
|
||||||
|
/// The security oracle's valuation of this balance in SRI.
|
||||||
|
fn sri_value(balance: ExternalBalance) -> Amount;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ pub enum Call {
|
|||||||
stand_against {
|
stand_against {
|
||||||
/// The signal to stand against.
|
/// The signal to stand against.
|
||||||
signal: Signal,
|
signal: Signal,
|
||||||
|
/// The network this validator is standing against the signal on behalf of.
|
||||||
|
with_network: NetworkId,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ use serai_primitives::{
|
|||||||
pub enum Call {
|
pub enum Call {
|
||||||
/// Set the keys for a validator set.
|
/// Set the keys for a validator set.
|
||||||
set_keys {
|
set_keys {
|
||||||
/// The validator set which is setting their keys.
|
/// The network whose latest decided validator set is setting their keys..
|
||||||
validator_set: ExternalValidatorSet,
|
network: ExternalNetworkId,
|
||||||
/// The keys being set.
|
/// The keys being set.
|
||||||
key_pair: KeyPair,
|
key_pair: KeyPair,
|
||||||
/// The participants in the validator set who signed off on these keys.
|
/// The participants in the validator set who signed off on these keys.
|
||||||
@@ -29,8 +29,8 @@ pub enum Call {
|
|||||||
},
|
},
|
||||||
/// Report a validator set's slashes onto Serai.
|
/// Report a validator set's slashes onto Serai.
|
||||||
report_slashes {
|
report_slashes {
|
||||||
/// The validator set which is setting their keys.
|
/// The network whose latest retired validator set is reporting their slashes.
|
||||||
validator_set: ExternalValidatorSet,
|
network: ExternalNetworkId,
|
||||||
/// The slashes they're reporting.
|
/// The slashes they're reporting.
|
||||||
slashes: SlashReport,
|
slashes: SlashReport,
|
||||||
/// The signature confirming the validity of this slash report.
|
/// The signature confirming the validity of this slash report.
|
||||||
@@ -77,12 +77,24 @@ impl Call {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The timeline for a deallocation.
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)]
|
||||||
|
pub enum DeallocationTimeline {
|
||||||
|
/// The deallocation is available immediately.
|
||||||
|
Immediate,
|
||||||
|
/// The dealocation was delayed.
|
||||||
|
Delayed {
|
||||||
|
/// The session the deallocation unlocks at and can be claimed.
|
||||||
|
unlocks_at: Session,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
/// An event from the validator sets.
|
/// An event from the validator sets.
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)]
|
#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
/// A new validator set was declared.
|
/// A new validator set was decided.
|
||||||
NewSet {
|
SetDecided {
|
||||||
/// The set declared.
|
/// The set decided.
|
||||||
set: ValidatorSet,
|
set: ValidatorSet,
|
||||||
},
|
},
|
||||||
/// A validator set has set their keys.
|
/// A validator set has set their keys.
|
||||||
@@ -97,10 +109,20 @@ pub enum Event {
|
|||||||
/// The set which accepted responsibility from the prior set.
|
/// The set which accepted responsibility from the prior set.
|
||||||
set: ValidatorSet,
|
set: ValidatorSet,
|
||||||
},
|
},
|
||||||
/// A validator set has retired.
|
/// A slash report has been entered for this validator set.
|
||||||
SetRetired {
|
///
|
||||||
/// The set retired.
|
/// This may be due to a slash report being published or a default being used due to one not
|
||||||
set: ValidatorSet,
|
/// being received within time.
|
||||||
|
SlashReport {
|
||||||
|
/// The set whose slash report has been entered.
|
||||||
|
set: ExternalValidatorSet,
|
||||||
|
},
|
||||||
|
/// A validator set their keys on an embedded elliptic curve for a network.
|
||||||
|
SetEmbeddedEllipticCurveKeys {
|
||||||
|
/// The validator which set their keys.
|
||||||
|
validator: SeraiAddress,
|
||||||
|
/// The network which they set embedded elliptic curve keys for.
|
||||||
|
network: ExternalNetworkId,
|
||||||
},
|
},
|
||||||
/// A validator's allocation to a network has increased.
|
/// A validator's allocation to a network has increased.
|
||||||
Allocation {
|
Allocation {
|
||||||
@@ -119,13 +141,11 @@ pub enum Event {
|
|||||||
network: NetworkId,
|
network: NetworkId,
|
||||||
/// The amount of stake deallocated.
|
/// The amount of stake deallocated.
|
||||||
amount: Amount,
|
amount: Amount,
|
||||||
/// The session which claiming the deallocation was delayed until.
|
/// The timeline for this deallocation.
|
||||||
delayed_until: Option<Session>,
|
timeline: DeallocationTimeline,
|
||||||
},
|
},
|
||||||
/// A validator's deallocation from a network has been claimed.
|
/// A validator's delayed deallocation from a network has been claimed.
|
||||||
///
|
DelayedDeallocationClaimed {
|
||||||
/// This is only emited for deallocations which were delayed and has to be explicitly claimed.
|
|
||||||
DeallocationClaimed {
|
|
||||||
/// The validator who claimed their deallocation.
|
/// The validator who claimed their deallocation.
|
||||||
validator: SeraiAddress,
|
validator: SeraiAddress,
|
||||||
/// The validator set the deallocation was delayed until.
|
/// The validator set the deallocation was delayed until.
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ serde_json = { version = "1", optional = true }
|
|||||||
serai-abi = { path = "../abi", version = "0.1" }
|
serai-abi = { path = "../abi", version = "0.1" }
|
||||||
|
|
||||||
multiaddr = { version = "0.18", optional = true }
|
multiaddr = { version = "0.18", optional = true }
|
||||||
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", optional = true }
|
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", optional = true }
|
||||||
sp-runtime = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", optional = true }
|
sp-runtime = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", optional = true }
|
||||||
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", optional = true }
|
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", optional = true }
|
||||||
|
|
||||||
async-lock = "3"
|
async-lock = "3"
|
||||||
|
|
||||||
|
|||||||
@@ -18,10 +18,10 @@ workspace = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
|
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
|
||||||
|
|
||||||
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
serai-abi = { path = "../abi", default-features = false, features = ["substrate"] }
|
serai-abi = { path = "../abi", default-features = false, features = ["substrate"] }
|
||||||
serai-core-pallet = { path = "../core", default-features = false }
|
serai-core-pallet = { path = "../core", default-features = false }
|
||||||
@@ -29,7 +29,7 @@ serai-core-pallet = { path = "../core", default-features = false }
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] }
|
borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] }
|
||||||
|
|
||||||
sp-io = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false, features = ["std"] }
|
sp-io = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false, features = ["std"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
std = [
|
std = [
|
||||||
|
|||||||
@@ -49,10 +49,12 @@ mod pallet {
|
|||||||
/// The instance used to represent coins on the Serai network.
|
/// The instance used to represent coins on the Serai network.
|
||||||
///
|
///
|
||||||
/// This would either be SRI itself or the sriXYZ coins swappable via pools.
|
/// This would either be SRI itself or the sriXYZ coins swappable via pools.
|
||||||
|
#[derive(Default)]
|
||||||
pub struct CoinsInstance;
|
pub struct CoinsInstance;
|
||||||
/// The instance used to represent liquidity tokens on the Serai network.
|
/// The instance used to represent liquidity tokens on the Serai network.
|
||||||
///
|
///
|
||||||
/// Coin::XYZ would be considered as the liquidity token for the Coin::SRI - Coin::XYZ pool.
|
/// Coin::XYZ would be considered as the liquidity token for the Coin::SRI - Coin::XYZ pool.
|
||||||
|
#[derive(Default)]
|
||||||
pub struct LiquidityTokensInstance;
|
pub struct LiquidityTokensInstance;
|
||||||
|
|
||||||
/// The configuration of this pallet.
|
/// The configuration of this pallet.
|
||||||
@@ -66,7 +68,7 @@ mod pallet {
|
|||||||
|
|
||||||
/// The genesis state to use for this pallet.
|
/// The genesis state to use for this pallet.
|
||||||
#[pallet::genesis_config]
|
#[pallet::genesis_config]
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct GenesisConfig<T: Config<I>, I: 'static = ()> {
|
pub struct GenesisConfig<T: Config<I>, I: 'static = ()> {
|
||||||
/// The balances to initiate the state with.
|
/// The balances to initiate the state with.
|
||||||
///
|
///
|
||||||
@@ -76,10 +78,9 @@ mod pallet {
|
|||||||
/// PhantomData to bind `I`.
|
/// PhantomData to bind `I`.
|
||||||
pub _instance: PhantomData<I>,
|
pub _instance: PhantomData<I>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Config<I>, I: 'static> Default for GenesisConfig<T, I> {
|
impl<T: Config<I>, I: 'static> Default for GenesisConfig<T, I> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
GenesisConfig { accounts: Default::default(), _instance: Default::default() }
|
Self { accounts: Default::default(), _instance: PhantomData }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ borsh = { version = "1", default-features = false, features = ["derive", "de_str
|
|||||||
|
|
||||||
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
|
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
|
||||||
|
|
||||||
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
serai-abi = { path = "../abi", default-features = false, features = ["substrate"] }
|
serai-abi = { path = "../abi", default-features = false, features = ["substrate"] }
|
||||||
|
|
||||||
|
|||||||
@@ -21,15 +21,15 @@ workspace = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
scale = { package = "parity-scale-codec", version = "3.6.1", default-features = false }
|
scale = { package = "parity-scale-codec", version = "3.6.1", default-features = false }
|
||||||
|
|
||||||
sp-std = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-std = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
sp-io = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-io = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
sp-api = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-api = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
sp-runtime = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-runtime = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
frame-benchmarking = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false, optional = true }
|
frame-benchmarking = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false, optional = true }
|
||||||
|
|
||||||
coins-pallet = { package = "serai-coins-pallet", path = "../coins", default-features = false }
|
coins-pallet = { package = "serai-coins-pallet", path = "../coins", default-features = false }
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ workspace = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
|
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
|
||||||
|
|
||||||
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
dex-pallet = { package = "serai-dex-pallet", path = "../dex", default-features = false }
|
dex-pallet = { package = "serai-dex-pallet", path = "../dex", default-features = false }
|
||||||
coins-pallet = { package = "serai-coins-pallet", path = "../coins", default-features = false }
|
coins-pallet = { package = "serai-coins-pallet", path = "../coins", default-features = false }
|
||||||
@@ -30,16 +30,16 @@ coins-pallet = { package = "serai-coins-pallet", path = "../coins", default-feat
|
|||||||
serai-primitives = { path = "../primitives", default-features = false }
|
serai-primitives = { path = "../primitives", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pallet-babe = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
pallet-babe = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
pallet-grandpa = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
pallet-grandpa = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
pallet-timestamp = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
pallet-timestamp = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
validator-sets-pallet = { package = "serai-validator-sets-pallet", path = "../validator-sets", default-features = false }
|
validator-sets-pallet = { package = "serai-validator-sets-pallet", path = "../validator-sets", default-features = false }
|
||||||
|
|
||||||
sp-io = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-io = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
sp-runtime = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-runtime = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
sp-consensus-babe = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-consensus-babe = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
std = [
|
std = [
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ workspace = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
|
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
|
||||||
|
|
||||||
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
sp-std = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-std = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
sp-runtime = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-runtime = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
coins-pallet = { package = "serai-coins-pallet", path = "../coins", default-features = false }
|
coins-pallet = { package = "serai-coins-pallet", path = "../coins", default-features = false }
|
||||||
validator-sets-pallet = { package = "serai-validator-sets-pallet", path = "../validator-sets", default-features = false }
|
validator-sets-pallet = { package = "serai-validator-sets-pallet", path = "../validator-sets", default-features = false }
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ workspace = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
|
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
|
||||||
|
|
||||||
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
sp-std = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-std = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
sp-application-crypto = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-application-crypto = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
dex-pallet = { package = "serai-dex-pallet", path = "../dex", default-features = false }
|
dex-pallet = { package = "serai-dex-pallet", path = "../dex", default-features = false }
|
||||||
coins-pallet = { package = "serai-coins-pallet", path = "../coins", default-features = false }
|
coins-pallet = { package = "serai-coins-pallet", path = "../coins", default-features = false }
|
||||||
|
|||||||
@@ -24,14 +24,14 @@ bitvec = { version = "1", default-features = false, features = ["alloc"] }
|
|||||||
|
|
||||||
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive", "max-encoded-len"] }
|
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive", "max-encoded-len"] }
|
||||||
|
|
||||||
sp-std = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-std = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
sp-application-crypto = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-application-crypto = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
sp-io = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-io = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
sp-runtime = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-runtime = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
serai-primitives = { path = "../primitives", default-features = false }
|
serai-primitives = { path = "../primitives", default-features = false }
|
||||||
|
|
||||||
@@ -42,9 +42,9 @@ genesis-liquidity-pallet = { package = "serai-genesis-liquidity-pallet", path =
|
|||||||
emissions-pallet = { package = "serai-emissions-pallet", path = "../emissions", default-features = false }
|
emissions-pallet = { package = "serai-emissions-pallet", path = "../emissions", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pallet-babe = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
pallet-babe = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
pallet-grandpa = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
pallet-grandpa = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
pallet-timestamp = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
pallet-timestamp = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
economic-security-pallet = { package = "serai-economic-security-pallet", path = "../economic-security", default-features = false }
|
economic-security-pallet = { package = "serai-economic-security-pallet", path = "../economic-security", default-features = false }
|
||||||
|
|
||||||
|
|||||||
@@ -34,16 +34,16 @@ secq256k1 = { path = "../../crypto/secq256k1" }
|
|||||||
|
|
||||||
libp2p = "0.56"
|
libp2p = "0.56"
|
||||||
|
|
||||||
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
sp-keystore = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sp-keystore = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
sp-timestamp = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sp-timestamp = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
sp-io = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sp-io = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
sp-blockchain = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sp-blockchain = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
sp-api = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sp-api = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
sp-block-builder = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sp-block-builder = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
sp-consensus-babe = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sp-consensus-babe = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
|
|
||||||
frame-benchmarking = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
frame-benchmarking = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
|
|
||||||
serai-runtime = { path = "../runtime", features = ["std"] }
|
serai-runtime = { path = "../runtime", features = ["std"] }
|
||||||
|
|
||||||
@@ -55,24 +55,24 @@ jsonrpsee = { version = "0.24", features = ["server"] }
|
|||||||
|
|
||||||
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
|
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
|
||||||
|
|
||||||
sc-transaction-pool = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sc-transaction-pool = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
sc-transaction-pool-api = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sc-transaction-pool-api = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
sc-basic-authorship = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sc-basic-authorship = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
sc-executor = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sc-executor = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
sc-service = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sc-service = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
sc-client-api = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sc-client-api = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
sc-network-common = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sc-network-common = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
sc-network = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sc-network = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
sc-consensus = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sc-consensus = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
sc-consensus-babe = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sc-consensus-babe = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
sc-consensus-grandpa = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sc-consensus-grandpa = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
sc-authority-discovery = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sc-authority-discovery = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
|
|
||||||
sc-telemetry = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sc-telemetry = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
sc-cli = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false, features = ["rocksdb"] }
|
sc-cli = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false, features = ["rocksdb"] }
|
||||||
|
|
||||||
sc-rpc-api = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
sc-rpc-api = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
|
|
||||||
serai-env = { path = "../../common/env" }
|
serai-env = { path = "../../common/env" }
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ borsh = { version = "1", default-features = false, features = ["derive", "de_str
|
|||||||
|
|
||||||
bitvec = { version = "1", default-features = false, features = ["alloc"] }
|
bitvec = { version = "1", default-features = false, features = ["alloc"] }
|
||||||
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"], optional = true }
|
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"], optional = true }
|
||||||
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
ciphersuite = { path = "../../crypto/ciphersuite", default-features = false, features = ["alloc"] }
|
ciphersuite = { path = "../../crypto/ciphersuite", default-features = false, features = ["alloc"] }
|
||||||
schnorr-signatures = { path = "../../crypto/schnorr", default-features = false }
|
schnorr-signatures = { path = "../../crypto/schnorr", default-features = false }
|
||||||
|
|||||||
@@ -20,16 +20,22 @@ workspace = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
|
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
|
||||||
|
|
||||||
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
sp-version = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-session = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
sp-runtime = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-version = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
sp-api = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-runtime = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
sp-api = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
serai-abi = { path = "../abi", default-features = false, features = ["substrate"] }
|
serai-abi = { path = "../abi", default-features = false, features = ["substrate"] }
|
||||||
|
|
||||||
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
frame-executive = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-executive = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
|
pallet-timestamp = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
pallet-session = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
pallet-babe = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
pallet-grandpa = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
serai-core-pallet = { path = "../core", default-features = false }
|
serai-core-pallet = { path = "../core", default-features = false }
|
||||||
serai-coins-pallet = { path = "../coins", default-features = false }
|
serai-coins-pallet = { path = "../coins", default-features = false }
|
||||||
@@ -37,13 +43,14 @@ serai-validator-sets-pallet = { path = "../validator-sets", default-features = f
|
|||||||
serai-signals-pallet = { path = "../signals", default-features = false }
|
serai-signals-pallet = { path = "../signals", default-features = false }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
substrate-wasm-builder = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7" }
|
substrate-wasm-builder = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
std = [
|
std = [
|
||||||
"scale/std",
|
"scale/std",
|
||||||
|
|
||||||
"sp-core/std",
|
"sp-core/std",
|
||||||
|
"sp-session/std",
|
||||||
"sp-version/std",
|
"sp-version/std",
|
||||||
"sp-runtime/std",
|
"sp-runtime/std",
|
||||||
"sp-api/std",
|
"sp-api/std",
|
||||||
@@ -54,6 +61,10 @@ std = [
|
|||||||
"frame-support/std",
|
"frame-support/std",
|
||||||
"frame-executive/std",
|
"frame-executive/std",
|
||||||
|
|
||||||
|
"pallet-session/std",
|
||||||
|
"pallet-babe/std",
|
||||||
|
"pallet-grandpa/std",
|
||||||
|
|
||||||
"serai-core-pallet/std",
|
"serai-core-pallet/std",
|
||||||
"serai-coins-pallet/std",
|
"serai-coins-pallet/std",
|
||||||
"serai-validator-sets-pallet/std",
|
"serai-validator-sets-pallet/std",
|
||||||
@@ -69,6 +80,10 @@ try-runtime = [
|
|||||||
"frame-support/try-runtime",
|
"frame-support/try-runtime",
|
||||||
"frame-executive/try-runtime",
|
"frame-executive/try-runtime",
|
||||||
|
|
||||||
|
"pallet-session/try-runtime",
|
||||||
|
"pallet-babe/try-runtime",
|
||||||
|
"pallet-grandpa/try-runtime",
|
||||||
|
|
||||||
"serai-core-pallet/try-runtime",
|
"serai-core-pallet/try-runtime",
|
||||||
"serai-coins-pallet/try-runtime",
|
"serai-coins-pallet/try-runtime",
|
||||||
"serai-validator-sets-pallet/try-runtime",
|
"serai-validator-sets-pallet/try-runtime",
|
||||||
@@ -81,6 +96,10 @@ runtime-benchmarks = [
|
|||||||
"frame-system/runtime-benchmarks",
|
"frame-system/runtime-benchmarks",
|
||||||
"frame-support/runtime-benchmarks",
|
"frame-support/runtime-benchmarks",
|
||||||
|
|
||||||
|
"pallet-babe/runtime-benchmarks",
|
||||||
|
"pallet-grandpa/runtime-benchmarks",
|
||||||
|
|
||||||
|
"pallet-session/runtime-benchmarks",
|
||||||
"serai-core-pallet/runtime-benchmarks",
|
"serai-core-pallet/runtime-benchmarks",
|
||||||
"serai-coins-pallet/runtime-benchmarks",
|
"serai-coins-pallet/runtime-benchmarks",
|
||||||
"serai-validator-sets-pallet/runtime-benchmarks",
|
"serai-validator-sets-pallet/runtime-benchmarks",
|
||||||
|
|||||||
@@ -8,13 +8,17 @@ extern crate alloc;
|
|||||||
|
|
||||||
use alloc::borrow::Cow;
|
use alloc::borrow::Cow;
|
||||||
|
|
||||||
use sp_core::sr25519::Public;
|
use sp_core::{ConstU32, ConstU64, sr25519::Public};
|
||||||
use sp_runtime::{Perbill, Weight};
|
use sp_runtime::{Perbill, Weight};
|
||||||
use sp_version::RuntimeVersion;
|
use sp_version::RuntimeVersion;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
use serai_abi::{
|
use serai_abi::{
|
||||||
primitives::address::SeraiAddress, SubstrateHeader as Header, SubstrateBlock,
|
primitives::{
|
||||||
|
network_id::{ExternalNetworkId, NetworkId},
|
||||||
|
balance::{Amount, ExternalBalance},
|
||||||
|
address::SeraiAddress,
|
||||||
|
},
|
||||||
|
SubstrateHeader as Header, SubstrateBlock,
|
||||||
};
|
};
|
||||||
|
|
||||||
use serai_coins_pallet::{CoinsInstance, LiquidityTokensInstance};
|
use serai_coins_pallet::{CoinsInstance, LiquidityTokensInstance};
|
||||||
@@ -79,13 +83,22 @@ mod runtime {
|
|||||||
pub type Coins = serai_coins_pallet::Pallet<Runtime, CoinsInstance>;
|
pub type Coins = serai_coins_pallet::Pallet<Runtime, CoinsInstance>;
|
||||||
|
|
||||||
#[runtime::pallet_index(3)]
|
#[runtime::pallet_index(3)]
|
||||||
pub type LiquidityTokens = serai_coins_pallet::Pallet<Runtime, LiquidityTokensInstance>;
|
|
||||||
|
|
||||||
#[runtime::pallet_index(4)]
|
|
||||||
pub type ValidatorSets = serai_validator_sets_pallet::Pallet<Runtime>;
|
pub type ValidatorSets = serai_validator_sets_pallet::Pallet<Runtime>;
|
||||||
|
|
||||||
#[runtime::pallet_index(5)]
|
#[runtime::pallet_index(4)]
|
||||||
pub type Signals = serai_signals_pallet::Pallet<Runtime>;
|
pub type Signals = serai_signals_pallet::Pallet<Runtime>;
|
||||||
|
|
||||||
|
#[runtime::pallet_index(5)]
|
||||||
|
pub type LiquidityTokens = serai_coins_pallet::Pallet<Runtime, LiquidityTokensInstance>;
|
||||||
|
|
||||||
|
#[runtime::pallet_index(0xfd)]
|
||||||
|
pub type Session = pallet_session::Pallet<Runtime>;
|
||||||
|
|
||||||
|
#[runtime::pallet_index(0xfe)]
|
||||||
|
pub type Babe = pallet_babe::Pallet<Runtime>;
|
||||||
|
|
||||||
|
#[runtime::pallet_index(0xff)]
|
||||||
|
pub type Grandpa = pallet_grandpa::Pallet<Runtime>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Runtime {
|
impl frame_system::Config for Runtime {
|
||||||
@@ -104,7 +117,7 @@ impl frame_system::Config for Runtime {
|
|||||||
type Block = Block;
|
type Block = Block;
|
||||||
// Don't track old block hashes within the System pallet
|
// 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
|
// We use not a number -> hash index, but a hash -> () index, in our own pallet
|
||||||
type BlockHashCount = sp_core::ConstU64<1>;
|
type BlockHashCount = ConstU64<1>;
|
||||||
type DbWeight = frame_support::weights::constants::RocksDbWeight;
|
type DbWeight = frame_support::weights::constants::RocksDbWeight;
|
||||||
type Version = Version;
|
type Version = Version;
|
||||||
type PalletInfo = PalletInfo;
|
type PalletInfo = PalletInfo;
|
||||||
@@ -118,7 +131,7 @@ impl frame_system::Config for Runtime {
|
|||||||
// We don't invoke any hooks on-set-code as we don't perform upgrades via the blockchain yet via
|
// 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
|
// nodes, ensuring everyone who upgrades consents to the rules they upgrade to
|
||||||
type OnSetCode = ();
|
type OnSetCode = ();
|
||||||
type MaxConsumers = sp_core::ConstU32<{ u32::MAX }>;
|
type MaxConsumers = ConstU32<{ u32::MAX }>;
|
||||||
// No migrations set
|
// No migrations set
|
||||||
type SingleBlockMigrations = ();
|
type SingleBlockMigrations = ();
|
||||||
type MultiBlockMigrator = ();
|
type MultiBlockMigrator = ();
|
||||||
@@ -133,15 +146,84 @@ impl serai_core_pallet::Config for Runtime {}
|
|||||||
impl serai_coins_pallet::Config<CoinsInstance> for Runtime {
|
impl serai_coins_pallet::Config<CoinsInstance> for Runtime {
|
||||||
type AllowMint = serai_coins_pallet::AlwaysAllowMint; // TODO
|
type AllowMint = serai_coins_pallet::AlwaysAllowMint; // TODO
|
||||||
}
|
}
|
||||||
impl serai_coins_pallet::Config<LiquidityTokensInstance> for Runtime {
|
|
||||||
type AllowMint = serai_coins_pallet::AlwaysAllowMint;
|
#[doc(hidden)]
|
||||||
|
pub struct EconomicSecurity; // TODO
|
||||||
|
impl serai_abi::economic_security::EconomicSecurity for EconomicSecurity {
|
||||||
|
fn achieved_economic_security(_network: ExternalNetworkId) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
fn sri_value(_balance: ExternalBalance) -> Amount {
|
||||||
|
Amount(0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
impl serai_validator_sets_pallet::Config for Runtime {
|
impl serai_validator_sets_pallet::Config for Runtime {
|
||||||
type ShouldEndSession = Babe;
|
type ShouldEndSession = Babe;
|
||||||
|
type EconomicSecurity = EconomicSecurity;
|
||||||
}
|
}
|
||||||
impl serai_signals_pallet::Config for Runtime {
|
impl serai_signals_pallet::Config for Runtime {
|
||||||
type RetirementValidityDuration = sp_core::ConstU64<0>; // TODO
|
type RetirementValidityDuration = ConstU64<0>; // TODO
|
||||||
type RetirementLockInDuration = sp_core::ConstU64<0>; // TODO
|
type RetirementLockInDuration = ConstU64<0>; // TODO
|
||||||
|
}
|
||||||
|
impl serai_coins_pallet::Config<LiquidityTokensInstance> for Runtime {
|
||||||
|
type AllowMint = serai_coins_pallet::AlwaysAllowMint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
`pallet-babe` requires we implement `pallet-timestamp` for the associated constants. It does not
|
||||||
|
actually require we offer the timestamp pallet however, and we don't as we follow our methodology
|
||||||
|
(using the block header for timestamps, not an inherent transaction).
|
||||||
|
|
||||||
|
TODO: Set timestamp when executing a block.
|
||||||
|
*/
|
||||||
|
impl pallet_timestamp::Config for Runtime {
|
||||||
|
type Moment = u64;
|
||||||
|
type OnTimestampSet = Babe;
|
||||||
|
type MinimumPeriod = ConstU64<0>; // TODO
|
||||||
|
type WeightInfo = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub struct GetCurrentSessionForSubstrate;
|
||||||
|
impl pallet_session::GetCurrentSessionForSubstrate for GetCurrentSessionForSubstrate {
|
||||||
|
fn get() -> u32 {
|
||||||
|
serai_validator_sets_pallet::Pallet::<Runtime>::current_session(NetworkId::Serai)
|
||||||
|
.map(|session| session.0)
|
||||||
|
.unwrap_or(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl pallet_session::Config for Runtime {
|
||||||
|
type Session = GetCurrentSessionForSubstrate;
|
||||||
|
}
|
||||||
|
|
||||||
|
type MaxAuthorities =
|
||||||
|
ConstU32<{ serai_abi::primitives::validator_sets::KeyShares::MAX_PER_SET_U32 }>;
|
||||||
|
impl pallet_babe::Config for Runtime {
|
||||||
|
type EpochDuration = ConstU64<0>; // TODO
|
||||||
|
|
||||||
|
type ExpectedBlockTime = ConstU64<0>; // TODO
|
||||||
|
type EpochChangeTrigger = pallet_babe::ExternalTrigger;
|
||||||
|
|
||||||
|
type WeightInfo = ();
|
||||||
|
type MaxAuthorities = MaxAuthorities;
|
||||||
|
type MaxNominators = ConstU32<1>;
|
||||||
|
|
||||||
|
// TODO: https://github.com/serai-dex/serai/issues/657
|
||||||
|
type DisabledValidators = ();
|
||||||
|
type KeyOwnerProof = sp_session::MembershipProof;
|
||||||
|
type EquivocationReportSystem = ();
|
||||||
|
}
|
||||||
|
impl pallet_grandpa::Config for Runtime {
|
||||||
|
type RuntimeEvent = RuntimeEvent;
|
||||||
|
|
||||||
|
type WeightInfo = ();
|
||||||
|
type MaxAuthorities = MaxAuthorities;
|
||||||
|
type MaxNominators = ConstU32<1>;
|
||||||
|
|
||||||
|
// TODO: https://github.com/serai-dex/serai/issues/657
|
||||||
|
type MaxSetIdSessionEntries = ConstU64<0>;
|
||||||
|
type KeyOwnerProof = sp_session::MembershipProof;
|
||||||
|
type EquivocationReportSystem = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Option<SeraiAddress>> for RuntimeOrigin {
|
impl From<Option<SeraiAddress>> for RuntimeOrigin {
|
||||||
@@ -158,36 +240,54 @@ impl From<serai_abi::Call> for RuntimeCall {
|
|||||||
match call {
|
match call {
|
||||||
serai_abi::Call::Coins(call) => {
|
serai_abi::Call::Coins(call) => {
|
||||||
use serai_abi::coins::Call;
|
use serai_abi::coins::Call;
|
||||||
match call {
|
use serai_coins_pallet::Call as Scall;
|
||||||
Call::transfer { to, coins } => {
|
RuntimeCall::Coins(match call {
|
||||||
RuntimeCall::Coins(serai_coins_pallet::Call::transfer { to: to.into(), coins })
|
Call::transfer { to, coins } => Scall::transfer { to: to.into(), coins },
|
||||||
}
|
Call::burn { coins } => Scall::burn { coins },
|
||||||
Call::burn { coins } => RuntimeCall::Coins(serai_coins_pallet::Call::burn { coins }),
|
|
||||||
Call::burn_with_instruction { instruction } => {
|
Call::burn_with_instruction { instruction } => {
|
||||||
RuntimeCall::Coins(serai_coins_pallet::Call::burn_with_instruction { instruction })
|
Scall::burn_with_instruction { instruction }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
serai_abi::Call::ValidatorSets(call) => {
|
serai_abi::Call::ValidatorSets(call) => {
|
||||||
use serai_abi::validator_sets::Call;
|
use serai_abi::validator_sets::Call;
|
||||||
match call {
|
use serai_validator_sets_pallet::Call as Scall;
|
||||||
Call::set_keys { .. } |
|
RuntimeCall::ValidatorSets(match call {
|
||||||
Call::report_slashes { .. } |
|
Call::set_keys { network, key_pair, signature_participants, signature } => {
|
||||||
Call::set_embedded_elliptic_curve_keys { .. } |
|
Scall::set_keys { network, key_pair, signature_participants, signature }
|
||||||
Call::allocate { .. } |
|
|
||||||
Call::deallocate { .. } |
|
|
||||||
Call::claim_deallocation { .. } => todo!("TODO"),
|
|
||||||
}
|
}
|
||||||
|
Call::report_slashes { network, slashes, signature } => {
|
||||||
|
Scall::report_slashes { network, slashes, signature }
|
||||||
|
}
|
||||||
|
Call::set_embedded_elliptic_curve_keys { keys } => {
|
||||||
|
Scall::set_embedded_elliptic_curve_keys { keys }
|
||||||
|
}
|
||||||
|
Call::allocate { network, amount } => Scall::allocate { network, amount },
|
||||||
|
Call::deallocate { network, amount } => Scall::deallocate { network, amount },
|
||||||
|
Call::claim_deallocation { deallocation } => Scall::claim_deallocation {
|
||||||
|
network: deallocation.network,
|
||||||
|
session: deallocation.session,
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
serai_abi::Call::Signals(call) => {
|
serai_abi::Call::Signals(call) => {
|
||||||
use serai_abi::signals::Call;
|
use serai_abi::signals::Call;
|
||||||
match call {
|
use serai_signals_pallet::Call as Scall;
|
||||||
Call::register_retirement_signal { .. } |
|
RuntimeCall::Signals(match call {
|
||||||
Call::revoke_retirement_signal { .. } |
|
Call::register_retirement_signal { in_favor_of } => {
|
||||||
Call::favor { .. } |
|
Scall::register_retirement_signal { in_favor_of }
|
||||||
Call::revoke_favor { .. } |
|
|
||||||
Call::stand_against { .. } => todo!("TODO"),
|
|
||||||
}
|
}
|
||||||
|
Call::revoke_retirement_signal { was_in_favor_of } => {
|
||||||
|
Scall::revoke_retirement_signal { retirement_signal: was_in_favor_of }
|
||||||
|
}
|
||||||
|
Call::favor { signal, with_network } => Scall::favor { signal, with_network },
|
||||||
|
Call::revoke_favor { signal, with_network } => {
|
||||||
|
Scall::revoke_favor { signal, with_network }
|
||||||
|
}
|
||||||
|
Call::stand_against { signal, with_network } => {
|
||||||
|
Scall::stand_against { signal, with_network }
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
serai_abi::Call::Dex(call) => {
|
serai_abi::Call::Dex(call) => {
|
||||||
use serai_abi::dex::Call;
|
use serai_abi::dex::Call;
|
||||||
@@ -331,9 +431,6 @@ pub use in_instructions_pallet as in_instructions;
|
|||||||
|
|
||||||
pub use signals_pallet as signals;
|
pub use signals_pallet as signals;
|
||||||
|
|
||||||
pub use pallet_babe as babe;
|
|
||||||
pub use pallet_grandpa as grandpa;
|
|
||||||
|
|
||||||
pub use genesis_liquidity_pallet as genesis_liquidity;
|
pub use genesis_liquidity_pallet as genesis_liquidity;
|
||||||
pub use emissions_pallet as emissions;
|
pub use emissions_pallet as emissions;
|
||||||
|
|
||||||
@@ -492,43 +589,9 @@ impl pallet_authorship::Config for Runtime {
|
|||||||
type EventHandler = ();
|
type EventHandler = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maximum number of authorities per session.
|
|
||||||
pub type MaxAuthorities = ConstU32<{ validator_sets::primitives::MAX_KEY_SHARES_PER_SET_U32 }>;
|
|
||||||
|
|
||||||
/// Longevity of an offence report.
|
/// Longevity of an offence report.
|
||||||
pub type ReportLongevity = <Runtime as pallet_babe::Config>::EpochDuration;
|
pub type ReportLongevity = <Runtime as pallet_babe::Config>::EpochDuration;
|
||||||
|
|
||||||
impl babe::Config for Runtime {
|
|
||||||
#[cfg(feature = "fast-epoch")]
|
|
||||||
type EpochDuration = ConstU64<{ FAST_EPOCH_DURATION }>;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "fast-epoch"))]
|
|
||||||
type EpochDuration = ConstU64<{ 4 * 7 * DAYS }>;
|
|
||||||
|
|
||||||
type ExpectedBlockTime = ConstU64<{ TARGET_BLOCK_TIME * 1000 }>;
|
|
||||||
type EpochChangeTrigger = babe::ExternalTrigger;
|
|
||||||
type DisabledValidators = ValidatorSets;
|
|
||||||
|
|
||||||
type WeightInfo = ();
|
|
||||||
type MaxAuthorities = MaxAuthorities;
|
|
||||||
|
|
||||||
type KeyOwnerProof = MembershipProof<Self>;
|
|
||||||
type EquivocationReportSystem =
|
|
||||||
babe::EquivocationReportSystem<Self, ValidatorSets, ValidatorSets, ReportLongevity>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl grandpa::Config for Runtime {
|
|
||||||
type RuntimeEvent = RuntimeEvent;
|
|
||||||
|
|
||||||
type WeightInfo = ();
|
|
||||||
type MaxAuthorities = MaxAuthorities;
|
|
||||||
|
|
||||||
type MaxSetIdSessionEntries = ConstU64<0>;
|
|
||||||
type KeyOwnerProof = MembershipProof<Self>;
|
|
||||||
type EquivocationReportSystem =
|
|
||||||
grandpa::EquivocationReportSystem<Self, ValidatorSets, ValidatorSets, ReportLongevity>;
|
|
||||||
}
|
|
||||||
|
|
||||||
construct_runtime!(
|
construct_runtime!(
|
||||||
pub enum Runtime {
|
pub enum Runtime {
|
||||||
System: system exclude_parts { Call },
|
System: system exclude_parts { Call },
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ workspace = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
|
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
|
||||||
|
|
||||||
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
serai-abi = { path = "../abi", default-features = false, features = ["substrate"] }
|
serai-abi = { path = "../abi", default-features = false, features = ["substrate"] }
|
||||||
|
|
||||||
|
|||||||
@@ -36,13 +36,13 @@ pub mod pallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[pallet::genesis_config]
|
#[pallet::genesis_config]
|
||||||
#[derive(Debug, Encode, Decode)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct GenesisConfig<T: Config> {
|
pub struct GenesisConfig<T: Config> {
|
||||||
_config: PhantomData<T>,
|
_config: PhantomData<T>,
|
||||||
}
|
}
|
||||||
impl<T: Config> Default for GenesisConfig<T> {
|
impl<T: Config> Default for GenesisConfig<T> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
GenesisConfig { _config: PhantomData }
|
Self { _config: PhantomData }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[pallet::genesis_build]
|
#[pallet::genesis_build]
|
||||||
@@ -221,20 +221,16 @@ pub mod pallet {
|
|||||||
fn revoke_favor_internal(
|
fn revoke_favor_internal(
|
||||||
validator: T::AccountId,
|
validator: T::AccountId,
|
||||||
signal: Signal,
|
signal: Signal,
|
||||||
for_network: NetworkId,
|
with_network: NetworkId,
|
||||||
) -> DispatchResult {
|
) -> DispatchResult {
|
||||||
if !Favors::<T>::contains_key((signal, for_network), validator) {
|
if !Favors::<T>::contains_key((signal, with_network), validator) {
|
||||||
Err::<(), _>(Error::<T>::RevokingNonExistentFavor)?;
|
Err::<(), _>(Error::<T>::RevokingNonExistentFavor)?;
|
||||||
}
|
}
|
||||||
Favors::<T>::remove((signal, for_network), validator);
|
Favors::<T>::remove((signal, with_network), validator);
|
||||||
Core::<T>::emit_event(Event::FavorRevoked {
|
Core::<T>::emit_event(Event::FavorRevoked { signal, by: validator.into(), with_network });
|
||||||
signal,
|
|
||||||
by: validator.into(),
|
|
||||||
with_network: for_network,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update the tally for this network
|
// Update the tally for this network
|
||||||
Self::tally_for_network(signal, for_network);
|
Self::tally_for_network(signal, with_network);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -342,7 +338,7 @@ pub mod pallet {
|
|||||||
/// Favor a signal.
|
/// Favor a signal.
|
||||||
#[pallet::call_index(2)]
|
#[pallet::call_index(2)]
|
||||||
#[pallet::weight((0, DispatchClass::Normal))] // TODO
|
#[pallet::weight((0, DispatchClass::Normal))] // TODO
|
||||||
pub fn favor(origin: OriginFor<T>, signal: Signal, for_network: NetworkId) -> DispatchResult {
|
pub fn favor(origin: OriginFor<T>, signal: Signal, with_network: NetworkId) -> DispatchResult {
|
||||||
let validator = ensure_signed(origin)?;
|
let validator = ensure_signed(origin)?;
|
||||||
|
|
||||||
// Perform the relevant checks for this class of signal
|
// Perform the relevant checks for this class of signal
|
||||||
@@ -373,21 +369,17 @@ pub mod pallet {
|
|||||||
Signal::Halt { .. } => {}
|
Signal::Halt { .. } => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if Favors::<T>::contains_key((signal, for_network), validator) {
|
if Favors::<T>::contains_key((signal, with_network), validator) {
|
||||||
Err::<(), _>(Error::<T>::AlreadyInFavor)?;
|
Err::<(), _>(Error::<T>::AlreadyInFavor)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the validator as in favor
|
// Set the validator as in favor
|
||||||
Favors::<T>::set((signal, for_network), validator, Some(()));
|
Favors::<T>::set((signal, with_network), validator, Some(()));
|
||||||
|
|
||||||
Core::<T>::emit_event(Event::SignalFavored {
|
Core::<T>::emit_event(Event::SignalFavored { signal, by: validator.into(), with_network });
|
||||||
signal,
|
|
||||||
by: validator.into(),
|
|
||||||
with_network: for_network,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Check if the network is in favor
|
// Check if the network is in favor
|
||||||
let network_in_favor = Self::tally_for_network(signal, for_network);
|
let network_in_favor = Self::tally_for_network(signal, with_network);
|
||||||
|
|
||||||
// If this network is in favor, check if enough networks are
|
// If this network is in favor, check if enough networks are
|
||||||
if network_in_favor && Self::tally_for_all_networks(signal) {
|
if network_in_favor && Self::tally_for_all_networks(signal) {
|
||||||
@@ -416,7 +408,7 @@ pub mod pallet {
|
|||||||
pub fn revoke_favor(
|
pub fn revoke_favor(
|
||||||
origin: OriginFor<T>,
|
origin: OriginFor<T>,
|
||||||
signal: Signal,
|
signal: Signal,
|
||||||
for_network: NetworkId,
|
with_network: NetworkId,
|
||||||
) -> DispatchResult {
|
) -> DispatchResult {
|
||||||
match signal {
|
match signal {
|
||||||
Signal::Retire { .. } => {
|
Signal::Retire { .. } => {
|
||||||
@@ -428,7 +420,7 @@ pub mod pallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let validator = ensure_signed(origin)?;
|
let validator = ensure_signed(origin)?;
|
||||||
Self::revoke_favor_internal(validator, signal, for_network)
|
Self::revoke_favor_internal(validator, signal, with_network)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emit an event standing against the signal.
|
/// Emit an event standing against the signal.
|
||||||
@@ -442,7 +434,7 @@ pub mod pallet {
|
|||||||
pub fn stand_against(
|
pub fn stand_against(
|
||||||
origin: OriginFor<T>,
|
origin: OriginFor<T>,
|
||||||
signal: Signal,
|
signal: Signal,
|
||||||
for_network: NetworkId,
|
with_network: NetworkId,
|
||||||
) -> DispatchResult {
|
) -> DispatchResult {
|
||||||
match signal {
|
match signal {
|
||||||
Signal::Retire { .. } => {
|
Signal::Retire { .. } => {
|
||||||
@@ -455,8 +447,8 @@ pub mod pallet {
|
|||||||
|
|
||||||
let validator = ensure_signed(origin)?;
|
let validator = ensure_signed(origin)?;
|
||||||
// If currently in favor, revoke the favor
|
// If currently in favor, revoke the favor
|
||||||
if Favors::<T>::contains_key((signal, for_network), validator) {
|
if Favors::<T>::contains_key((signal, with_network), validator) {
|
||||||
Self::revoke_favor_internal(validator, signal, for_network)?;
|
Self::revoke_favor_internal(validator, signal, with_network)?;
|
||||||
} else {
|
} else {
|
||||||
// Check this Signal exists (which would've been implied by `Favors` for it existing)
|
// Check this Signal exists (which would've been implied by `Favors` for it existing)
|
||||||
match signal {
|
match signal {
|
||||||
@@ -472,7 +464,7 @@ pub mod pallet {
|
|||||||
Core::<T>::emit_event(Event::AgainstSignal {
|
Core::<T>::emit_event(Event::AgainstSignal {
|
||||||
signal,
|
signal,
|
||||||
account: validator.into(),
|
account: validator.into(),
|
||||||
with_network: for_network,
|
with_network,
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -20,20 +20,21 @@ bitvec = { version = "1", default-features = false, features = ["alloc", "serde"
|
|||||||
|
|
||||||
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive", "bit-vec"] }
|
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive", "bit-vec"] }
|
||||||
|
|
||||||
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
sp-application-crypto = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-application-crypto = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
sp-io = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-io = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
sp-api = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
sp-api = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
pallet-session = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
pallet-session = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
pallet-babe = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
pallet-babe = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
pallet-grandpa = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "16336c737dbe833e9d138a256af99698aba637c7", default-features = false }
|
pallet-grandpa = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "ef18bfc7029d4a3d7c27e1d0b84da5091628a7d9", default-features = false }
|
||||||
|
|
||||||
serai-abi = { path = "../abi", default-features = false, features = ["substrate"] }
|
serai-abi = { path = "../abi", default-features = false, features = ["substrate"] }
|
||||||
|
|
||||||
|
serai-core-pallet = { path = "../core", default-features = false }
|
||||||
serai-coins-pallet = { path = "../coins", default-features = false }
|
serai-coins-pallet = { path = "../coins", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
@@ -63,6 +64,7 @@ std = [
|
|||||||
|
|
||||||
"serai-abi/std",
|
"serai-abi/std",
|
||||||
|
|
||||||
|
"serai-core-pallet/std",
|
||||||
"serai-coins-pallet/std",
|
"serai-coins-pallet/std",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -75,6 +77,9 @@ try-runtime = [
|
|||||||
"pallet-session/try-runtime",
|
"pallet-session/try-runtime",
|
||||||
"pallet-babe/try-runtime",
|
"pallet-babe/try-runtime",
|
||||||
"pallet-grandpa/try-runtime",
|
"pallet-grandpa/try-runtime",
|
||||||
|
|
||||||
|
"serai-core-pallet/try-runtime",
|
||||||
|
"serai-coins-pallet/try-runtime",
|
||||||
]
|
]
|
||||||
|
|
||||||
runtime-benchmarks = [
|
runtime-benchmarks = [
|
||||||
@@ -83,6 +88,9 @@ runtime-benchmarks = [
|
|||||||
|
|
||||||
"pallet-babe/runtime-benchmarks",
|
"pallet-babe/runtime-benchmarks",
|
||||||
"pallet-grandpa/runtime-benchmarks",
|
"pallet-grandpa/runtime-benchmarks",
|
||||||
|
|
||||||
|
"serai-core-pallet/runtime-benchmarks",
|
||||||
|
"serai-coins-pallet/runtime-benchmarks",
|
||||||
]
|
]
|
||||||
|
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ pub(crate) trait Keys {
|
|||||||
|
|
||||||
/// Clear a historic set of keys.
|
/// Clear a historic set of keys.
|
||||||
fn clear_keys(set: ExternalValidatorSet);
|
fn clear_keys(set: ExternalValidatorSet);
|
||||||
|
|
||||||
|
/// The oraclization key for a validator set.
|
||||||
|
fn oraclization_key(set: ExternalValidatorSet) -> Option<Public>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: KeysStorage> Keys for S {
|
impl<S: KeysStorage> Keys for S {
|
||||||
@@ -46,4 +49,8 @@ impl<S: KeysStorage> Keys for S {
|
|||||||
S::OraclizationKeys::remove(set);
|
S::OraclizationKeys::remove(set);
|
||||||
S::ExternalKeys::remove(set);
|
S::ExternalKeys::remove(set);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn oraclization_key(set: ExternalValidatorSet) -> Option<Public> {
|
||||||
|
S::OraclizationKeys::get(set)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
use alloc::vec::Vec;
|
use alloc::{vec, vec::Vec};
|
||||||
|
|
||||||
mod embedded_elliptic_curve_keys;
|
mod embedded_elliptic_curve_keys;
|
||||||
use embedded_elliptic_curve_keys::*;
|
use embedded_elliptic_curve_keys::*;
|
||||||
@@ -21,6 +21,7 @@ use keys::{KeysStorage, Keys as _};
|
|||||||
#[frame_support::pallet]
|
#[frame_support::pallet]
|
||||||
mod pallet {
|
mod pallet {
|
||||||
use sp_core::sr25519::Public;
|
use sp_core::sr25519::Public;
|
||||||
|
use sp_application_crypto::RuntimePublic;
|
||||||
|
|
||||||
use frame_system::pallet_prelude::*;
|
use frame_system::pallet_prelude::*;
|
||||||
use frame_support::{pallet_prelude::*, traits::OneSessionHandler};
|
use frame_support::{pallet_prelude::*, traits::OneSessionHandler};
|
||||||
@@ -35,13 +36,18 @@ mod pallet {
|
|||||||
network_id::*,
|
network_id::*,
|
||||||
coin::*,
|
coin::*,
|
||||||
balance::*,
|
balance::*,
|
||||||
validator_sets::{Session, ExternalValidatorSet, ValidatorSet, KeyShares as KeySharesStruct},
|
validator_sets::{
|
||||||
|
Session, ExternalValidatorSet, ValidatorSet, KeyShares as KeySharesStruct, SlashReport,
|
||||||
|
},
|
||||||
address::SeraiAddress,
|
address::SeraiAddress,
|
||||||
},
|
},
|
||||||
economic_security::EconomicSecurity,
|
economic_security::EconomicSecurity,
|
||||||
|
validator_sets::{DeallocationTimeline, Event},
|
||||||
};
|
};
|
||||||
|
|
||||||
use serai_coins_pallet::Pallet as Coins;
|
use serai_core_pallet::Pallet as Core;
|
||||||
|
use serai_coins_pallet::AllowMint;
|
||||||
|
type Coins<T> = serai_coins_pallet::Pallet<T, serai_coins_pallet::CoinsInstance>;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@@ -51,6 +57,7 @@ mod pallet {
|
|||||||
+ pallet_session::Config
|
+ pallet_session::Config
|
||||||
+ pallet_babe::Config
|
+ pallet_babe::Config
|
||||||
+ pallet_grandpa::Config
|
+ pallet_grandpa::Config
|
||||||
|
+ serai_core_pallet::Config
|
||||||
+ serai_coins_pallet::Config<serai_coins_pallet::CoinsInstance>
|
+ serai_coins_pallet::Config<serai_coins_pallet::CoinsInstance>
|
||||||
{
|
{
|
||||||
type ShouldEndSession: ShouldEndSession<BlockNumberFor<Self>>;
|
type ShouldEndSession: ShouldEndSession<BlockNumberFor<Self>>;
|
||||||
@@ -58,11 +65,16 @@ mod pallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[pallet::genesis_config]
|
#[pallet::genesis_config]
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct GenesisConfig<T: Config> {
|
pub struct GenesisConfig<T: Config> {
|
||||||
/// List of participants to place in the initial validator sets.
|
/// List of participants to place in the initial validator sets.
|
||||||
pub participants: Vec<(T::AccountId, Vec<SignedEmbeddedEllipticCurveKeys>)>,
|
pub participants: Vec<(T::AccountId, Vec<SignedEmbeddedEllipticCurveKeys>)>,
|
||||||
}
|
}
|
||||||
|
impl<T: Config> Default for GenesisConfig<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { participants: Default::default() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[pallet::pallet]
|
#[pallet::pallet]
|
||||||
pub struct Pallet<T>(PhantomData<T>);
|
pub struct Pallet<T>(PhantomData<T>);
|
||||||
@@ -123,8 +135,12 @@ mod pallet {
|
|||||||
#[pallet::storage]
|
#[pallet::storage]
|
||||||
type DelayedDeallocations<T: Config> =
|
type DelayedDeallocations<T: Config> =
|
||||||
StorageDoubleMap<_, Blake2_128Concat, Public, Identity, Session, Amount, OptionQuery>;
|
StorageDoubleMap<_, Blake2_128Concat, Public, Identity, Session, Amount, OptionQuery>;
|
||||||
|
#[pallet::storage]
|
||||||
|
type PendingSlashReport<T: Config> = StorageMap<_, Identity, ExternalNetworkId, (), OptionQuery>;
|
||||||
|
|
||||||
impl<T: Config> SessionsStorage for Abstractions<T> {
|
impl<T: Config> SessionsStorage for Abstractions<T> {
|
||||||
|
type Config = T;
|
||||||
|
|
||||||
type GenesisValidators = GenesisValidators<T>;
|
type GenesisValidators = GenesisValidators<T>;
|
||||||
type AllocationPerKeyShare = AllocationPerKeyShare<T>;
|
type AllocationPerKeyShare = AllocationPerKeyShare<T>;
|
||||||
type CurrentSession = CurrentSession<T>;
|
type CurrentSession = CurrentSession<T>;
|
||||||
@@ -133,6 +149,7 @@ mod pallet {
|
|||||||
type SelectedValidators = SelectedValidators<T>;
|
type SelectedValidators = SelectedValidators<T>;
|
||||||
type TotalAllocatedStake = TotalAllocatedStake<T>;
|
type TotalAllocatedStake = TotalAllocatedStake<T>;
|
||||||
type DelayedDeallocations = DelayedDeallocations<T>;
|
type DelayedDeallocations = DelayedDeallocations<T>;
|
||||||
|
type PendingSlashReport = PendingSlashReport<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Satisfy the `Keys` abstractions
|
// Satisfy the `Keys` abstractions
|
||||||
@@ -148,51 +165,6 @@ mod pallet {
|
|||||||
type ExternalKeys = ExternalKeys<T>;
|
type ExternalKeys = ExternalKeys<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO
|
|
||||||
/// The key for validator sets which can (and still need to) publish their slash reports.
|
|
||||||
#[pallet::storage]
|
|
||||||
pub type PendingSlashReport<T: Config> =
|
|
||||||
StorageMap<_, Identity, ExternalNetworkId, Public, OptionQuery>;
|
|
||||||
|
|
||||||
#[pallet::event]
|
|
||||||
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
|
||||||
pub enum Event<T: Config> {
|
|
||||||
NewSet {
|
|
||||||
set: ValidatorSet,
|
|
||||||
},
|
|
||||||
ParticipantRemoved {
|
|
||||||
set: ValidatorSet,
|
|
||||||
removed: T::AccountId,
|
|
||||||
},
|
|
||||||
KeyGen {
|
|
||||||
set: ExternalValidatorSet,
|
|
||||||
key_pair: KeyPair,
|
|
||||||
},
|
|
||||||
AcceptedHandover {
|
|
||||||
set: ValidatorSet,
|
|
||||||
},
|
|
||||||
SetRetired {
|
|
||||||
set: ValidatorSet,
|
|
||||||
},
|
|
||||||
AllocationIncreased {
|
|
||||||
validator: T::AccountId,
|
|
||||||
network: NetworkId,
|
|
||||||
amount: Amount,
|
|
||||||
},
|
|
||||||
AllocationDecreased {
|
|
||||||
validator: T::AccountId,
|
|
||||||
network: NetworkId,
|
|
||||||
amount: Amount,
|
|
||||||
delayed_until: Option<Session>,
|
|
||||||
},
|
|
||||||
DeallocationClaimed {
|
|
||||||
validator: T::AccountId,
|
|
||||||
network: NetworkId,
|
|
||||||
session: Session,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#[pallet::error]
|
#[pallet::error]
|
||||||
pub enum Error<T> {
|
pub enum Error<T> {
|
||||||
/// The provided embedded elliptic curve keys were invalid.
|
/// The provided embedded elliptic curve keys were invalid.
|
||||||
@@ -308,116 +280,28 @@ mod pallet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO
|
/// The required amount of stake for a balance.
|
||||||
/// Decreases a validator's allocation to a set.
|
fn stake_requirement(balance: ExternalBalance) -> AmountRepr {
|
||||||
///
|
let value = T::EconomicSecurity::sri_value(balance).0;
|
||||||
/// Errors if the capacity provided by this allocation is in use.
|
// As 67% can misbehave, 67% of stake must be sufficient to secure this
|
||||||
///
|
let requirement = value.saturating_mul(3) / 2;
|
||||||
/// Errors if a partial decrease of allocation which puts the remaining allocation below the
|
// We add an additional margin of 20%
|
||||||
/// minimum requirement.
|
let margin = requirement / 5;
|
||||||
///
|
requirement.saturating_add(margin)
|
||||||
/// The capacity prior provided by the allocation is immediately removed, in order to ensure it
|
|
||||||
/// doesn't become used (preventing deallocation).
|
|
||||||
///
|
|
||||||
/// Returns if the amount is immediately eligible for deallocation.
|
|
||||||
fn decrease_allocation(
|
|
||||||
network: NetworkId,
|
|
||||||
account: T::AccountId,
|
|
||||||
amount: Amount,
|
|
||||||
) -> Result<bool, DispatchError> {
|
|
||||||
// Check it's safe to decrease this set's stake by this amount
|
|
||||||
if let NetworkId::External(n) = network {
|
|
||||||
let new_total_staked = Self::total_allocated_stake(NetworkId::from(n))
|
|
||||||
.unwrap()
|
|
||||||
.0
|
|
||||||
.checked_sub(amount.0)
|
|
||||||
.ok_or(Error::<T>::NotEnoughAllocated)?;
|
|
||||||
let required_stake = Self::required_stake_for_network(n);
|
|
||||||
if new_total_staked < required_stake {
|
|
||||||
Err(Error::<T>::DeallocationWouldRemoveEconomicSecurity)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let decreased_key_shares =
|
/// The required amount of stake for a network.
|
||||||
(old_allocation / allocation_per_key_share) > (new_allocation / allocation_per_key_share);
|
fn network_stake_requirement(network: ExternalNetworkId) -> AmountRepr {
|
||||||
|
let mut requirement = AmountRepr::zero();
|
||||||
// If this decreases the validator's key shares, error if the new set is unable to handle
|
|
||||||
// byzantine faults
|
|
||||||
let mut was_bft = None;
|
|
||||||
if decreased_key_shares {
|
|
||||||
was_bft = Some(Self::is_bft(network));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(was_bft) = was_bft {
|
|
||||||
if was_bft && (!Self::is_bft(network)) {
|
|
||||||
Err(Error::<T>::DeallocationWouldRemoveFaultTolerance)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Sessions::<T>::decrease_allocation(network, account, amount)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: This is called retire_set, yet just starts retiring the set
|
|
||||||
// Update the nomenclature within this function
|
|
||||||
pub fn retire_set(set: ValidatorSet) {
|
|
||||||
// Serai doesn't set keys and network slashes are handled by BABE/GRANDPA
|
|
||||||
if let NetworkId::External(n) = set.network {
|
|
||||||
// If the prior prior set didn't report, emit they're retired now
|
|
||||||
if PendingSlashReport::<T>::get(n).is_some() {
|
|
||||||
Self::deposit_event(Event::SetRetired {
|
|
||||||
set: ValidatorSet { network: set.network, session: Session(set.session.0 - 1) },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// This overwrites the prior value as the prior to-report set's stake presumably just
|
|
||||||
// unlocked, making their report unenforceable
|
|
||||||
let keys =
|
|
||||||
Keys::<T>::take(ExternalValidatorSet { network: n, session: set.session }).unwrap();
|
|
||||||
PendingSlashReport::<T>::set(n, Some(keys.0));
|
|
||||||
} else {
|
|
||||||
// emit the event for serai network
|
|
||||||
Self::deposit_event(Event::SetRetired { set });
|
|
||||||
}
|
|
||||||
|
|
||||||
// We're retiring this set because the set after it accepted the handover
|
|
||||||
Self::deposit_event(Event::AcceptedHandover {
|
|
||||||
set: ValidatorSet { network: set.network, session: Session(set.session.0 + 1) },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the required stake in terms SRI for a given `Balance`.
|
|
||||||
pub fn required_stake(balance: &ExternalBalance) -> SubstrateAmount {
|
|
||||||
use dex_pallet::HigherPrecisionBalance;
|
|
||||||
|
|
||||||
// This is inclusive to an increase in accuracy
|
|
||||||
let sri_per_coin = Dex::<T>::security_oracle_value(balance.coin).unwrap_or(Amount(0));
|
|
||||||
|
|
||||||
// See dex-pallet for the reasoning on these
|
|
||||||
let coin_decimals = balance.coin.decimals().max(5);
|
|
||||||
let accuracy_increase = HigherPrecisionBalance::from(SubstrateAmount::pow(10, coin_decimals));
|
|
||||||
|
|
||||||
let total_coin_value = u64::try_from(
|
|
||||||
HigherPrecisionBalance::from(balance.amount.0) *
|
|
||||||
HigherPrecisionBalance::from(sri_per_coin.0) /
|
|
||||||
accuracy_increase,
|
|
||||||
)
|
|
||||||
.unwrap_or(u64::MAX);
|
|
||||||
|
|
||||||
// required stake formula (COIN_VALUE * 1.5) + margin(20%)
|
|
||||||
let required_stake = total_coin_value.saturating_mul(3).saturating_div(2);
|
|
||||||
required_stake.saturating_add(total_coin_value.saturating_div(5))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the current total required stake for a given `network`.
|
|
||||||
pub fn required_stake_for_network(network: ExternalNetworkId) -> SubstrateAmount {
|
|
||||||
let mut total_required = 0;
|
|
||||||
for coin in network.coins() {
|
for coin in network.coins() {
|
||||||
let supply = Coins::<T>::supply(Coin::from(coin));
|
let supply = Coins::<T>::supply(Coin::from(coin));
|
||||||
total_required += Self::required_stake(&ExternalBalance { coin, amount: Amount(supply) });
|
requirement = requirement
|
||||||
|
.saturating_add(Self::stake_requirement(ExternalBalance { coin, amount: supply }));
|
||||||
}
|
}
|
||||||
total_required
|
requirement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO
|
||||||
pub fn distribute_block_rewards(
|
pub fn distribute_block_rewards(
|
||||||
network: NetworkId,
|
network: NetworkId,
|
||||||
account: T::AccountId,
|
account: T::AccountId,
|
||||||
@@ -541,7 +425,9 @@ mod pallet {
|
|||||||
let session = Self::current_session(NetworkId::from(network))
|
let session = Self::current_session(NetworkId::from(network))
|
||||||
.expect("validated `set_keys` for a non-existent session");
|
.expect("validated `set_keys` for a non-existent session");
|
||||||
let set = ExternalValidatorSet { network, session };
|
let set = ExternalValidatorSet { network, session };
|
||||||
Abstractions::<T>::set_keys(set, key_pair);
|
Abstractions::<T>::set_keys(set, key_pair.clone());
|
||||||
|
|
||||||
|
Core::<T>::emit_event(Event::SetKeys { set, key_pair });
|
||||||
|
|
||||||
// If this is the first session of an external network, mark them current, not solely decided
|
// If this is the first session of an external network, mark them current, not solely decided
|
||||||
if session == Session(0) {
|
if session == Session(0) {
|
||||||
@@ -551,7 +437,6 @@ mod pallet {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO
|
|
||||||
#[pallet::call_index(1)]
|
#[pallet::call_index(1)]
|
||||||
#[pallet::weight((0, DispatchClass::Operational))] // TODO
|
#[pallet::weight((0, DispatchClass::Operational))] // TODO
|
||||||
pub fn report_slashes(
|
pub fn report_slashes(
|
||||||
@@ -562,24 +447,13 @@ mod pallet {
|
|||||||
) -> DispatchResult {
|
) -> DispatchResult {
|
||||||
ensure_none(origin)?;
|
ensure_none(origin)?;
|
||||||
|
|
||||||
// signature isn't checked as this is an unsigned transaction, and validate_unsigned
|
// `signature` is checked within `ValidateUnsigned`
|
||||||
// (called by pre_dispatch) checks it
|
|
||||||
let _ = signature;
|
let _ = signature;
|
||||||
|
|
||||||
// TODO: Handle slashes
|
Abstractions::<T>::handle_slash_report(network, slashes);
|
||||||
let _ = slashes;
|
|
||||||
|
|
||||||
// Emit set retireed
|
|
||||||
Pallet::<T>::deposit_event(Event::SetRetired {
|
|
||||||
set: ValidatorSet {
|
|
||||||
network: network.into(),
|
|
||||||
session: Session(Self::session(NetworkId::from(network)).unwrap().0 - 1),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
#[pallet::call_index(2)]
|
#[pallet::call_index(2)]
|
||||||
#[pallet::weight((0, DispatchClass::Normal))] // TODO
|
#[pallet::weight((0, DispatchClass::Normal))] // TODO
|
||||||
@@ -587,11 +461,16 @@ mod pallet {
|
|||||||
origin: OriginFor<T>,
|
origin: OriginFor<T>,
|
||||||
keys: SignedEmbeddedEllipticCurveKeys,
|
keys: SignedEmbeddedEllipticCurveKeys,
|
||||||
) -> DispatchResult {
|
) -> DispatchResult {
|
||||||
let signer = ensure_signed(origin)?;
|
let validator = ensure_signed(origin)?;
|
||||||
|
let network = keys.network();
|
||||||
<Abstractions<T> as crate::EmbeddedEllipticCurveKeys>::set_embedded_elliptic_curve_keys(
|
<Abstractions<T> as crate::EmbeddedEllipticCurveKeys>::set_embedded_elliptic_curve_keys(
|
||||||
signer, keys,
|
validator, keys,
|
||||||
)
|
)
|
||||||
.map_err(|()| Error::<T>::InvalidEmbeddedEllipticCurveKeys)?;
|
.map_err(|()| Error::<T>::InvalidEmbeddedEllipticCurveKeys)?;
|
||||||
|
Core::<T>::emit_event(Event::SetEmbeddedEllipticCurveKeys {
|
||||||
|
validator: validator.into(),
|
||||||
|
network,
|
||||||
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,11 +478,7 @@ mod pallet {
|
|||||||
#[pallet::weight((0, DispatchClass::Normal))] // TODO
|
#[pallet::weight((0, DispatchClass::Normal))] // TODO
|
||||||
pub fn allocate(origin: OriginFor<T>, network: NetworkId, amount: Amount) -> DispatchResult {
|
pub fn allocate(origin: OriginFor<T>, network: NetworkId, amount: Amount) -> DispatchResult {
|
||||||
let validator = ensure_signed(origin)?;
|
let validator = ensure_signed(origin)?;
|
||||||
Coins::<T, serai_coins_pallet::CoinsInstance>::transfer_fn(
|
Coins::<T>::transfer_fn(validator, Self::account(), Balance { coin: Coin::Serai, amount })?;
|
||||||
validator,
|
|
||||||
Self::account(),
|
|
||||||
Balance { coin: Coin::Serai, amount },
|
|
||||||
)?;
|
|
||||||
Abstractions::<T>::increase_allocation(network, validator, amount, false)
|
Abstractions::<T>::increase_allocation(network, validator, amount, false)
|
||||||
.map_err(Error::<T>::AllocationError)?;
|
.map_err(Error::<T>::AllocationError)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -612,16 +487,20 @@ mod pallet {
|
|||||||
#[pallet::call_index(4)]
|
#[pallet::call_index(4)]
|
||||||
#[pallet::weight((0, DispatchClass::Normal))] // TODO
|
#[pallet::weight((0, DispatchClass::Normal))] // TODO
|
||||||
pub fn deallocate(origin: OriginFor<T>, network: NetworkId, amount: Amount) -> DispatchResult {
|
pub fn deallocate(origin: OriginFor<T>, network: NetworkId, amount: Amount) -> DispatchResult {
|
||||||
let account = ensure_signed(origin)?;
|
let validator = ensure_signed(origin)?;
|
||||||
|
|
||||||
let deallocation_timeline = Abstractions::<T>::decrease_allocation(network, account, amount)
|
let timeline = Abstractions::<T>::decrease_allocation(network, validator, amount)
|
||||||
.map_err(Error::<T>::DeallocationError)?;
|
.map_err(Error::<T>::DeallocationError)?;
|
||||||
if matches!(deallocation_timeline, DeallocationTimeline::Immediate) {
|
|
||||||
Coins::<T, serai_coins_pallet::CoinsInstance>::transfer_fn(
|
Core::<T>::emit_event(Event::Deallocation {
|
||||||
Self::account(),
|
validator: validator.into(),
|
||||||
account,
|
network,
|
||||||
Balance { coin: Coin::Serai, amount },
|
amount,
|
||||||
)?;
|
timeline,
|
||||||
|
});
|
||||||
|
|
||||||
|
if matches!(timeline, DeallocationTimeline::Immediate) {
|
||||||
|
Coins::<T>::transfer_fn(Self::account(), validator, Balance { coin: Coin::Serai, amount })?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -634,14 +513,16 @@ mod pallet {
|
|||||||
network: NetworkId,
|
network: NetworkId,
|
||||||
session: Session,
|
session: Session,
|
||||||
) -> DispatchResult {
|
) -> DispatchResult {
|
||||||
let account = ensure_signed(origin)?;
|
let validator = ensure_signed(origin)?;
|
||||||
let amount = Abstractions::<T>::claim_delayed_deallocation(account, network, session)
|
let amount = Abstractions::<T>::claim_delayed_deallocation(validator, network, session)
|
||||||
.map_err(Error::<T>::DeallocationError)?;
|
.map_err(Error::<T>::DeallocationError)?;
|
||||||
Coins::<T, serai_coins_pallet::CoinsInstance>::transfer_fn(
|
|
||||||
Self::account(),
|
Core::<T>::emit_event(Event::DelayedDeallocationClaimed {
|
||||||
account,
|
validator: validator.into(),
|
||||||
Balance { coin: Coin::Serai, amount },
|
deallocation: ValidatorSet { network, session },
|
||||||
)?;
|
});
|
||||||
|
|
||||||
|
Coins::<T>::transfer_fn(Self::account(), validator, Balance { coin: Coin::Serai, amount })?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -705,7 +586,6 @@ mod pallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify the signature with the MuSig key of the signers
|
// Verify the signature with the MuSig key of the signers
|
||||||
use sp_application_crypto::RuntimePublic;
|
|
||||||
if !set.musig_key(&signers).verify(&set.set_keys_message(key_pair), &signature.0.into()) {
|
if !set.musig_key(&signers).verify(&set.set_keys_message(key_pair), &signature.0.into()) {
|
||||||
Err(InvalidTransaction::BadProof)?;
|
Err(InvalidTransaction::BadProof)?;
|
||||||
}
|
}
|
||||||
@@ -716,30 +596,23 @@ mod pallet {
|
|||||||
.propagate(true)
|
.propagate(true)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
/* TODO
|
|
||||||
Call::report_slashes { network, ref slashes, ref signature } => {
|
Call::report_slashes { network, ref slashes, ref signature } => {
|
||||||
let network = *network;
|
let network = *network;
|
||||||
let Some(key) = PendingSlashReport::<T>::take(network) else {
|
|
||||||
// Assumed already published
|
let Some(key) = Abstractions::<T>::waiting_for_slash_report(network) else {
|
||||||
Err(InvalidTransaction::Stale)?
|
Err(InvalidTransaction::Stale)?
|
||||||
};
|
};
|
||||||
|
|
||||||
// There must have been a previous session is PendingSlashReport is populated
|
if !key.verify(&slashes.report_slashes_message(), &signature.0.into()) {
|
||||||
let set = ExternalValidatorSet {
|
|
||||||
network,
|
|
||||||
session: Session(Self::session(NetworkId::from(network)).unwrap().0 - 1),
|
|
||||||
};
|
|
||||||
if !key.verify(&slashes.report_slashes_message(), signature) {
|
|
||||||
Err(InvalidTransaction::BadProof)?;
|
Err(InvalidTransaction::BadProof)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
ValidTransaction::with_tag_prefix("ValidatorSets")
|
ValidTransaction::with_tag_prefix("ValidatorSets")
|
||||||
.and_provides((1, set))
|
.and_provides((1, key))
|
||||||
.longevity(MAX_KEY_SHARES_PER_SET_U32.into())
|
.longevity(KeySharesStruct::MAX_PER_SET_U32.into())
|
||||||
.propagate(true)
|
.propagate(true)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
Call::set_embedded_elliptic_curve_keys { .. } |
|
Call::set_embedded_elliptic_curve_keys { .. } |
|
||||||
Call::allocate { .. } |
|
Call::allocate { .. } |
|
||||||
Call::deallocate { .. } |
|
Call::deallocate { .. } |
|
||||||
@@ -754,20 +627,20 @@ mod pallet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO
|
/*
|
||||||
|
TODO: Add an intent. While we shouldn't allow `Transfer`, `AddLiquidity` when we're within a
|
||||||
|
certain range of the limit, we should still allow swaps.
|
||||||
|
*/
|
||||||
impl<T: Config> AllowMint for Pallet<T> {
|
impl<T: Config> AllowMint for Pallet<T> {
|
||||||
fn is_allowed(balance: &ExternalBalance) -> bool {
|
fn is_allowed(balance: &ExternalBalance) -> bool {
|
||||||
// get the required stake
|
let current_requirement = Self::network_stake_requirement(balance.coin.network());
|
||||||
let current_required = Self::required_stake_for_network(balance.coin.network());
|
let new_requirement = current_requirement.saturating_add(Self::stake_requirement(*balance));
|
||||||
let new_required = current_required + Self::required_stake(balance);
|
|
||||||
|
|
||||||
// get the total stake for the network & compare.
|
|
||||||
let staked =
|
let staked =
|
||||||
Self::total_allocated_stake(NetworkId::from(balance.coin.network())).unwrap_or(Amount(0));
|
Abstractions::<T>::stake_for_current_validator_set(balance.coin.network().into())
|
||||||
staked.0 >= new_required
|
.unwrap_or(Amount(0));
|
||||||
|
staked.0 >= new_requirement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
pub use pallet::*;
|
pub use pallet::*;
|
||||||
|
|
||||||
|
|||||||
@@ -1,217 +0,0 @@
|
|||||||
//! Test environment for ValidatorSets pallet.
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use frame_support::{
|
|
||||||
construct_runtime,
|
|
||||||
traits::{ConstU16, ConstU32, ConstU64},
|
|
||||||
};
|
|
||||||
|
|
||||||
use sp_core::{
|
|
||||||
H256, Pair as PairTrait,
|
|
||||||
sr25519::{Public, Pair},
|
|
||||||
};
|
|
||||||
use sp_runtime::{
|
|
||||||
traits::{BlakeTwo256, IdentityLookup},
|
|
||||||
BuildStorage,
|
|
||||||
};
|
|
||||||
|
|
||||||
use serai_abi::primitives::*;
|
|
||||||
use validator_sets::{primitives::MAX_KEY_SHARES_PER_SET_U32, MembershipProof};
|
|
||||||
|
|
||||||
pub use crate as validator_sets;
|
|
||||||
pub use serai_coins_pallet as coins;
|
|
||||||
pub use dex_pallet as dex;
|
|
||||||
pub use pallet_babe as babe;
|
|
||||||
pub use pallet_grandpa as grandpa;
|
|
||||||
pub use pallet_timestamp as timestamp;
|
|
||||||
|
|
||||||
type Block = frame_system::mocking::MockBlock<Test>;
|
|
||||||
// Maximum number of authorities per session.
|
|
||||||
pub type MaxAuthorities = ConstU32<{ MAX_KEY_SHARES_PER_SET_U32 }>;
|
|
||||||
|
|
||||||
pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4);
|
|
||||||
pub const BABE_GENESIS_EPOCH_CONFIG: sp_consensus_babe::BabeEpochConfiguration =
|
|
||||||
sp_consensus_babe::BabeEpochConfiguration {
|
|
||||||
c: PRIMARY_PROBABILITY,
|
|
||||||
allowed_slots: sp_consensus_babe::AllowedSlots::PrimaryAndSecondaryPlainSlots,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const MEDIAN_PRICE_WINDOW_LENGTH: u16 = 10;
|
|
||||||
|
|
||||||
construct_runtime!(
|
|
||||||
pub enum Test
|
|
||||||
{
|
|
||||||
System: frame_system,
|
|
||||||
Timestamp: timestamp,
|
|
||||||
Coins: coins,
|
|
||||||
LiquidityTokens: coins::<Instance1>::{Pallet, Call, Storage, Event<T>},
|
|
||||||
ValidatorSets: validator_sets,
|
|
||||||
Dex: dex,
|
|
||||||
Babe: babe,
|
|
||||||
Grandpa: grandpa,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
|
||||||
type BaseCallFilter = frame_support::traits::Everything;
|
|
||||||
type BlockWeights = ();
|
|
||||||
type BlockLength = ();
|
|
||||||
type RuntimeOrigin = RuntimeOrigin;
|
|
||||||
type RuntimeCall = RuntimeCall;
|
|
||||||
type Nonce = u64;
|
|
||||||
type Hash = H256;
|
|
||||||
type Hashing = BlakeTwo256;
|
|
||||||
type AccountId = Public;
|
|
||||||
type Lookup = IdentityLookup<Self::AccountId>;
|
|
||||||
type Block = Block;
|
|
||||||
type RuntimeEvent = RuntimeEvent;
|
|
||||||
type BlockHashCount = ConstU64<250>;
|
|
||||||
type DbWeight = ();
|
|
||||||
type Version = ();
|
|
||||||
type PalletInfo = PalletInfo;
|
|
||||||
type AccountData = ();
|
|
||||||
type OnNewAccount = ();
|
|
||||||
type OnKilledAccount = ();
|
|
||||||
type SystemWeightInfo = ();
|
|
||||||
type SS58Prefix = ();
|
|
||||||
type OnSetCode = ();
|
|
||||||
type MaxConsumers = ConstU32<16>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl timestamp::Config for Test {
|
|
||||||
type Moment = u64;
|
|
||||||
type OnTimestampSet = Babe;
|
|
||||||
type MinimumPeriod = ConstU64<{ (TARGET_BLOCK_TIME * 1000) / 2 }>;
|
|
||||||
type WeightInfo = ();
|
|
||||||
}
|
|
||||||
|
|
||||||
impl babe::Config for Test {
|
|
||||||
type EpochDuration = ConstU64<{ FAST_EPOCH_DURATION }>;
|
|
||||||
|
|
||||||
type ExpectedBlockTime = ConstU64<{ TARGET_BLOCK_TIME * 1000 }>;
|
|
||||||
type EpochChangeTrigger = babe::ExternalTrigger;
|
|
||||||
type DisabledValidators = ValidatorSets;
|
|
||||||
|
|
||||||
type WeightInfo = ();
|
|
||||||
type MaxAuthorities = MaxAuthorities;
|
|
||||||
|
|
||||||
type KeyOwnerProof = MembershipProof<Self>;
|
|
||||||
type EquivocationReportSystem = ();
|
|
||||||
}
|
|
||||||
|
|
||||||
impl grandpa::Config for Test {
|
|
||||||
type RuntimeEvent = RuntimeEvent;
|
|
||||||
|
|
||||||
type WeightInfo = ();
|
|
||||||
type MaxAuthorities = MaxAuthorities;
|
|
||||||
|
|
||||||
type MaxSetIdSessionEntries = ConstU64<0>;
|
|
||||||
type KeyOwnerProof = MembershipProof<Self>;
|
|
||||||
type EquivocationReportSystem = ();
|
|
||||||
}
|
|
||||||
|
|
||||||
impl coins::Config for Test {
|
|
||||||
type RuntimeEvent = RuntimeEvent;
|
|
||||||
type AllowMint = ValidatorSets;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl coins::Config<coins::Instance1> for Test {
|
|
||||||
type RuntimeEvent = RuntimeEvent;
|
|
||||||
type AllowMint = ();
|
|
||||||
}
|
|
||||||
|
|
||||||
impl dex::Config for Test {
|
|
||||||
type RuntimeEvent = RuntimeEvent;
|
|
||||||
|
|
||||||
type LPFee = ConstU32<3>; // 0.3%
|
|
||||||
type MintMinLiquidity = ConstU64<10000>;
|
|
||||||
|
|
||||||
type MaxSwapPathLength = ConstU32<3>; // coin1 -> SRI -> coin2
|
|
||||||
|
|
||||||
type MedianPriceWindowLength = ConstU16<{ MEDIAN_PRICE_WINDOW_LENGTH }>;
|
|
||||||
|
|
||||||
type WeightInfo = dex::weights::SubstrateWeight<Test>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Config for Test {
|
|
||||||
type RuntimeEvent = RuntimeEvent;
|
|
||||||
type ShouldEndSession = Babe;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For a const we can't define
|
|
||||||
pub fn genesis_participants() -> Vec<Pair> {
|
|
||||||
vec![
|
|
||||||
insecure_pair_from_name("Alice"),
|
|
||||||
insecure_pair_from_name("Bob"),
|
|
||||||
insecure_pair_from_name("Charlie"),
|
|
||||||
insecure_pair_from_name("Dave"),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Amounts for single key share per network
|
|
||||||
pub fn key_shares() -> HashMap<NetworkId, Amount> {
|
|
||||||
HashMap::from([
|
|
||||||
(NetworkId::Serai, Amount(50_000 * 10_u64.pow(8))),
|
|
||||||
(NetworkId::External(ExternalNetworkId::Bitcoin), Amount(1_000_000 * 10_u64.pow(8))),
|
|
||||||
(NetworkId::External(ExternalNetworkId::Ethereum), Amount(1_000_000 * 10_u64.pow(8))),
|
|
||||||
(NetworkId::External(ExternalNetworkId::Monero), Amount(100_000 * 10_u64.pow(8))),
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn new_test_ext() -> sp_io::TestExternalities {
|
|
||||||
let mut t = frame_system::GenesisConfig::<Test>::default().build_storage().unwrap();
|
|
||||||
let networks: Vec<(NetworkId, Amount)> = key_shares().into_iter().collect::<Vec<_>>();
|
|
||||||
|
|
||||||
coins::GenesisConfig::<Test> {
|
|
||||||
accounts: genesis_participants()
|
|
||||||
.clone()
|
|
||||||
.into_iter()
|
|
||||||
.map(|a| (a.public(), Balance { coin: Coin::Serai, amount: Amount(1 << 60) }))
|
|
||||||
.collect(),
|
|
||||||
_ignore: Default::default(),
|
|
||||||
}
|
|
||||||
.assimilate_storage(&mut t)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
#[expect(unused_variables, unreachable_code, clippy::diverging_sub_expression)]
|
|
||||||
validator_sets::GenesisConfig::<Test> {
|
|
||||||
networks,
|
|
||||||
participants: genesis_participants()
|
|
||||||
.into_iter()
|
|
||||||
.map(|p| {
|
|
||||||
let keys: crate::AllEmbeddedEllipticCurveKeysAtGenesis = todo!("TODO");
|
|
||||||
(p.public(), keys)
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
}
|
|
||||||
.assimilate_storage(&mut t)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
babe::GenesisConfig::<Test> {
|
|
||||||
authorities: genesis_participants()
|
|
||||||
.into_iter()
|
|
||||||
.map(|validator| (validator.public().into(), 1))
|
|
||||||
.collect(),
|
|
||||||
epoch_config: Some(BABE_GENESIS_EPOCH_CONFIG),
|
|
||||||
_config: PhantomData,
|
|
||||||
}
|
|
||||||
.assimilate_storage(&mut t)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
grandpa::GenesisConfig::<Test> {
|
|
||||||
authorities: genesis_participants()
|
|
||||||
.into_iter()
|
|
||||||
.map(|validator| (validator.public().into(), 1))
|
|
||||||
.collect(),
|
|
||||||
_config: PhantomData,
|
|
||||||
}
|
|
||||||
.assimilate_storage(&mut t)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut ext = sp_io::TestExternalities::new(t);
|
|
||||||
ext.execute_with(|| System::set_block_number(0));
|
|
||||||
ext
|
|
||||||
}
|
|
||||||
@@ -1,14 +1,21 @@
|
|||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use sp_core::{Encode, Decode, ConstU32, sr25519::Public, bounded::BoundedVec};
|
use sp_core::{Encode, Decode, ConstU32, sr25519::Public, bounded::BoundedVec};
|
||||||
|
|
||||||
use serai_abi::primitives::{
|
use serai_abi::{
|
||||||
network_id::NetworkId,
|
primitives::{
|
||||||
|
network_id::{ExternalNetworkId, NetworkId},
|
||||||
balance::Amount,
|
balance::Amount,
|
||||||
validator_sets::{KeyShares as KeySharesStruct, Session, ExternalValidatorSet, ValidatorSet},
|
validator_sets::{
|
||||||
|
KeyShares as KeySharesStruct, Session, ExternalValidatorSet, ValidatorSet, SlashReport,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
validator_sets::{DeallocationTimeline, Event},
|
||||||
};
|
};
|
||||||
|
|
||||||
use frame_support::storage::{StorageValue, StorageMap, StorageDoubleMap, StoragePrefixedMap};
|
use frame_support::storage::{StorageValue, StorageMap, StorageDoubleMap, StoragePrefixedMap};
|
||||||
|
|
||||||
|
use serai_core_pallet::Pallet as Core;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
embedded_elliptic_curve_keys::EmbeddedEllipticCurveKeys, allocations::Allocations, keys::Keys,
|
embedded_elliptic_curve_keys::EmbeddedEllipticCurveKeys, allocations::Allocations, keys::Keys,
|
||||||
};
|
};
|
||||||
@@ -21,6 +28,9 @@ pub(crate) type GenesisValidators =
|
|||||||
pub(crate) type SelectedValidatorsKey = (ValidatorSet, [u8; 16], Public);
|
pub(crate) type SelectedValidatorsKey = (ValidatorSet, [u8; 16], Public);
|
||||||
|
|
||||||
pub(crate) trait SessionsStorage: EmbeddedEllipticCurveKeys + Allocations + Keys {
|
pub(crate) trait SessionsStorage: EmbeddedEllipticCurveKeys + Allocations + Keys {
|
||||||
|
/// The configuration for the core pallet.
|
||||||
|
type Config: serai_core_pallet::Config;
|
||||||
|
|
||||||
/// The genesis validators
|
/// The genesis validators
|
||||||
///
|
///
|
||||||
/// The usage of is shared with the rest of the pallet. `Sessions` only reads it.
|
/// The usage of is shared with the rest of the pallet. `Sessions` only reads it.
|
||||||
@@ -68,6 +78,11 @@ pub(crate) trait SessionsStorage: EmbeddedEllipticCurveKeys + Allocations + Keys
|
|||||||
///
|
///
|
||||||
/// This is opaque and to be exclusively read/write by `Sessions`.
|
/// This is opaque and to be exclusively read/write by `Sessions`.
|
||||||
type DelayedDeallocations: StorageDoubleMap<Public, Session, Amount, Query = Option<Amount>>;
|
type DelayedDeallocations: StorageDoubleMap<Public, Session, Amount, Query = Option<Amount>>;
|
||||||
|
|
||||||
|
/// Networks for which we're awaiting slash reports.
|
||||||
|
///
|
||||||
|
/// This is opaque and to be exclusively read/write by `Sessions`.
|
||||||
|
type PendingSlashReport: StorageMap<ExternalNetworkId, (), Query = Option<()>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The storage key for the SelectedValidators map.
|
/// The storage key for the SelectedValidators map.
|
||||||
@@ -119,11 +134,6 @@ pub enum AllocationError {
|
|||||||
IntroducesSinglePointOfFailure,
|
IntroducesSinglePointOfFailure,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) enum DeallocationTimeline {
|
|
||||||
Immediate,
|
|
||||||
Delayed { unlocks_at: Session },
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An error when deallocating.
|
/// An error when deallocating.
|
||||||
#[derive(
|
#[derive(
|
||||||
scale::Encode, scale::Decode, scale::DecodeWithMemTracking, frame_support::PalletError,
|
scale::Encode, scale::Decode, scale::DecodeWithMemTracking, frame_support::PalletError,
|
||||||
@@ -193,6 +203,11 @@ pub(crate) trait Sessions {
|
|||||||
session: Session,
|
session: Session,
|
||||||
) -> Result<Amount, DeallocationError>;
|
) -> Result<Amount, DeallocationError>;
|
||||||
|
|
||||||
|
/// Handle a slash report.
|
||||||
|
///
|
||||||
|
/// This will panic if this slash report isn't pending.
|
||||||
|
fn handle_slash_report(network: ExternalNetworkId, slashes: SlashReport);
|
||||||
|
|
||||||
/// The currently active session for a network.
|
/// The currently active session for a network.
|
||||||
fn current_session(network: NetworkId) -> Option<Session>;
|
fn current_session(network: NetworkId) -> Option<Session>;
|
||||||
|
|
||||||
@@ -232,6 +247,11 @@ pub(crate) trait Sessions {
|
|||||||
.map(|(validator, _key_shares)| (validator, validator))
|
.map(|(validator, _key_shares)| (validator, validator))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If this network is awaiting a slash report.
|
||||||
|
///
|
||||||
|
/// If so, this returns the key which should publish the slash report.
|
||||||
|
fn waiting_for_slash_report(network: ExternalNetworkId) -> Option<Public>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Storage: SessionsStorage> Sessions for Storage {
|
impl<Storage: SessionsStorage> Sessions for Storage {
|
||||||
@@ -313,11 +333,13 @@ impl<Storage: SessionsStorage> Sessions for Storage {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Core::<Storage::Config>::emit_event(Event::SetDecided { set: latest_decided_set });
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn accept_handover(network: NetworkId) {
|
fn accept_handover(network: NetworkId) {
|
||||||
let current = {
|
let (prior, current) = {
|
||||||
let current = Storage::CurrentSession::get(network);
|
let current = Storage::CurrentSession::get(network);
|
||||||
let latest_decided = Storage::LatestDecidedSession::get(network)
|
let latest_decided = Storage::LatestDecidedSession::get(network)
|
||||||
.expect("accepting handover but never decided a session");
|
.expect("accepting handover but never decided a session");
|
||||||
@@ -328,8 +350,8 @@ impl<Storage: SessionsStorage> Sessions for Storage {
|
|||||||
);
|
);
|
||||||
// Set the CurrentSession variable
|
// Set the CurrentSession variable
|
||||||
Storage::CurrentSession::set(network, Some(latest_decided));
|
Storage::CurrentSession::set(network, Some(latest_decided));
|
||||||
// Return `latest_decided` as `current` as it is now current
|
// Return `latest_decided` as `current` as it is now current, and `current` as `prior`
|
||||||
latest_decided
|
(current, latest_decided)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut total_allocated_stake = Amount(0);
|
let mut total_allocated_stake = Amount(0);
|
||||||
@@ -343,6 +365,23 @@ impl<Storage: SessionsStorage> Sessions for Storage {
|
|||||||
// Update the total allocated stake variable to the current session
|
// Update the total allocated stake variable to the current session
|
||||||
Storage::TotalAllocatedStake::set(network, Some(total_allocated_stake));
|
Storage::TotalAllocatedStake::set(network, Some(total_allocated_stake));
|
||||||
|
|
||||||
|
match network {
|
||||||
|
NetworkId::Serai => {}
|
||||||
|
NetworkId::External(network) => {
|
||||||
|
// If this network never submitted its slash report, treat it as submitting `vec![]`
|
||||||
|
if Storage::PendingSlashReport::take(network).is_some() {
|
||||||
|
Core::<Storage::Config>::emit_event(Event::SlashReport {
|
||||||
|
set: ExternalValidatorSet {
|
||||||
|
network,
|
||||||
|
session: prior.expect("pending slash report yet no prior session"),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Mark this network as pending a slash report
|
||||||
|
Storage::PendingSlashReport::insert(network, ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Clean-up the historic set's storage, if one exists
|
// Clean-up the historic set's storage, if one exists
|
||||||
if let Some(historic_session) = current.0.checked_sub(2).map(Session) {
|
if let Some(historic_session) = current.0.checked_sub(2).map(Session) {
|
||||||
let historic_set = ValidatorSet { network, session: historic_session };
|
let historic_set = ValidatorSet { network, session: historic_session };
|
||||||
@@ -355,6 +394,10 @@ impl<Storage: SessionsStorage> Sessions for Storage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Core::<Storage::Config>::emit_event(Event::AcceptedHandover {
|
||||||
|
set: ValidatorSet { network, session: current },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn increase_allocation(
|
fn increase_allocation(
|
||||||
@@ -437,6 +480,12 @@ impl<Storage: SessionsStorage> Sessions for Storage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Core::<Storage::Config>::emit_event(Event::Allocation {
|
||||||
|
validator: validator.into(),
|
||||||
|
network,
|
||||||
|
amount,
|
||||||
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,6 +494,9 @@ impl<Storage: SessionsStorage> Sessions for Storage {
|
|||||||
validator: Public,
|
validator: Public,
|
||||||
amount: Amount,
|
amount: Amount,
|
||||||
) -> Result<DeallocationTimeline, DeallocationError> {
|
) -> Result<DeallocationTimeline, DeallocationError> {
|
||||||
|
// TODO: Check if this would introduce a single point of failure
|
||||||
|
// TODO: Check if this would violate economic security
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Decrease the allocation.
|
Decrease the allocation.
|
||||||
|
|
||||||
@@ -522,6 +574,22 @@ impl<Storage: SessionsStorage> Sessions for Storage {
|
|||||||
Ok(DeallocationTimeline::Immediate)
|
Ok(DeallocationTimeline::Immediate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_slash_report(network: ExternalNetworkId, _slashes: SlashReport) {
|
||||||
|
Storage::PendingSlashReport::take(network)
|
||||||
|
.expect("handling a slash report which wasn't pending");
|
||||||
|
|
||||||
|
let current_session =
|
||||||
|
Self::current_session(network.into()).expect("handling slash report yet no current session");
|
||||||
|
let prior_session = Session(
|
||||||
|
current_session.0.checked_sub(1).expect("handling slash report yet no prior session"),
|
||||||
|
);
|
||||||
|
Core::<Storage::Config>::emit_event(Event::SlashReport {
|
||||||
|
set: ExternalValidatorSet { network, session: prior_session },
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: Actually handle `_slashes`
|
||||||
|
}
|
||||||
|
|
||||||
fn claim_delayed_deallocation(
|
fn claim_delayed_deallocation(
|
||||||
validator: Public,
|
validator: Public,
|
||||||
network: NetworkId,
|
network: NetworkId,
|
||||||
@@ -566,4 +634,19 @@ impl<Storage: SessionsStorage> Sessions for Storage {
|
|||||||
fn selected_validators(set: ValidatorSet) -> impl Iterator<Item = (Public, KeySharesStruct)> {
|
fn selected_validators(set: ValidatorSet) -> impl Iterator<Item = (Public, KeySharesStruct)> {
|
||||||
selected_validators::<Storage::SelectedValidators>(set)
|
selected_validators::<Storage::SelectedValidators>(set)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn waiting_for_slash_report(network: ExternalNetworkId) -> Option<Public> {
|
||||||
|
if !Storage::PendingSlashReport::contains_key(network) {
|
||||||
|
None?;
|
||||||
|
}
|
||||||
|
let current_session = Self::current_session(network.into())
|
||||||
|
.expect("network awaiting slash report yet no current session");
|
||||||
|
let prior_session = Session(
|
||||||
|
current_session.0.checked_sub(1).expect("network awaiting slash report yet no prior session"),
|
||||||
|
);
|
||||||
|
Some(
|
||||||
|
Storage::oraclization_key(ExternalValidatorSet { network, session: prior_session })
|
||||||
|
.expect("no oraclization key for set waiting for a slash report"),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,558 +0,0 @@
|
|||||||
use crate::{mock::*, primitives::*};
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use ciphersuite::{WrappedGroup, GroupIo};
|
|
||||||
use dkg_musig::musig;
|
|
||||||
use schnorrkel::{frost::curve::Ristretto, Schnorrkel};
|
|
||||||
|
|
||||||
use zeroize::Zeroizing;
|
|
||||||
use rand_core::OsRng;
|
|
||||||
|
|
||||||
use frame_support::{
|
|
||||||
assert_noop, assert_ok,
|
|
||||||
pallet_prelude::{InvalidTransaction, TransactionSource},
|
|
||||||
traits::{OnFinalize, OnInitialize},
|
|
||||||
};
|
|
||||||
use frame_system::RawOrigin;
|
|
||||||
|
|
||||||
use sp_core::{
|
|
||||||
sr25519::{Public, Pair, Signature},
|
|
||||||
Pair as PairTrait,
|
|
||||||
};
|
|
||||||
use sp_runtime::traits::ValidateUnsigned;
|
|
||||||
|
|
||||||
use serai_abi::primitives::*;
|
|
||||||
|
|
||||||
fn active_network_validators(network: NetworkId) -> Vec<(Public, u64)> {
|
|
||||||
if network == NetworkId::Serai {
|
|
||||||
Babe::authorities().into_iter().map(|(id, key_share)| (id.into_inner(), key_share)).collect()
|
|
||||||
} else {
|
|
||||||
ValidatorSets::participants_for_latest_decided_set(network).unwrap().into_inner()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn verify_session_and_active_validators(network: NetworkId, participants: &[Public], session: u32) {
|
|
||||||
let mut validators: Vec<Public> = active_network_validators(network)
|
|
||||||
.into_iter()
|
|
||||||
.map(|(p, ks)| {
|
|
||||||
assert_eq!(ks, 1);
|
|
||||||
p
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
validators.sort();
|
|
||||||
|
|
||||||
assert_eq!(ValidatorSets::session(network).unwrap(), Session(session));
|
|
||||||
assert_eq!(participants, validators);
|
|
||||||
|
|
||||||
// TODO: how to make sure block finalizations work as usual here?
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_session_at_which_changes_activate(network: NetworkId) -> u32 {
|
|
||||||
let current_session = ValidatorSets::session(network).unwrap().0;
|
|
||||||
// changes should be active in the next session
|
|
||||||
if network == NetworkId::Serai {
|
|
||||||
// it takes 1 extra session for serai net to make the changes active.
|
|
||||||
current_session + 2
|
|
||||||
} else {
|
|
||||||
current_session + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_keys_for_session(network: ExternalNetworkId) {
|
|
||||||
ValidatorSets::set_keys(
|
|
||||||
RawOrigin::None.into(),
|
|
||||||
network,
|
|
||||||
KeyPair(insecure_pair_from_name("Alice").public(), vec![].try_into().unwrap()),
|
|
||||||
vec![].try_into().unwrap(),
|
|
||||||
Signature([0u8; 64]),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_keys_signature(set: &ExternalValidatorSet, key_pair: &KeyPair, pairs: &[Pair]) -> Signature {
|
|
||||||
let mut pub_keys = vec![];
|
|
||||||
for pair in pairs {
|
|
||||||
let public_key =
|
|
||||||
<Ristretto as GroupIo>::read_G::<&[u8]>(&mut pair.public().0.as_ref()).unwrap();
|
|
||||||
pub_keys.push(public_key);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut threshold_keys = vec![];
|
|
||||||
for i in 0 .. pairs.len() {
|
|
||||||
let secret_key = <Ristretto as GroupIo>::read_F::<&[u8]>(
|
|
||||||
&mut pairs[i].as_ref().secret.to_bytes()[.. 32].as_ref(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(Ristretto::generator() * secret_key, pub_keys[i]);
|
|
||||||
|
|
||||||
threshold_keys.push(
|
|
||||||
musig::<Ristretto>(musig_context((*set).into()), Zeroizing::new(secret_key), &pub_keys)
|
|
||||||
.unwrap(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut musig_keys = HashMap::new();
|
|
||||||
for threshold_keys in threshold_keys {
|
|
||||||
musig_keys.insert(threshold_keys.params().i(), threshold_keys);
|
|
||||||
}
|
|
||||||
|
|
||||||
let sig = frost::tests::sign_without_caching(
|
|
||||||
&mut OsRng,
|
|
||||||
frost::tests::algorithm_machines(&mut OsRng, &Schnorrkel::new(b"substrate"), &musig_keys),
|
|
||||||
&set_keys_message(set, key_pair),
|
|
||||||
);
|
|
||||||
|
|
||||||
Signature(sig.to_bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_ordered_keys(network: NetworkId, participants: &[Pair]) -> Vec<Pair> {
|
|
||||||
// retrieve the current session validators so that we know the order of the keys
|
|
||||||
// that is necessary for the correct musig signature.
|
|
||||||
let validators = ValidatorSets::participants_for_latest_decided_set(network).unwrap();
|
|
||||||
|
|
||||||
// collect the pairs of the validators
|
|
||||||
let mut pairs = vec![];
|
|
||||||
for (v, _) in validators {
|
|
||||||
let p = participants.iter().find(|pair| pair.public() == v).unwrap().clone();
|
|
||||||
pairs.push(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
pairs
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rotate_session_until(network: NetworkId, session: u32) {
|
|
||||||
let mut current = ValidatorSets::session(network).unwrap().0;
|
|
||||||
while current < session {
|
|
||||||
Babe::on_initialize(System::block_number() + 1);
|
|
||||||
ValidatorSets::rotate_session();
|
|
||||||
if let NetworkId::External(n) = network {
|
|
||||||
set_keys_for_session(n);
|
|
||||||
}
|
|
||||||
ValidatorSets::retire_set(ValidatorSet { session: Session(current), network });
|
|
||||||
current += 1;
|
|
||||||
}
|
|
||||||
assert_eq!(current, session);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn rotate_session() {
|
|
||||||
new_test_ext().execute_with(|| {
|
|
||||||
let genesis_participants: Vec<Public> =
|
|
||||||
genesis_participants().into_iter().map(|p| p.public()).collect();
|
|
||||||
let key_shares = key_shares();
|
|
||||||
|
|
||||||
let mut participants = HashMap::from([
|
|
||||||
(NetworkId::Serai, genesis_participants.clone()),
|
|
||||||
(NetworkId::External(ExternalNetworkId::Bitcoin), genesis_participants.clone()),
|
|
||||||
(NetworkId::External(ExternalNetworkId::Ethereum), genesis_participants.clone()),
|
|
||||||
(NetworkId::External(ExternalNetworkId::Monero), genesis_participants),
|
|
||||||
]);
|
|
||||||
|
|
||||||
// rotate session
|
|
||||||
for network in NETWORKS {
|
|
||||||
let participants = participants.get_mut(&network).unwrap();
|
|
||||||
|
|
||||||
// verify for session 0
|
|
||||||
participants.sort();
|
|
||||||
if let NetworkId::External(n) = network {
|
|
||||||
set_keys_for_session(n);
|
|
||||||
}
|
|
||||||
verify_session_and_active_validators(network, participants, 0);
|
|
||||||
|
|
||||||
// add 1 participant
|
|
||||||
let new_participant = insecure_pair_from_name("new-guy").public();
|
|
||||||
Coins::mint(new_participant, Balance { coin: Coin::Serai, amount: key_shares[&network] })
|
|
||||||
.unwrap();
|
|
||||||
ValidatorSets::allocate(
|
|
||||||
RawOrigin::Signed(new_participant).into(),
|
|
||||||
network,
|
|
||||||
key_shares[&network],
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
participants.push(new_participant);
|
|
||||||
|
|
||||||
// move network to the activation session
|
|
||||||
let activation_session = get_session_at_which_changes_activate(network);
|
|
||||||
rotate_session_until(network, activation_session);
|
|
||||||
|
|
||||||
// verify
|
|
||||||
participants.sort();
|
|
||||||
verify_session_and_active_validators(network, participants, activation_session);
|
|
||||||
|
|
||||||
// remove 1 participant
|
|
||||||
let participant_to_remove = participants[0];
|
|
||||||
ValidatorSets::deallocate(
|
|
||||||
RawOrigin::Signed(participant_to_remove).into(),
|
|
||||||
network,
|
|
||||||
key_shares[&network],
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
participants
|
|
||||||
.swap_remove(participants.iter().position(|k| *k == participant_to_remove).unwrap());
|
|
||||||
|
|
||||||
// check pending deallocations
|
|
||||||
let pending = ValidatorSets::pending_deallocations(
|
|
||||||
(network, participant_to_remove),
|
|
||||||
Session(if network == NetworkId::Serai {
|
|
||||||
activation_session + 3
|
|
||||||
} else {
|
|
||||||
activation_session + 2
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
assert_eq!(pending, Some(key_shares[&network]));
|
|
||||||
|
|
||||||
// move network to the activation session
|
|
||||||
let activation_session = get_session_at_which_changes_activate(network);
|
|
||||||
rotate_session_until(network, activation_session);
|
|
||||||
|
|
||||||
// verify
|
|
||||||
participants.sort();
|
|
||||||
verify_session_and_active_validators(network, participants, activation_session);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn allocate() {
|
|
||||||
new_test_ext().execute_with(|| {
|
|
||||||
let genesis_participants: Vec<Public> =
|
|
||||||
genesis_participants().into_iter().map(|p| p.public()).collect();
|
|
||||||
let key_shares = key_shares();
|
|
||||||
let participant = insecure_pair_from_name("random1").public();
|
|
||||||
let network = NetworkId::External(ExternalNetworkId::Ethereum);
|
|
||||||
|
|
||||||
// check genesis TAS
|
|
||||||
set_keys_for_session(network.try_into().unwrap());
|
|
||||||
assert_eq!(
|
|
||||||
ValidatorSets::total_allocated_stake(network).unwrap().0,
|
|
||||||
key_shares[&network].0 * u64::try_from(genesis_participants.len()).unwrap()
|
|
||||||
);
|
|
||||||
|
|
||||||
// we can't allocate less than a key share
|
|
||||||
let amount = Amount(key_shares[&network].0 * 3);
|
|
||||||
Coins::mint(participant, Balance { coin: Coin::Serai, amount }).unwrap();
|
|
||||||
assert_noop!(
|
|
||||||
ValidatorSets::allocate(
|
|
||||||
RawOrigin::Signed(participant).into(),
|
|
||||||
network,
|
|
||||||
Amount(key_shares[&network].0 - 1)
|
|
||||||
),
|
|
||||||
validator_sets::Error::<Test>::InsufficientAllocation
|
|
||||||
);
|
|
||||||
|
|
||||||
// we can't allocate too much that the net exhibits the ability to handle any single node
|
|
||||||
// becoming byzantine
|
|
||||||
assert_noop!(
|
|
||||||
ValidatorSets::allocate(RawOrigin::Signed(participant).into(), network, amount),
|
|
||||||
validator_sets::Error::<Test>::AllocationWouldRemoveFaultTolerance
|
|
||||||
);
|
|
||||||
|
|
||||||
// we should be allocate a proper amount
|
|
||||||
assert_ok!(ValidatorSets::allocate(
|
|
||||||
RawOrigin::Signed(participant).into(),
|
|
||||||
network,
|
|
||||||
key_shares[&network]
|
|
||||||
));
|
|
||||||
assert_eq!(Coins::balance(participant, Coin::Serai).0, amount.0 - key_shares[&network].0);
|
|
||||||
|
|
||||||
// check new amount is reflected on TAS on new session
|
|
||||||
rotate_session_until(network, 1);
|
|
||||||
assert_eq!(
|
|
||||||
ValidatorSets::total_allocated_stake(network).unwrap().0,
|
|
||||||
key_shares[&network].0 * (u64::try_from(genesis_participants.len()).unwrap() + 1)
|
|
||||||
);
|
|
||||||
|
|
||||||
// check that new participants match
|
|
||||||
let mut active_participants: Vec<Public> =
|
|
||||||
active_network_validators(network).into_iter().map(|(p, _)| p).collect();
|
|
||||||
|
|
||||||
let mut current_participants = genesis_participants.clone();
|
|
||||||
current_participants.push(participant);
|
|
||||||
|
|
||||||
current_participants.sort();
|
|
||||||
active_participants.sort();
|
|
||||||
assert_eq!(current_participants, active_participants);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn deallocate_pending() {
|
|
||||||
new_test_ext().execute_with(|| {
|
|
||||||
let genesis_participants: Vec<Public> =
|
|
||||||
genesis_participants().into_iter().map(|p| p.public()).collect();
|
|
||||||
let key_shares = key_shares();
|
|
||||||
let participant = insecure_pair_from_name("random1").public();
|
|
||||||
let network = NetworkId::External(ExternalNetworkId::Bitcoin);
|
|
||||||
|
|
||||||
// check genesis TAS
|
|
||||||
set_keys_for_session(network.try_into().unwrap());
|
|
||||||
assert_eq!(
|
|
||||||
ValidatorSets::total_allocated_stake(network).unwrap().0,
|
|
||||||
key_shares[&network].0 * u64::try_from(genesis_participants.len()).unwrap()
|
|
||||||
);
|
|
||||||
|
|
||||||
// allocate some amount
|
|
||||||
Coins::mint(participant, Balance { coin: Coin::Serai, amount: key_shares[&network] }).unwrap();
|
|
||||||
assert_ok!(ValidatorSets::allocate(
|
|
||||||
RawOrigin::Signed(participant).into(),
|
|
||||||
network,
|
|
||||||
key_shares[&network]
|
|
||||||
));
|
|
||||||
assert_eq!(Coins::balance(participant, Coin::Serai).0, 0);
|
|
||||||
|
|
||||||
// move to next session
|
|
||||||
let mut current_session = ValidatorSets::session(network).unwrap().0;
|
|
||||||
current_session += 1;
|
|
||||||
rotate_session_until(network, current_session);
|
|
||||||
assert_eq!(
|
|
||||||
ValidatorSets::total_allocated_stake(network).unwrap().0,
|
|
||||||
key_shares[&network].0 * (u64::try_from(genesis_participants.len()).unwrap() + 1)
|
|
||||||
);
|
|
||||||
|
|
||||||
// we can deallocate all of our allocation
|
|
||||||
assert_ok!(ValidatorSets::deallocate(
|
|
||||||
RawOrigin::Signed(participant).into(),
|
|
||||||
network,
|
|
||||||
key_shares[&network]
|
|
||||||
));
|
|
||||||
|
|
||||||
// check pending deallocations
|
|
||||||
let pending_session =
|
|
||||||
if network == NetworkId::Serai { current_session + 3 } else { current_session + 2 };
|
|
||||||
assert_eq!(
|
|
||||||
ValidatorSets::pending_deallocations((network, participant), Session(pending_session)),
|
|
||||||
Some(key_shares[&network])
|
|
||||||
);
|
|
||||||
|
|
||||||
// we can't claim it immediately
|
|
||||||
assert_noop!(
|
|
||||||
ValidatorSets::claim_deallocation(
|
|
||||||
RawOrigin::Signed(participant).into(),
|
|
||||||
network,
|
|
||||||
Session(pending_session),
|
|
||||||
),
|
|
||||||
validator_sets::Error::<Test>::NonExistentDeallocation
|
|
||||||
);
|
|
||||||
|
|
||||||
// we should be able to claim it in the pending session
|
|
||||||
rotate_session_until(network, pending_session);
|
|
||||||
assert_ok!(ValidatorSets::claim_deallocation(
|
|
||||||
RawOrigin::Signed(participant).into(),
|
|
||||||
network,
|
|
||||||
Session(pending_session),
|
|
||||||
));
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn deallocate_immediately() {
|
|
||||||
new_test_ext().execute_with(|| {
|
|
||||||
let genesis_participants: Vec<Public> =
|
|
||||||
genesis_participants().into_iter().map(|p| p.public()).collect();
|
|
||||||
let key_shares = key_shares();
|
|
||||||
let participant = insecure_pair_from_name("random1").public();
|
|
||||||
let network = NetworkId::External(ExternalNetworkId::Monero);
|
|
||||||
|
|
||||||
// check genesis TAS
|
|
||||||
set_keys_for_session(network.try_into().unwrap());
|
|
||||||
assert_eq!(
|
|
||||||
ValidatorSets::total_allocated_stake(network).unwrap().0,
|
|
||||||
key_shares[&network].0 * u64::try_from(genesis_participants.len()).unwrap()
|
|
||||||
);
|
|
||||||
|
|
||||||
// we can't deallocate when we don't have an allocation
|
|
||||||
assert_noop!(
|
|
||||||
ValidatorSets::deallocate(
|
|
||||||
RawOrigin::Signed(participant).into(),
|
|
||||||
network,
|
|
||||||
key_shares[&network]
|
|
||||||
),
|
|
||||||
validator_sets::Error::<Test>::NonExistentValidator
|
|
||||||
);
|
|
||||||
|
|
||||||
// allocate some amount
|
|
||||||
Coins::mint(participant, Balance { coin: Coin::Serai, amount: key_shares[&network] }).unwrap();
|
|
||||||
assert_ok!(ValidatorSets::allocate(
|
|
||||||
RawOrigin::Signed(participant).into(),
|
|
||||||
network,
|
|
||||||
key_shares[&network]
|
|
||||||
));
|
|
||||||
assert_eq!(Coins::balance(participant, Coin::Serai).0, 0);
|
|
||||||
|
|
||||||
// we can't deallocate more than our allocation
|
|
||||||
assert_noop!(
|
|
||||||
ValidatorSets::deallocate(
|
|
||||||
RawOrigin::Signed(participant).into(),
|
|
||||||
network,
|
|
||||||
Amount(key_shares[&network].0 + 1)
|
|
||||||
),
|
|
||||||
validator_sets::Error::<Test>::NotEnoughAllocated
|
|
||||||
);
|
|
||||||
|
|
||||||
// we can't deallocate an amount that would left us less than a key share as long as it isn't 0
|
|
||||||
assert_noop!(
|
|
||||||
ValidatorSets::deallocate(
|
|
||||||
RawOrigin::Signed(participant).into(),
|
|
||||||
network,
|
|
||||||
Amount(key_shares[&network].0 / 2)
|
|
||||||
),
|
|
||||||
validator_sets::Error::<Test>::DeallocationWouldRemoveParticipant
|
|
||||||
);
|
|
||||||
|
|
||||||
// we can deallocate all of our allocation
|
|
||||||
assert_ok!(ValidatorSets::deallocate(
|
|
||||||
RawOrigin::Signed(participant).into(),
|
|
||||||
network,
|
|
||||||
key_shares[&network]
|
|
||||||
));
|
|
||||||
|
|
||||||
// It should be immediately deallocated since we are not yet in an active set
|
|
||||||
assert_eq!(Coins::balance(participant, Coin::Serai), key_shares[&network]);
|
|
||||||
assert!(ValidatorSets::pending_deallocations((network, participant), Session(1)).is_none());
|
|
||||||
|
|
||||||
// allocate again
|
|
||||||
assert_ok!(ValidatorSets::allocate(
|
|
||||||
RawOrigin::Signed(participant).into(),
|
|
||||||
network,
|
|
||||||
key_shares[&network]
|
|
||||||
));
|
|
||||||
assert_eq!(Coins::balance(participant, Coin::Serai).0, 0);
|
|
||||||
|
|
||||||
// make a pool so that we have security oracle value for the coin
|
|
||||||
let liq_acc = insecure_pair_from_name("liq-acc").public();
|
|
||||||
let coin = ExternalCoin::Monero;
|
|
||||||
let balance = ExternalBalance { coin, amount: Amount(2 * key_shares[&network].0) };
|
|
||||||
Coins::mint(liq_acc, balance.into()).unwrap();
|
|
||||||
Coins::mint(liq_acc, Balance { coin: Coin::Serai, amount: balance.amount }).unwrap();
|
|
||||||
Dex::add_liquidity(
|
|
||||||
RawOrigin::Signed(liq_acc).into(),
|
|
||||||
coin,
|
|
||||||
balance.amount.0 / 2,
|
|
||||||
balance.amount.0 / 2,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
liq_acc,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
Dex::on_finalize(1);
|
|
||||||
assert!(Dex::security_oracle_value(coin).unwrap().0 > 0);
|
|
||||||
|
|
||||||
// we can't deallocate if it would break economic security
|
|
||||||
// The reason we don't have economic security for the network now is that we just set
|
|
||||||
// the value for coin/SRI to 1:1 when making the pool and we minted 2 * key_share amount
|
|
||||||
// of coin but we only allocated 1 key_share of SRI for the network although we need more than
|
|
||||||
// 3 for the same amount of coin.
|
|
||||||
assert_noop!(
|
|
||||||
ValidatorSets::deallocate(
|
|
||||||
RawOrigin::Signed(participant).into(),
|
|
||||||
network,
|
|
||||||
key_shares[&network]
|
|
||||||
),
|
|
||||||
validator_sets::Error::<Test>::DeallocationWouldRemoveEconomicSecurity
|
|
||||||
);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn set_keys_keys_exist() {
|
|
||||||
new_test_ext().execute_with(|| {
|
|
||||||
let network = ExternalNetworkId::Monero;
|
|
||||||
|
|
||||||
// set the keys first
|
|
||||||
ValidatorSets::set_keys(
|
|
||||||
RawOrigin::None.into(),
|
|
||||||
network,
|
|
||||||
KeyPair(insecure_pair_from_name("name").public(), Vec::new().try_into().unwrap()),
|
|
||||||
vec![].try_into().unwrap(),
|
|
||||||
Signature([0u8; 64]),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let call = validator_sets::Call::<Test>::set_keys {
|
|
||||||
network,
|
|
||||||
key_pair: KeyPair(insecure_pair_from_name("name").public(), Vec::new().try_into().unwrap()),
|
|
||||||
signature_participants: vec![].try_into().unwrap(),
|
|
||||||
signature: Signature([0u8; 64]),
|
|
||||||
};
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
ValidatorSets::validate_unsigned(TransactionSource::External, &call),
|
|
||||||
InvalidTransaction::Stale.into()
|
|
||||||
);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn set_keys_invalid_signature() {
|
|
||||||
new_test_ext().execute_with(|| {
|
|
||||||
let network = ExternalNetworkId::Ethereum;
|
|
||||||
let mut participants = get_ordered_keys(network.into(), &genesis_participants());
|
|
||||||
|
|
||||||
// we can't have invalid set
|
|
||||||
let mut set = ExternalValidatorSet { network, session: Session(1) };
|
|
||||||
let key_pair =
|
|
||||||
KeyPair(insecure_pair_from_name("name").public(), Vec::new().try_into().unwrap());
|
|
||||||
let signature = set_keys_signature(&set, &key_pair, &participants);
|
|
||||||
|
|
||||||
let call = validator_sets::Call::<Test>::set_keys {
|
|
||||||
network,
|
|
||||||
key_pair: key_pair.clone(),
|
|
||||||
signature_participants: vec![].try_into().unwrap(),
|
|
||||||
signature,
|
|
||||||
};
|
|
||||||
assert_eq!(
|
|
||||||
ValidatorSets::validate_unsigned(TransactionSource::External, &call),
|
|
||||||
InvalidTransaction::BadProof.into()
|
|
||||||
);
|
|
||||||
|
|
||||||
// fix the set
|
|
||||||
set.session = Session(0);
|
|
||||||
|
|
||||||
// participants should match
|
|
||||||
participants.push(insecure_pair_from_name("random1"));
|
|
||||||
let signature = set_keys_signature(&set, &key_pair, &participants);
|
|
||||||
|
|
||||||
let call = validator_sets::Call::<Test>::set_keys {
|
|
||||||
network,
|
|
||||||
key_pair: key_pair.clone(),
|
|
||||||
signature_participants: vec![].try_into().unwrap(),
|
|
||||||
signature,
|
|
||||||
};
|
|
||||||
assert_eq!(
|
|
||||||
ValidatorSets::validate_unsigned(TransactionSource::External, &call),
|
|
||||||
InvalidTransaction::BadProof.into()
|
|
||||||
);
|
|
||||||
|
|
||||||
// fix the participants
|
|
||||||
participants.pop();
|
|
||||||
|
|
||||||
// msg key pair and the key pair to set should match
|
|
||||||
let key_pair2 =
|
|
||||||
KeyPair(insecure_pair_from_name("name2").public(), Vec::new().try_into().unwrap());
|
|
||||||
let signature = set_keys_signature(&set, &key_pair2, &participants);
|
|
||||||
|
|
||||||
let call = validator_sets::Call::<Test>::set_keys {
|
|
||||||
network,
|
|
||||||
key_pair: key_pair.clone(),
|
|
||||||
signature_participants: vec![].try_into().unwrap(),
|
|
||||||
signature,
|
|
||||||
};
|
|
||||||
assert_eq!(
|
|
||||||
ValidatorSets::validate_unsigned(TransactionSource::External, &call),
|
|
||||||
InvalidTransaction::BadProof.into()
|
|
||||||
);
|
|
||||||
|
|
||||||
// use the same key pair
|
|
||||||
let signature = set_keys_signature(&set, &key_pair, &participants);
|
|
||||||
let call = validator_sets::Call::<Test>::set_keys {
|
|
||||||
network,
|
|
||||||
key_pair,
|
|
||||||
signature_participants: vec![].try_into().unwrap(),
|
|
||||||
signature,
|
|
||||||
};
|
|
||||||
ValidatorSets::validate_unsigned(TransactionSource::External, &call).unwrap();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: add report_slashes tests when the feature is complete.
|
|
||||||
Reference in New Issue
Block a user