1
1
// Copyright 2019-2024 ChainSafe Systems
2
2
// SPDX-License-Identifier: Apache-2.0, MIT
3
3
4
- use std:: {
5
- borrow:: Cow ,
6
- fmt:: { Debug , Display } ,
7
- sync:: Arc ,
8
- } ;
9
-
10
- use crate :: blocks:: { Block , Tipset } ;
11
- use crate :: chain:: Scale ;
12
- use crate :: message:: SignedMessage ;
13
- use crate :: message_pool:: MessagePool ;
14
- use crate :: state_manager:: StateManager ;
15
- use async_trait:: async_trait;
16
4
use futures:: { stream:: FuturesUnordered , StreamExt } ;
17
- use fvm_ipld_blockstore:: Blockstore ;
18
5
use nunny:: Vec as NonEmpty ;
19
- use tokio:: task:: JoinSet ;
20
-
21
- /// The `Consensus` trait encapsulates consensus specific rules of validation
22
- /// and block creation. Behind the scenes they can farm out the total ordering
23
- /// of transactions to an arbitrary consensus engine, but in the end they
24
- /// package the transactions into Filecoin compatible blocks.
25
- ///
26
- /// Not all fields will be made use of, however, so the validation of these
27
- /// blocks at least partially have to be trusted to the `Consensus` component.
28
- ///
29
- /// Common rules for message ordering will be followed, and can be validated
30
- /// outside by the host system during chain synchronization.
31
- #[ async_trait]
32
- pub trait Consensus : Scale + Debug + Send + Sync + Unpin + ' static {
33
- type Error : Debug + Display + Send + Sync ;
34
-
35
- /// Perform block validation asynchronously and return all encountered
36
- /// errors if failed.
37
- ///
38
- /// Being asynchronous gives the method a chance to construct a pipeline of
39
- /// validations, i.e. do some common ones before branching out.
40
- async fn validate_block < DB > (
41
- & self ,
42
- state_manager : Arc < StateManager < DB > > ,
43
- block : Arc < Block > ,
44
- ) -> Result < ( ) , NonEmpty < Self :: Error > >
45
- where
46
- DB : Blockstore + Sync + Send + ' static ;
47
- }
48
6
49
7
/// Helper function to collect errors from async validations.
50
8
pub async fn collect_errs < E > (
@@ -63,93 +21,3 @@ pub async fn collect_errs<E>(
63
21
Err ( _) => Ok ( ( ) ) ,
64
22
}
65
23
}
66
-
67
- /// The `Proposer` trait expresses the ability to "mine", or in more general,
68
- /// to propose blocks to the network according to the rules of the consensus
69
- /// protocol.
70
- ///
71
- /// It is separate from the `Consensus` trait because it is only expected to
72
- /// be called once, then left to run in the background and try to publish
73
- /// blocks to the network which may or may not be adopted.
74
- ///
75
- /// It exists mostly as a way for us to describe what kind of dependencies
76
- /// mining processes are expected to take.
77
- #[ async_trait]
78
- pub trait Proposer {
79
- /// Start proposing blocks in the background and never return, unless
80
- /// something went horribly wrong. Broadly, they should select messages
81
- /// from the `mempool`, come up with a total ordering for them, then create
82
- /// blocks and publish them to the network.
83
- ///
84
- /// To establish total ordering, the proposer might have to communicate
85
- /// with other peers using custom P2P messages, however that is its own
86
- /// concern, the dependencies to implement a suitable network later must
87
- /// come from somewhere else, because they are not common across all
88
- /// consensus variants.
89
- ///
90
- /// The method returns a vector of handles so that it can start unspecified
91
- /// number of background tasks, which can all be canceled by the main thread
92
- /// if the application needs to exit. The method is async so that it can
93
- /// use async operations to initialize itself, during which it might
94
- /// encounter some errors.
95
- async fn spawn < DB , MP > (
96
- self ,
97
- // NOTE: We will need access to the `ChainStore` as well, or, ideally
98
- // a wrapper over it that only allows us to do what we need to, but
99
- // for example not reset the Genesis. But since the `StateManager`
100
- // already exposes the `ChainStore` as is, and this is how it's
101
- // accessed during validation for example, I think we can defer
102
- // these for later refactoring and just use the same pattern.
103
- state_manager : Arc < StateManager < DB > > ,
104
- mpool : Arc < MP > ,
105
- services : & mut JoinSet < anyhow:: Result < ( ) > > ,
106
- ) -> anyhow:: Result < ( ) >
107
- where
108
- DB : Blockstore + Sync + Send + ' static ,
109
- MP : MessagePoolApi + Sync + Send + ' static ;
110
- }
111
-
112
- /// The `MessagePoolApi` is the window of consensus to the contents of the
113
- /// `MessagePool`.
114
- ///
115
- /// It exists to narrow down the possible operations that a consensus engine can
116
- /// do with the `MessagePool` to only those that it should reasonably exercise,
117
- /// which are mostly read-only queries to get transactions which can be expected
118
- /// to be put in the next block, based on their account nonce values and the
119
- /// current state.
120
- ///
121
- /// The `MessagePool` is still expected to monitor the chain growth and remove
122
- /// messages which were included in blocks on its own.
123
- pub trait MessagePoolApi {
124
- /// Select the set of suitable signed messages based on a tipset we are
125
- /// about to build the next block on.
126
- ///
127
- /// The result is a `Cow` in case the source can avoid cloning messages and
128
- /// just return a reference. They will be sent to the data store for
129
- /// storage, but a reference is enough for that.
130
- fn select_signed < DB > (
131
- & self ,
132
- state_manager : & StateManager < DB > ,
133
- base : & Tipset ,
134
- ) -> anyhow:: Result < Vec < Cow < SignedMessage > > >
135
- where
136
- DB : Blockstore ;
137
- }
138
-
139
- impl < P > MessagePoolApi for MessagePool < P >
140
- where
141
- P : crate :: message_pool:: Provider + Send + Sync + ' static ,
142
- {
143
- fn select_signed < DB > (
144
- & self ,
145
- _: & StateManager < DB > ,
146
- base : & Tipset ,
147
- ) -> anyhow:: Result < Vec < Cow < SignedMessage > > >
148
- where
149
- DB : Blockstore ,
150
- {
151
- self . select_messages_for_block ( base)
152
- . map_err ( |e| e. into ( ) )
153
- . map ( |v| v. into_iter ( ) . map ( Cow :: Owned ) . collect ( ) )
154
- }
155
- }
0 commit comments