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>;
}