From 123b8ad11b171b4ac2525fa2672cf12b81484fad Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Fri, 21 Oct 2022 05:28:26 -0400 Subject: [PATCH] Tendermint SelectChain This is incompatible with Substrate's expectations, yet should be valid for ours --- substrate/consensus/src/lib.rs | 3 ++ substrate/consensus/src/select_chain.rs | 55 +++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 substrate/consensus/src/select_chain.rs diff --git a/substrate/consensus/src/lib.rs b/substrate/consensus/src/lib.rs index 56734f57..7dc9e730 100644 --- a/substrate/consensus/src/lib.rs +++ b/substrate/consensus/src/lib.rs @@ -16,6 +16,9 @@ mod weights; mod import_queue; use import_queue::TendermintImportQueue; +mod select_chain; +pub use select_chain::TendermintSelectChain; + pub struct ExecutorDispatch; impl NativeExecutionDispatch for ExecutorDispatch { #[cfg(feature = "runtime-benchmarks")] diff --git a/substrate/consensus/src/select_chain.rs b/substrate/consensus/src/select_chain.rs new file mode 100644 index 00000000..e10910e2 --- /dev/null +++ b/substrate/consensus/src/select_chain.rs @@ -0,0 +1,55 @@ +use std::{marker::PhantomData, sync::Arc}; + +use async_trait::async_trait; + +use sp_api::BlockId; +use sp_runtime::traits::Block; +use sp_blockchain::{HeaderBackend, Backend as BlockchainBackend}; +use sc_client_api::Backend; +use sp_consensus::{Error, SelectChain}; + +pub struct TendermintSelectChain>(Arc, PhantomData); + +impl> Clone for TendermintSelectChain { + fn clone(&self) -> Self { + TendermintSelectChain(self.0.clone(), PhantomData) + } +} + +impl> TendermintSelectChain { + pub fn new(backend: Arc) -> TendermintSelectChain { + TendermintSelectChain(backend, PhantomData) + } +} + +#[async_trait] +impl> SelectChain for TendermintSelectChain { + async fn leaves(&self) -> Result, Error> { + panic!("should never be called") + + // Substrate may call this at some point in the future? + // It doesn't appear to do so now, and we have the question of what to do if/when it does + // Either we return the chain tip, which is the true leaf yet breaks the documented definition, + // or we return the actual leaves, when those don't contribute value + // + // Both become risky as best_chain, which is presumably used for block building, is explicitly + // defined as one of these leaves. If it's returning the best chain, the finalized chain tip, + // then it's wrong. The real comment is that this API does not support the Tendermint model + // + // Since it appears the blockchain operations happen on the Backend's leaves, not the + // SelectChain's, leaving this as a panic for now should be optimal + // + // TODO: Triple check this isn't reachable + } + + async fn best_chain(&self) -> Result { + Ok( + self + .0 + .blockchain() + .header(BlockId::Hash(self.0.blockchain().last_finalized().unwrap())) + .unwrap() + .unwrap(), + ) + } +}