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(), ) } }