mirror of
https://github.com/serai-dex/serai.git
synced 2025-02-03 11:46:31 +00:00
Implement block proposal logic
This commit is contained in:
parent
adfc9a5d1d
commit
bf5bdb89c2
9 changed files with 91 additions and 23 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -7387,6 +7387,7 @@ name = "serai-consensus"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"log",
|
||||
"sc-basic-authorship",
|
||||
"sc-client-api",
|
||||
"sc-consensus",
|
||||
|
|
|
@ -15,6 +15,8 @@ rustdoc-args = ["--cfg", "docsrs"]
|
|||
[dependencies]
|
||||
async-trait = "0.1"
|
||||
|
||||
log = "0.4"
|
||||
|
||||
tokio = "1"
|
||||
|
||||
sp-core = { git = "https://github.com/serai-dex/substrate" }
|
||||
|
|
|
@ -14,24 +14,27 @@
|
|||
use std::{
|
||||
marker::PhantomData,
|
||||
sync::{Arc, RwLock},
|
||||
time::Duration,
|
||||
collections::HashMap,
|
||||
};
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
||||
use log::warn;
|
||||
|
||||
use tokio::sync::RwLock as AsyncRwLock;
|
||||
|
||||
use sp_core::{Encode, Decode};
|
||||
use sp_application_crypto::sr25519::Signature;
|
||||
use sp_inherents::CreateInherentDataProviders;
|
||||
use sp_inherents::{InherentData, InherentDataProvider, CreateInherentDataProviders};
|
||||
use sp_runtime::{
|
||||
traits::{Header, Block},
|
||||
Justification,
|
||||
Digest, Justification,
|
||||
};
|
||||
use sp_blockchain::HeaderBackend;
|
||||
use sp_api::{BlockId, TransactionFor, ProvideRuntimeApi};
|
||||
|
||||
use sp_consensus::{Error, CacheKeyId};
|
||||
use sp_consensus::{Error, CacheKeyId, Proposer, Environment};
|
||||
#[rustfmt::skip] // rustfmt doesn't know how to handle this line
|
||||
use sc_consensus::{
|
||||
ForkChoiceStrategy,
|
||||
|
@ -63,6 +66,7 @@ struct TendermintImport<
|
|||
C: Send + Sync + HeaderBackend<B> + Finalizer<B, Be> + ProvideRuntimeApi<B> + 'static,
|
||||
I: Send + Sync + BlockImport<B, Transaction = TransactionFor<C, B>> + 'static,
|
||||
CIDP: CreateInherentDataProviders<B, ()> + 'static,
|
||||
E: Send + Sync + Environment<B> + 'static,
|
||||
> {
|
||||
_block: PhantomData<B>,
|
||||
_backend: PhantomData<Be>,
|
||||
|
@ -72,6 +76,8 @@ struct TendermintImport<
|
|||
client: Arc<C>,
|
||||
inner: Arc<AsyncRwLock<I>>,
|
||||
providers: Arc<CIDP>,
|
||||
|
||||
env: Arc<AsyncRwLock<E>>,
|
||||
}
|
||||
|
||||
impl<
|
||||
|
@ -80,7 +86,8 @@ impl<
|
|||
C: Send + Sync + HeaderBackend<B> + Finalizer<B, Be> + ProvideRuntimeApi<B> + 'static,
|
||||
I: Send + Sync + BlockImport<B, Transaction = TransactionFor<C, B>> + 'static,
|
||||
CIDP: CreateInherentDataProviders<B, ()> + 'static,
|
||||
> Clone for TendermintImport<B, Be, C, I, CIDP>
|
||||
E: Send + Sync + Environment<B> + 'static,
|
||||
> Clone for TendermintImport<B, Be, C, I, CIDP, E>
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
TendermintImport {
|
||||
|
@ -92,6 +99,8 @@ impl<
|
|||
client: self.client.clone(),
|
||||
inner: self.inner.clone(),
|
||||
providers: self.providers.clone(),
|
||||
|
||||
env: self.env.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,7 +111,8 @@ impl<
|
|||
C: Send + Sync + HeaderBackend<B> + Finalizer<B, Be> + ProvideRuntimeApi<B> + 'static,
|
||||
I: Send + Sync + BlockImport<B, Transaction = TransactionFor<C, B>> + 'static,
|
||||
CIDP: CreateInherentDataProviders<B, ()> + 'static,
|
||||
> TendermintImport<B, Be, C, I, CIDP>
|
||||
E: Send + Sync + Environment<B> + 'static,
|
||||
> TendermintImport<B, Be, C, I, CIDP, E>
|
||||
{
|
||||
async fn check_inherents(
|
||||
&self,
|
||||
|
@ -240,7 +250,8 @@ impl<
|
|||
C: Send + Sync + HeaderBackend<B> + Finalizer<B, Be> + ProvideRuntimeApi<B> + 'static,
|
||||
I: Send + Sync + BlockImport<B, Transaction = TransactionFor<C, B>> + 'static,
|
||||
CIDP: CreateInherentDataProviders<B, ()> + 'static,
|
||||
> BlockImport<B> for TendermintImport<B, Be, C, I, CIDP>
|
||||
E: Send + Sync + Environment<B> + 'static,
|
||||
> BlockImport<B> for TendermintImport<B, Be, C, I, CIDP, E>
|
||||
where
|
||||
I::Error: Into<Error>,
|
||||
{
|
||||
|
@ -281,7 +292,8 @@ impl<
|
|||
C: Send + Sync + HeaderBackend<B> + Finalizer<B, Be> + ProvideRuntimeApi<B> + 'static,
|
||||
I: Send + Sync + BlockImport<B, Transaction = TransactionFor<C, B>> + 'static,
|
||||
CIDP: CreateInherentDataProviders<B, ()> + 'static,
|
||||
> JustificationImport<B> for TendermintImport<B, Be, C, I, CIDP>
|
||||
E: Send + Sync + Environment<B> + 'static,
|
||||
> JustificationImport<B> for TendermintImport<B, Be, C, I, CIDP, E>
|
||||
{
|
||||
type Error = Error;
|
||||
|
||||
|
@ -306,7 +318,8 @@ impl<
|
|||
C: Send + Sync + HeaderBackend<B> + Finalizer<B, Be> + ProvideRuntimeApi<B> + 'static,
|
||||
I: Send + Sync + BlockImport<B, Transaction = TransactionFor<C, B>> + 'static,
|
||||
CIDP: CreateInherentDataProviders<B, ()> + 'static,
|
||||
> Verifier<B> for TendermintImport<B, Be, C, I, CIDP>
|
||||
E: Send + Sync + Environment<B> + 'static,
|
||||
> Verifier<B> for TendermintImport<B, Be, C, I, CIDP, E>
|
||||
{
|
||||
async fn verify(
|
||||
&mut self,
|
||||
|
@ -324,7 +337,8 @@ impl<
|
|||
C: Send + Sync + HeaderBackend<B> + Finalizer<B, Be> + ProvideRuntimeApi<B> + 'static,
|
||||
I: Send + Sync + BlockImport<B, Transaction = TransactionFor<C, B>> + 'static,
|
||||
CIDP: CreateInherentDataProviders<B, ()> + 'static,
|
||||
> Network for TendermintImport<B, Be, C, I, CIDP>
|
||||
E: Send + Sync + Environment<B> + 'static,
|
||||
> Network for TendermintImport<B, Be, C, I, CIDP, E>
|
||||
{
|
||||
type ValidatorId = u16;
|
||||
type SignatureScheme = TendermintSigner;
|
||||
|
@ -356,10 +370,38 @@ impl<
|
|||
// Ok(())
|
||||
}
|
||||
|
||||
fn add_block(&mut self, block: B, commit: Commit<TendermintSigner>) -> B {
|
||||
self.import_justification_actual(block.hash(), (CONSENSUS_ID, commit.encode())).unwrap();
|
||||
// Next block proposal
|
||||
todo!()
|
||||
async fn add_block(&mut self, block: B, commit: Commit<TendermintSigner>) -> B {
|
||||
let hash = block.hash();
|
||||
self.import_justification_actual(hash, (CONSENSUS_ID, commit.encode())).unwrap();
|
||||
|
||||
let inherent_data = match self.providers.create_inherent_data_providers(hash, ()).await {
|
||||
Ok(providers) => match providers.create_inherent_data() {
|
||||
Ok(data) => Some(data),
|
||||
Err(err) => {
|
||||
warn!(target: "tendermint", "Failed to create inherent data: {}", err);
|
||||
None
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
warn!(target: "tendermint", "Failed to create inherent data providers: {}", err);
|
||||
None
|
||||
}
|
||||
}
|
||||
.unwrap_or_else(InherentData::new);
|
||||
|
||||
let proposer = self
|
||||
.env
|
||||
.write()
|
||||
.await
|
||||
.init(block.header())
|
||||
.await
|
||||
.expect("Failed to create a proposer for the new block");
|
||||
// TODO: Production time, size limit
|
||||
let proposal = proposer
|
||||
.propose(inherent_data, Digest::default(), Duration::from_secs(1), None)
|
||||
.await
|
||||
.expect("Failed to crate a new block proposal");
|
||||
proposal.block
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -371,10 +413,12 @@ pub fn import_queue<
|
|||
C: Send + Sync + HeaderBackend<B> + Finalizer<B, Be> + ProvideRuntimeApi<B> + 'static,
|
||||
I: Send + Sync + BlockImport<B, Transaction = TransactionFor<C, B>> + 'static,
|
||||
CIDP: CreateInherentDataProviders<B, ()> + 'static,
|
||||
E: Send + Sync + Environment<B> + 'static,
|
||||
>(
|
||||
client: Arc<C>,
|
||||
inner: I,
|
||||
providers: Arc<CIDP>,
|
||||
env: E,
|
||||
spawner: &impl sp_core::traits::SpawnEssentialNamed,
|
||||
registry: Option<&Registry>,
|
||||
) -> TendermintImportQueue<B, TransactionFor<C, B>>
|
||||
|
@ -390,6 +434,8 @@ where
|
|||
client,
|
||||
inner: Arc::new(AsyncRwLock::new(inner)),
|
||||
providers,
|
||||
|
||||
env: Arc::new(AsyncRwLock::new(env)),
|
||||
};
|
||||
let boxed = Box::new(import.clone());
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ use sp_api::TransactionFor;
|
|||
use sp_consensus::Error;
|
||||
|
||||
use sc_executor::{NativeVersion, NativeExecutionDispatch, NativeElseWasmExecutor};
|
||||
use sc_transaction_pool::FullPool;
|
||||
use sc_service::{TaskManager, TFullClient};
|
||||
|
||||
use substrate_prometheus_endpoint::Registry;
|
||||
|
@ -40,12 +41,20 @@ pub type FullClient = TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Exec
|
|||
pub fn import_queue(
|
||||
task_manager: &TaskManager,
|
||||
client: Arc<FullClient>,
|
||||
pool: Arc<FullPool<Block, FullClient>>,
|
||||
registry: Option<&Registry>,
|
||||
) -> Result<TendermintImportQueue<Block, TransactionFor<FullClient, Block>>, Error> {
|
||||
Ok(import_queue::import_queue(
|
||||
client.clone(),
|
||||
client,
|
||||
client.clone(),
|
||||
Arc::new(|_, _| async { Ok(sp_timestamp::InherentDataProvider::from_system_time()) }),
|
||||
sc_basic_authorship::ProposerFactory::new(
|
||||
task_manager.spawn_handle(),
|
||||
client,
|
||||
pool,
|
||||
registry,
|
||||
None,
|
||||
),
|
||||
&task_manager.spawn_essential_handle(),
|
||||
registry,
|
||||
))
|
||||
|
@ -56,7 +65,7 @@ pub fn authority(
|
|||
task_manager: &TaskManager,
|
||||
client: Arc<FullClient>,
|
||||
network: Arc<sc_network::NetworkService<Block, <Block as sp_runtime::traits::Block>::Hash>>,
|
||||
pool: Arc<sc_transaction_pool::FullPool<Block, FullClient>>,
|
||||
pool: Arc<FullPool<Block, FullClient>>,
|
||||
registry: Option<&Registry>,
|
||||
) {
|
||||
todo!()
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use sc_service::ChainType;
|
||||
|
||||
use sp_runtime::traits::Verify;
|
||||
use sp_core::{Pair as PairTrait, sr25519::Pair};
|
||||
|
||||
use serai_runtime::{WASM_BINARY, AccountId, Signature, GenesisConfig, SystemConfig, BalancesConfig};
|
||||
use serai_runtime::{WASM_BINARY, AccountId, GenesisConfig, SystemConfig, BalancesConfig};
|
||||
|
||||
pub type ChainSpec = sc_service::GenericChainSpec<GenesisConfig>;
|
||||
|
||||
|
|
|
@ -63,8 +63,12 @@ pub fn new_partial(config: &Configuration) -> Result<PartialComponents, ServiceE
|
|||
client.clone(),
|
||||
);
|
||||
|
||||
let import_queue =
|
||||
serai_consensus::import_queue(&task_manager, client.clone(), config.prometheus_registry())?;
|
||||
let import_queue = serai_consensus::import_queue(
|
||||
&task_manager,
|
||||
client.clone(),
|
||||
transaction_pool.clone(),
|
||||
config.prometheus_registry(),
|
||||
)?;
|
||||
|
||||
let select_chain = serai_consensus::TendermintSelectChain::new(backend.clone());
|
||||
|
||||
|
|
|
@ -186,6 +186,9 @@ pub trait Network: Send + Sync {
|
|||
/// consider it valid and created a commit for it. This deviates from the paper which will have a
|
||||
/// local node refuse to decide on a block it considers invalid. This library acknowledges the
|
||||
/// network did decide on it, leaving handling of it to the network, and outside of this scope.
|
||||
fn add_block(&mut self, block: Self::Block, commit: Commit<Self::SignatureScheme>)
|
||||
-> Self::Block;
|
||||
async fn add_block(
|
||||
&mut self,
|
||||
block: Self::Block,
|
||||
commit: Commit<Self::SignatureScheme>,
|
||||
) -> Self::Block;
|
||||
}
|
||||
|
|
|
@ -318,7 +318,7 @@ impl<N: Network + 'static> TendermintMachine<N> {
|
|||
};
|
||||
debug_assert!(machine.network.read().await.verify_commit(block.id(), &commit));
|
||||
|
||||
let proposal = machine.network.write().await.add_block(block, commit);
|
||||
let proposal = machine.network.write().await.add_block(block, commit).await;
|
||||
machine.reset(proposal).await;
|
||||
}
|
||||
Err(TendermintError::Malicious(validator)) => {
|
||||
|
|
|
@ -113,7 +113,11 @@ impl Network for TestNetwork {
|
|||
block.valid
|
||||
}
|
||||
|
||||
fn add_block(&mut self, block: TestBlock, commit: Commit<TestSignatureScheme>) -> TestBlock {
|
||||
async fn add_block(
|
||||
&mut self,
|
||||
block: TestBlock,
|
||||
commit: Commit<TestSignatureScheme>,
|
||||
) -> TestBlock {
|
||||
dbg!("Adding ", &block);
|
||||
assert!(block.valid.is_ok());
|
||||
assert!(self.verify_commit(block.id(), &commit));
|
||||
|
|
Loading…
Reference in a new issue