2
2
3
3
#[ doc( inline) ]
4
4
pub use super :: attributes:: {
5
- ComputeAllocation , FreezingThreshold , MemoryAllocation , ReservedCyclesLimit ,
5
+ ComputeAllocation , FreezingThreshold , MemoryAllocation , ReservedCyclesLimit , WasmMemoryLimit ,
6
6
} ;
7
7
use super :: { ChunkHash , ManagementCanister } ;
8
8
use crate :: {
@@ -62,6 +62,16 @@ pub struct CanisterSettings {
62
62
/// If set to 0, disables the reservation mechanism for the canister.
63
63
/// Doing so will cause the canister to trap when it tries to allocate storage, if the subnet's usage exceeds 450 GiB.
64
64
pub reserved_cycles_limit : Option < Nat > ,
65
+
66
+ /// A soft limit on the Wasm memory usage of the canister.
67
+ ///
68
+ /// Update calls, timers, heartbeats, install, and post-upgrade fail if the
69
+ /// Wasm memory usage exceeds this limit. The main purpose of this field is
70
+ /// to protect against the case when the canister reaches the hard 4GiB
71
+ /// limit.
72
+ ///
73
+ /// Must be a number between 0 and 2^48^ (i.e 256TB), inclusively.
74
+ pub wasm_memory_limit : Option < Nat > ,
65
75
}
66
76
67
77
/// A builder for a `create_canister` call.
@@ -74,6 +84,7 @@ pub struct CreateCanisterBuilder<'agent, 'canister: 'agent> {
74
84
memory_allocation : Option < Result < MemoryAllocation , AgentError > > ,
75
85
freezing_threshold : Option < Result < FreezingThreshold , AgentError > > ,
76
86
reserved_cycles_limit : Option < Result < ReservedCyclesLimit , AgentError > > ,
87
+ wasm_memory_limit : Option < Result < WasmMemoryLimit , AgentError > > ,
77
88
is_provisional_create : bool ,
78
89
amount : Option < u128 > ,
79
90
specified_id : Option < Principal > ,
@@ -90,6 +101,7 @@ impl<'agent, 'canister: 'agent> CreateCanisterBuilder<'agent, 'canister> {
90
101
memory_allocation : None ,
91
102
freezing_threshold : None ,
92
103
reserved_cycles_limit : None ,
104
+ wasm_memory_limit : None ,
93
105
is_provisional_create : false ,
94
106
amount : None ,
95
107
specified_id : None ,
@@ -278,6 +290,32 @@ impl<'agent, 'canister: 'agent> CreateCanisterBuilder<'agent, 'canister> {
278
290
}
279
291
}
280
292
293
+ /// Pass in a Wasm memory limit value for the canister.
294
+ pub fn with_wasm_memory_limit < C , E > ( self , wasm_memory_limit : C ) -> Self
295
+ where
296
+ E : std:: fmt:: Display ,
297
+ C : TryInto < WasmMemoryLimit , Error = E > ,
298
+ {
299
+ self . with_optional_wasm_memory_limit ( Some ( wasm_memory_limit) )
300
+ }
301
+
302
+ /// Pass in a Wasm memory limit optional value for the canister. If this is [None],
303
+ /// it will revert the Wasm memory limit to default.
304
+ pub fn with_optional_wasm_memory_limit < E , C > ( self , wasm_memory_limit : Option < C > ) -> Self
305
+ where
306
+ E : std:: fmt:: Display ,
307
+ C : TryInto < WasmMemoryLimit , Error = E > ,
308
+ {
309
+ Self {
310
+ wasm_memory_limit : wasm_memory_limit. map ( |limit| {
311
+ limit
312
+ . try_into ( )
313
+ . map_err ( |e| AgentError :: MessageError ( format ! ( "{}" , e) ) )
314
+ } ) ,
315
+ ..self
316
+ }
317
+ }
318
+
281
319
/// Create an [AsyncCall] implementation that, when called, will create a
282
320
/// canister.
283
321
pub fn build ( self ) -> Result < impl ' agent + AsyncCall < ( Principal , ) > , AgentError > {
@@ -306,6 +344,11 @@ impl<'agent, 'canister: 'agent> CreateCanisterBuilder<'agent, 'canister> {
306
344
Some ( Ok ( x) ) => Some ( Nat :: from ( u128:: from ( x) ) ) ,
307
345
None => None ,
308
346
} ;
347
+ let wasm_memory_limit = match self . wasm_memory_limit {
348
+ Some ( Err ( x) ) => return Err ( AgentError :: MessageError ( format ! ( "{}" , x) ) ) ,
349
+ Some ( Ok ( x) ) => Some ( Nat :: from ( u64:: from ( x) ) ) ,
350
+ None => None ,
351
+ } ;
309
352
310
353
#[ derive( Deserialize , CandidType ) ]
311
354
struct Out {
@@ -327,6 +370,7 @@ impl<'agent, 'canister: 'agent> CreateCanisterBuilder<'agent, 'canister> {
327
370
memory_allocation,
328
371
freezing_threshold,
329
372
reserved_cycles_limit,
373
+ wasm_memory_limit,
330
374
} ,
331
375
specified_id : self . specified_id ,
332
376
} ;
@@ -343,6 +387,7 @@ impl<'agent, 'canister: 'agent> CreateCanisterBuilder<'agent, 'canister> {
343
387
memory_allocation,
344
388
freezing_threshold,
345
389
reserved_cycles_limit,
390
+ wasm_memory_limit,
346
391
} )
347
392
. with_effective_canister_id ( self . effective_canister_id )
348
393
} ;
@@ -808,6 +853,7 @@ pub struct UpdateCanisterBuilder<'agent, 'canister: 'agent> {
808
853
memory_allocation : Option < Result < MemoryAllocation , AgentError > > ,
809
854
freezing_threshold : Option < Result < FreezingThreshold , AgentError > > ,
810
855
reserved_cycles_limit : Option < Result < ReservedCyclesLimit , AgentError > > ,
856
+ wasm_memory_limit : Option < Result < WasmMemoryLimit , AgentError > > ,
811
857
}
812
858
813
859
impl < ' agent , ' canister : ' agent > UpdateCanisterBuilder < ' agent , ' canister > {
@@ -821,6 +867,7 @@ impl<'agent, 'canister: 'agent> UpdateCanisterBuilder<'agent, 'canister> {
821
867
memory_allocation : None ,
822
868
freezing_threshold : None ,
823
869
reserved_cycles_limit : None ,
870
+ wasm_memory_limit : None ,
824
871
}
825
872
}
826
873
@@ -963,6 +1010,32 @@ impl<'agent, 'canister: 'agent> UpdateCanisterBuilder<'agent, 'canister> {
963
1010
}
964
1011
}
965
1012
1013
+ /// Pass in a Wasm memory limit value for the canister.
1014
+ pub fn with_wasm_memory_limit < C , E > ( self , wasm_memory_limit : C ) -> Self
1015
+ where
1016
+ E : std:: fmt:: Display ,
1017
+ C : TryInto < WasmMemoryLimit , Error = E > ,
1018
+ {
1019
+ self . with_optional_wasm_memory_limit ( Some ( wasm_memory_limit) )
1020
+ }
1021
+
1022
+ /// Pass in a Wasm memory limit optional value for the canister. If this is [None],
1023
+ /// leaves the Wasm memory limit unchanged.
1024
+ pub fn with_optional_wasm_memory_limit < E , C > ( self , wasm_memory_limit : Option < C > ) -> Self
1025
+ where
1026
+ E : std:: fmt:: Display ,
1027
+ C : TryInto < WasmMemoryLimit , Error = E > ,
1028
+ {
1029
+ Self {
1030
+ wasm_memory_limit : wasm_memory_limit. map ( |limit| {
1031
+ limit
1032
+ . try_into ( )
1033
+ . map_err ( |e| AgentError :: MessageError ( format ! ( "{}" , e) ) )
1034
+ } ) ,
1035
+ ..self
1036
+ }
1037
+ }
1038
+
966
1039
/// Create an [AsyncCall] implementation that, when called, will update a
967
1040
/// canisters settings.
968
1041
pub fn build ( self ) -> Result < impl ' agent + AsyncCall < ( ) > , AgentError > {
@@ -997,6 +1070,11 @@ impl<'agent, 'canister: 'agent> UpdateCanisterBuilder<'agent, 'canister> {
997
1070
Some ( Ok ( x) ) => Some ( Nat :: from ( u128:: from ( x) ) ) ,
998
1071
None => None ,
999
1072
} ;
1073
+ let wasm_memory_limit = match self . wasm_memory_limit {
1074
+ Some ( Err ( x) ) => return Err ( AgentError :: MessageError ( format ! ( "{}" , x) ) ) ,
1075
+ Some ( Ok ( x) ) => Some ( Nat :: from ( u64:: from ( x) ) ) ,
1076
+ None => None ,
1077
+ } ;
1000
1078
1001
1079
Ok ( self
1002
1080
. canister
@@ -1009,6 +1087,7 @@ impl<'agent, 'canister: 'agent> UpdateCanisterBuilder<'agent, 'canister> {
1009
1087
memory_allocation,
1010
1088
freezing_threshold,
1011
1089
reserved_cycles_limit,
1090
+ wasm_memory_limit,
1012
1091
} ,
1013
1092
} )
1014
1093
. with_effective_canister_id ( self . canister_id )
0 commit comments