@@ -20,6 +20,7 @@ use super::event::{DynamicNotarizationCreated, Event, LockedNotarizationCreated}
2020use super :: metadata:: ImmutableMetadata ;
2121use super :: operations:: { NotarizationImpl , NotarizationOperations } ;
2222use super :: state:: State ;
23+ use super :: timelock:: { LockMetadata , TimeLock } ;
2324use crate :: error:: Error ;
2425use crate :: package:: notarization_package_id;
2526
@@ -50,6 +51,38 @@ impl<M: Clone> CreateNotarization<M> {
5051 }
5152 }
5253
54+ /// Indicates if the invariants for `NotarizationMethod::Dynamic` are satisfied:
55+ ///
56+ /// - Dynamic notarization can only have transfer locking or no
57+ /// `immutable_metadata.locking`.
58+ /// If `immutable_metadata.locking` exists, all locks except `transfer_lock`
59+ /// must be `TimeLock::None`
60+ /// and the `transfer_lock` must not be `TimeLock::None`.
61+ fn are_dynamic_notarization_invariants_ok ( locking : & Option < LockMetadata > ) -> bool {
62+ match locking {
63+ Some ( lock_metadata) => {
64+ lock_metadata. delete_lock == TimeLock :: None
65+ && lock_metadata. update_lock == TimeLock :: None
66+ && lock_metadata. transfer_lock != TimeLock :: None
67+ }
68+ None => true ,
69+ }
70+ }
71+
72+ /// Indicates if the invariants for `NotarizationMethod::Locked` are satisfied:
73+ ///
74+ /// - `locking` must exist.
75+ /// - `update_lock` and `transfer_lock` must be `TimeLock::UntilDestroyed`.
76+ fn are_locked_notarization_invariants_ok ( locking : & Option < LockMetadata > ) -> bool {
77+ match locking {
78+ Some ( lock_metadata) => {
79+ lock_metadata. transfer_lock == TimeLock :: UntilDestroyed
80+ && lock_metadata. update_lock == TimeLock :: UntilDestroyed
81+ }
82+ None => false ,
83+ }
84+ }
85+
5386 /// Makes a [`ProgrammableTransaction`] for the [`CreateNotarization`] instance.
5487 async fn make_ptb ( & self , client : & impl CoreClientReadOnly ) -> Result < ProgrammableTransaction , Error > {
5588 let NotarizationBuilder {
@@ -74,6 +107,20 @@ impl<M: Clone> CreateNotarization<M> {
74107 ) ) ;
75108 }
76109
110+ // Construct the locking metadata for dynamic notarization
111+ let locking = transfer_lock. as_ref ( ) . map ( |t_lock| LockMetadata {
112+ update_lock : TimeLock :: None ,
113+ delete_lock : TimeLock :: None ,
114+ transfer_lock : t_lock. clone ( ) ,
115+ } ) ;
116+
117+ // Check invariants
118+ if !Self :: are_dynamic_notarization_invariants_ok ( & locking) {
119+ return Err ( Error :: InvalidArgument (
120+ "Dynamic notarization invariants are not satisfied" . to_string ( ) ,
121+ ) ) ;
122+ }
123+
77124 NotarizationImpl :: new_dynamic (
78125 package_id,
79126 state,
@@ -93,6 +140,20 @@ impl<M: Clone> CreateNotarization<M> {
93140 Error :: InvalidArgument ( "Delete lock is required for locked notarizations" . to_string ( ) )
94141 } ) ?;
95142
143+ // Construct the locking metadata for locked notarization
144+ let locking = Some ( LockMetadata {
145+ update_lock : TimeLock :: UntilDestroyed ,
146+ delete_lock : delete_lock. clone ( ) ,
147+ transfer_lock : TimeLock :: UntilDestroyed ,
148+ } ) ;
149+
150+ // Check invariants
151+ if !Self :: are_locked_notarization_invariants_ok ( & locking) {
152+ return Err ( Error :: InvalidArgument (
153+ "Locked notarization invariants are not satisfied" . to_string ( ) ,
154+ ) ) ;
155+ }
156+
96157 NotarizationImpl :: new_locked (
97158 package_id,
98159 state,
@@ -186,3 +247,42 @@ pub(crate) async fn get_object_ref_by_id_with_bcs<T: DeserializeOwned>(
186247
187248 Ok ( notarization)
188249}
250+
251+ #[ cfg( test) ]
252+ mod tests {
253+ use super :: * ;
254+
255+ #[ test]
256+ fn test_dynamic_notarization_invariants ( ) {
257+ let are_dynamic_notarization_invariants_ok = CreateNotarization :: < ( ) > :: are_dynamic_notarization_invariants_ok;
258+
259+ assert ! ( are_dynamic_notarization_invariants_ok( & None ) ) ;
260+ assert ! ( are_dynamic_notarization_invariants_ok( & Some ( LockMetadata {
261+ update_lock: TimeLock :: None ,
262+ delete_lock: TimeLock :: None ,
263+ transfer_lock: TimeLock :: UntilDestroyed ,
264+ } ) ) ) ;
265+ assert ! ( !are_dynamic_notarization_invariants_ok( & Some ( LockMetadata {
266+ update_lock: TimeLock :: None ,
267+ delete_lock: TimeLock :: None ,
268+ transfer_lock: TimeLock :: None ,
269+ } ) ) ) ;
270+ }
271+
272+ #[ test]
273+ fn test_locked_notarization_invariants ( ) {
274+ let are_locked_notarization_invariants_ok = CreateNotarization :: < ( ) > :: are_locked_notarization_invariants_ok;
275+
276+ assert ! ( !are_locked_notarization_invariants_ok( & None ) ) ;
277+ assert ! ( are_locked_notarization_invariants_ok( & Some ( LockMetadata {
278+ update_lock: TimeLock :: UntilDestroyed ,
279+ delete_lock: TimeLock :: UntilDestroyed ,
280+ transfer_lock: TimeLock :: UntilDestroyed ,
281+ } ) ) ) ;
282+ assert ! ( !are_locked_notarization_invariants_ok( & Some ( LockMetadata {
283+ update_lock: TimeLock :: UntilDestroyed ,
284+ delete_lock: TimeLock :: UntilDestroyed ,
285+ transfer_lock: TimeLock :: None ,
286+ } ) ) ) ;
287+ }
288+ }
0 commit comments