@@ -201,10 +201,9 @@ decl_module! {
201
201
// Bundle as a requirement.
202
202
let id = Self :: get_latest_requirement_id( ticker) + 1u32 ;
203
203
let mut new_req = ComplianceRequirement { sender_conditions, receiver_conditions, id } ;
204
- new_req. dedup( ) ;
205
204
206
- // Ensure issuers are limited in length.
207
- Self :: ensure_issuers_in_req_limited ( & new_req) ?;
205
+ // Dedup `ClaimType`s and ensure issuers are limited in length.
206
+ Self :: dedup_and_ensure_requirement_limited ( & mut new_req) ?;
208
207
209
208
// Add to existing requirements, and place a limit on the total complexity.
210
209
let mut asset_compliance = AssetCompliances :: get( ticker) ;
@@ -245,6 +244,9 @@ decl_module! {
245
244
246
245
/// Replaces an asset's compliance by ticker with a new compliance.
247
246
///
247
+ /// Compliance requirements will be sorted (ascending by id) before
248
+ /// replacing the current requirements.
249
+ ///
248
250
/// # Arguments
249
251
/// * `ticker` - the asset ticker,
250
252
/// * `asset_compliance - the new asset compliance.
@@ -265,14 +267,14 @@ decl_module! {
265
267
// Ensure there are no duplicate requirement ids.
266
268
let mut asset_compliance = asset_compliance;
267
269
let start_len = asset_compliance. len( ) ;
270
+ asset_compliance. sort_by_key( |r| r. id) ;
268
271
asset_compliance. dedup_by_key( |r| r. id) ;
269
272
ensure!( start_len == asset_compliance. len( ) , Error :: <T >:: DuplicateComplianceRequirements ) ;
270
273
271
- // Dedup `ClaimType`s in `TrustedFor::Specific` .
272
- asset_compliance. iter_mut( ) . for_each ( |r| r . dedup ( ) ) ;
274
+ // Dedup `ClaimType`s and ensure issuers are limited in length .
275
+ asset_compliance. iter_mut( ) . try_for_each ( Self :: dedup_and_ensure_requirement_limited ) ? ;
273
276
274
- // Ensure issuers are limited in length + limit the complexity.
275
- asset_compliance. iter( ) . try_for_each( Self :: ensure_issuers_in_req_limited) ?;
277
+ // Ensure the complexity is limited.
276
278
Self :: verify_compliance_complexity( & asset_compliance, ticker, 0 ) ?;
277
279
278
280
// Commit changes to storage + emit event.
@@ -400,19 +402,24 @@ decl_module! {
400
402
// Ensure `Scope::Custom(..)`s are limited.
401
403
Self :: ensure_custom_scopes_limited( new_req. conditions( ) ) ?;
402
404
403
- ensure!( Self :: get_latest_requirement_id( ticker) >= new_req. id, Error :: <T >:: InvalidComplianceRequirementId ) ;
404
-
405
405
let mut asset_compliance = AssetCompliances :: get( ticker) ;
406
406
let reqs = & mut asset_compliance. requirements;
407
- if let Some ( req) = reqs. iter_mut( ) . find( |req| req. id == new_req. id) {
408
- let mut new_req = new_req;
409
- new_req. dedup( ) ;
410
-
411
- * req = new_req. clone( ) ;
412
- Self :: verify_compliance_complexity( & reqs, ticker, 0 ) ?;
413
- AssetCompliances :: insert( & ticker, asset_compliance) ;
414
- Self :: deposit_event( Event :: ComplianceRequirementChanged ( did, ticker, new_req) ) ;
415
- }
407
+
408
+ // If the compliance requirement is not found, throw an error.
409
+ let pos = reqs. binary_search_by_key( & new_req. id, |req| req. id)
410
+ . map_err( |_| Error :: <T >:: InvalidComplianceRequirementId ) ?;
411
+
412
+ // Dedup `ClaimType`s and ensure issuers are limited in length.
413
+ let mut new_req = new_req;
414
+ Self :: dedup_and_ensure_requirement_limited( & mut new_req) ?;
415
+
416
+ // Update asset compliance and verify complexity is limited.
417
+ reqs[ pos] = new_req. clone( ) ;
418
+ Self :: verify_compliance_complexity( & reqs, ticker, 0 ) ?;
419
+
420
+ // Store updated asset compliance.
421
+ AssetCompliances :: insert( & ticker, asset_compliance) ;
422
+ Self :: deposit_event( Event :: ComplianceRequirementChanged ( did, ticker, new_req) ) ;
416
423
}
417
424
}
418
425
}
@@ -617,6 +624,14 @@ impl<T: Config> Module<T> {
617
624
. try_for_each ( Identity :: < T > :: ensure_custom_scopes_limited)
618
625
}
619
626
627
+ fn dedup_and_ensure_requirement_limited ( req : & mut ComplianceRequirement ) -> DispatchResult {
628
+ // Dedup `ClaimType`s in `TrustedFor::Specific`.
629
+ req. dedup ( ) ;
630
+
631
+ // Ensure issuers are limited in length.
632
+ Self :: ensure_issuers_in_req_limited ( req)
633
+ }
634
+
620
635
fn ensure_issuers_in_req_limited ( req : & ComplianceRequirement ) -> DispatchResult {
621
636
req. conditions ( ) . try_for_each ( |cond| {
622
637
ensure_length_ok :: < T > ( cond. issuers . len ( ) ) ?;
0 commit comments