4
4
// Fix clippy for sp_api::decl_runtime_apis!
5
5
#![ allow( clippy:: too_many_arguments, clippy:: unnecessary_mut_passed) ]
6
6
7
- use codec:: { Decode , Encode } ;
8
- use frame_support:: traits:: IsSubType ;
7
+ use codec:: { Decode , Encode , MaxEncodedLen } ;
9
8
use frame_support:: weights:: DispatchInfo ;
9
+ use frame_support:: { parameter_types, traits:: IsSubType , WeakBoundedVec } ;
10
10
pub use pallet:: * ;
11
11
use scale_info:: TypeInfo ;
12
12
#[ cfg( feature = "std" ) ]
@@ -85,9 +85,17 @@ pub struct Authenticate<OpaqueAuthTicket, Commitment> {
85
85
pub ticket_signature : Commitment ,
86
86
}
87
87
88
+ parameter_types ! {
89
+ /// The maximum length of a single nonce (in bytes).
90
+ pub const AuthTicketNonceMaxBytes : u32 = 256 ;
91
+ }
92
+
88
93
/// The nonce used by robonode in the auth tickets.
89
94
pub type AuthTicketNonce = Vec < u8 > ;
90
95
96
+ /// The nonce type in this pallet with bounded number of bytes at the nonce.
97
+ pub type BoundedAuthTicketNonce = WeakBoundedVec < u8 , AuthTicketNonceMaxBytes > ;
98
+
91
99
/// The auth ticket passed to us from the robonode.
92
100
#[ cfg_attr( feature = "std" , derive( Serialize , Deserialize ) ) ]
93
101
#[ derive( PartialEq , Eq , Default , Clone , Encode , Decode , Hash , Debug , TypeInfo ) ]
@@ -100,7 +108,7 @@ pub struct AuthTicket<PublicKey> {
100
108
101
109
/// The state that we keep in the blockchain for an active authentication.
102
110
#[ cfg_attr( feature = "std" , derive( Serialize , Deserialize ) ) ]
103
- #[ derive( PartialEq , Eq , Default , Clone , Encode , Decode , Hash , Debug , TypeInfo ) ]
111
+ #[ derive( PartialEq , Eq , Default , Clone , Encode , Decode , Hash , Debug , TypeInfo , MaxEncodedLen ) ]
104
112
pub struct Authentication < PublicKey , Moment > {
105
113
/// The public key of a validator.
106
114
pub public_key : PublicKey ,
@@ -119,10 +127,14 @@ pub struct Authentication<PublicKey, Moment> {
119
127
pub mod pallet {
120
128
use crate :: {
121
129
weights:: WeightInfo , AuthTicket , AuthTicketNonce , Authenticate , Authentication ,
122
- CurrentMoment , TryConvert , ValidatorSetUpdater , Verifier ,
130
+ BoundedAuthTicketNonce , CurrentMoment , TryConvert , ValidatorSetUpdater , Verifier ,
123
131
} ;
124
132
125
- use frame_support:: { pallet_prelude:: * , sp_tracing:: error, storage:: types:: ValueQuery } ;
133
+ use codec:: MaxEncodedLen ;
134
+ use frame_support:: {
135
+ dispatch:: DispatchResult , pallet_prelude:: * , sp_tracing:: error, storage:: types:: ValueQuery ,
136
+ WeakBoundedVec ,
137
+ } ;
126
138
use frame_system:: pallet_prelude:: * ;
127
139
use sp_runtime:: { app_crypto:: MaybeHash , traits:: AtLeast32Bit } ;
128
140
use sp_std:: prelude:: * ;
@@ -141,10 +153,15 @@ pub mod pallet {
141
153
+ Parameter
142
154
+ MaybeSerializeDeserialize
143
155
+ Verifier < Self :: RobonodeSignature >
144
- + Default ;
156
+ + Default
157
+ + MaxEncodedLen ;
145
158
146
159
/// The public key of the validator.
147
- type ValidatorPublicKey : Member + Parameter + MaybeSerializeDeserialize + MaybeHash ;
160
+ type ValidatorPublicKey : Member
161
+ + Parameter
162
+ + MaybeSerializeDeserialize
163
+ + MaybeHash
164
+ + MaxEncodedLen ;
148
165
149
166
/// The opaque auth ticket type.
150
167
type OpaqueAuthTicket : Parameter + AsRef < [ u8 ] > + Send + Sync ;
@@ -156,7 +173,12 @@ pub mod pallet {
156
173
> ;
157
174
158
175
/// Type used for expressing timestamp.
159
- type Moment : Parameter + Default + AtLeast32Bit + Copy + MaybeSerializeDeserialize ;
176
+ type Moment : Parameter
177
+ + Default
178
+ + AtLeast32Bit
179
+ + Copy
180
+ + MaybeSerializeDeserialize
181
+ + MaxEncodedLen ;
160
182
161
183
/// Type used for pretty printing the timestamp.
162
184
type DisplayMoment : From < Self :: Moment > + core:: fmt:: Display ;
@@ -172,10 +194,17 @@ pub mod pallet {
172
194
173
195
/// Weight information for extrinsics in this pallet.
174
196
type WeightInfo : WeightInfo ;
197
+
198
+ /// The maximum number of authentications.
199
+ type MaxAuthentications : Get < u32 > ;
200
+
201
+ /// The maximum number of nonces.
202
+ type MaxNonces : Get < u32 > ;
175
203
}
176
204
177
205
#[ pallet:: pallet]
178
206
#[ pallet:: generate_store( pub ( super ) trait Store ) ]
207
+ #[ pallet:: generate_storage_info]
179
208
pub struct Pallet < T > ( _ ) ;
180
209
181
210
/// The public key of the robonode.
@@ -186,13 +215,17 @@ pub mod pallet {
186
215
/// A list of all consumed nonces.
187
216
#[ pallet:: storage]
188
217
#[ pallet:: getter( fn consumed_auth_ticket_nonces) ]
189
- pub type ConsumedAuthTicketNonces < T > = StorageValue < _ , Vec < AuthTicketNonce > , ValueQuery > ;
218
+ pub type ConsumedAuthTicketNonces < T : Config > =
219
+ StorageValue < _ , WeakBoundedVec < BoundedAuthTicketNonce , T :: MaxNonces > , ValueQuery > ;
190
220
191
221
/// A list of all active authentications.
192
222
#[ pallet:: storage]
193
223
#[ pallet:: getter( fn active_authentications) ]
194
- pub type ActiveAuthentications < T : Config > =
195
- StorageValue < _ , Vec < Authentication < T :: ValidatorPublicKey , T :: Moment > > , ValueQuery > ;
224
+ pub type ActiveAuthentications < T : Config > = StorageValue <
225
+ _ ,
226
+ WeakBoundedVec < Authentication < T :: ValidatorPublicKey , T :: Moment > , T :: MaxAuthentications > ,
227
+ ValueQuery ,
228
+ > ;
196
229
197
230
#[ pallet:: genesis_config]
198
231
pub struct GenesisConfig < T : Config > {
@@ -217,9 +250,27 @@ pub mod pallet {
217
250
#[ pallet:: genesis_build]
218
251
impl < T : Config > GenesisBuild < T > for GenesisConfig < T > {
219
252
fn build ( & self ) {
253
+ let bounded_consumed_auth_ticket_nonces = WeakBoundedVec :: < _ , T :: MaxNonces > :: try_from (
254
+ self . consumed_auth_ticket_nonces
255
+ . iter ( )
256
+ . cloned ( )
257
+ . map ( |nonce| {
258
+ BoundedAuthTicketNonce :: try_from ( nonce)
259
+ . expect ( "Initial nonce len must be less than AuthTicketNonceMaxBytes" )
260
+ } )
261
+ . collect :: < Vec < _ > > ( ) ,
262
+ )
263
+ . expect ( "Initial nonces must be less than T::MaxNonces" ) ;
264
+
265
+ let bounded_active_authentications =
266
+ WeakBoundedVec :: < _ , T :: MaxAuthentications > :: try_from (
267
+ self . active_authentications . clone ( ) ,
268
+ )
269
+ . expect ( "Initial authentications must be less than T::MaxAuthentications" ) ;
270
+
220
271
<RobonodePublicKey < T > >:: put ( & self . robonode_public_key ) ;
221
- <ConsumedAuthTicketNonces < T > >:: put ( & self . consumed_auth_ticket_nonces ) ;
222
- <ActiveAuthentications < T > >:: put ( & self . active_authentications ) ;
272
+ <ConsumedAuthTicketNonces < T > >:: put ( bounded_consumed_auth_ticket_nonces ) ;
273
+ <ActiveAuthentications < T > >:: put ( bounded_active_authentications ) ;
223
274
224
275
<Pallet < T > >:: issue_validators_set_init ( & self . active_authentications ) ;
225
276
}
@@ -285,7 +336,7 @@ pub mod pallet {
285
336
/// Validate the incloming authentication attempt, checking the auth ticket data against
286
337
/// the passed input.
287
338
fn validate_authentication_attempt < ' a , T : Config > (
288
- consumed_auth_ticket_nonces : & ' a [ AuthTicketNonce ] ,
339
+ consumed_auth_ticket_nonces : & ' a [ BoundedAuthTicketNonce ] ,
289
340
active_authentications : & ' a [ Authentication < T :: ValidatorPublicKey , T :: Moment > ] ,
290
341
auth_ticket : & AuthTicket < T :: ValidatorPublicKey > ,
291
342
) -> Result < ( ) , AuthenticationAttemptValidationError < ' a , T > > {
@@ -318,7 +369,6 @@ pub mod pallet {
318
369
ensure_none ( origin) ?;
319
370
320
371
let auth_ticket = Self :: extract_auth_ticket_checked ( req) ?;
321
-
322
372
let public_key = auth_ticket. public_key . clone ( ) ;
323
373
324
374
// Update storage.
@@ -334,12 +384,35 @@ pub mod pallet {
334
384
335
385
// Update internal state.
336
386
let current_moment = T :: CurrentMoment :: now ( ) ;
337
- consumed_auth_ticket_nonces. push ( auth_ticket. nonce ) ;
338
- active_authentications. push ( Authentication {
387
+ let mut updated_consumed_auth_ticket_nonces =
388
+ consumed_auth_ticket_nonces. clone ( ) . into_inner ( ) ;
389
+
390
+ updated_consumed_auth_ticket_nonces. push (
391
+ BoundedAuthTicketNonce :: force_from (
392
+ auth_ticket. nonce ,
393
+ Some ( "bioauth::authenticate::auth_ticket_nonce" ) ,
394
+ ) ,
395
+ ) ;
396
+
397
+ * consumed_auth_ticket_nonces =
398
+ WeakBoundedVec :: < _ , T :: MaxNonces > :: force_from (
399
+ updated_consumed_auth_ticket_nonces,
400
+ Some ( "bioauth::authenticate::nonces" ) ,
401
+ ) ;
402
+
403
+ let mut updated_active_authentications =
404
+ active_authentications. clone ( ) . into_inner ( ) ;
405
+ updated_active_authentications. push ( Authentication {
339
406
public_key : public_key. clone ( ) ,
340
407
expires_at : current_moment + T :: AuthenticationsExpireAfter :: get ( ) ,
341
408
} ) ;
342
409
410
+ * active_authentications =
411
+ WeakBoundedVec :: < _ , T :: MaxAuthentications > :: force_from (
412
+ updated_active_authentications,
413
+ Some ( "bioauth::authentication::authentications" ) ,
414
+ ) ;
415
+
343
416
// Issue an update to the external validators set.
344
417
Self :: issue_validators_set_update ( active_authentications. as_slice ( ) ) ;
345
418
@@ -372,8 +445,15 @@ pub mod pallet {
372
445
let update_required =
373
446
possibly_expired_authentications_len != active_authentications. len ( ) ;
374
447
if update_required {
448
+ // We use force_from and None as a resulted active authentications Vec
449
+ // can't become bigger than it was. Just filtering was done before.
450
+ let bounded_active_authentications =
451
+ WeakBoundedVec :: < _ , T :: MaxAuthentications > :: force_from (
452
+ active_authentications. clone ( ) ,
453
+ None ,
454
+ ) ;
375
455
Self :: issue_validators_set_update ( active_authentications. as_slice ( ) ) ;
376
- <ActiveAuthentications < T > >:: put ( active_authentications ) ;
456
+ <ActiveAuthentications < T > >:: put ( bounded_active_authentications ) ;
377
457
}
378
458
379
459
T :: WeightInfo :: on_initialize ( update_required)
0 commit comments