mirror of
https://github.com/serai-dex/serai.git
synced 2025-03-15 16:12:44 +00:00
Take in a Keystore and validator ID
This commit is contained in:
parent
aa0a4cf106
commit
5832007a45
5 changed files with 56 additions and 20 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -7342,6 +7342,7 @@ dependencies = [
|
||||||
"sp-consensus",
|
"sp-consensus",
|
||||||
"sp-core",
|
"sp-core",
|
||||||
"sp-inherents",
|
"sp-inherents",
|
||||||
|
"sp-keystore",
|
||||||
"sp-runtime",
|
"sp-runtime",
|
||||||
"sp-staking",
|
"sp-staking",
|
||||||
"sp-tendermint",
|
"sp-tendermint",
|
||||||
|
|
|
@ -22,6 +22,7 @@ tokio = { version = "1", features = ["sync", "rt"] }
|
||||||
|
|
||||||
sp-core = { git = "https://github.com/serai-dex/substrate" }
|
sp-core = { git = "https://github.com/serai-dex/substrate" }
|
||||||
sp-application-crypto = { git = "https://github.com/serai-dex/substrate" }
|
sp-application-crypto = { git = "https://github.com/serai-dex/substrate" }
|
||||||
|
sp-keystore = { git = "https://github.com/serai-dex/substrate" }
|
||||||
sp-inherents = { git = "https://github.com/serai-dex/substrate" }
|
sp-inherents = { git = "https://github.com/serai-dex/substrate" }
|
||||||
sp-staking = { git = "https://github.com/serai-dex/substrate" }
|
sp-staking = { git = "https://github.com/serai-dex/substrate" }
|
||||||
sp-blockchain = { git = "https://github.com/serai-dex/substrate" }
|
sp-blockchain = { git = "https://github.com/serai-dex/substrate" }
|
||||||
|
|
|
@ -135,6 +135,7 @@ impl<T: TendermintValidator> TendermintAuthority<T> {
|
||||||
providers: T::CIDP,
|
providers: T::CIDP,
|
||||||
env: T::Environment,
|
env: T::Environment,
|
||||||
network: T::Network,
|
network: T::Network,
|
||||||
|
validator: (u16, T::Keystore),
|
||||||
registry: Option<&Registry>,
|
registry: Option<&Registry>,
|
||||||
) {
|
) {
|
||||||
let (best_hash, last) = self.get_last();
|
let (best_hash, last) = self.get_last();
|
||||||
|
@ -164,16 +165,15 @@ impl<T: TendermintValidator> TendermintAuthority<T> {
|
||||||
env,
|
env,
|
||||||
announce: network,
|
announce: network,
|
||||||
});
|
});
|
||||||
|
let (validator, keys) = validator;
|
||||||
|
self.import.validators.set_keys(keys).await;
|
||||||
|
|
||||||
let proposal = self
|
let proposal = self
|
||||||
.get_proposal(&self.import.client.header(BlockId::Hash(best_hash)).unwrap().unwrap())
|
.get_proposal(&self.import.client.header(BlockId::Hash(best_hash)).unwrap().unwrap())
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
TendermintMachine::new(
|
// We no longer need self, so let TendermintMachine become its owner
|
||||||
self, // We no longer need self, so let TendermintMachine become its owner
|
TendermintMachine::new(self, validator, last, proposal)
|
||||||
0, // TODO: ValidatorId
|
|
||||||
last, proposal,
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Start receiving messages about the Tendermint process for this block
|
// Start receiving messages about the Tendermint process for this block
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use sp_core::crypto::KeyTypeId;
|
||||||
|
use sp_keystore::CryptoStore;
|
||||||
use sp_inherents::CreateInherentDataProviders;
|
use sp_inherents::CreateInherentDataProviders;
|
||||||
use sp_runtime::traits::{Header, Block};
|
use sp_runtime::traits::{Header, Block};
|
||||||
use sp_blockchain::HeaderBackend;
|
use sp_blockchain::HeaderBackend;
|
||||||
|
@ -28,6 +30,7 @@ pub(crate) mod authority;
|
||||||
pub use authority::TendermintAuthority;
|
pub use authority::TendermintAuthority;
|
||||||
|
|
||||||
const CONSENSUS_ID: [u8; 4] = *b"tend";
|
const CONSENSUS_ID: [u8; 4] = *b"tend";
|
||||||
|
const KEY_TYPE_ID: KeyTypeId = KeyTypeId(CONSENSUS_ID);
|
||||||
|
|
||||||
/// Trait consolidating all generics required by sc_tendermint for processing.
|
/// Trait consolidating all generics required by sc_tendermint for processing.
|
||||||
pub trait TendermintClient: Send + Sync + 'static {
|
pub trait TendermintClient: Send + Sync + 'static {
|
||||||
|
@ -55,6 +58,8 @@ pub trait TendermintClient: Send + Sync + 'static {
|
||||||
+ Finalizer<Self::Block, Self::Backend>
|
+ Finalizer<Self::Block, Self::Backend>
|
||||||
+ ProvideRuntimeApi<Self::Block, Api = Self::Api>
|
+ ProvideRuntimeApi<Self::Block, Api = Self::Api>
|
||||||
+ 'static;
|
+ 'static;
|
||||||
|
|
||||||
|
type Keystore: CryptoStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait implementable on firm types to automatically provide a full TendermintClient impl.
|
/// Trait implementable on firm types to automatically provide a full TendermintClient impl.
|
||||||
|
@ -72,6 +77,8 @@ pub trait TendermintClientMinimal: Send + Sync + 'static {
|
||||||
+ Finalizer<Self::Block, Self::Backend>
|
+ Finalizer<Self::Block, Self::Backend>
|
||||||
+ ProvideRuntimeApi<Self::Block, Api = Self::Api>
|
+ ProvideRuntimeApi<Self::Block, Api = Self::Api>
|
||||||
+ 'static;
|
+ 'static;
|
||||||
|
|
||||||
|
type Keystore: CryptoStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: TendermintClientMinimal> TendermintClient for T
|
impl<T: TendermintClientMinimal> TendermintClient for T
|
||||||
|
@ -89,6 +96,8 @@ where
|
||||||
type StateBackend = StateBackendFor<T::Client, T::Block>;
|
type StateBackend = StateBackendFor<T::Client, T::Block>;
|
||||||
type Api = <T::Client as ProvideRuntimeApi<T::Block>>::Api;
|
type Api = <T::Client as ProvideRuntimeApi<T::Block>>::Api;
|
||||||
type Client = T::Client;
|
type Client = T::Client;
|
||||||
|
|
||||||
|
type Keystore = T::Keystore;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait consolidating additional generics required by sc_tendermint for authoring.
|
/// Trait consolidating additional generics required by sc_tendermint for authoring.
|
||||||
|
|
|
@ -3,10 +3,14 @@ use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
use tokio::sync::RwLock as AsyncRwLock;
|
||||||
|
|
||||||
|
use sp_core::Decode;
|
||||||
use sp_application_crypto::{
|
use sp_application_crypto::{
|
||||||
RuntimePublic as PublicTrait, Pair as PairTrait,
|
RuntimePublic as PublicTrait,
|
||||||
sr25519::{Public, Pair, Signature},
|
sr25519::{Public, Signature},
|
||||||
};
|
};
|
||||||
|
use sp_keystore::CryptoStore;
|
||||||
|
|
||||||
use sp_staking::SessionIndex;
|
use sp_staking::SessionIndex;
|
||||||
use sp_api::{BlockId, ProvideRuntimeApi};
|
use sp_api::{BlockId, ProvideRuntimeApi};
|
||||||
|
@ -17,7 +21,7 @@ use tendermint_machine::ext::{BlockNumber, Round, Weights, SignatureScheme};
|
||||||
|
|
||||||
use sp_tendermint::TendermintApi;
|
use sp_tendermint::TendermintApi;
|
||||||
|
|
||||||
use crate::TendermintClient;
|
use crate::{KEY_TYPE_ID, TendermintClient};
|
||||||
|
|
||||||
struct TendermintValidatorsStruct {
|
struct TendermintValidatorsStruct {
|
||||||
session: SessionIndex,
|
session: SessionIndex,
|
||||||
|
@ -25,19 +29,18 @@ struct TendermintValidatorsStruct {
|
||||||
total_weight: u64,
|
total_weight: u64,
|
||||||
weights: Vec<u64>,
|
weights: Vec<u64>,
|
||||||
|
|
||||||
keys: Pair, // TODO: sp_keystore
|
|
||||||
lookup: Vec<Public>,
|
lookup: Vec<Public>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TendermintValidatorsStruct {
|
impl TendermintValidatorsStruct {
|
||||||
fn from_module<T: TendermintClient>(client: &Arc<T::Client>) -> TendermintValidatorsStruct {
|
fn from_module<T: TendermintClient>(client: &Arc<T::Client>) -> Self {
|
||||||
let last = client.info().finalized_hash;
|
let last = client.info().finalized_hash;
|
||||||
let api = client.runtime_api();
|
let api = client.runtime_api();
|
||||||
let session = api.current_session(&BlockId::Hash(last)).unwrap();
|
let session = api.current_session(&BlockId::Hash(last)).unwrap();
|
||||||
let validators = api.validators(&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();
|
|
||||||
TendermintValidatorsStruct {
|
Self {
|
||||||
session,
|
session,
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -45,7 +48,6 @@ impl TendermintValidatorsStruct {
|
||||||
weights: vec![1; validators.len()],
|
weights: vec![1; validators.len()],
|
||||||
|
|
||||||
lookup: validators,
|
lookup: validators,
|
||||||
keys,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,15 +84,25 @@ impl<T: TendermintClient> Deref for Refresh<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tendermint validators observer, providing data on the active validators.
|
/// Tendermint validators observer, providing data on the active validators.
|
||||||
pub struct TendermintValidators<T: TendermintClient>(Refresh<T>);
|
pub struct TendermintValidators<T: TendermintClient>(
|
||||||
|
Refresh<T>,
|
||||||
|
Arc<AsyncRwLock<Option<T::Keystore>>>,
|
||||||
|
);
|
||||||
|
|
||||||
impl<T: TendermintClient> TendermintValidators<T> {
|
impl<T: TendermintClient> TendermintValidators<T> {
|
||||||
pub(crate) fn new(client: Arc<T::Client>) -> TendermintValidators<T> {
|
pub(crate) fn new(client: Arc<T::Client>) -> TendermintValidators<T> {
|
||||||
TendermintValidators(Refresh {
|
TendermintValidators(
|
||||||
_tc: PhantomData,
|
Refresh {
|
||||||
_refresh: Arc::new(RwLock::new(TendermintValidatorsStruct::from_module::<T>(&client))),
|
_tc: PhantomData,
|
||||||
client,
|
_refresh: Arc::new(RwLock::new(TendermintValidatorsStruct::from_module::<T>(&client))),
|
||||||
})
|
client,
|
||||||
|
},
|
||||||
|
Arc::new(AsyncRwLock::new(None)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn set_keys(&self, keys: T::Keystore) {
|
||||||
|
*self.1.write().await = Some(keys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +113,20 @@ impl<T: TendermintClient> SignatureScheme for TendermintValidators<T> {
|
||||||
type AggregateSignature = Vec<Signature>;
|
type AggregateSignature = Vec<Signature>;
|
||||||
|
|
||||||
async fn sign(&self, msg: &[u8]) -> Signature {
|
async fn sign(&self, msg: &[u8]) -> Signature {
|
||||||
self.0.read().unwrap().keys.sign(msg)
|
let read = self.1.read().await;
|
||||||
|
let keys = read.as_ref().unwrap();
|
||||||
|
let key = {
|
||||||
|
let pubs = keys.sr25519_public_keys(KEY_TYPE_ID).await;
|
||||||
|
if pubs.is_empty() {
|
||||||
|
keys.sr25519_generate_new(KEY_TYPE_ID, None).await.unwrap()
|
||||||
|
} else {
|
||||||
|
pubs[0]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Signature::decode(
|
||||||
|
&mut keys.sign_with(KEY_TYPE_ID, &key.into(), msg).await.unwrap().unwrap().as_ref(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify(&self, validator: u16, msg: &[u8], sig: &Signature) -> bool {
|
fn verify(&self, validator: u16, msg: &[u8], sig: &Signature) -> bool {
|
||||||
|
|
Loading…
Reference in a new issue