mirror of
https://github.com/serai-dex/serai.git
synced 2025-01-24 11:36:18 +00:00
TendermintApi, compilation fixes
This commit is contained in:
parent
66f7663cb2
commit
5c08fa9701
14 changed files with 202 additions and 110 deletions
13
Cargo.lock
generated
13
Cargo.lock
generated
|
@ -5115,6 +5115,8 @@ dependencies = [
|
||||||
"parity-scale-codec",
|
"parity-scale-codec",
|
||||||
"scale-info",
|
"scale-info",
|
||||||
"sp-application-crypto",
|
"sp-application-crypto",
|
||||||
|
"sp-core",
|
||||||
|
"sp-std",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -7439,6 +7441,7 @@ dependencies = [
|
||||||
"sp-inherents",
|
"sp-inherents",
|
||||||
"sp-runtime",
|
"sp-runtime",
|
||||||
"sp-staking",
|
"sp-staking",
|
||||||
|
"sp-tendermint",
|
||||||
"sp-timestamp",
|
"sp-timestamp",
|
||||||
"substrate-prometheus-endpoint",
|
"substrate-prometheus-endpoint",
|
||||||
"tendermint-machine",
|
"tendermint-machine",
|
||||||
|
@ -7558,6 +7561,7 @@ dependencies = [
|
||||||
"sp-runtime",
|
"sp-runtime",
|
||||||
"sp-session",
|
"sp-session",
|
||||||
"sp-std",
|
"sp-std",
|
||||||
|
"sp-tendermint",
|
||||||
"sp-transaction-pool",
|
"sp-transaction-pool",
|
||||||
"sp-version",
|
"sp-version",
|
||||||
"substrate-wasm-builder",
|
"substrate-wasm-builder",
|
||||||
|
@ -8318,6 +8322,15 @@ dependencies = [
|
||||||
"sp-std",
|
"sp-std",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sp-tendermint"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"sp-api",
|
||||||
|
"sp-core",
|
||||||
|
"sp-std",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sp-timestamp"
|
name = "sp-timestamp"
|
||||||
version = "4.0.0-dev"
|
version = "4.0.0-dev"
|
||||||
|
|
|
@ -47,9 +47,9 @@ sc-rpc-api = { git = "https://github.com/serai-dex/substrate" }
|
||||||
substrate-frame-rpc-system = { git = "https://github.com/serai-dex/substrate" }
|
substrate-frame-rpc-system = { git = "https://github.com/serai-dex/substrate" }
|
||||||
pallet-transaction-payment-rpc = { git = "https://github.com/serai-dex/substrate" }
|
pallet-transaction-payment-rpc = { git = "https://github.com/serai-dex/substrate" }
|
||||||
|
|
||||||
pallet-tendermint = { path = "../pallet-tendermint", default-features = false }
|
pallet-tendermint = { path = "../tendermint/pallet", default-features = false }
|
||||||
serai-runtime = { path = "../runtime" }
|
serai-runtime = { path = "../runtime" }
|
||||||
serai-consensus = { path = "../consensus" }
|
serai-consensus = { path = "../tendermint/client" }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
substrate-build-script-utils = { git = "https://github.com/serai-dex/substrate.git" }
|
substrate-build-script-utils = { git = "https://github.com/serai-dex/substrate.git" }
|
||||||
|
|
|
@ -29,6 +29,8 @@ sp-block-builder = { git = "https://github.com/serai-dex/substrate", default-fea
|
||||||
sp-runtime = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
sp-runtime = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||||
sp-api = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
sp-api = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||||
|
|
||||||
|
sp-tendermint = { path = "../tendermint/primitives", default-features = false }
|
||||||
|
|
||||||
frame-system = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
frame-system = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||||
frame-support = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
frame-support = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||||
frame-executive = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
frame-executive = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||||
|
@ -43,7 +45,7 @@ pallet-contracts-primitives = { git = "https://github.com/serai-dex/substrate",
|
||||||
pallet-contracts = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
pallet-contracts = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||||
|
|
||||||
pallet-session = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
pallet-session = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||||
pallet-tendermint = { path = "../pallet-tendermint", default-features = false }
|
pallet-tendermint = { path = "../tendermint/pallet", default-features = false }
|
||||||
|
|
||||||
frame-system-rpc-runtime-api = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
frame-system-rpc-runtime-api = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||||
pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||||
|
@ -68,6 +70,8 @@ std = [
|
||||||
"sp-runtime/std",
|
"sp-runtime/std",
|
||||||
"sp-api/std",
|
"sp-api/std",
|
||||||
|
|
||||||
|
"sp-tendermint/std",
|
||||||
|
|
||||||
"frame-system/std",
|
"frame-system/std",
|
||||||
"frame-support/std",
|
"frame-support/std",
|
||||||
"frame-executive/std",
|
"frame-executive/std",
|
||||||
|
|
|
@ -361,6 +361,16 @@ sp_api::impl_runtime_apis! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl sp_tendermint::TendermintApi<Block> for Runtime {
|
||||||
|
fn current_session() -> u32 {
|
||||||
|
Tendermint::session()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validators() -> Vec<Public> {
|
||||||
|
Session::validators()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {
|
impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {
|
||||||
fn account_nonce(account: AccountId) -> Index {
|
fn account_nonce(account: AccountId) -> Index {
|
||||||
System::account_nonce(account)
|
System::account_nonce(account)
|
||||||
|
|
|
@ -30,6 +30,8 @@ sp-runtime = { git = "https://github.com/serai-dex/substrate" }
|
||||||
sp-api = { git = "https://github.com/serai-dex/substrate" }
|
sp-api = { git = "https://github.com/serai-dex/substrate" }
|
||||||
sp-consensus = { git = "https://github.com/serai-dex/substrate" }
|
sp-consensus = { git = "https://github.com/serai-dex/substrate" }
|
||||||
|
|
||||||
|
sp-tendermint = { path = "../primitives" }
|
||||||
|
|
||||||
sc-transaction-pool = { git = "https://github.com/serai-dex/substrate" }
|
sc-transaction-pool = { git = "https://github.com/serai-dex/substrate" }
|
||||||
sc-basic-authorship = { git = "https://github.com/serai-dex/substrate" }
|
sc-basic-authorship = { git = "https://github.com/serai-dex/substrate" }
|
||||||
sc-executor = { git = "https://github.com/serai-dex/substrate" }
|
sc-executor = { git = "https://github.com/serai-dex/substrate" }
|
||||||
|
@ -43,6 +45,6 @@ pallet-session = { git = "https://github.com/serai-dex/substrate" }
|
||||||
|
|
||||||
substrate-prometheus-endpoint = { git = "https://github.com/serai-dex/substrate" }
|
substrate-prometheus-endpoint = { git = "https://github.com/serai-dex/substrate" }
|
||||||
|
|
||||||
tendermint-machine = { path = "../tendermint", features = ["substrate"] }
|
tendermint-machine = { path = "../machine", features = ["substrate"] }
|
||||||
|
|
||||||
serai-runtime = { path = "../runtime" }
|
serai-runtime = { path = "../../runtime" }
|
||||||
|
|
|
@ -2,7 +2,6 @@ use std::{sync::Arc, collections::HashMap};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
use sp_core::sr25519::Public;
|
|
||||||
use sp_inherents::CreateInherentDataProviders;
|
use sp_inherents::CreateInherentDataProviders;
|
||||||
use sp_runtime::traits::Block;
|
use sp_runtime::traits::Block;
|
||||||
use sp_api::TransactionFor;
|
use sp_api::TransactionFor;
|
||||||
|
@ -12,7 +11,7 @@ use sc_consensus::{BlockCheckParams, BlockImportParams, ImportResult, BlockImpor
|
||||||
|
|
||||||
use sc_client_api::Backend;
|
use sc_client_api::Backend;
|
||||||
|
|
||||||
use frame_support::traits::ValidatorSet;
|
use sp_tendermint::TendermintApi;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
tendermint::{TendermintClient, TendermintImport},
|
tendermint::{TendermintClient, TendermintImport},
|
||||||
|
@ -32,7 +31,7 @@ where
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
TransactionFor<C, B>: Send + Sync + 'static,
|
||||||
Arc<C>: BlockImport<B, Transaction = TransactionFor<C, B>>,
|
Arc<C>: BlockImport<B, Transaction = TransactionFor<C, B>>,
|
||||||
<Arc<C> as BlockImport<B>>::Error: Into<Error>,
|
<Arc<C> as BlockImport<B>>::Error: Into<Error>,
|
||||||
C::Api: ValidatorSet<Public>,
|
C::Api: TendermintApi<B>,
|
||||||
{
|
{
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Transaction = TransactionFor<C, B>;
|
type Transaction = TransactionFor<C, B>;
|
||||||
|
|
|
@ -6,7 +6,7 @@ use std::{
|
||||||
time::{UNIX_EPOCH, SystemTime},
|
time::{UNIX_EPOCH, SystemTime},
|
||||||
};
|
};
|
||||||
|
|
||||||
use sp_core::{Decode, sr25519::Public};
|
use sp_core::Decode;
|
||||||
use sp_inherents::CreateInherentDataProviders;
|
use sp_inherents::CreateInherentDataProviders;
|
||||||
use sp_runtime::traits::{Header, Block};
|
use sp_runtime::traits::{Header, Block};
|
||||||
use sp_api::{BlockId, TransactionFor};
|
use sp_api::{BlockId, TransactionFor};
|
||||||
|
@ -19,13 +19,13 @@ use sc_client_api::Backend;
|
||||||
|
|
||||||
use substrate_prometheus_endpoint::Registry;
|
use substrate_prometheus_endpoint::Registry;
|
||||||
|
|
||||||
use frame_support::traits::ValidatorSet;
|
|
||||||
|
|
||||||
use tendermint_machine::{
|
use tendermint_machine::{
|
||||||
ext::{BlockNumber, Commit},
|
ext::{BlockNumber, Commit},
|
||||||
TendermintMachine,
|
TendermintMachine,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use sp_tendermint::TendermintApi;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
CONSENSUS_ID,
|
CONSENSUS_ID,
|
||||||
validators::TendermintValidators,
|
validators::TendermintValidators,
|
||||||
|
@ -100,7 +100,7 @@ where
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
TransactionFor<C, B>: Send + Sync + 'static,
|
||||||
Arc<C>: BlockImport<B, Transaction = TransactionFor<C, B>>,
|
Arc<C>: BlockImport<B, Transaction = TransactionFor<C, B>>,
|
||||||
<Arc<C> as BlockImport<B>>::Error: Into<Error>,
|
<Arc<C> as BlockImport<B>>::Error: Into<Error>,
|
||||||
C::Api: ValidatorSet<Public>,
|
C::Api: TendermintApi<B>,
|
||||||
{
|
{
|
||||||
let import = TendermintImport::new(client, announce, providers, env);
|
let import = TendermintImport::new(client, announce, providers, env);
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ where
|
||||||
Ok(best) => BlockNumber(best),
|
Ok(best) => BlockNumber(best),
|
||||||
Err(_) => panic!("BlockNumber exceeded u64"),
|
Err(_) => panic!("BlockNumber exceeded u64"),
|
||||||
},
|
},
|
||||||
Commit::<TendermintValidators<B, C>>::decode(
|
Commit::<TendermintValidators<B, Be, C>>::decode(
|
||||||
&mut import_clone
|
&mut import_clone
|
||||||
.client
|
.client
|
||||||
.justifications(&BlockId::Number(best))
|
.justifications(&BlockId::Number(best))
|
||||||
|
|
|
@ -10,10 +10,7 @@ use log::warn;
|
||||||
|
|
||||||
use tokio::sync::RwLock as AsyncRwLock;
|
use tokio::sync::RwLock as AsyncRwLock;
|
||||||
|
|
||||||
use sp_core::{
|
use sp_core::{Encode, Decode, sr25519::Signature};
|
||||||
Encode, Decode,
|
|
||||||
sr25519::{Public, Signature},
|
|
||||||
};
|
|
||||||
use sp_inherents::{InherentData, InherentDataProvider, CreateInherentDataProviders};
|
use sp_inherents::{InherentData, InherentDataProvider, CreateInherentDataProviders};
|
||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
traits::{Header, Block},
|
traits::{Header, Block},
|
||||||
|
@ -28,13 +25,13 @@ use sc_consensus::{ForkChoiceStrategy, BlockImportParams, BlockImport, import_qu
|
||||||
use sc_service::ImportQueue;
|
use sc_service::ImportQueue;
|
||||||
use sc_client_api::{BlockBackend, Backend, Finalizer};
|
use sc_client_api::{BlockBackend, Backend, Finalizer};
|
||||||
|
|
||||||
use frame_support::traits::ValidatorSet;
|
|
||||||
|
|
||||||
use tendermint_machine::{
|
use tendermint_machine::{
|
||||||
ext::{BlockError, Commit, Network},
|
ext::{BlockError, Commit, Network},
|
||||||
SignedMessage, TendermintHandle,
|
SignedMessage, TendermintHandle,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use sp_tendermint::TendermintApi;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
CONSENSUS_ID,
|
CONSENSUS_ID,
|
||||||
validators::TendermintValidators,
|
validators::TendermintValidators,
|
||||||
|
@ -53,7 +50,7 @@ pub trait TendermintClient<B: Block, Be: Backend<B> + 'static>:
|
||||||
+ 'static
|
+ 'static
|
||||||
where
|
where
|
||||||
TransactionFor<Self, B>: Send + Sync + 'static,
|
TransactionFor<Self, B>: Send + Sync + 'static,
|
||||||
Self::Api: ValidatorSet<Public>,
|
Self::Api: TendermintApi<B>,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
impl<
|
impl<
|
||||||
|
@ -70,7 +67,7 @@ impl<
|
||||||
> TendermintClient<B, Be> for C
|
> TendermintClient<B, Be> for C
|
||||||
where
|
where
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
TransactionFor<C, B>: Send + Sync + 'static,
|
||||||
C::Api: ValidatorSet<Public>,
|
C::Api: TendermintApi<B>,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,12 +80,12 @@ pub(crate) struct TendermintImport<
|
||||||
A: Announce<B>,
|
A: Announce<B>,
|
||||||
> where
|
> where
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
TransactionFor<C, B>: Send + Sync + 'static,
|
||||||
C::Api: ValidatorSet<Public>,
|
C::Api: TendermintApi<B>,
|
||||||
{
|
{
|
||||||
_block: PhantomData<B>,
|
_block: PhantomData<B>,
|
||||||
_backend: PhantomData<Be>,
|
_backend: PhantomData<Be>,
|
||||||
|
|
||||||
validators: Arc<TendermintValidators<B, C>>,
|
validators: Arc<TendermintValidators<B, Be, C>>,
|
||||||
|
|
||||||
importing_block: Arc<RwLock<Option<B::Hash>>>,
|
importing_block: Arc<RwLock<Option<B::Hash>>>,
|
||||||
pub(crate) machine: Arc<RwLock<Option<TendermintHandle<Self>>>>,
|
pub(crate) machine: Arc<RwLock<Option<TendermintHandle<Self>>>>,
|
||||||
|
@ -111,7 +108,7 @@ impl<
|
||||||
> Clone for TendermintImport<B, Be, C, CIDP, E, A>
|
> Clone for TendermintImport<B, Be, C, CIDP, E, A>
|
||||||
where
|
where
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
TransactionFor<C, B>: Send + Sync + 'static,
|
||||||
C::Api: ValidatorSet<Public>,
|
C::Api: TendermintApi<B>,
|
||||||
{
|
{
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
TendermintImport {
|
TendermintImport {
|
||||||
|
@ -143,7 +140,7 @@ impl<
|
||||||
> TendermintImport<B, Be, C, CIDP, E, A>
|
> TendermintImport<B, Be, C, CIDP, E, A>
|
||||||
where
|
where
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
TransactionFor<C, B>: Send + Sync + 'static,
|
||||||
C::Api: ValidatorSet<Public>,
|
C::Api: TendermintApi<B>,
|
||||||
{
|
{
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
client: Arc<C>,
|
client: Arc<C>,
|
||||||
|
@ -155,7 +152,7 @@ where
|
||||||
_block: PhantomData,
|
_block: PhantomData,
|
||||||
_backend: PhantomData,
|
_backend: PhantomData,
|
||||||
|
|
||||||
validators: TendermintValidators::new(client),
|
validators: Arc::new(TendermintValidators::new(client.clone())),
|
||||||
|
|
||||||
importing_block: Arc::new(RwLock::new(None)),
|
importing_block: Arc::new(RwLock::new(None)),
|
||||||
machine: Arc::new(RwLock::new(None)),
|
machine: Arc::new(RwLock::new(None)),
|
||||||
|
@ -215,7 +212,7 @@ where
|
||||||
Err(Error::InvalidJustification)?;
|
Err(Error::InvalidJustification)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let commit: Commit<TendermintValidators<B, C>> =
|
let commit: Commit<TendermintValidators<B, Be, C>> =
|
||||||
Commit::decode(&mut justification.1.as_ref()).map_err(|_| Error::InvalidJustification)?;
|
Commit::decode(&mut justification.1.as_ref()).map_err(|_| Error::InvalidJustification)?;
|
||||||
if !self.verify_commit(hash, &commit) {
|
if !self.verify_commit(hash, &commit) {
|
||||||
Err(Error::InvalidJustification)?;
|
Err(Error::InvalidJustification)?;
|
||||||
|
@ -328,20 +325,20 @@ impl<
|
||||||
> Network for TendermintImport<B, Be, C, CIDP, E, A>
|
> Network for TendermintImport<B, Be, C, CIDP, E, A>
|
||||||
where
|
where
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
TransactionFor<C, B>: Send + Sync + 'static,
|
||||||
C::Api: ValidatorSet<Public>,
|
C::Api: TendermintApi<B>,
|
||||||
{
|
{
|
||||||
type ValidatorId = u16;
|
type ValidatorId = u16;
|
||||||
type SignatureScheme = TendermintValidators<B, C>;
|
type SignatureScheme = TendermintValidators<B, Be, C>;
|
||||||
type Weights = TendermintValidators<B, C>;
|
type Weights = TendermintValidators<B, Be, C>;
|
||||||
type Block = B;
|
type Block = B;
|
||||||
|
|
||||||
const BLOCK_TIME: u32 = { (serai_runtime::MILLISECS_PER_BLOCK / 1000) as u32 };
|
const BLOCK_TIME: u32 = { (serai_runtime::MILLISECS_PER_BLOCK / 1000) as u32 };
|
||||||
|
|
||||||
fn signature_scheme(&self) -> Arc<TendermintValidators<B, C>> {
|
fn signature_scheme(&self) -> Arc<TendermintValidators<B, Be, C>> {
|
||||||
self.validators.clone()
|
self.validators.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn weights(&self) -> Arc<TendermintValidators<B, C>> {
|
fn weights(&self) -> Arc<TendermintValidators<B, Be, C>> {
|
||||||
self.validators.clone()
|
self.validators.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,7 +407,7 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn add_block(&mut self, block: B, commit: Commit<TendermintValidators<B, C>>) -> B {
|
async fn add_block(&mut self, block: B, commit: Commit<TendermintValidators<B, Be, C>>) -> B {
|
||||||
let hash = block.hash();
|
let hash = block.hash();
|
||||||
let justification = (CONSENSUS_ID, commit.encode());
|
let justification = (CONSENSUS_ID, commit.encode());
|
||||||
debug_assert!(self.verify_justification(hash, &justification).is_ok());
|
debug_assert!(self.verify_justification(hash, &justification).is_ok());
|
||||||
|
|
|
@ -8,12 +8,16 @@ use sp_application_crypto::{
|
||||||
|
|
||||||
use sp_runtime::traits::Block;
|
use sp_runtime::traits::Block;
|
||||||
use sp_staking::SessionIndex;
|
use sp_staking::SessionIndex;
|
||||||
use sp_api::ProvideRuntimeApi;
|
use sp_api::{BlockId, TransactionFor};
|
||||||
|
|
||||||
use frame_support::traits::ValidatorSet;
|
use sc_client_api::Backend;
|
||||||
|
|
||||||
use tendermint_machine::ext::{BlockNumber, Round, Weights, SignatureScheme};
|
use tendermint_machine::ext::{BlockNumber, Round, Weights, SignatureScheme};
|
||||||
|
|
||||||
|
use sp_tendermint::TendermintApi;
|
||||||
|
|
||||||
|
use crate::tendermint::TendermintClient;
|
||||||
|
|
||||||
struct TendermintValidatorsStruct {
|
struct TendermintValidatorsStruct {
|
||||||
session: SessionIndex,
|
session: SessionIndex,
|
||||||
|
|
||||||
|
@ -25,17 +29,21 @@ struct TendermintValidatorsStruct {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TendermintValidatorsStruct {
|
impl TendermintValidatorsStruct {
|
||||||
fn from_module<B: Block, C: Send + Sync + ProvideRuntimeApi<B>>(
|
fn from_module<B: Block, Be: Backend<B> + 'static, C: TendermintClient<B, Be>>(
|
||||||
client: C,
|
client: &Arc<C>,
|
||||||
) -> TendermintValidatorsStruct
|
) -> TendermintValidatorsStruct
|
||||||
where
|
where
|
||||||
C::Api: ValidatorSet<Public>,
|
TransactionFor<C, B>: Send + Sync + 'static,
|
||||||
|
C::Api: TendermintApi<B>,
|
||||||
{
|
{
|
||||||
let validators = client.runtime_api().validators();
|
let last = client.info().best_hash;
|
||||||
|
let api = client.runtime_api();
|
||||||
|
let session = api.current_session(&BlockId::Hash(last)).unwrap();
|
||||||
|
let validators = api.validators(&BlockId::Hash(last)).unwrap();
|
||||||
assert_eq!(validators.len(), 1);
|
assert_eq!(validators.len(), 1);
|
||||||
let keys = Pair::from_string("//Alice", None).unwrap();
|
let keys = Pair::from_string("//Alice", None).unwrap();
|
||||||
TendermintValidatorsStruct {
|
TendermintValidatorsStruct {
|
||||||
session: client.runtime_api().session_index(),
|
session,
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
total_weight: validators.len().try_into().unwrap(),
|
total_weight: validators.len().try_into().unwrap(),
|
||||||
|
@ -48,27 +56,42 @@ impl TendermintValidatorsStruct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap every access of the validators struct in something which forces calling refresh
|
// Wrap every access of the validators struct in something which forces calling refresh
|
||||||
struct Refresh<B: Block, C: Send + Sync + ProvideRuntimeApi<B>> {
|
struct Refresh<B: Block, Be: Backend<B> + 'static, C: TendermintClient<B, Be>>
|
||||||
|
where
|
||||||
|
TransactionFor<C, B>: Send + Sync + 'static,
|
||||||
|
C::Api: TendermintApi<B>,
|
||||||
|
{
|
||||||
_block: PhantomData<B>,
|
_block: PhantomData<B>,
|
||||||
client: C,
|
_backend: PhantomData<Be>,
|
||||||
|
|
||||||
|
client: Arc<C>,
|
||||||
_refresh: Arc<RwLock<TendermintValidatorsStruct>>,
|
_refresh: Arc<RwLock<TendermintValidatorsStruct>>,
|
||||||
}
|
}
|
||||||
impl<B: Block, C: Send + Sync + ProvideRuntimeApi<B>> Refresh<B, C>
|
|
||||||
|
impl<B: Block, Be: Backend<B> + 'static, C: TendermintClient<B, Be>> Refresh<B, Be, C>
|
||||||
where
|
where
|
||||||
C::Api: ValidatorSet<Public>,
|
TransactionFor<C, B>: Send + Sync + 'static,
|
||||||
|
C::Api: TendermintApi<B>,
|
||||||
{
|
{
|
||||||
// If the session has changed, re-create the struct with the data on it
|
// If the session has changed, re-create the struct with the data on it
|
||||||
fn refresh(&self) {
|
fn refresh(&self) {
|
||||||
let session = self._refresh.read().unwrap().session;
|
let session = self._refresh.read().unwrap().session;
|
||||||
if session != self.client.runtime_api().session_index() {
|
if session !=
|
||||||
*self._refresh.write().unwrap() = TendermintValidatorsStruct::from_module(self.client);
|
self
|
||||||
|
.client
|
||||||
|
.runtime_api()
|
||||||
|
.current_session(&BlockId::Hash(self.client.info().best_hash))
|
||||||
|
.unwrap()
|
||||||
|
{
|
||||||
|
*self._refresh.write().unwrap() = TendermintValidatorsStruct::from_module(&self.client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: Block, C: Send + Sync + ProvideRuntimeApi<B>> Deref for Refresh<B, C>
|
impl<B: Block, Be: Backend<B> + 'static, C: TendermintClient<B, Be>> Deref for Refresh<B, Be, C>
|
||||||
where
|
where
|
||||||
C::Api: ValidatorSet<Public>,
|
TransactionFor<C, B>: Send + Sync + 'static,
|
||||||
|
C::Api: TendermintApi<B>,
|
||||||
{
|
{
|
||||||
type Target = RwLock<TendermintValidatorsStruct>;
|
type Target = RwLock<TendermintValidatorsStruct>;
|
||||||
fn deref(&self) -> &RwLock<TendermintValidatorsStruct> {
|
fn deref(&self) -> &RwLock<TendermintValidatorsStruct> {
|
||||||
|
@ -77,25 +100,36 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct TendermintValidators<B: Block, C: Send + Sync + ProvideRuntimeApi<B>>(
|
pub(crate) struct TendermintValidators<
|
||||||
Refresh<B, C>,
|
B: Block,
|
||||||
);
|
Be: Backend<B> + 'static,
|
||||||
impl<B: Block, C: Send + Sync + ProvideRuntimeApi<B>> TendermintValidators<B, C>
|
C: TendermintClient<B, Be>,
|
||||||
|
>(Refresh<B, Be, C>)
|
||||||
where
|
where
|
||||||
C::Api: ValidatorSet<Public>,
|
TransactionFor<C, B>: Send + Sync + 'static,
|
||||||
|
C::Api: TendermintApi<B>;
|
||||||
|
|
||||||
|
impl<B: Block, Be: Backend<B> + 'static, C: TendermintClient<B, Be>> TendermintValidators<B, Be, C>
|
||||||
|
where
|
||||||
|
TransactionFor<C, B>: Send + Sync + 'static,
|
||||||
|
C::Api: TendermintApi<B>,
|
||||||
{
|
{
|
||||||
pub(crate) fn new(client: C) -> TendermintValidators<B, C> {
|
pub(crate) fn new(client: Arc<C>) -> TendermintValidators<B, Be, C> {
|
||||||
TendermintValidators(Refresh {
|
TendermintValidators(Refresh {
|
||||||
_block: PhantomData,
|
_block: PhantomData,
|
||||||
|
_backend: PhantomData,
|
||||||
|
|
||||||
|
_refresh: Arc::new(RwLock::new(TendermintValidatorsStruct::from_module(&client))),
|
||||||
client,
|
client,
|
||||||
_refresh: Arc::new(RwLock::new(TendermintValidatorsStruct::from_module())),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: Block, C: Send + Sync + ProvideRuntimeApi<B>> SignatureScheme for TendermintValidators<B, C>
|
impl<B: Block, Be: Backend<B> + 'static, C: TendermintClient<B, Be>> SignatureScheme
|
||||||
|
for TendermintValidators<B, Be, C>
|
||||||
where
|
where
|
||||||
C::Api: ValidatorSet<Public>,
|
TransactionFor<C, B>: Send + Sync + 'static,
|
||||||
|
C::Api: TendermintApi<B>,
|
||||||
{
|
{
|
||||||
type ValidatorId = u16;
|
type ValidatorId = u16;
|
||||||
type Signature = Signature;
|
type Signature = Signature;
|
||||||
|
@ -126,9 +160,11 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: Block, C: Send + Sync + ProvideRuntimeApi<B>> Weights for TendermintValidators<B, C>
|
impl<B: Block, Be: Backend<B> + 'static, C: TendermintClient<B, Be>> Weights
|
||||||
|
for TendermintValidators<B, Be, C>
|
||||||
where
|
where
|
||||||
C::Api: ValidatorSet<Public>,
|
TransactionFor<C, B>: Send + Sync + 'static,
|
||||||
|
C::Api: TendermintApi<B>,
|
||||||
{
|
{
|
||||||
type ValidatorId = u16;
|
type ValidatorId = u16;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
use sp_core::sr25519::Public;
|
|
||||||
use sp_inherents::CreateInherentDataProviders;
|
use sp_inherents::CreateInherentDataProviders;
|
||||||
use sp_runtime::traits::Block;
|
use sp_runtime::traits::Block;
|
||||||
use sp_api::TransactionFor;
|
use sp_api::TransactionFor;
|
||||||
|
@ -12,7 +11,7 @@ use sc_consensus::{BlockImportParams, BlockImport, Verifier};
|
||||||
|
|
||||||
use sc_client_api::Backend;
|
use sc_client_api::Backend;
|
||||||
|
|
||||||
use frame_support::traits::ValidatorSet;
|
use sp_tendermint::TendermintApi;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
tendermint::{TendermintClient, TendermintImport},
|
tendermint::{TendermintClient, TendermintImport},
|
||||||
|
@ -32,7 +31,7 @@ where
|
||||||
TransactionFor<C, B>: Send + Sync + 'static,
|
TransactionFor<C, B>: Send + Sync + 'static,
|
||||||
Arc<C>: BlockImport<B, Transaction = TransactionFor<C, B>>,
|
Arc<C>: BlockImport<B, Transaction = TransactionFor<C, B>>,
|
||||||
<Arc<C> as BlockImport<B>>::Error: Into<Error>,
|
<Arc<C> as BlockImport<B>>::Error: Into<Error>,
|
||||||
C::Api: ValidatorSet<Public>,
|
C::Api: TendermintApi<B>,
|
||||||
{
|
{
|
||||||
async fn verify(
|
async fn verify(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -15,6 +15,8 @@ rustdoc-args = ["--cfg", "docsrs"]
|
||||||
parity-scale-codec = { version = "3", default-features = false, features = ["derive"] }
|
parity-scale-codec = { version = "3", default-features = false, features = ["derive"] }
|
||||||
scale-info = { version = "2", default-features = false, features = ["derive"] }
|
scale-info = { version = "2", default-features = false, features = ["derive"] }
|
||||||
|
|
||||||
|
sp-core = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||||
|
sp-std = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||||
sp-application-crypto = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
sp-application-crypto = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||||
|
|
||||||
frame-system = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
frame-system = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||||
|
|
|
@ -1,60 +1,73 @@
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
use frame_support::traits::OneSessionHandler;
|
|
||||||
|
|
||||||
#[frame_support::pallet]
|
#[frame_support::pallet]
|
||||||
pub mod pallet {
|
pub mod pallet {
|
||||||
|
use sp_std::vec::Vec;
|
||||||
|
use sp_core::sr25519::Public;
|
||||||
|
|
||||||
use frame_support::pallet_prelude::*;
|
use frame_support::pallet_prelude::*;
|
||||||
|
use frame_support::traits::{ConstU32, OneSessionHandler};
|
||||||
|
|
||||||
|
type MaxValidators = ConstU32<{ u16::MAX as u32 }>;
|
||||||
|
|
||||||
#[pallet::config]
|
#[pallet::config]
|
||||||
pub trait Config: frame_system::Config {}
|
pub trait Config: frame_system::Config {}
|
||||||
|
|
||||||
#[pallet::pallet]
|
#[pallet::pallet]
|
||||||
|
#[pallet::generate_store(pub(super) trait Store)]
|
||||||
pub struct Pallet<T>(PhantomData<T>);
|
pub struct Pallet<T>(PhantomData<T>);
|
||||||
|
|
||||||
|
#[pallet::storage]
|
||||||
|
#[pallet::getter(fn session)]
|
||||||
|
pub type Session<T: Config> = StorageValue<_, u32, ValueQuery>;
|
||||||
|
|
||||||
|
#[pallet::storage]
|
||||||
|
#[pallet::getter(fn validators)]
|
||||||
|
pub type Validators<T: Config> = StorageValue<_, BoundedVec<Public, MaxValidators>, ValueQuery>;
|
||||||
|
|
||||||
|
pub mod crypto {
|
||||||
|
use sp_application_crypto::{KeyTypeId, app_crypto, sr25519};
|
||||||
|
app_crypto!(sr25519, KeyTypeId(*b"tend"));
|
||||||
|
|
||||||
|
impl<T> sp_application_crypto::BoundToRuntimeAppPublic for crate::Pallet<T> {
|
||||||
|
type Public = Public;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp_application_crypto::with_pair! {
|
||||||
|
pub type AuthorityPair = Pair;
|
||||||
|
}
|
||||||
|
pub type AuthoritySignature = Signature;
|
||||||
|
pub type AuthorityId = Public;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Config, V> OneSessionHandler<V> for Pallet<T> {
|
||||||
|
type Key = crypto::Public;
|
||||||
|
|
||||||
|
fn on_genesis_session<'a, I: 'a>(_validators: I)
|
||||||
|
where
|
||||||
|
I: Iterator<Item = (&'a V, Self::Key)>,
|
||||||
|
V: 'a,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_new_session<'a, I: 'a>(changed: bool, validators: I, _queued: I)
|
||||||
|
where
|
||||||
|
I: Iterator<Item = (&'a V, Self::Key)>,
|
||||||
|
V: 'a,
|
||||||
|
{
|
||||||
|
if !changed {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Session::<T>::put(Self::session() + 1);
|
||||||
|
Validators::<T>::put(
|
||||||
|
BoundedVec::try_from(validators.map(|(_, key)| key.into()).collect::<Vec<Public>>())
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_disabled(_validator_index: u32) {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use pallet::*;
|
pub use pallet::*;
|
||||||
|
|
||||||
pub mod crypto {
|
|
||||||
use sp_application_crypto::{KeyTypeId, app_crypto, sr25519};
|
|
||||||
app_crypto!(sr25519, KeyTypeId(*b"tend"));
|
|
||||||
|
|
||||||
impl<C> sp_application_crypto::BoundToRuntimeAppPublic for crate::Pallet<C> {
|
|
||||||
type Public = Public;
|
|
||||||
}
|
|
||||||
|
|
||||||
sp_application_crypto::with_pair! {
|
|
||||||
pub type AuthorityPair = Pair;
|
|
||||||
}
|
|
||||||
pub type AuthoritySignature = Signature;
|
|
||||||
pub type AuthorityId = Public;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C, V> OneSessionHandler<V> for Pallet<C> {
|
|
||||||
type Key = crypto::Public;
|
|
||||||
|
|
||||||
fn on_genesis_session<'a, I: 'a>(_validators: I)
|
|
||||||
where
|
|
||||||
I: Iterator<Item = (&'a V, Self::Key)>,
|
|
||||||
V: 'a,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_new_session<'a, I: 'a>(_changed: bool, _validators: I, _queued: I)
|
|
||||||
where
|
|
||||||
I: Iterator<Item = (&'a V, Self::Key)>,
|
|
||||||
V: 'a,
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
if !changed {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for validator in validators {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_disabled(_validator_index: u32) {}
|
|
||||||
}
|
|
||||||
|
|
|
@ -10,3 +10,12 @@ edition = "2021"
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
sp-core = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||||
|
sp-std = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||||
|
sp-api = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
std = ["sp-core/std", "sp-std/std", "sp-api/std"]
|
||||||
|
default = ["std"]
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
use sp_core::sr25519::Public;
|
use sp_core::sr25519::Public;
|
||||||
|
use sp_std::vec::Vec;
|
||||||
|
|
||||||
trait TendermintApi {
|
sp_api::decl_runtime_apis! {
|
||||||
fn validators() -> Vec<Public>;
|
pub trait TendermintApi {
|
||||||
|
/// Current session number. A session is NOT a fixed length of blocks, yet rather a continuous
|
||||||
|
/// set of validators.
|
||||||
|
fn current_session() -> u32;
|
||||||
|
|
||||||
|
/// Current validators.
|
||||||
|
fn validators() -> Vec<Public>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue