@@ -21,6 +21,8 @@ mod mock;
21
21
#[ cfg( test) ]
22
22
mod test;
23
23
24
+ mod deadline;
25
+ mod partition;
24
26
mod proofs;
25
27
mod sector;
26
28
mod storage_provider;
@@ -53,7 +55,7 @@ pub mod pallet {
53
55
} ,
54
56
sector:: {
55
57
ProveCommitSector , SectorOnChainInfo , SectorPreCommitInfo , SectorPreCommitOnChainInfo ,
56
- SECTORS_MAX ,
58
+ MAX_SECTORS ,
57
59
} ,
58
60
storage_provider:: { StorageProviderInfo , StorageProviderState } ,
59
61
} ;
@@ -71,30 +73,100 @@ pub mod pallet {
71
73
pub trait Config : frame_system:: Config {
72
74
/// Because this pallet emits events, it depends on the runtime's definition of an event.
73
75
type RuntimeEvent : From < Event < Self > > + IsType < <Self as frame_system:: Config >:: RuntimeEvent > ;
76
+
74
77
/// Peer ID is derived by hashing an encoded public key.
75
78
/// Usually represented in bytes.
76
79
/// https://github.com/libp2p/specs/blob/2ea41e8c769f1bead8e637a9d4ebf8c791976e8a/peer-ids/peer-ids.md#peer-ids
77
80
/// More information about libp2p peer ids: https://docs.libp2p.io/concepts/fundamentals/peers/
78
81
type PeerId : Clone + Debug + Decode + Encode + Eq + TypeInfo ;
82
+
79
83
/// Currency mechanism, used for collateral
80
84
type Currency : ReservableCurrency < Self :: AccountId > ;
85
+
81
86
/// Market trait implementation for activating deals
82
87
type Market : Market < Self :: AccountId , BlockNumberFor < Self > > ;
83
- /// Proving period for submitting Window PoSt, 24 hours is blocks
88
+
89
+ /// Window PoSt proving period — equivalent to 24 hours worth of blocks.
90
+ ///
91
+ /// During the proving period, storage providers submit Spacetime proofs over smaller
92
+ /// intervals that make it unreasonable to cheat the system, if they fail to provide a proof
93
+ /// in time, they will get slashed.
94
+ ///
95
+ /// In Filecoin, this concept starts with wall time — i.e. 24 hours — and is quantized into
96
+ /// discrete blocks. In our case, we need to consistently put out blocks, every 12 seconds
97
+ /// or 5 blocks per minute, as such, we instead work by block numbers only.
98
+ ///
99
+ /// For example, consider that the first proving period was started at block `0`, to figure
100
+ /// out the proving period for an arbitrary block we must perform integer division between
101
+ /// the block number and the amount of blocks expected to be produced in 24 hours:
102
+ ///
103
+ /// ```text
104
+ /// proving_period = current_block // DAYS
105
+ /// ```
106
+ ///
107
+ /// If we produce 5 blocks per minute, in an hour, we produce `60 * 5 = 300`, following that
108
+ /// we produce `24 * 300 = 7200` blocks per day.
109
+ ///
110
+ /// Hence, if we're in the block number `6873` we get `6873 // 7200 = 0` meaning we are in
111
+ /// the proving period `0`; moving that forward, consider the block `745711`, we'll get
112
+ /// `745711 // 7200 = 103`, thus, we're in the proving period `103`.
113
+ ///
114
+ /// References:
115
+ /// * <https://spec.filecoin.io/#section-algorithms.pos.post.design>
116
+ /// * <https://spec.filecoin.io/#section-systems.filecoin_mining.storage_mining.proof-of-spacetime>
84
117
#[ pallet:: constant]
85
118
type WPoStProvingPeriod : Get < BlockNumberFor < Self > > ;
119
+
120
+ /// Window PoSt challenge window — equivalent to 30 minutes worth of blocks.
121
+ ///
122
+ /// To better understand the following explanation, read [`WPoStProvingPeriod`] first.
123
+ ///
124
+ /// During the Window PoSt proving period, challenges are issued to storage providers to
125
+ /// prove they are still (correctly) storing the data they accepted, in the case of failure
126
+ /// the storage provider will get slashed and have the sector marked as faulty.
127
+ ///
128
+ /// Given that our system works around block numbers, we have time quantization by default,
129
+ /// however it still is necessary to figure out where we stand in the current challenge
130
+ /// window.
131
+ ///
132
+ /// Since we know that, in Filecoin, each 24 hour period is subdivided into 30 minute
133
+ /// epochs, we also subdivide our 24 hour period by 48, just in blocks.
134
+ ///
135
+ /// Consider the block number `745711` (like in the [`WPoStProvingPeriod`]) and that every
136
+ /// 30 minutes, we produce `150` blocks (`300 blocks / hour // 2`). To calculate the current
137
+ /// challenge window we perform the following steps:
138
+ ///
139
+ /// 1. calculate the current proving period — `745711 // 7200 = 103`
140
+ /// 2. calculate the start of said proving period — `103 * 7200 = 741600`
141
+ /// 3. calculate how many blocks elapsed since the beginning of said proving period —
142
+ /// `745711 - 741600 = 4111`
143
+ /// 4. calculate the number of elapsed challenge windows — `4111 // 150 = 27`
144
+ ///
145
+ /// In some cases, it will be helpful to calculate the next deadline as well, picking up
146
+ /// where we left, we perform the following steps:
147
+ ///
148
+ /// 5. calculate the block in which the current challenge window started —
149
+ /// for the "sub-block" `27 * 150 = 4050` & for the block `103 * 7200 + 4050 = 745650`
150
+ /// 6. calculate the next deadline — `745650 + 150 = 745800`
151
+ ///
152
+ /// References:
153
+ /// * <https://spec.filecoin.io/#section-algorithms.pos.post.design>
86
154
/// Window PoSt challenge window (default 30 minutes in blocks)
87
155
#[ pallet:: constant]
88
156
type WPoStChallengeWindow : Get < BlockNumberFor < Self > > ;
157
+
89
158
/// Minimum number of blocks past the current block a sector may be set to expire.
90
159
#[ pallet:: constant]
91
160
type MinSectorExpiration : Get < BlockNumberFor < Self > > ;
161
+
92
162
/// Maximum number of blocks past the current block a sector may be set to expire.
93
163
#[ pallet:: constant]
94
164
type MaxSectorExpirationExtension : Get < BlockNumberFor < Self > > ;
165
+
95
166
/// Maximum number of blocks a sector can stay in pre-committed state
96
167
#[ pallet:: constant]
97
168
type SectorMaximumLifetime : Get < BlockNumberFor < Self > > ;
169
+
98
170
/// Maximum duration to allow for the sealing process for seal algorithms.
99
171
#[ pallet:: constant]
100
172
type MaxProveCommitDuration : Get < BlockNumberFor < Self > > ;
@@ -148,8 +220,6 @@ pub mod pallet {
148
220
InvalidProofType ,
149
221
/// Emitted when there is not enough funds to run an extrinsic.
150
222
NotEnoughFunds ,
151
- /// Emitted when a storage provider tries to commit more sectors than MAX_SECTORS.
152
- MaxPreCommittedSectorExceeded ,
153
223
/// Emitted when a sector fails to activate.
154
224
SectorActivateFailed ,
155
225
/// Emitted when removing a pre_committed sector after proving fails.
@@ -168,11 +238,17 @@ pub mod pallet {
168
238
InvalidCid ,
169
239
/// Emitted when a sector fails to activate
170
240
CouldNotActivateSector ,
171
- /// Emitted when a prove commit is sent after the dealine
241
+ /// Emitted when a prove commit is sent after the deadline
172
242
/// These precommits will be cleaned up in the hook
173
243
ProveCommitAfterDeadline ,
174
244
/// Emitted when a PoSt supplied by by the SP is invalid
175
245
PoStProofInvalid ,
246
+ /// Wrapper around the [`DeadlineError`] type.
247
+ DeadlineError ( crate :: deadline:: DeadlineError ) ,
248
+ /// Wrapper around the [`PartitionError`] type.
249
+ PartitionError ( crate :: partition:: PartitionError ) ,
250
+ /// Wrapper around the [`StorageProviderError`] type.
251
+ StorageProviderError ( crate :: storage_provider:: StorageProviderError ) ,
176
252
}
177
253
178
254
#[ pallet:: call]
@@ -224,7 +300,7 @@ pub mod pallet {
224
300
let sector_number = sector. sector_number ;
225
301
let current_block = <frame_system:: Pallet < T > >:: block_number ( ) ;
226
302
ensure ! (
227
- sector_number <= SECTORS_MAX . into( ) ,
303
+ sector_number <= MAX_SECTORS . into( ) ,
228
304
Error :: <T >:: InvalidSector
229
305
) ;
230
306
ensure ! (
@@ -256,7 +332,7 @@ pub mod pallet {
256
332
deposit,
257
333
<frame_system:: Pallet < T > >:: block_number ( ) ,
258
334
) )
259
- . map_err ( |_ | Error :: < T > :: MaxPreCommittedSectorExceeded ) ?;
335
+ . map_err ( |e | Error :: < T > :: StorageProviderError ( e ) ) ?;
260
336
Ok ( ( ) )
261
337
} ) ?;
262
338
Self :: deposit_event ( Event :: SectorPreCommitted { owner, sector } ) ;
@@ -275,12 +351,12 @@ pub mod pallet {
275
351
. map_err ( |_| Error :: < T > :: StorageProviderNotFound ) ?;
276
352
let sector_number = sector. sector_number ;
277
353
ensure ! (
278
- sector_number <= SECTORS_MAX . into( ) ,
354
+ sector_number <= MAX_SECTORS . into( ) ,
279
355
Error :: <T >:: InvalidSector
280
356
) ;
281
357
let precommit = sp
282
358
. get_pre_committed_sector ( sector_number)
283
- . map_err ( |_ | Error :: < T > :: InvalidSector ) ?;
359
+ . map_err ( |e | Error :: < T > :: StorageProviderError ( e ) ) ?;
284
360
let current_block = <frame_system:: Pallet < T > >:: block_number ( ) ;
285
361
let prove_commit_due =
286
362
precommit. pre_commit_block_number + T :: MaxProveCommitDuration :: get ( ) ;
@@ -299,9 +375,9 @@ pub mod pallet {
299
375
. as_mut ( )
300
376
. ok_or ( Error :: < T > :: StorageProviderNotFound ) ?;
301
377
sp. activate_sector ( sector_number, new_sector)
302
- . map_err ( |_ | Error :: < T > :: SectorActivateFailed ) ?;
378
+ . map_err ( |e | Error :: < T > :: StorageProviderError ( e ) ) ?;
303
379
sp. remove_pre_committed_sector ( sector_number)
304
- . map_err ( |_ | Error :: < T > :: CouldNotRemoveSector ) ?;
380
+ . map_err ( |e | Error :: < T > :: StorageProviderError ( e ) ) ?;
305
381
Ok ( ( ) )
306
382
} ) ?;
307
383
let mut sector_deals = BoundedVec :: new ( ) ;
@@ -337,7 +413,11 @@ pub mod pallet {
337
413
log:: error!( target: LOG_TARGET , "submit_window_post: PoSt submission is invalid {e:?}" ) ;
338
414
return Err ( e. into ( ) ) ;
339
415
}
340
- // Set new deadline for PoSt submission
416
+ // Get deadlines and check the given deadline index is within range.
417
+ let deadlines = sp. get_deadlines ( ) ;
418
+ let _deadline = deadlines
419
+ . load_deadline ( windowed_post. deadline as usize )
420
+ . map_err ( |e| Error :: < T > :: DeadlineError ( e) ) ?;
341
421
Self :: deposit_event ( Event :: ValidPoStSubmitted { owner } ) ;
342
422
Ok ( ( ) )
343
423
}
0 commit comments