1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
use std::{
fmt::{Debug, Display},
hash::Hash,
marker::Send,
};
use parity_scale_codec::Codec;
use crate::BlockId;
mod data;
mod forest;
mod handler;
mod message_limiter;
mod metrics;
#[cfg(test)]
mod mock;
mod service;
pub mod substrate;
mod task_queue;
mod tasks;
mod ticker;
pub use handler::DatabaseIO;
pub use service::{Service, IO};
pub use substrate::{
JustificationTranslator, SubstrateChainStatus, SubstrateChainStatusNotifier,
SubstrateFinalizationInfo, VerifierCache,
};
const LOG_TARGET: &str = "phron-block-sync";
/// The identifier of a connected peer.
pub trait PeerId: Debug + Clone + Hash + Eq {}
impl<T: Debug + Clone + Hash + Eq> PeerId for T {}
/// The unverified header of a block, containing information about the parent relation.
pub trait UnverifiedHeader: Clone + Codec + Debug + Send + Sync + 'static {
/// The identifier of this block.
fn id(&self) -> BlockId;
}
/// The header of a block, containing information about the parent relation.
pub trait Header: Clone + Codec + Debug + Send + Sync + 'static {
type Unverified: UnverifiedHeader;
/// The identifier of this block.
fn id(&self) -> BlockId;
/// The identifier of this block's parent.
fn parent_id(&self) -> Option<BlockId>;
/// Return an unverified version of this, for sending over the network.
fn into_unverified(self) -> Self::Unverified;
}
/// The block, including a header.
pub trait Block: Clone + Codec + Debug + Send + Sync + 'static {
type UnverifiedHeader: UnverifiedHeader;
/// The header of the block.
fn header(&self) -> &Self::UnverifiedHeader;
}
/// The block importer.
pub trait BlockImport<B>: Send + 'static {
/// Import the block.
fn import_block(&mut self, block: B);
}
pub trait UnverifiedJustification: Clone + Codec + Send + Sync + Debug + 'static {
type UnverifiedHeader: UnverifiedHeader;
/// The header of the block.
fn header(&self) -> &Self::UnverifiedHeader;
}
/// The verified justification of a block, including a header.
pub trait Justification: Clone + Send + Sync + Debug + 'static {
type Header: Header;
type Unverified: UnverifiedJustification<
UnverifiedHeader = <Self::Header as Header>::Unverified,
>;
/// The header of the block.
fn header(&self) -> &Self::Header;
/// Return an unverified version of this, for sending over the network.
fn into_unverified(self) -> Self::Unverified;
}
type UnverifiedHeaderFor<J> = <<J as Justification>::Header as Header>::Unverified;
/// A verifier of justifications and headers.
pub trait Verifier<J: Justification> {
type Error: Display;
/// Verifies the raw justification and returns a full justification if successful, otherwise an
/// error.
fn verify_justification(&mut self, justification: J::Unverified) -> Result<J, Self::Error>;
// /// Verifies the raw header and returns a full header if successful, otherwise an error.
fn verify_header(&mut self, header: UnverifiedHeaderFor<J>) -> Result<J::Header, Self::Error>;
}
/// A facility for finalizing blocks using justifications.
pub trait Finalizer<J: Justification> {
type Error: Display;
/// Finalize a block using this justification. Since the justification contains the header, we
/// don't need to additionally specify the block.
fn finalize(&self, justification: J) -> Result<(), Self::Error>;
}
/// A notification about the chain status changing.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ChainStatusNotification<H: Header> {
/// A block has been imported.
BlockImported(H),
/// A block has been finalized.
BlockFinalized(H),
}
/// A stream of notifications about the chain status in the database changing.
/// We assume that this will return all the events, otherwise we will end up with a broken state.
#[async_trait::async_trait]
pub trait ChainStatusNotifier<H: Header> {
type Error: Debug + Display;
/// Returns a chain status notification when it is available.
/// This method's implementation must be cancellation safe.
async fn next(&mut self) -> Result<ChainStatusNotification<H>, Self::Error>;
}
/// The status of a block in the database.
pub enum BlockStatus<J: Justification> {
/// The block is justified and thus finalized.
Justified(J),
/// The block is present, might be finalized if a descendant is justified.
Present(J::Header),
/// The block is not known.
Unknown,
}
/// FinalizationStatus of the block
pub enum FinalizationStatus<J: Justification> {
/// The block is finalized by justification.
FinalizedWithJustification(J),
/// The block is finalized because one of its children is finalized.
FinalizedByDescendant(J::Header),
/// The block is not finalized
NotFinalized,
}
impl<J: Justification> FinalizationStatus<J> {
pub fn has_justification(&self) -> Option<J> {
use FinalizationStatus::*;
match self {
FinalizedWithJustification(just) => Some(just.clone()),
_ => None,
}
}
}
/// The knowledge about the chain status.
#[allow(dead_code)]
pub trait ChainStatus<B, J>: Clone + Send + Sync + 'static
where
J: Justification,
B: Block<UnverifiedHeader = UnverifiedHeaderFor<J>>,
{
type Error: Display;
/// The status of the block.
fn status_of(&self, id: BlockId) -> Result<BlockStatus<J>, Self::Error>;
/// Export a copy of the block.
fn block(&self, id: BlockId) -> Result<Option<B>, Self::Error>;
/// The justification at this block number, if we have it otherwise just block id if
/// the block is finalized without justification. Should return NotFinalized variant if
/// the request is above the top finalized.
fn finalized_at(&self, number: u32) -> Result<FinalizationStatus<J>, Self::Error>;
/// The header of the best block.
fn best_block(&self) -> Result<J::Header, Self::Error>;
/// The justification of the top finalized block.
fn top_finalized(&self) -> Result<J, Self::Error>;
/// Children of the specified block.
fn children(&self, id: BlockId) -> Result<Vec<J::Header>, Self::Error>;
}
/// An interface for submitting additional justifications to the justification sync.
/// Chiefly ones created by ABFT, but others will also be handled appropriately.
/// The block corresponding to the submitted `Justification` MUST be obtained and
/// imported into the Substrate database by the user, as soon as possible.
pub trait JustificationSubmissions<J: Justification>: Clone + Send + 'static {
type Error: Display;
/// Submit a justification to the underlying justification sync.
fn submit(&mut self, justification: J::Unverified) -> Result<(), Self::Error>;
}
/// An interface for requesting specific blocks from the block sync.
/// Required by the data availability mechanism in ABFT.
pub trait RequestBlocks: Clone + Send + Sync + 'static {
type Error: Display;
/// Request the given block.
fn request_block(&self, block_id: BlockId) -> Result<(), Self::Error>;
}