iota_protocol_config/
lib.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use std::{
6    cell::RefCell,
7    cmp::min,
8    sync::atomic::{AtomicBool, Ordering},
9};
10
11use clap::*;
12use iota_protocol_config_macros::{
13    ProtocolConfigAccessors, ProtocolConfigFeatureFlagsGetters, ProtocolConfigOverride,
14};
15use move_vm_config::verifier::VerifierConfig;
16use serde::{Deserialize, Serialize};
17use serde_with::skip_serializing_none;
18use tracing::{info, warn};
19
20/// The minimum and maximum protocol versions supported by this build.
21const MIN_PROTOCOL_VERSION: u64 = 1;
22pub const MAX_PROTOCOL_VERSION: u64 = 9;
23
24// Record history of protocol version allocations here:
25//
26// Version 1: Original version.
27// Version 2: Don't redistribute slashed staking rewards, fix computation of
28//            SystemEpochInfoEventV1.
29// Version 3: Set the `relocate_event_module` to be true so that the module that
30//            is associated as the "sending module" for an event is relocated by
31//            linkage.
32//            Add `Clock` based unlock to `Timelock` objects.
33// Version 4: Introduce the `max_type_to_layout_nodes` config that sets the
34//            maximal nodes which are allowed when converting to a type layout.
35// Version 5: Introduce fixed protocol-defined base fee, IotaSystemStateV2 and
36//            SystemEpochInfoEventV2.
37//            Disallow adding new modules in `deps-only` packages.
38//            Improve gas/wall time efficiency of some Move stdlib vector
39//            functions.
40//            Add new gas model version to update charging of functions.
41//            Enable proper conversion of certain type argument errors in the
42//            execution layer.
43// Version 6: Bound size of values created in the adapter.
44// Version 7: Improve handling of stake withdrawal from candidate validators.
45// Version 8: Variants as type nodes.
46//            Enable smart ancestor selection for testnet.
47//            Enable probing for accepted rounds in round prober for testnet.
48//            Switch to distributed vote scoring in consensus in testnet.
49//            Enable zstd compression for consensus tonic network in testnet.
50//            Enable consensus garbage collection for testnet
51//            Enable the new consensus commit rule for testnet.
52//            Enable min_free_execution_slot for the shared object congestion
53//            tracker in devnet.
54// Version 9: Disable smart ancestor selection for the testnet.
55//            Enable zstd compression for consensus tonic network in mainnet.
56//            Enable passkey auth in multisig for devnet.
57//            Remove the iota-bridge from the framework.
58
59#[derive(Copy, Clone, Debug, Hash, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
60pub struct ProtocolVersion(u64);
61
62impl ProtocolVersion {
63    // The minimum and maximum protocol version supported by this binary.
64    // Counterintuitively, this constant may change over time as support for old
65    // protocol versions is removed from the source. This ensures that when a
66    // new network (such as a testnet) is created, its genesis committee will
67    // use a protocol version that is actually supported by the binary.
68    pub const MIN: Self = Self(MIN_PROTOCOL_VERSION);
69
70    pub const MAX: Self = Self(MAX_PROTOCOL_VERSION);
71
72    #[cfg(not(msim))]
73    const MAX_ALLOWED: Self = Self::MAX;
74
75    // We create one additional "fake" version in simulator builds so that we can
76    // test upgrades.
77    #[cfg(msim)]
78    pub const MAX_ALLOWED: Self = Self(MAX_PROTOCOL_VERSION + 1);
79
80    pub fn new(v: u64) -> Self {
81        Self(v)
82    }
83
84    pub const fn as_u64(&self) -> u64 {
85        self.0
86    }
87
88    // For serde deserialization - we don't define a Default impl because there
89    // isn't a single universally appropriate default value.
90    pub fn max() -> Self {
91        Self::MAX
92    }
93}
94
95impl From<u64> for ProtocolVersion {
96    fn from(v: u64) -> Self {
97        Self::new(v)
98    }
99}
100
101impl std::ops::Sub<u64> for ProtocolVersion {
102    type Output = Self;
103    fn sub(self, rhs: u64) -> Self::Output {
104        Self::new(self.0 - rhs)
105    }
106}
107
108impl std::ops::Add<u64> for ProtocolVersion {
109    type Output = Self;
110    fn add(self, rhs: u64) -> Self::Output {
111        Self::new(self.0 + rhs)
112    }
113}
114
115#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Copy, PartialOrd, Ord, Eq, ValueEnum)]
116pub enum Chain {
117    Mainnet,
118    Testnet,
119    Unknown,
120}
121
122impl Default for Chain {
123    fn default() -> Self {
124        Self::Unknown
125    }
126}
127
128impl Chain {
129    pub fn as_str(self) -> &'static str {
130        match self {
131            Chain::Mainnet => "mainnet",
132            Chain::Testnet => "testnet",
133            Chain::Unknown => "unknown",
134        }
135    }
136}
137
138pub struct Error(pub String);
139
140// TODO: There are quite a few non boolean values in the feature flags. We
141// should move them out.
142/// Records on/off feature flags that may vary at each protocol version.
143#[derive(Default, Clone, Serialize, Deserialize, Debug, ProtocolConfigFeatureFlagsGetters)]
144struct FeatureFlags {
145    // Add feature flags here, e.g.:
146    // new_protocol_feature: bool,
147
148    // Disables unnecessary invariant check in the Move VM when swapping the value out of a local
149    // This flag is used to provide the correct MoveVM configuration for clients.
150    #[serde(skip_serializing_if = "is_true")]
151    disable_invariant_violation_check_in_swap_loc: bool,
152
153    // If true, checks no extra bytes in a compiled module
154    // This flag is used to provide the correct MoveVM configuration for clients.
155    #[serde(skip_serializing_if = "is_true")]
156    no_extraneous_module_bytes: bool,
157
158    // Enable zklogin auth
159    #[serde(skip_serializing_if = "is_false")]
160    zklogin_auth: bool,
161
162    // How we order transactions coming out of consensus before sending to execution.
163    #[serde(skip_serializing_if = "ConsensusTransactionOrdering::is_none")]
164    consensus_transaction_ordering: ConsensusTransactionOrdering,
165
166    #[serde(skip_serializing_if = "is_false")]
167    enable_jwk_consensus_updates: bool,
168
169    // If true, multisig containing zkLogin sig is accepted.
170    #[serde(skip_serializing_if = "is_false")]
171    accept_zklogin_in_multisig: bool,
172
173    // If true, use the hardened OTW check
174    // This flag is used to provide the correct MoveVM configuration for clients.
175    #[serde(skip_serializing_if = "is_true")]
176    hardened_otw_check: bool,
177
178    // Enable the poseidon hash function
179    #[serde(skip_serializing_if = "is_false")]
180    enable_poseidon: bool,
181
182    // Enable native function for msm.
183    #[serde(skip_serializing_if = "is_false")]
184    enable_group_ops_native_function_msm: bool,
185
186    // Controls the behavior of per object congestion control in consensus handler.
187    #[serde(skip_serializing_if = "PerObjectCongestionControlMode::is_none")]
188    per_object_congestion_control_mode: PerObjectCongestionControlMode,
189
190    // The consensus protocol to be used for the epoch.
191    #[serde(skip_serializing_if = "ConsensusChoice::is_mysticeti")]
192    consensus_choice: ConsensusChoice,
193
194    // Consensus network to use.
195    #[serde(skip_serializing_if = "ConsensusNetwork::is_tonic")]
196    consensus_network: ConsensusNetwork,
197
198    // Set the upper bound allowed for max_epoch in zklogin signature.
199    #[serde(skip_serializing_if = "Option::is_none")]
200    zklogin_max_epoch_upper_bound_delta: Option<u64>,
201
202    // Enable VDF
203    #[serde(skip_serializing_if = "is_false")]
204    enable_vdf: bool,
205
206    // Enable passkey auth (SIP-9)
207    #[serde(skip_serializing_if = "is_false")]
208    passkey_auth: bool,
209
210    // Rethrow type layout errors during serialization instead of trying to convert them.
211    // This flag is used to provide the correct MoveVM configuration for clients.
212    #[serde(skip_serializing_if = "is_true")]
213    rethrow_serialization_type_layout_errors: bool,
214
215    // Makes the event's sending module version-aware.
216    #[serde(skip_serializing_if = "is_false")]
217    relocate_event_module: bool,
218
219    // Enable a protocol-defined base gas price for all transactions.
220    #[serde(skip_serializing_if = "is_false")]
221    protocol_defined_base_fee: bool,
222
223    // Enable uncompressed group elements in BLS123-81 G1
224    #[serde(skip_serializing_if = "is_false")]
225    uncompressed_g1_group_elements: bool,
226
227    // Disallow adding new modules in `deps-only` packages.
228    #[serde(skip_serializing_if = "is_false")]
229    disallow_new_modules_in_deps_only_packages: bool,
230
231    // Enable v2 native charging for natives.
232    #[serde(skip_serializing_if = "is_false")]
233    native_charging_v2: bool,
234
235    // Properly convert certain type argument errors in the execution layer.
236    #[serde(skip_serializing_if = "is_false")]
237    convert_type_argument_error: bool,
238
239    // Probe rounds received by peers from every authority.
240    #[serde(skip_serializing_if = "is_false")]
241    consensus_round_prober: bool,
242
243    // Use distributed vote leader scoring strategy in consensus.
244    #[serde(skip_serializing_if = "is_false")]
245    consensus_distributed_vote_scoring_strategy: bool,
246
247    // Enables the new logic for collecting the subdag in the consensus linearizer. The new logic
248    // does not stop the recursion at the highest committed round for each authority, but
249    // allows to commit uncommitted blocks up to gc round (excluded) for that authority.
250    #[serde(skip_serializing_if = "is_false")]
251    consensus_linearize_subdag_v2: bool,
252
253    // Variants count as nodes
254    #[serde(skip_serializing_if = "is_false")]
255    variant_nodes: bool,
256
257    // Use smart ancestor selection in consensus.
258    #[serde(skip_serializing_if = "is_false")]
259    consensus_smart_ancestor_selection: bool,
260
261    // Probe accepted rounds in round prober.
262    #[serde(skip_serializing_if = "is_false")]
263    consensus_round_prober_probe_accepted_rounds: bool,
264
265    // If true, enable zstd compression for consensus tonic network.
266    #[serde(skip_serializing_if = "is_false")]
267    consensus_zstd_compression: bool,
268
269    // Use the minimum free execution slot to schedule execution of a transaction in the shared
270    // object congestion tracker.
271    #[serde(skip_serializing_if = "is_false")]
272    congestion_control_min_free_execution_slot: bool,
273
274    // If true, multisig containing passkey sig is accepted.
275    #[serde(skip_serializing_if = "is_false")]
276    accept_passkey_in_multisig: bool,
277}
278
279fn is_true(b: &bool) -> bool {
280    *b
281}
282
283fn is_false(b: &bool) -> bool {
284    !b
285}
286
287/// Ordering mechanism for transactions in one consensus output.
288#[derive(Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
289pub enum ConsensusTransactionOrdering {
290    /// No ordering. Transactions are processed in the order they appear in the
291    /// consensus output.
292    #[default]
293    None,
294    /// Order transactions by gas price, highest first.
295    ByGasPrice,
296}
297
298impl ConsensusTransactionOrdering {
299    pub fn is_none(&self) -> bool {
300        matches!(self, ConsensusTransactionOrdering::None)
301    }
302}
303
304// The config for per object congestion control in consensus handler.
305#[derive(Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
306pub enum PerObjectCongestionControlMode {
307    #[default]
308    None, // No congestion control.
309    TotalGasBudget, // Use txn gas budget as execution cost.
310    TotalTxCount,   // Use total txn count as execution cost.
311}
312
313impl PerObjectCongestionControlMode {
314    pub fn is_none(&self) -> bool {
315        matches!(self, PerObjectCongestionControlMode::None)
316    }
317}
318
319// Configuration options for consensus algorithm.
320#[derive(Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
321pub enum ConsensusChoice {
322    #[default]
323    Mysticeti,
324}
325
326impl ConsensusChoice {
327    pub fn is_mysticeti(&self) -> bool {
328        matches!(self, ConsensusChoice::Mysticeti)
329    }
330}
331
332// Configuration options for consensus network.
333#[derive(Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
334pub enum ConsensusNetwork {
335    #[default]
336    Tonic,
337}
338
339impl ConsensusNetwork {
340    pub fn is_tonic(&self) -> bool {
341        matches!(self, ConsensusNetwork::Tonic)
342    }
343}
344
345/// Constants that change the behavior of the protocol.
346///
347/// The value of each constant here must be fixed for a given protocol version.
348/// To change the value of a constant, advance the protocol version, and add
349/// support for it in `get_for_version` under the new version number.
350/// (below).
351///
352/// To add a new field to this struct, use the following procedure:
353/// - Advance the protocol version.
354/// - Add the field as a private `Option<T>` to the struct.
355/// - Initialize the field to `None` in prior protocol versions.
356/// - Initialize the field to `Some(val)` for your new protocol version.
357/// - Add a public getter that simply unwraps the field.
358/// - Two public getters of the form `field(&self) -> field_type` and
359///   `field_as_option(&self) -> Option<field_type>` will be automatically
360///   generated for you.
361/// Example for a field: `new_constant: Option<u64>`
362/// ```rust,ignore
363///      pub fn new_constant(&self) -> u64 {
364///         self.new_constant.expect(Self::CONSTANT_ERR_MSG)
365///     }
366///      pub fn new_constant_as_option(&self) -> Option<u64> {
367///         self.new_constant.expect(Self::CONSTANT_ERR_MSG)
368///     }
369/// ```
370/// With `pub fn new_constant(&self) -> u64`, if the constant is accessed in a
371/// protocol version in which it is not defined, the validator will crash.
372/// (Crashing is necessary because this type of error would almost always result
373/// in forking if not prevented here). If you don't want the validator to crash,
374/// you can use the `pub fn new_constant_as_option(&self) -> Option<u64>`
375/// getter, which will return `None` if the field is not defined at that
376/// version.
377/// - If you want a customized getter, you can add a method in the impl.
378#[skip_serializing_none]
379#[derive(Clone, Serialize, Debug, ProtocolConfigAccessors, ProtocolConfigOverride)]
380pub struct ProtocolConfig {
381    pub version: ProtocolVersion,
382
383    feature_flags: FeatureFlags,
384
385    // ==== Transaction input limits ====
386
387    //
388    /// Maximum serialized size of a transaction (in bytes).
389    max_tx_size_bytes: Option<u64>,
390
391    /// Maximum number of input objects to a transaction. Enforced by the
392    /// transaction input checker
393    max_input_objects: Option<u64>,
394
395    /// Max size of objects a transaction can write to disk after completion.
396    /// Enforce by the IOTA adapter. This is the sum of the serialized size
397    /// of all objects written to disk. The max size of individual objects
398    /// on the other hand is `max_move_object_size`.
399    max_size_written_objects: Option<u64>,
400    /// Max size of objects a system transaction can write to disk after
401    /// completion. Enforce by the IOTA adapter. Similar to
402    /// `max_size_written_objects` but for system transactions.
403    max_size_written_objects_system_tx: Option<u64>,
404
405    /// Maximum size of serialized transaction effects.
406    max_serialized_tx_effects_size_bytes: Option<u64>,
407
408    /// Maximum size of serialized transaction effects for system transactions.
409    max_serialized_tx_effects_size_bytes_system_tx: Option<u64>,
410
411    /// Maximum number of gas payment objects for a transaction.
412    max_gas_payment_objects: Option<u32>,
413
414    /// Maximum number of modules in a Publish transaction.
415    max_modules_in_publish: Option<u32>,
416
417    /// Maximum number of transitive dependencies in a package when publishing.
418    max_package_dependencies: Option<u32>,
419
420    /// Maximum number of arguments in a move call or a
421    /// ProgrammableTransaction's TransferObjects command.
422    max_arguments: Option<u32>,
423
424    /// Maximum number of total type arguments, computed recursively.
425    max_type_arguments: Option<u32>,
426
427    /// Maximum depth of an individual type argument.
428    max_type_argument_depth: Option<u32>,
429
430    /// Maximum size of a Pure CallArg.
431    max_pure_argument_size: Option<u32>,
432
433    /// Maximum number of Commands in a ProgrammableTransaction.
434    max_programmable_tx_commands: Option<u32>,
435
436    // ==== Move VM, Move bytecode verifier, and execution limits ===
437
438    //
439    /// Maximum Move bytecode version the VM understands. All older versions are
440    /// accepted.
441    move_binary_format_version: Option<u32>,
442    min_move_binary_format_version: Option<u32>,
443
444    /// Configuration controlling binary tables size.
445    binary_module_handles: Option<u16>,
446    binary_struct_handles: Option<u16>,
447    binary_function_handles: Option<u16>,
448    binary_function_instantiations: Option<u16>,
449    binary_signatures: Option<u16>,
450    binary_constant_pool: Option<u16>,
451    binary_identifiers: Option<u16>,
452    binary_address_identifiers: Option<u16>,
453    binary_struct_defs: Option<u16>,
454    binary_struct_def_instantiations: Option<u16>,
455    binary_function_defs: Option<u16>,
456    binary_field_handles: Option<u16>,
457    binary_field_instantiations: Option<u16>,
458    binary_friend_decls: Option<u16>,
459    binary_enum_defs: Option<u16>,
460    binary_enum_def_instantiations: Option<u16>,
461    binary_variant_handles: Option<u16>,
462    binary_variant_instantiation_handles: Option<u16>,
463
464    /// Maximum size of the `contents` part of an object, in bytes. Enforced by
465    /// the IOTA adapter when effects are produced.
466    max_move_object_size: Option<u64>,
467
468    // TODO: Option<increase to 500 KB. currently, publishing a package > 500 KB exceeds the max
469    // computation gas cost
470    /// Maximum size of a Move package object, in bytes. Enforced by the IOTA
471    /// adapter at the end of a publish transaction.
472    max_move_package_size: Option<u64>,
473
474    /// Max number of publish or upgrade commands allowed in a programmable
475    /// transaction block.
476    max_publish_or_upgrade_per_ptb: Option<u64>,
477
478    /// Maximum gas budget in NANOS that a transaction can use.
479    max_tx_gas: Option<u64>,
480
481    /// Maximum amount of the proposed gas price in NANOS (defined in the
482    /// transaction).
483    max_gas_price: Option<u64>,
484
485    /// The max computation bucket for gas. This is the max that can be charged
486    /// for computation.
487    max_gas_computation_bucket: Option<u64>,
488
489    // Define the value used to round up computation gas charges
490    gas_rounding_step: Option<u64>,
491
492    /// Maximum number of nested loops. Enforced by the Move bytecode verifier.
493    max_loop_depth: Option<u64>,
494
495    /// Maximum number of type arguments that can be bound to generic type
496    /// parameters. Enforced by the Move bytecode verifier.
497    max_generic_instantiation_length: Option<u64>,
498
499    /// Maximum number of parameters that a Move function can have. Enforced by
500    /// the Move bytecode verifier.
501    max_function_parameters: Option<u64>,
502
503    /// Maximum number of basic blocks that a Move function can have. Enforced
504    /// by the Move bytecode verifier.
505    max_basic_blocks: Option<u64>,
506
507    /// Maximum stack size value. Enforced by the Move bytecode verifier.
508    max_value_stack_size: Option<u64>,
509
510    /// Maximum number of "type nodes", a metric for how big a SignatureToken
511    /// will be when expanded into a fully qualified type. Enforced by the Move
512    /// bytecode verifier.
513    max_type_nodes: Option<u64>,
514
515    /// Maximum number of push instructions in one function. Enforced by the
516    /// Move bytecode verifier.
517    max_push_size: Option<u64>,
518
519    /// Maximum number of struct definitions in a module. Enforced by the Move
520    /// bytecode verifier.
521    max_struct_definitions: Option<u64>,
522
523    /// Maximum number of function definitions in a module. Enforced by the Move
524    /// bytecode verifier.
525    max_function_definitions: Option<u64>,
526
527    /// Maximum number of fields allowed in a struct definition. Enforced by the
528    /// Move bytecode verifier.
529    max_fields_in_struct: Option<u64>,
530
531    /// Maximum dependency depth. Enforced by the Move linker when loading
532    /// dependent modules.
533    max_dependency_depth: Option<u64>,
534
535    /// Maximum number of Move events that a single transaction can emit.
536    /// Enforced by the VM during execution.
537    max_num_event_emit: Option<u64>,
538
539    /// Maximum number of new IDs that a single transaction can create. Enforced
540    /// by the VM during execution.
541    max_num_new_move_object_ids: Option<u64>,
542
543    /// Maximum number of new IDs that a single system transaction can create.
544    /// Enforced by the VM during execution.
545    max_num_new_move_object_ids_system_tx: Option<u64>,
546
547    /// Maximum number of IDs that a single transaction can delete. Enforced by
548    /// the VM during execution.
549    max_num_deleted_move_object_ids: Option<u64>,
550
551    /// Maximum number of IDs that a single system transaction can delete.
552    /// Enforced by the VM during execution.
553    max_num_deleted_move_object_ids_system_tx: Option<u64>,
554
555    /// Maximum number of IDs that a single transaction can transfer. Enforced
556    /// by the VM during execution.
557    max_num_transferred_move_object_ids: Option<u64>,
558
559    /// Maximum number of IDs that a single system transaction can transfer.
560    /// Enforced by the VM during execution.
561    max_num_transferred_move_object_ids_system_tx: Option<u64>,
562
563    /// Maximum size of a Move user event. Enforced by the VM during execution.
564    max_event_emit_size: Option<u64>,
565
566    /// Maximum size of a Move user event. Enforced by the VM during execution.
567    max_event_emit_size_total: Option<u64>,
568
569    /// Maximum length of a vector in Move. Enforced by the VM during execution,
570    /// and for constants, by the verifier.
571    max_move_vector_len: Option<u64>,
572
573    /// Maximum length of an `Identifier` in Move. Enforced by the bytecode
574    /// verifier at signing.
575    max_move_identifier_len: Option<u64>,
576
577    /// Maximum depth of a Move value within the VM.
578    max_move_value_depth: Option<u64>,
579
580    /// Maximum number of variants in an enum. Enforced by the bytecode verifier
581    /// at signing.
582    max_move_enum_variants: Option<u64>,
583
584    /// Maximum number of back edges in Move function. Enforced by the bytecode
585    /// verifier at signing.
586    max_back_edges_per_function: Option<u64>,
587
588    /// Maximum number of back edges in Move module. Enforced by the bytecode
589    /// verifier at signing.
590    max_back_edges_per_module: Option<u64>,
591
592    /// Maximum number of meter `ticks` spent verifying a Move function.
593    /// Enforced by the bytecode verifier at signing.
594    max_verifier_meter_ticks_per_function: Option<u64>,
595
596    /// Maximum number of meter `ticks` spent verifying a Move function.
597    /// Enforced by the bytecode verifier at signing.
598    max_meter_ticks_per_module: Option<u64>,
599
600    /// Maximum number of meter `ticks` spent verifying a Move package. Enforced
601    /// by the bytecode verifier at signing.
602    max_meter_ticks_per_package: Option<u64>,
603
604    // === Object runtime internal operation limits ====
605    // These affect dynamic fields
606
607    //
608    /// Maximum number of cached objects in the object runtime ObjectStore.
609    /// Enforced by object runtime during execution
610    object_runtime_max_num_cached_objects: Option<u64>,
611
612    /// Maximum number of cached objects in the object runtime ObjectStore in
613    /// system transaction. Enforced by object runtime during execution
614    object_runtime_max_num_cached_objects_system_tx: Option<u64>,
615
616    /// Maximum number of stored objects accessed by object runtime ObjectStore.
617    /// Enforced by object runtime during execution
618    object_runtime_max_num_store_entries: Option<u64>,
619
620    /// Maximum number of stored objects accessed by object runtime ObjectStore
621    /// in system transaction. Enforced by object runtime during execution
622    object_runtime_max_num_store_entries_system_tx: Option<u64>,
623
624    // === Execution gas costs ====
625
626    //
627    /// Base cost for any IOTA transaction
628    base_tx_cost_fixed: Option<u64>,
629
630    /// Additional cost for a transaction that publishes a package
631    /// i.e., the base cost of such a transaction is base_tx_cost_fixed +
632    /// package_publish_cost_fixed
633    package_publish_cost_fixed: Option<u64>,
634
635    /// Cost per byte of a Move call transaction
636    /// i.e., the cost of such a transaction is base_cost +
637    /// (base_tx_cost_per_byte * size)
638    base_tx_cost_per_byte: Option<u64>,
639
640    /// Cost per byte for a transaction that publishes a package
641    package_publish_cost_per_byte: Option<u64>,
642
643    // Per-byte cost of reading an object during transaction execution
644    obj_access_cost_read_per_byte: Option<u64>,
645
646    // Per-byte cost of writing an object during transaction execution
647    obj_access_cost_mutate_per_byte: Option<u64>,
648
649    // Per-byte cost of deleting an object during transaction execution
650    obj_access_cost_delete_per_byte: Option<u64>,
651
652    /// Per-byte cost charged for each input object to a transaction.
653    /// Meant to approximate the cost of checking locks for each object
654    // TODO: Option<I'm not sure that this cost makes sense. Checking locks is "free"
655    // in the sense that an invalid tx that can never be committed/pay gas can
656    // force validators to check an arbitrary number of locks. If those checks are
657    // "free" for invalid transactions, why charge for them in valid transactions
658    // TODO: Option<if we keep this, I think we probably want it to be a fixed cost rather
659    // than a per-byte cost. checking an object lock should not require loading an
660    // entire object, just consulting an ID -> tx digest map
661    obj_access_cost_verify_per_byte: Option<u64>,
662
663    // Maximal nodes which are allowed when converting to a type layout.
664    max_type_to_layout_nodes: Option<u64>,
665
666    // Maximal size in bytes that a PTB value can be
667    max_ptb_value_size: Option<u64>,
668
669    // === Gas version. gas model ===
670
671    //
672    /// Gas model version, what code we are using to charge gas
673    gas_model_version: Option<u64>,
674
675    // === Storage gas costs ===
676
677    //
678    /// Per-byte cost of storing an object in the IOTA global object store. Some
679    /// of this cost may be refundable if the object is later freed
680    obj_data_cost_refundable: Option<u64>,
681
682    // Per-byte cost of storing an object in the IOTA transaction log (e.g., in
683    // CertifiedTransactionEffects) This depends on the size of various fields including the
684    // effects TODO: Option<I don't fully understand this^ and more details would be useful
685    obj_metadata_cost_non_refundable: Option<u64>,
686
687    // === Tokenomics ===
688
689    // TODO: Option<this should be changed to u64.
690    /// Sender of a txn that touches an object will get this percent of the
691    /// storage rebate back. In basis point.
692    storage_rebate_rate: Option<u64>,
693
694    /// The share of rewards that will be slashed and redistributed is 50%.
695    /// In basis point.
696    reward_slashing_rate: Option<u64>,
697
698    /// Unit storage gas price, Nanos per internal gas unit.
699    storage_gas_price: Option<u64>,
700
701    // Base gas price for computation gas, nanos per computation unit.
702    base_gas_price: Option<u64>,
703
704    /// The number of tokens minted as a validator subsidy per epoch.
705    validator_target_reward: Option<u64>,
706
707    // === Core Protocol ===
708
709    //
710    /// Max number of transactions per checkpoint.
711    /// Note that this is a protocol constant and not a config as validators
712    /// must have this set to the same value, otherwise they *will* fork.
713    max_transactions_per_checkpoint: Option<u64>,
714
715    /// Max size of a checkpoint in bytes.
716    /// Note that this is a protocol constant and not a config as validators
717    /// must have this set to the same value, otherwise they *will* fork.
718    max_checkpoint_size_bytes: Option<u64>,
719
720    /// A protocol upgrade always requires 2f+1 stake to agree. We support a
721    /// buffer of additional stake (as a fraction of f, expressed in basis
722    /// points) that is required before an upgrade can happen automatically.
723    /// 10000bps would indicate that complete unanimity is required (all
724    /// 3f+1 must vote), while 0bps would indicate that 2f+1 is sufficient.
725    buffer_stake_for_protocol_upgrade_bps: Option<u64>,
726
727    // === Native Function Costs ===
728
729    // `address` module
730    // Cost params for the Move native function `address::from_bytes(bytes: vector<u8>)`
731    address_from_bytes_cost_base: Option<u64>,
732    // Cost params for the Move native function `address::to_u256(address): u256`
733    address_to_u256_cost_base: Option<u64>,
734    // Cost params for the Move native function `address::from_u256(u256): address`
735    address_from_u256_cost_base: Option<u64>,
736
737    // `config` module
738    // Cost params for the Move native function `read_setting_impl<Name: copy + drop + store,
739    // SettingValue: key + store, SettingDataValue: store, Value: copy + drop + store,
740    // >(config: address, name: address, current_epoch: u64): Option<Value>`
741    config_read_setting_impl_cost_base: Option<u64>,
742    config_read_setting_impl_cost_per_byte: Option<u64>,
743
744    // `dynamic_field` module
745    // Cost params for the Move native function `hash_type_and_key<K: copy + drop + store>(parent:
746    // address, k: K): address`
747    dynamic_field_hash_type_and_key_cost_base: Option<u64>,
748    dynamic_field_hash_type_and_key_type_cost_per_byte: Option<u64>,
749    dynamic_field_hash_type_and_key_value_cost_per_byte: Option<u64>,
750    dynamic_field_hash_type_and_key_type_tag_cost_per_byte: Option<u64>,
751    // Cost params for the Move native function `add_child_object<Child: key>(parent: address,
752    // child: Child)`
753    dynamic_field_add_child_object_cost_base: Option<u64>,
754    dynamic_field_add_child_object_type_cost_per_byte: Option<u64>,
755    dynamic_field_add_child_object_value_cost_per_byte: Option<u64>,
756    dynamic_field_add_child_object_struct_tag_cost_per_byte: Option<u64>,
757    // Cost params for the Move native function `borrow_child_object_mut<Child: key>(parent: &mut
758    // UID, id: address): &mut Child`
759    dynamic_field_borrow_child_object_cost_base: Option<u64>,
760    dynamic_field_borrow_child_object_child_ref_cost_per_byte: Option<u64>,
761    dynamic_field_borrow_child_object_type_cost_per_byte: Option<u64>,
762    // Cost params for the Move native function `remove_child_object<Child: key>(parent: address,
763    // id: address): Child`
764    dynamic_field_remove_child_object_cost_base: Option<u64>,
765    dynamic_field_remove_child_object_child_cost_per_byte: Option<u64>,
766    dynamic_field_remove_child_object_type_cost_per_byte: Option<u64>,
767    // Cost params for the Move native function `has_child_object(parent: address, id: address):
768    // bool`
769    dynamic_field_has_child_object_cost_base: Option<u64>,
770    // Cost params for the Move native function `has_child_object_with_ty<Child: key>(parent:
771    // address, id: address): bool`
772    dynamic_field_has_child_object_with_ty_cost_base: Option<u64>,
773    dynamic_field_has_child_object_with_ty_type_cost_per_byte: Option<u64>,
774    dynamic_field_has_child_object_with_ty_type_tag_cost_per_byte: Option<u64>,
775
776    // `event` module
777    // Cost params for the Move native function `event::emit<T: copy + drop>(event: T)`
778    event_emit_cost_base: Option<u64>,
779    event_emit_value_size_derivation_cost_per_byte: Option<u64>,
780    event_emit_tag_size_derivation_cost_per_byte: Option<u64>,
781    event_emit_output_cost_per_byte: Option<u64>,
782
783    //  `object` module
784    // Cost params for the Move native function `borrow_uid<T: key>(obj: &T): &UID`
785    object_borrow_uid_cost_base: Option<u64>,
786    // Cost params for the Move native function `delete_impl(id: address)`
787    object_delete_impl_cost_base: Option<u64>,
788    // Cost params for the Move native function `record_new_uid(id: address)`
789    object_record_new_uid_cost_base: Option<u64>,
790
791    // Transfer
792    // Cost params for the Move native function `transfer_impl<T: key>(obj: T, recipient: address)`
793    transfer_transfer_internal_cost_base: Option<u64>,
794    // Cost params for the Move native function `freeze_object<T: key>(obj: T)`
795    transfer_freeze_object_cost_base: Option<u64>,
796    // Cost params for the Move native function `share_object<T: key>(obj: T)`
797    transfer_share_object_cost_base: Option<u64>,
798    // Cost params for the Move native function
799    // `receive_object<T: key>(p: &mut UID, recv: Receiving<T>T)`
800    transfer_receive_object_cost_base: Option<u64>,
801
802    // TxContext
803    // Cost params for the Move native function `transfer_impl<T: key>(obj: T, recipient: address)`
804    tx_context_derive_id_cost_base: Option<u64>,
805
806    // Types
807    // Cost params for the Move native function `is_one_time_witness<T: drop>(_: &T): bool`
808    types_is_one_time_witness_cost_base: Option<u64>,
809    types_is_one_time_witness_type_tag_cost_per_byte: Option<u64>,
810    types_is_one_time_witness_type_cost_per_byte: Option<u64>,
811
812    // Validator
813    // Cost params for the Move native function `validate_metadata_bcs(metadata: vector<u8>)`
814    validator_validate_metadata_cost_base: Option<u64>,
815    validator_validate_metadata_data_cost_per_byte: Option<u64>,
816
817    // Crypto natives
818    crypto_invalid_arguments_cost: Option<u64>,
819    // bls12381::bls12381_min_sig_verify
820    bls12381_bls12381_min_sig_verify_cost_base: Option<u64>,
821    bls12381_bls12381_min_sig_verify_msg_cost_per_byte: Option<u64>,
822    bls12381_bls12381_min_sig_verify_msg_cost_per_block: Option<u64>,
823
824    // bls12381::bls12381_min_pk_verify
825    bls12381_bls12381_min_pk_verify_cost_base: Option<u64>,
826    bls12381_bls12381_min_pk_verify_msg_cost_per_byte: Option<u64>,
827    bls12381_bls12381_min_pk_verify_msg_cost_per_block: Option<u64>,
828
829    // ecdsa_k1::ecrecover
830    ecdsa_k1_ecrecover_keccak256_cost_base: Option<u64>,
831    ecdsa_k1_ecrecover_keccak256_msg_cost_per_byte: Option<u64>,
832    ecdsa_k1_ecrecover_keccak256_msg_cost_per_block: Option<u64>,
833    ecdsa_k1_ecrecover_sha256_cost_base: Option<u64>,
834    ecdsa_k1_ecrecover_sha256_msg_cost_per_byte: Option<u64>,
835    ecdsa_k1_ecrecover_sha256_msg_cost_per_block: Option<u64>,
836
837    // ecdsa_k1::decompress_pubkey
838    ecdsa_k1_decompress_pubkey_cost_base: Option<u64>,
839
840    // ecdsa_k1::secp256k1_verify
841    ecdsa_k1_secp256k1_verify_keccak256_cost_base: Option<u64>,
842    ecdsa_k1_secp256k1_verify_keccak256_msg_cost_per_byte: Option<u64>,
843    ecdsa_k1_secp256k1_verify_keccak256_msg_cost_per_block: Option<u64>,
844    ecdsa_k1_secp256k1_verify_sha256_cost_base: Option<u64>,
845    ecdsa_k1_secp256k1_verify_sha256_msg_cost_per_byte: Option<u64>,
846    ecdsa_k1_secp256k1_verify_sha256_msg_cost_per_block: Option<u64>,
847
848    // ecdsa_r1::ecrecover
849    ecdsa_r1_ecrecover_keccak256_cost_base: Option<u64>,
850    ecdsa_r1_ecrecover_keccak256_msg_cost_per_byte: Option<u64>,
851    ecdsa_r1_ecrecover_keccak256_msg_cost_per_block: Option<u64>,
852    ecdsa_r1_ecrecover_sha256_cost_base: Option<u64>,
853    ecdsa_r1_ecrecover_sha256_msg_cost_per_byte: Option<u64>,
854    ecdsa_r1_ecrecover_sha256_msg_cost_per_block: Option<u64>,
855
856    // ecdsa_r1::secp256k1_verify
857    ecdsa_r1_secp256r1_verify_keccak256_cost_base: Option<u64>,
858    ecdsa_r1_secp256r1_verify_keccak256_msg_cost_per_byte: Option<u64>,
859    ecdsa_r1_secp256r1_verify_keccak256_msg_cost_per_block: Option<u64>,
860    ecdsa_r1_secp256r1_verify_sha256_cost_base: Option<u64>,
861    ecdsa_r1_secp256r1_verify_sha256_msg_cost_per_byte: Option<u64>,
862    ecdsa_r1_secp256r1_verify_sha256_msg_cost_per_block: Option<u64>,
863
864    // ecvrf::verify
865    ecvrf_ecvrf_verify_cost_base: Option<u64>,
866    ecvrf_ecvrf_verify_alpha_string_cost_per_byte: Option<u64>,
867    ecvrf_ecvrf_verify_alpha_string_cost_per_block: Option<u64>,
868
869    // ed25519
870    ed25519_ed25519_verify_cost_base: Option<u64>,
871    ed25519_ed25519_verify_msg_cost_per_byte: Option<u64>,
872    ed25519_ed25519_verify_msg_cost_per_block: Option<u64>,
873
874    // groth16::prepare_verifying_key
875    groth16_prepare_verifying_key_bls12381_cost_base: Option<u64>,
876    groth16_prepare_verifying_key_bn254_cost_base: Option<u64>,
877
878    // groth16::verify_groth16_proof_internal
879    groth16_verify_groth16_proof_internal_bls12381_cost_base: Option<u64>,
880    groth16_verify_groth16_proof_internal_bls12381_cost_per_public_input: Option<u64>,
881    groth16_verify_groth16_proof_internal_bn254_cost_base: Option<u64>,
882    groth16_verify_groth16_proof_internal_bn254_cost_per_public_input: Option<u64>,
883    groth16_verify_groth16_proof_internal_public_input_cost_per_byte: Option<u64>,
884
885    // hash::blake2b256
886    hash_blake2b256_cost_base: Option<u64>,
887    hash_blake2b256_data_cost_per_byte: Option<u64>,
888    hash_blake2b256_data_cost_per_block: Option<u64>,
889
890    // hash::keccak256
891    hash_keccak256_cost_base: Option<u64>,
892    hash_keccak256_data_cost_per_byte: Option<u64>,
893    hash_keccak256_data_cost_per_block: Option<u64>,
894
895    // poseidon::poseidon_bn254
896    poseidon_bn254_cost_base: Option<u64>,
897    poseidon_bn254_cost_per_block: Option<u64>,
898
899    // group_ops
900    group_ops_bls12381_decode_scalar_cost: Option<u64>,
901    group_ops_bls12381_decode_g1_cost: Option<u64>,
902    group_ops_bls12381_decode_g2_cost: Option<u64>,
903    group_ops_bls12381_decode_gt_cost: Option<u64>,
904    group_ops_bls12381_scalar_add_cost: Option<u64>,
905    group_ops_bls12381_g1_add_cost: Option<u64>,
906    group_ops_bls12381_g2_add_cost: Option<u64>,
907    group_ops_bls12381_gt_add_cost: Option<u64>,
908    group_ops_bls12381_scalar_sub_cost: Option<u64>,
909    group_ops_bls12381_g1_sub_cost: Option<u64>,
910    group_ops_bls12381_g2_sub_cost: Option<u64>,
911    group_ops_bls12381_gt_sub_cost: Option<u64>,
912    group_ops_bls12381_scalar_mul_cost: Option<u64>,
913    group_ops_bls12381_g1_mul_cost: Option<u64>,
914    group_ops_bls12381_g2_mul_cost: Option<u64>,
915    group_ops_bls12381_gt_mul_cost: Option<u64>,
916    group_ops_bls12381_scalar_div_cost: Option<u64>,
917    group_ops_bls12381_g1_div_cost: Option<u64>,
918    group_ops_bls12381_g2_div_cost: Option<u64>,
919    group_ops_bls12381_gt_div_cost: Option<u64>,
920    group_ops_bls12381_g1_hash_to_base_cost: Option<u64>,
921    group_ops_bls12381_g2_hash_to_base_cost: Option<u64>,
922    group_ops_bls12381_g1_hash_to_cost_per_byte: Option<u64>,
923    group_ops_bls12381_g2_hash_to_cost_per_byte: Option<u64>,
924    group_ops_bls12381_g1_msm_base_cost: Option<u64>,
925    group_ops_bls12381_g2_msm_base_cost: Option<u64>,
926    group_ops_bls12381_g1_msm_base_cost_per_input: Option<u64>,
927    group_ops_bls12381_g2_msm_base_cost_per_input: Option<u64>,
928    group_ops_bls12381_msm_max_len: Option<u32>,
929    group_ops_bls12381_pairing_cost: Option<u64>,
930    group_ops_bls12381_g1_to_uncompressed_g1_cost: Option<u64>,
931    group_ops_bls12381_uncompressed_g1_to_g1_cost: Option<u64>,
932    group_ops_bls12381_uncompressed_g1_sum_base_cost: Option<u64>,
933    group_ops_bls12381_uncompressed_g1_sum_cost_per_term: Option<u64>,
934    group_ops_bls12381_uncompressed_g1_sum_max_terms: Option<u64>,
935
936    // hmac::hmac_sha3_256
937    hmac_hmac_sha3_256_cost_base: Option<u64>,
938    hmac_hmac_sha3_256_input_cost_per_byte: Option<u64>,
939    hmac_hmac_sha3_256_input_cost_per_block: Option<u64>,
940
941    // zklogin::check_zklogin_id
942    check_zklogin_id_cost_base: Option<u64>,
943    // zklogin::check_zklogin_issuer
944    check_zklogin_issuer_cost_base: Option<u64>,
945
946    vdf_verify_vdf_cost: Option<u64>,
947    vdf_hash_to_input_cost: Option<u64>,
948
949    // Stdlib costs
950    bcs_per_byte_serialized_cost: Option<u64>,
951    bcs_legacy_min_output_size_cost: Option<u64>,
952    bcs_failure_cost: Option<u64>,
953
954    hash_sha2_256_base_cost: Option<u64>,
955    hash_sha2_256_per_byte_cost: Option<u64>,
956    hash_sha2_256_legacy_min_input_len_cost: Option<u64>,
957    hash_sha3_256_base_cost: Option<u64>,
958    hash_sha3_256_per_byte_cost: Option<u64>,
959    hash_sha3_256_legacy_min_input_len_cost: Option<u64>,
960    type_name_get_base_cost: Option<u64>,
961    type_name_get_per_byte_cost: Option<u64>,
962
963    string_check_utf8_base_cost: Option<u64>,
964    string_check_utf8_per_byte_cost: Option<u64>,
965    string_is_char_boundary_base_cost: Option<u64>,
966    string_sub_string_base_cost: Option<u64>,
967    string_sub_string_per_byte_cost: Option<u64>,
968    string_index_of_base_cost: Option<u64>,
969    string_index_of_per_byte_pattern_cost: Option<u64>,
970    string_index_of_per_byte_searched_cost: Option<u64>,
971
972    vector_empty_base_cost: Option<u64>,
973    vector_length_base_cost: Option<u64>,
974    vector_push_back_base_cost: Option<u64>,
975    vector_push_back_legacy_per_abstract_memory_unit_cost: Option<u64>,
976    vector_borrow_base_cost: Option<u64>,
977    vector_pop_back_base_cost: Option<u64>,
978    vector_destroy_empty_base_cost: Option<u64>,
979    vector_swap_base_cost: Option<u64>,
980    debug_print_base_cost: Option<u64>,
981    debug_print_stack_trace_base_cost: Option<u64>,
982
983    // === Execution Version ===
984    execution_version: Option<u64>,
985
986    // Dictates the threshold (percentage of stake) that is used to calculate the "bad" nodes to be
987    // swapped when creating the consensus schedule. The values should be of the range [0 - 33].
988    // Anything above 33 (f) will not be allowed.
989    consensus_bad_nodes_stake_threshold: Option<u64>,
990
991    max_jwk_votes_per_validator_per_epoch: Option<u64>,
992    // The maximum age of a JWK in epochs before it is removed from the AuthenticatorState object.
993    // Applied at the end of an epoch as a delta from the new epoch value, so setting this to 1
994    // will cause the new epoch to start with JWKs from the previous epoch still valid.
995    max_age_of_jwk_in_epochs: Option<u64>,
996
997    // === random beacon ===
998    /// Maximum allowed precision loss when reducing voting weights for the
999    /// random beacon protocol.
1000    random_beacon_reduction_allowed_delta: Option<u16>,
1001
1002    /// Minimum number of shares below which voting weights will not be reduced
1003    /// for the random beacon protocol.
1004    random_beacon_reduction_lower_bound: Option<u32>,
1005
1006    /// Consensus Round after which DKG should be aborted and randomness
1007    /// disabled for the epoch, if it hasn't already completed.
1008    random_beacon_dkg_timeout_round: Option<u32>,
1009
1010    /// Minimum interval between consecutive rounds of generated randomness.
1011    random_beacon_min_round_interval_ms: Option<u64>,
1012
1013    /// Version of the random beacon DKG protocol.
1014    /// 0 was deprecated (and currently not supported), 1 is the default
1015    /// version.
1016    random_beacon_dkg_version: Option<u64>,
1017
1018    /// The maximum serialized transaction size (in bytes) accepted by
1019    /// consensus. `consensus_max_transaction_size_bytes` should include
1020    /// space for additional metadata, on top of the `max_tx_size_bytes`
1021    /// value.
1022    consensus_max_transaction_size_bytes: Option<u64>,
1023    /// The maximum size of transactions included in a consensus block.
1024    consensus_max_transactions_in_block_bytes: Option<u64>,
1025    /// The maximum number of transactions included in a consensus block.
1026    consensus_max_num_transactions_in_block: Option<u64>,
1027
1028    /// The max number of consensus rounds a transaction can be deferred due to
1029    /// shared object congestion. Transactions will be cancelled after this
1030    /// many rounds.
1031    max_deferral_rounds_for_congestion_control: Option<u64>,
1032
1033    /// Minimum interval of commit timestamps between consecutive checkpoints.
1034    min_checkpoint_interval_ms: Option<u64>,
1035
1036    /// Version number to use for version_specific_data in `CheckpointSummary`.
1037    checkpoint_summary_version_specific_data: Option<u64>,
1038
1039    /// The max number of transactions that can be included in a single Soft
1040    /// Bundle.
1041    max_soft_bundle_size: Option<u64>,
1042
1043    /// Deprecated because of bridge removal.
1044    /// Whether to try to form bridge committee
1045    // Note: this is not a feature flag because we want to distinguish between
1046    // `None` and `Some(false)`, as committee was already finalized on Testnet.
1047    bridge_should_try_to_finalize_committee: Option<bool>,
1048
1049    /// The max accumulated txn execution cost per object in a mysticeti commit.
1050    /// Transactions in a commit will be deferred once their touch shared
1051    /// objects hit this limit.
1052    max_accumulated_txn_cost_per_object_in_mysticeti_commit: Option<u64>,
1053
1054    /// Maximum number of committee (validators taking part in consensus)
1055    /// validators at any moment. We do not allow the number of committee
1056    /// validators in any epoch to go above this.
1057    max_committee_members_count: Option<u64>,
1058
1059    /// Configures the garbage collection depth for consensus. When is unset or
1060    /// `0` then the garbage collection is disabled.
1061    consensus_gc_depth: Option<u32>,
1062}
1063
1064// feature flags
1065impl ProtocolConfig {
1066    // Add checks for feature flag support here, e.g.:
1067    // pub fn check_new_protocol_feature_supported(&self) -> Result<(), Error> {
1068    //     if self.feature_flags.new_protocol_feature_supported {
1069    //         Ok(())
1070    //     } else {
1071    //         Err(Error(format!(
1072    //             "new_protocol_feature is not supported at {:?}",
1073    //             self.version
1074    //         )))
1075    //     }
1076    // }
1077
1078    pub fn disable_invariant_violation_check_in_swap_loc(&self) -> bool {
1079        self.feature_flags
1080            .disable_invariant_violation_check_in_swap_loc
1081    }
1082
1083    pub fn no_extraneous_module_bytes(&self) -> bool {
1084        self.feature_flags.no_extraneous_module_bytes
1085    }
1086
1087    pub fn zklogin_auth(&self) -> bool {
1088        self.feature_flags.zklogin_auth
1089    }
1090
1091    pub fn consensus_transaction_ordering(&self) -> ConsensusTransactionOrdering {
1092        self.feature_flags.consensus_transaction_ordering
1093    }
1094
1095    pub fn enable_jwk_consensus_updates(&self) -> bool {
1096        self.feature_flags.enable_jwk_consensus_updates
1097    }
1098
1099    // this function only exists for readability in the genesis code.
1100    pub fn create_authenticator_state_in_genesis(&self) -> bool {
1101        self.enable_jwk_consensus_updates()
1102    }
1103
1104    pub fn dkg_version(&self) -> u64 {
1105        // Version 0 was deprecated and removed, the default is 1 if not set.
1106        self.random_beacon_dkg_version.unwrap_or(1)
1107    }
1108
1109    pub fn accept_zklogin_in_multisig(&self) -> bool {
1110        self.feature_flags.accept_zklogin_in_multisig
1111    }
1112
1113    pub fn zklogin_max_epoch_upper_bound_delta(&self) -> Option<u64> {
1114        self.feature_flags.zklogin_max_epoch_upper_bound_delta
1115    }
1116
1117    pub fn hardened_otw_check(&self) -> bool {
1118        self.feature_flags.hardened_otw_check
1119    }
1120
1121    pub fn enable_poseidon(&self) -> bool {
1122        self.feature_flags.enable_poseidon
1123    }
1124
1125    pub fn enable_group_ops_native_function_msm(&self) -> bool {
1126        self.feature_flags.enable_group_ops_native_function_msm
1127    }
1128
1129    pub fn per_object_congestion_control_mode(&self) -> PerObjectCongestionControlMode {
1130        self.feature_flags.per_object_congestion_control_mode
1131    }
1132
1133    pub fn consensus_choice(&self) -> ConsensusChoice {
1134        self.feature_flags.consensus_choice
1135    }
1136
1137    pub fn consensus_network(&self) -> ConsensusNetwork {
1138        self.feature_flags.consensus_network
1139    }
1140
1141    pub fn enable_vdf(&self) -> bool {
1142        self.feature_flags.enable_vdf
1143    }
1144
1145    pub fn passkey_auth(&self) -> bool {
1146        self.feature_flags.passkey_auth
1147    }
1148
1149    pub fn max_transaction_size_bytes(&self) -> u64 {
1150        // Provide a default value if protocol config version is too low.
1151        self.consensus_max_transaction_size_bytes
1152            .unwrap_or(256 * 1024)
1153    }
1154
1155    pub fn max_transactions_in_block_bytes(&self) -> u64 {
1156        // Provide a default value if protocol config version is too low.
1157        self.consensus_max_transactions_in_block_bytes
1158            .unwrap_or(512 * 1024)
1159    }
1160
1161    pub fn max_num_transactions_in_block(&self) -> u64 {
1162        // 500 is the value used before this field is introduced.
1163        self.consensus_max_num_transactions_in_block.unwrap_or(500)
1164    }
1165
1166    pub fn rethrow_serialization_type_layout_errors(&self) -> bool {
1167        self.feature_flags.rethrow_serialization_type_layout_errors
1168    }
1169
1170    pub fn relocate_event_module(&self) -> bool {
1171        self.feature_flags.relocate_event_module
1172    }
1173
1174    pub fn protocol_defined_base_fee(&self) -> bool {
1175        self.feature_flags.protocol_defined_base_fee
1176    }
1177
1178    pub fn uncompressed_g1_group_elements(&self) -> bool {
1179        self.feature_flags.uncompressed_g1_group_elements
1180    }
1181
1182    pub fn disallow_new_modules_in_deps_only_packages(&self) -> bool {
1183        self.feature_flags
1184            .disallow_new_modules_in_deps_only_packages
1185    }
1186
1187    pub fn native_charging_v2(&self) -> bool {
1188        self.feature_flags.native_charging_v2
1189    }
1190
1191    pub fn consensus_round_prober(&self) -> bool {
1192        self.feature_flags.consensus_round_prober
1193    }
1194
1195    pub fn consensus_distributed_vote_scoring_strategy(&self) -> bool {
1196        self.feature_flags
1197            .consensus_distributed_vote_scoring_strategy
1198    }
1199
1200    pub fn gc_depth(&self) -> u32 {
1201        if cfg!(msim) {
1202            // exercise a very low gc_depth
1203            min(5, self.consensus_gc_depth.unwrap_or(0))
1204        } else {
1205            self.consensus_gc_depth.unwrap_or(0)
1206        }
1207    }
1208
1209    pub fn consensus_linearize_subdag_v2(&self) -> bool {
1210        let res = self.feature_flags.consensus_linearize_subdag_v2;
1211        assert!(
1212            !res || self.gc_depth() > 0,
1213            "The consensus linearize sub dag V2 requires GC to be enabled"
1214        );
1215        res
1216    }
1217
1218    pub fn variant_nodes(&self) -> bool {
1219        self.feature_flags.variant_nodes
1220    }
1221
1222    pub fn consensus_smart_ancestor_selection(&self) -> bool {
1223        self.feature_flags.consensus_smart_ancestor_selection
1224    }
1225
1226    pub fn consensus_round_prober_probe_accepted_rounds(&self) -> bool {
1227        self.feature_flags
1228            .consensus_round_prober_probe_accepted_rounds
1229    }
1230
1231    pub fn consensus_zstd_compression(&self) -> bool {
1232        self.feature_flags.consensus_zstd_compression
1233    }
1234
1235    pub fn congestion_control_min_free_execution_slot(&self) -> bool {
1236        self.feature_flags
1237            .congestion_control_min_free_execution_slot
1238    }
1239
1240    pub fn accept_passkey_in_multisig(&self) -> bool {
1241        self.feature_flags.accept_passkey_in_multisig
1242    }
1243}
1244
1245#[cfg(not(msim))]
1246static POISON_VERSION_METHODS: AtomicBool = const { AtomicBool::new(false) };
1247
1248// Use a thread local in sim tests for test isolation.
1249#[cfg(msim)]
1250thread_local! {
1251    static POISON_VERSION_METHODS: AtomicBool = const { AtomicBool::new(false) };
1252}
1253
1254// Instantiations for each protocol version.
1255impl ProtocolConfig {
1256    /// Get the value ProtocolConfig that are in effect during the given
1257    /// protocol version.
1258    pub fn get_for_version(version: ProtocolVersion, chain: Chain) -> Self {
1259        // ProtocolVersion can be deserialized so we need to check it here as well.
1260        assert!(
1261            version >= ProtocolVersion::MIN,
1262            "Network protocol version is {:?}, but the minimum supported version by the binary is {:?}. Please upgrade the binary.",
1263            version,
1264            ProtocolVersion::MIN.0,
1265        );
1266        assert!(
1267            version <= ProtocolVersion::MAX_ALLOWED,
1268            "Network protocol version is {:?}, but the maximum supported version by the binary is {:?}. Please upgrade the binary.",
1269            version,
1270            ProtocolVersion::MAX_ALLOWED.0,
1271        );
1272
1273        let mut ret = Self::get_for_version_impl(version, chain);
1274        ret.version = version;
1275
1276        ret = CONFIG_OVERRIDE.with(|ovr| {
1277            if let Some(override_fn) = &*ovr.borrow() {
1278                warn!(
1279                    "overriding ProtocolConfig settings with custom settings (you should not see this log outside of tests)"
1280                );
1281                override_fn(version, ret)
1282            } else {
1283                ret
1284            }
1285        });
1286
1287        if std::env::var("IOTA_PROTOCOL_CONFIG_OVERRIDE_ENABLE").is_ok() {
1288            warn!(
1289                "overriding ProtocolConfig settings with custom settings; this may break non-local networks"
1290            );
1291            let overrides: ProtocolConfigOptional =
1292                serde_env::from_env_with_prefix("IOTA_PROTOCOL_CONFIG_OVERRIDE")
1293                    .expect("failed to parse ProtocolConfig override env variables");
1294            overrides.apply_to(&mut ret);
1295        }
1296
1297        ret
1298    }
1299
1300    /// Get the value ProtocolConfig that are in effect during the given
1301    /// protocol version. Or none if the version is not supported.
1302    pub fn get_for_version_if_supported(version: ProtocolVersion, chain: Chain) -> Option<Self> {
1303        if version.0 >= ProtocolVersion::MIN.0 && version.0 <= ProtocolVersion::MAX_ALLOWED.0 {
1304            let mut ret = Self::get_for_version_impl(version, chain);
1305            ret.version = version;
1306            Some(ret)
1307        } else {
1308            None
1309        }
1310    }
1311
1312    #[cfg(not(msim))]
1313    pub fn poison_get_for_min_version() {
1314        POISON_VERSION_METHODS.store(true, Ordering::Relaxed);
1315    }
1316
1317    #[cfg(not(msim))]
1318    fn load_poison_get_for_min_version() -> bool {
1319        POISON_VERSION_METHODS.load(Ordering::Relaxed)
1320    }
1321
1322    #[cfg(msim)]
1323    pub fn poison_get_for_min_version() {
1324        POISON_VERSION_METHODS.with(|p| p.store(true, Ordering::Relaxed));
1325    }
1326
1327    #[cfg(msim)]
1328    fn load_poison_get_for_min_version() -> bool {
1329        POISON_VERSION_METHODS.with(|p| p.load(Ordering::Relaxed))
1330    }
1331
1332    pub fn convert_type_argument_error(&self) -> bool {
1333        self.feature_flags.convert_type_argument_error
1334    }
1335
1336    /// Convenience to get the constants at the current minimum supported
1337    /// version. Mainly used by client code that may not yet be
1338    /// protocol-version aware.
1339    pub fn get_for_min_version() -> Self {
1340        if Self::load_poison_get_for_min_version() {
1341            panic!("get_for_min_version called on validator");
1342        }
1343        ProtocolConfig::get_for_version(ProtocolVersion::MIN, Chain::Unknown)
1344    }
1345
1346    /// CAREFUL! - You probably want to use `get_for_version` instead.
1347    ///
1348    /// Convenience to get the constants at the current maximum supported
1349    /// version. Mainly used by genesis. Note well that this function uses
1350    /// the max version supported locally by the node, which is not
1351    /// necessarily the current version of the network. ALSO, this function
1352    /// disregards chain specific config (by using Chain::Unknown), thereby
1353    /// potentially returning a protocol config that is incorrect for some
1354    /// feature flags. Definitely safe for testing and for protocol version
1355    /// 11 and prior.
1356    #[expect(non_snake_case)]
1357    pub fn get_for_max_version_UNSAFE() -> Self {
1358        if Self::load_poison_get_for_min_version() {
1359            panic!("get_for_max_version_UNSAFE called on validator");
1360        }
1361        ProtocolConfig::get_for_version(ProtocolVersion::MAX, Chain::Unknown)
1362    }
1363
1364    fn get_for_version_impl(version: ProtocolVersion, chain: Chain) -> Self {
1365        #[cfg(msim)]
1366        {
1367            // populate the fake simulator version # with a different base tx cost.
1368            if version > ProtocolVersion::MAX {
1369                let mut config = Self::get_for_version_impl(ProtocolVersion::MAX, Chain::Unknown);
1370                config.base_tx_cost_fixed = Some(config.base_tx_cost_fixed() + 1000);
1371                return config;
1372            }
1373        }
1374
1375        // IMPORTANT: Never modify the value of any constant for a pre-existing protocol
1376        // version. To change the values here you must create a new protocol
1377        // version with the new values!
1378        let mut cfg = Self {
1379            version,
1380
1381            feature_flags: Default::default(),
1382
1383            max_tx_size_bytes: Some(128 * 1024),
1384            // We need this number to be at least 100x less than
1385            // `max_serialized_tx_effects_size_bytes`otherwise effects can be huge
1386            max_input_objects: Some(2048),
1387            max_serialized_tx_effects_size_bytes: Some(512 * 1024),
1388            max_serialized_tx_effects_size_bytes_system_tx: Some(512 * 1024 * 16),
1389            max_gas_payment_objects: Some(256),
1390            max_modules_in_publish: Some(64),
1391            max_package_dependencies: Some(32),
1392            max_arguments: Some(512),
1393            max_type_arguments: Some(16),
1394            max_type_argument_depth: Some(16),
1395            max_pure_argument_size: Some(16 * 1024),
1396            max_programmable_tx_commands: Some(1024),
1397            move_binary_format_version: Some(7),
1398            min_move_binary_format_version: Some(6),
1399            binary_module_handles: Some(100),
1400            binary_struct_handles: Some(300),
1401            binary_function_handles: Some(1500),
1402            binary_function_instantiations: Some(750),
1403            binary_signatures: Some(1000),
1404            binary_constant_pool: Some(4000),
1405            binary_identifiers: Some(10000),
1406            binary_address_identifiers: Some(100),
1407            binary_struct_defs: Some(200),
1408            binary_struct_def_instantiations: Some(100),
1409            binary_function_defs: Some(1000),
1410            binary_field_handles: Some(500),
1411            binary_field_instantiations: Some(250),
1412            binary_friend_decls: Some(100),
1413            binary_enum_defs: None,
1414            binary_enum_def_instantiations: None,
1415            binary_variant_handles: None,
1416            binary_variant_instantiation_handles: None,
1417            max_move_object_size: Some(250 * 1024),
1418            max_move_package_size: Some(100 * 1024),
1419            max_publish_or_upgrade_per_ptb: Some(5),
1420            // max gas budget is in NANOS and an absolute value 50IOTA
1421            max_tx_gas: Some(50_000_000_000),
1422            max_gas_price: Some(100_000),
1423            max_gas_computation_bucket: Some(5_000_000),
1424            max_loop_depth: Some(5),
1425            max_generic_instantiation_length: Some(32),
1426            max_function_parameters: Some(128),
1427            max_basic_blocks: Some(1024),
1428            max_value_stack_size: Some(1024),
1429            max_type_nodes: Some(256),
1430            max_push_size: Some(10000),
1431            max_struct_definitions: Some(200),
1432            max_function_definitions: Some(1000),
1433            max_fields_in_struct: Some(32),
1434            max_dependency_depth: Some(100),
1435            max_num_event_emit: Some(1024),
1436            max_num_new_move_object_ids: Some(2048),
1437            max_num_new_move_object_ids_system_tx: Some(2048 * 16),
1438            max_num_deleted_move_object_ids: Some(2048),
1439            max_num_deleted_move_object_ids_system_tx: Some(2048 * 16),
1440            max_num_transferred_move_object_ids: Some(2048),
1441            max_num_transferred_move_object_ids_system_tx: Some(2048 * 16),
1442            max_event_emit_size: Some(250 * 1024),
1443            max_move_vector_len: Some(256 * 1024),
1444            max_type_to_layout_nodes: None,
1445            max_ptb_value_size: None,
1446
1447            max_back_edges_per_function: Some(10_000),
1448            max_back_edges_per_module: Some(10_000),
1449
1450            max_verifier_meter_ticks_per_function: Some(16_000_000),
1451
1452            max_meter_ticks_per_module: Some(16_000_000),
1453            max_meter_ticks_per_package: Some(16_000_000),
1454
1455            object_runtime_max_num_cached_objects: Some(1000),
1456            object_runtime_max_num_cached_objects_system_tx: Some(1000 * 16),
1457            object_runtime_max_num_store_entries: Some(1000),
1458            object_runtime_max_num_store_entries_system_tx: Some(1000 * 16),
1459            // min gas budget is in NANOS and an absolute value 1000 NANOS or 0.000001IOTA
1460            base_tx_cost_fixed: Some(1_000),
1461            package_publish_cost_fixed: Some(1_000),
1462            base_tx_cost_per_byte: Some(0),
1463            package_publish_cost_per_byte: Some(80),
1464            obj_access_cost_read_per_byte: Some(15),
1465            obj_access_cost_mutate_per_byte: Some(40),
1466            obj_access_cost_delete_per_byte: Some(40),
1467            obj_access_cost_verify_per_byte: Some(200),
1468            obj_data_cost_refundable: Some(100),
1469            obj_metadata_cost_non_refundable: Some(50),
1470            gas_model_version: Some(1),
1471            storage_rebate_rate: Some(10000),
1472            // Change reward slashing rate to 100%.
1473            reward_slashing_rate: Some(10000),
1474            storage_gas_price: Some(76),
1475            base_gas_price: None,
1476            // The initial subsidy (target reward) for validators per epoch.
1477            // Refer to the IOTA tokenomics for the origin of this value.
1478            validator_target_reward: Some(767_000 * 1_000_000_000),
1479            max_transactions_per_checkpoint: Some(10_000),
1480            max_checkpoint_size_bytes: Some(30 * 1024 * 1024),
1481
1482            // For now, perform upgrades with a bare quorum of validators.
1483            buffer_stake_for_protocol_upgrade_bps: Some(5000),
1484
1485            // === Native Function Costs ===
1486            // `address` module
1487            // Cost params for the Move native function `address::from_bytes(bytes: vector<u8>)`
1488            address_from_bytes_cost_base: Some(52),
1489            // Cost params for the Move native function `address::to_u256(address): u256`
1490            address_to_u256_cost_base: Some(52),
1491            // Cost params for the Move native function `address::from_u256(u256): address`
1492            address_from_u256_cost_base: Some(52),
1493
1494            // `config` module
1495            // Cost params for the Move native function `read_setting_impl``
1496            config_read_setting_impl_cost_base: Some(100),
1497            config_read_setting_impl_cost_per_byte: Some(40),
1498
1499            // `dynamic_field` module
1500            // Cost params for the Move native function `hash_type_and_key<K: copy + drop +
1501            // store>(parent: address, k: K): address`
1502            dynamic_field_hash_type_and_key_cost_base: Some(100),
1503            dynamic_field_hash_type_and_key_type_cost_per_byte: Some(2),
1504            dynamic_field_hash_type_and_key_value_cost_per_byte: Some(2),
1505            dynamic_field_hash_type_and_key_type_tag_cost_per_byte: Some(2),
1506            // Cost params for the Move native function `add_child_object<Child: key>(parent:
1507            // address, child: Child)`
1508            dynamic_field_add_child_object_cost_base: Some(100),
1509            dynamic_field_add_child_object_type_cost_per_byte: Some(10),
1510            dynamic_field_add_child_object_value_cost_per_byte: Some(10),
1511            dynamic_field_add_child_object_struct_tag_cost_per_byte: Some(10),
1512            // Cost params for the Move native function `borrow_child_object_mut<Child: key>(parent:
1513            // &mut UID, id: address): &mut Child`
1514            dynamic_field_borrow_child_object_cost_base: Some(100),
1515            dynamic_field_borrow_child_object_child_ref_cost_per_byte: Some(10),
1516            dynamic_field_borrow_child_object_type_cost_per_byte: Some(10),
1517            // Cost params for the Move native function `remove_child_object<Child: key>(parent:
1518            // address, id: address): Child`
1519            dynamic_field_remove_child_object_cost_base: Some(100),
1520            dynamic_field_remove_child_object_child_cost_per_byte: Some(2),
1521            dynamic_field_remove_child_object_type_cost_per_byte: Some(2),
1522            // Cost params for the Move native function `has_child_object(parent: address, id:
1523            // address): bool`
1524            dynamic_field_has_child_object_cost_base: Some(100),
1525            // Cost params for the Move native function `has_child_object_with_ty<Child:
1526            // key>(parent: address, id: address): bool`
1527            dynamic_field_has_child_object_with_ty_cost_base: Some(100),
1528            dynamic_field_has_child_object_with_ty_type_cost_per_byte: Some(2),
1529            dynamic_field_has_child_object_with_ty_type_tag_cost_per_byte: Some(2),
1530
1531            // `event` module
1532            // Cost params for the Move native function `event::emit<T: copy + drop>(event: T)`
1533            event_emit_cost_base: Some(52),
1534            event_emit_value_size_derivation_cost_per_byte: Some(2),
1535            event_emit_tag_size_derivation_cost_per_byte: Some(5),
1536            event_emit_output_cost_per_byte: Some(10),
1537
1538            //  `object` module
1539            // Cost params for the Move native function `borrow_uid<T: key>(obj: &T): &UID`
1540            object_borrow_uid_cost_base: Some(52),
1541            // Cost params for the Move native function `delete_impl(id: address)`
1542            object_delete_impl_cost_base: Some(52),
1543            // Cost params for the Move native function `record_new_uid(id: address)`
1544            object_record_new_uid_cost_base: Some(52),
1545
1546            // `transfer` module
1547            // Cost params for the Move native function `transfer_impl<T: key>(obj: T, recipient:
1548            // address)`
1549            transfer_transfer_internal_cost_base: Some(52),
1550            // Cost params for the Move native function `freeze_object<T: key>(obj: T)`
1551            transfer_freeze_object_cost_base: Some(52),
1552            // Cost params for the Move native function `share_object<T: key>(obj: T)`
1553            transfer_share_object_cost_base: Some(52),
1554            transfer_receive_object_cost_base: Some(52),
1555
1556            // `tx_context` module
1557            // Cost params for the Move native function `transfer_impl<T: key>(obj: T, recipient:
1558            // address)`
1559            tx_context_derive_id_cost_base: Some(52),
1560
1561            // `types` module
1562            // Cost params for the Move native function `is_one_time_witness<T: drop>(_: &T): bool`
1563            types_is_one_time_witness_cost_base: Some(52),
1564            types_is_one_time_witness_type_tag_cost_per_byte: Some(2),
1565            types_is_one_time_witness_type_cost_per_byte: Some(2),
1566
1567            // `validator` module
1568            // Cost params for the Move native function `validate_metadata_bcs(metadata:
1569            // vector<u8>)`
1570            validator_validate_metadata_cost_base: Some(52),
1571            validator_validate_metadata_data_cost_per_byte: Some(2),
1572
1573            // Crypto
1574            crypto_invalid_arguments_cost: Some(100),
1575            // bls12381::bls12381_min_pk_verify
1576            bls12381_bls12381_min_sig_verify_cost_base: Some(52),
1577            bls12381_bls12381_min_sig_verify_msg_cost_per_byte: Some(2),
1578            bls12381_bls12381_min_sig_verify_msg_cost_per_block: Some(2),
1579
1580            // bls12381::bls12381_min_pk_verify
1581            bls12381_bls12381_min_pk_verify_cost_base: Some(52),
1582            bls12381_bls12381_min_pk_verify_msg_cost_per_byte: Some(2),
1583            bls12381_bls12381_min_pk_verify_msg_cost_per_block: Some(2),
1584
1585            // ecdsa_k1::ecrecover
1586            ecdsa_k1_ecrecover_keccak256_cost_base: Some(52),
1587            ecdsa_k1_ecrecover_keccak256_msg_cost_per_byte: Some(2),
1588            ecdsa_k1_ecrecover_keccak256_msg_cost_per_block: Some(2),
1589            ecdsa_k1_ecrecover_sha256_cost_base: Some(52),
1590            ecdsa_k1_ecrecover_sha256_msg_cost_per_byte: Some(2),
1591            ecdsa_k1_ecrecover_sha256_msg_cost_per_block: Some(2),
1592
1593            // ecdsa_k1::decompress_pubkey
1594            ecdsa_k1_decompress_pubkey_cost_base: Some(52),
1595
1596            // ecdsa_k1::secp256k1_verify
1597            ecdsa_k1_secp256k1_verify_keccak256_cost_base: Some(52),
1598            ecdsa_k1_secp256k1_verify_keccak256_msg_cost_per_byte: Some(2),
1599            ecdsa_k1_secp256k1_verify_keccak256_msg_cost_per_block: Some(2),
1600            ecdsa_k1_secp256k1_verify_sha256_cost_base: Some(52),
1601            ecdsa_k1_secp256k1_verify_sha256_msg_cost_per_byte: Some(2),
1602            ecdsa_k1_secp256k1_verify_sha256_msg_cost_per_block: Some(2),
1603
1604            // ecdsa_r1::ecrecover
1605            ecdsa_r1_ecrecover_keccak256_cost_base: Some(52),
1606            ecdsa_r1_ecrecover_keccak256_msg_cost_per_byte: Some(2),
1607            ecdsa_r1_ecrecover_keccak256_msg_cost_per_block: Some(2),
1608            ecdsa_r1_ecrecover_sha256_cost_base: Some(52),
1609            ecdsa_r1_ecrecover_sha256_msg_cost_per_byte: Some(2),
1610            ecdsa_r1_ecrecover_sha256_msg_cost_per_block: Some(2),
1611
1612            // ecdsa_r1::secp256k1_verify
1613            ecdsa_r1_secp256r1_verify_keccak256_cost_base: Some(52),
1614            ecdsa_r1_secp256r1_verify_keccak256_msg_cost_per_byte: Some(2),
1615            ecdsa_r1_secp256r1_verify_keccak256_msg_cost_per_block: Some(2),
1616            ecdsa_r1_secp256r1_verify_sha256_cost_base: Some(52),
1617            ecdsa_r1_secp256r1_verify_sha256_msg_cost_per_byte: Some(2),
1618            ecdsa_r1_secp256r1_verify_sha256_msg_cost_per_block: Some(2),
1619
1620            // ecvrf::verify
1621            ecvrf_ecvrf_verify_cost_base: Some(52),
1622            ecvrf_ecvrf_verify_alpha_string_cost_per_byte: Some(2),
1623            ecvrf_ecvrf_verify_alpha_string_cost_per_block: Some(2),
1624
1625            // ed25519
1626            ed25519_ed25519_verify_cost_base: Some(52),
1627            ed25519_ed25519_verify_msg_cost_per_byte: Some(2),
1628            ed25519_ed25519_verify_msg_cost_per_block: Some(2),
1629
1630            // groth16::prepare_verifying_key
1631            groth16_prepare_verifying_key_bls12381_cost_base: Some(52),
1632            groth16_prepare_verifying_key_bn254_cost_base: Some(52),
1633
1634            // groth16::verify_groth16_proof_internal
1635            groth16_verify_groth16_proof_internal_bls12381_cost_base: Some(52),
1636            groth16_verify_groth16_proof_internal_bls12381_cost_per_public_input: Some(2),
1637            groth16_verify_groth16_proof_internal_bn254_cost_base: Some(52),
1638            groth16_verify_groth16_proof_internal_bn254_cost_per_public_input: Some(2),
1639            groth16_verify_groth16_proof_internal_public_input_cost_per_byte: Some(2),
1640
1641            // hash::blake2b256
1642            hash_blake2b256_cost_base: Some(52),
1643            hash_blake2b256_data_cost_per_byte: Some(2),
1644            hash_blake2b256_data_cost_per_block: Some(2),
1645            // hash::keccak256
1646            hash_keccak256_cost_base: Some(52),
1647            hash_keccak256_data_cost_per_byte: Some(2),
1648            hash_keccak256_data_cost_per_block: Some(2),
1649
1650            poseidon_bn254_cost_base: None,
1651            poseidon_bn254_cost_per_block: None,
1652
1653            // hmac::hmac_sha3_256
1654            hmac_hmac_sha3_256_cost_base: Some(52),
1655            hmac_hmac_sha3_256_input_cost_per_byte: Some(2),
1656            hmac_hmac_sha3_256_input_cost_per_block: Some(2),
1657
1658            // group ops
1659            group_ops_bls12381_decode_scalar_cost: Some(52),
1660            group_ops_bls12381_decode_g1_cost: Some(52),
1661            group_ops_bls12381_decode_g2_cost: Some(52),
1662            group_ops_bls12381_decode_gt_cost: Some(52),
1663            group_ops_bls12381_scalar_add_cost: Some(52),
1664            group_ops_bls12381_g1_add_cost: Some(52),
1665            group_ops_bls12381_g2_add_cost: Some(52),
1666            group_ops_bls12381_gt_add_cost: Some(52),
1667            group_ops_bls12381_scalar_sub_cost: Some(52),
1668            group_ops_bls12381_g1_sub_cost: Some(52),
1669            group_ops_bls12381_g2_sub_cost: Some(52),
1670            group_ops_bls12381_gt_sub_cost: Some(52),
1671            group_ops_bls12381_scalar_mul_cost: Some(52),
1672            group_ops_bls12381_g1_mul_cost: Some(52),
1673            group_ops_bls12381_g2_mul_cost: Some(52),
1674            group_ops_bls12381_gt_mul_cost: Some(52),
1675            group_ops_bls12381_scalar_div_cost: Some(52),
1676            group_ops_bls12381_g1_div_cost: Some(52),
1677            group_ops_bls12381_g2_div_cost: Some(52),
1678            group_ops_bls12381_gt_div_cost: Some(52),
1679            group_ops_bls12381_g1_hash_to_base_cost: Some(52),
1680            group_ops_bls12381_g2_hash_to_base_cost: Some(52),
1681            group_ops_bls12381_g1_hash_to_cost_per_byte: Some(2),
1682            group_ops_bls12381_g2_hash_to_cost_per_byte: Some(2),
1683            group_ops_bls12381_g1_msm_base_cost: Some(52),
1684            group_ops_bls12381_g2_msm_base_cost: Some(52),
1685            group_ops_bls12381_g1_msm_base_cost_per_input: Some(52),
1686            group_ops_bls12381_g2_msm_base_cost_per_input: Some(52),
1687            group_ops_bls12381_msm_max_len: Some(32),
1688            group_ops_bls12381_pairing_cost: Some(52),
1689            group_ops_bls12381_g1_to_uncompressed_g1_cost: None,
1690            group_ops_bls12381_uncompressed_g1_to_g1_cost: None,
1691            group_ops_bls12381_uncompressed_g1_sum_base_cost: None,
1692            group_ops_bls12381_uncompressed_g1_sum_cost_per_term: None,
1693            group_ops_bls12381_uncompressed_g1_sum_max_terms: None,
1694
1695            // zklogin::check_zklogin_id
1696            check_zklogin_id_cost_base: Some(200),
1697            // zklogin::check_zklogin_issuer
1698            check_zklogin_issuer_cost_base: Some(200),
1699
1700            vdf_verify_vdf_cost: None,
1701            vdf_hash_to_input_cost: None,
1702
1703            bcs_per_byte_serialized_cost: Some(2),
1704            bcs_legacy_min_output_size_cost: Some(1),
1705            bcs_failure_cost: Some(52),
1706            hash_sha2_256_base_cost: Some(52),
1707            hash_sha2_256_per_byte_cost: Some(2),
1708            hash_sha2_256_legacy_min_input_len_cost: Some(1),
1709            hash_sha3_256_base_cost: Some(52),
1710            hash_sha3_256_per_byte_cost: Some(2),
1711            hash_sha3_256_legacy_min_input_len_cost: Some(1),
1712            type_name_get_base_cost: Some(52),
1713            type_name_get_per_byte_cost: Some(2),
1714            string_check_utf8_base_cost: Some(52),
1715            string_check_utf8_per_byte_cost: Some(2),
1716            string_is_char_boundary_base_cost: Some(52),
1717            string_sub_string_base_cost: Some(52),
1718            string_sub_string_per_byte_cost: Some(2),
1719            string_index_of_base_cost: Some(52),
1720            string_index_of_per_byte_pattern_cost: Some(2),
1721            string_index_of_per_byte_searched_cost: Some(2),
1722            vector_empty_base_cost: Some(52),
1723            vector_length_base_cost: Some(52),
1724            vector_push_back_base_cost: Some(52),
1725            vector_push_back_legacy_per_abstract_memory_unit_cost: Some(2),
1726            vector_borrow_base_cost: Some(52),
1727            vector_pop_back_base_cost: Some(52),
1728            vector_destroy_empty_base_cost: Some(52),
1729            vector_swap_base_cost: Some(52),
1730            debug_print_base_cost: Some(52),
1731            debug_print_stack_trace_base_cost: Some(52),
1732
1733            max_size_written_objects: Some(5 * 1000 * 1000),
1734            // max size of written objects during a system TXn to allow for larger writes
1735            // akin to `max_size_written_objects` but for system TXns
1736            max_size_written_objects_system_tx: Some(50 * 1000 * 1000),
1737
1738            // Limits the length of a Move identifier
1739            max_move_identifier_len: Some(128),
1740            max_move_value_depth: Some(128),
1741            max_move_enum_variants: None,
1742
1743            gas_rounding_step: Some(1_000),
1744
1745            execution_version: Some(1),
1746
1747            // We maintain the same total size limit for events, but increase the number of
1748            // events that can be emitted.
1749            max_event_emit_size_total: Some(
1750                256 /* former event count limit */ * 250 * 1024, // size limit per event
1751            ),
1752
1753            // Taking a baby step approach, we consider only 20% by stake as bad nodes so we
1754            // have a 80% by stake of nodes participating in the leader committee. That
1755            // allow us for more redundancy in case we have validators
1756            // under performing - since the responsibility is shared
1757            // amongst more nodes. We can increase that once we do have
1758            // higher confidence.
1759            consensus_bad_nodes_stake_threshold: Some(20),
1760
1761            // Max of 10 votes per hour.
1762            max_jwk_votes_per_validator_per_epoch: Some(240),
1763
1764            max_age_of_jwk_in_epochs: Some(1),
1765
1766            consensus_max_transaction_size_bytes: Some(256 * 1024), // 256KB
1767
1768            // Assume 1KB per transaction and 500 transactions per block.
1769            consensus_max_transactions_in_block_bytes: Some(512 * 1024),
1770
1771            random_beacon_reduction_allowed_delta: Some(800),
1772
1773            random_beacon_reduction_lower_bound: Some(1000),
1774            random_beacon_dkg_timeout_round: Some(3000),
1775            random_beacon_min_round_interval_ms: Some(500),
1776
1777            random_beacon_dkg_version: Some(1),
1778
1779            // Assume 20_000 TPS * 5% max stake per validator / (minimum) 4 blocks per round
1780            // = 250 transactions per block maximum Using a higher limit
1781            // that is 512, to account for bursty traffic and system transactions.
1782            consensus_max_num_transactions_in_block: Some(512),
1783
1784            max_deferral_rounds_for_congestion_control: Some(10),
1785
1786            min_checkpoint_interval_ms: Some(200),
1787
1788            checkpoint_summary_version_specific_data: Some(1),
1789
1790            max_soft_bundle_size: Some(5),
1791
1792            bridge_should_try_to_finalize_committee: None,
1793
1794            max_accumulated_txn_cost_per_object_in_mysticeti_commit: Some(10),
1795
1796            max_committee_members_count: None,
1797
1798            consensus_gc_depth: None,
1799            // When adding a new constant, set it to None in the earliest version, like this:
1800            // new_constant: None,
1801        };
1802
1803        cfg.feature_flags.consensus_transaction_ordering = ConsensusTransactionOrdering::ByGasPrice;
1804
1805        // MoveVM related flags
1806        {
1807            cfg.feature_flags
1808                .disable_invariant_violation_check_in_swap_loc = true;
1809            cfg.feature_flags.no_extraneous_module_bytes = true;
1810            cfg.feature_flags.hardened_otw_check = true;
1811            cfg.feature_flags.rethrow_serialization_type_layout_errors = true;
1812        }
1813
1814        // zkLogin related flags
1815        {
1816            cfg.feature_flags.zklogin_max_epoch_upper_bound_delta = Some(30);
1817        }
1818
1819        // Enable Mysticeti on mainnet.
1820        cfg.feature_flags.consensus_choice = ConsensusChoice::Mysticeti;
1821        // Use tonic networking for Mysticeti.
1822        cfg.feature_flags.consensus_network = ConsensusNetwork::Tonic;
1823
1824        cfg.feature_flags.per_object_congestion_control_mode =
1825            PerObjectCongestionControlMode::TotalTxCount;
1826
1827        // Do not allow bridge committee to finalize on mainnet.
1828        cfg.bridge_should_try_to_finalize_committee = Some(chain != Chain::Mainnet);
1829
1830        // Devnet
1831        if chain != Chain::Mainnet && chain != Chain::Testnet {
1832            cfg.feature_flags.enable_poseidon = true;
1833            cfg.poseidon_bn254_cost_base = Some(260);
1834            cfg.poseidon_bn254_cost_per_block = Some(10);
1835
1836            cfg.feature_flags.enable_group_ops_native_function_msm = true;
1837
1838            cfg.feature_flags.enable_vdf = true;
1839            // Set to 30x and 2x the cost of a signature verification for now. This
1840            // should be updated along with other native crypto functions.
1841            cfg.vdf_verify_vdf_cost = Some(1500);
1842            cfg.vdf_hash_to_input_cost = Some(100);
1843
1844            cfg.feature_flags.passkey_auth = true;
1845        }
1846
1847        for cur in 2..=version.0 {
1848            match cur {
1849                1 => unreachable!(),
1850                // version 2 is a new framework version but with no config changes
1851                2 => {}
1852                3 => {
1853                    cfg.feature_flags.relocate_event_module = true;
1854                }
1855                4 => {
1856                    cfg.max_type_to_layout_nodes = Some(512);
1857                }
1858                5 => {
1859                    cfg.feature_flags.protocol_defined_base_fee = true;
1860                    cfg.base_gas_price = Some(1000);
1861
1862                    cfg.feature_flags.disallow_new_modules_in_deps_only_packages = true;
1863                    cfg.feature_flags.convert_type_argument_error = true;
1864                    cfg.feature_flags.native_charging_v2 = true;
1865
1866                    if chain != Chain::Mainnet && chain != Chain::Testnet {
1867                        cfg.feature_flags.uncompressed_g1_group_elements = true;
1868                    }
1869
1870                    cfg.gas_model_version = Some(2);
1871
1872                    cfg.poseidon_bn254_cost_per_block = Some(388);
1873
1874                    cfg.bls12381_bls12381_min_sig_verify_cost_base = Some(44064);
1875                    cfg.bls12381_bls12381_min_pk_verify_cost_base = Some(49282);
1876                    cfg.ecdsa_k1_secp256k1_verify_keccak256_cost_base = Some(1470);
1877                    cfg.ecdsa_k1_secp256k1_verify_sha256_cost_base = Some(1470);
1878                    cfg.ecdsa_r1_secp256r1_verify_sha256_cost_base = Some(4225);
1879                    cfg.ecdsa_r1_secp256r1_verify_keccak256_cost_base = Some(4225);
1880                    cfg.ecvrf_ecvrf_verify_cost_base = Some(4848);
1881                    cfg.ed25519_ed25519_verify_cost_base = Some(1802);
1882
1883                    // Manually changed to be "under cost"
1884                    cfg.ecdsa_r1_ecrecover_keccak256_cost_base = Some(1173);
1885                    cfg.ecdsa_r1_ecrecover_sha256_cost_base = Some(1173);
1886                    cfg.ecdsa_k1_ecrecover_keccak256_cost_base = Some(500);
1887                    cfg.ecdsa_k1_ecrecover_sha256_cost_base = Some(500);
1888
1889                    cfg.groth16_prepare_verifying_key_bls12381_cost_base = Some(53838);
1890                    cfg.groth16_prepare_verifying_key_bn254_cost_base = Some(82010);
1891                    cfg.groth16_verify_groth16_proof_internal_bls12381_cost_base = Some(72090);
1892                    cfg.groth16_verify_groth16_proof_internal_bls12381_cost_per_public_input =
1893                        Some(8213);
1894                    cfg.groth16_verify_groth16_proof_internal_bn254_cost_base = Some(115502);
1895                    cfg.groth16_verify_groth16_proof_internal_bn254_cost_per_public_input =
1896                        Some(9484);
1897
1898                    cfg.hash_keccak256_cost_base = Some(10);
1899                    cfg.hash_blake2b256_cost_base = Some(10);
1900
1901                    // group ops
1902                    cfg.group_ops_bls12381_decode_scalar_cost = Some(7);
1903                    cfg.group_ops_bls12381_decode_g1_cost = Some(2848);
1904                    cfg.group_ops_bls12381_decode_g2_cost = Some(3770);
1905                    cfg.group_ops_bls12381_decode_gt_cost = Some(3068);
1906
1907                    cfg.group_ops_bls12381_scalar_add_cost = Some(10);
1908                    cfg.group_ops_bls12381_g1_add_cost = Some(1556);
1909                    cfg.group_ops_bls12381_g2_add_cost = Some(3048);
1910                    cfg.group_ops_bls12381_gt_add_cost = Some(188);
1911
1912                    cfg.group_ops_bls12381_scalar_sub_cost = Some(10);
1913                    cfg.group_ops_bls12381_g1_sub_cost = Some(1550);
1914                    cfg.group_ops_bls12381_g2_sub_cost = Some(3019);
1915                    cfg.group_ops_bls12381_gt_sub_cost = Some(497);
1916
1917                    cfg.group_ops_bls12381_scalar_mul_cost = Some(11);
1918                    cfg.group_ops_bls12381_g1_mul_cost = Some(4842);
1919                    cfg.group_ops_bls12381_g2_mul_cost = Some(9108);
1920                    cfg.group_ops_bls12381_gt_mul_cost = Some(27490);
1921
1922                    cfg.group_ops_bls12381_scalar_div_cost = Some(91);
1923                    cfg.group_ops_bls12381_g1_div_cost = Some(5091);
1924                    cfg.group_ops_bls12381_g2_div_cost = Some(9206);
1925                    cfg.group_ops_bls12381_gt_div_cost = Some(27804);
1926
1927                    cfg.group_ops_bls12381_g1_hash_to_base_cost = Some(2962);
1928                    cfg.group_ops_bls12381_g2_hash_to_base_cost = Some(8688);
1929
1930                    cfg.group_ops_bls12381_g1_msm_base_cost = Some(62648);
1931                    cfg.group_ops_bls12381_g2_msm_base_cost = Some(131192);
1932                    cfg.group_ops_bls12381_g1_msm_base_cost_per_input = Some(1333);
1933                    cfg.group_ops_bls12381_g2_msm_base_cost_per_input = Some(3216);
1934
1935                    cfg.group_ops_bls12381_uncompressed_g1_to_g1_cost = Some(677);
1936                    cfg.group_ops_bls12381_g1_to_uncompressed_g1_cost = Some(2099);
1937                    cfg.group_ops_bls12381_uncompressed_g1_sum_base_cost = Some(77);
1938                    cfg.group_ops_bls12381_uncompressed_g1_sum_cost_per_term = Some(26);
1939                    cfg.group_ops_bls12381_uncompressed_g1_sum_max_terms = Some(1200);
1940
1941                    cfg.group_ops_bls12381_pairing_cost = Some(26897);
1942
1943                    cfg.validator_validate_metadata_cost_base = Some(20000);
1944
1945                    cfg.max_committee_members_count = Some(50);
1946                }
1947                6 => {
1948                    cfg.max_ptb_value_size = Some(1024 * 1024);
1949                }
1950                // version 7 is a new framework version but with no config changes
1951                7 => {}
1952                8 => {
1953                    cfg.feature_flags.variant_nodes = true;
1954
1955                    if chain != Chain::Mainnet {
1956                        // Enable round prober in consensus.
1957                        cfg.feature_flags.consensus_round_prober = true;
1958                        // Enable distributed vote scoring.
1959                        cfg.feature_flags
1960                            .consensus_distributed_vote_scoring_strategy = true;
1961                        cfg.feature_flags.consensus_linearize_subdag_v2 = true;
1962                        // Enable smart ancestor selection for testnet
1963                        cfg.feature_flags.consensus_smart_ancestor_selection = true;
1964                        // Enable probing for accepted rounds in round prober for testnet
1965                        cfg.feature_flags
1966                            .consensus_round_prober_probe_accepted_rounds = true;
1967                        // Enable zstd compression for consensus in testnet
1968                        cfg.feature_flags.consensus_zstd_compression = true;
1969                        // Assuming a round rate of max 15/sec, then using a gc depth of 60 allow
1970                        // blocks within a window of ~4 seconds
1971                        // to be included before be considered garbage collected.
1972                        cfg.consensus_gc_depth = Some(60);
1973                    }
1974                    // Enable min_free_execution_slot for the shared object congestion tracker in
1975                    // devnet.
1976                    if chain != Chain::Testnet && chain != Chain::Mainnet {
1977                        cfg.feature_flags.congestion_control_min_free_execution_slot = true;
1978                    }
1979                }
1980                9 => {
1981                    if chain != Chain::Mainnet {
1982                        // Disable smart ancestor selection in the testnet and devnet.
1983                        cfg.feature_flags.consensus_smart_ancestor_selection = false;
1984                    }
1985
1986                    // Enable zstd compression for consensus
1987                    cfg.feature_flags.consensus_zstd_compression = true;
1988
1989                    // Enable passkey in multisig in devnet.
1990                    if chain != Chain::Testnet && chain != Chain::Mainnet {
1991                        cfg.feature_flags.accept_passkey_in_multisig = true;
1992                    }
1993
1994                    // this flag is now deprecated because of the bridge removal.
1995                    cfg.bridge_should_try_to_finalize_committee = None;
1996                }
1997                // Use this template when making changes:
1998                //
1999                //     // modify an existing constant.
2000                //     move_binary_format_version: Some(7),
2001                //
2002                //     // Add a new constant (which is set to None in prior versions).
2003                //     new_constant: Some(new_value),
2004                //
2005                //     // Remove a constant (ensure that it is never accessed during this version).
2006                //     max_move_object_size: None,
2007                _ => panic!("unsupported version {:?}", version),
2008            }
2009        }
2010        cfg
2011    }
2012
2013    // Extract the bytecode verifier config from this protocol config. `for_signing`
2014    // indicates whether this config is used for verification during signing or
2015    // execution.
2016    pub fn verifier_config(&self, signing_limits: Option<(usize, usize)>) -> VerifierConfig {
2017        let (max_back_edges_per_function, max_back_edges_per_module) = if let Some((
2018            max_back_edges_per_function,
2019            max_back_edges_per_module,
2020        )) = signing_limits
2021        {
2022            (
2023                Some(max_back_edges_per_function),
2024                Some(max_back_edges_per_module),
2025            )
2026        } else {
2027            (None, None)
2028        };
2029
2030        VerifierConfig {
2031            max_loop_depth: Some(self.max_loop_depth() as usize),
2032            max_generic_instantiation_length: Some(self.max_generic_instantiation_length() as usize),
2033            max_function_parameters: Some(self.max_function_parameters() as usize),
2034            max_basic_blocks: Some(self.max_basic_blocks() as usize),
2035            max_value_stack_size: self.max_value_stack_size() as usize,
2036            max_type_nodes: Some(self.max_type_nodes() as usize),
2037            max_push_size: Some(self.max_push_size() as usize),
2038            max_dependency_depth: Some(self.max_dependency_depth() as usize),
2039            max_fields_in_struct: Some(self.max_fields_in_struct() as usize),
2040            max_function_definitions: Some(self.max_function_definitions() as usize),
2041            max_data_definitions: Some(self.max_struct_definitions() as usize),
2042            max_constant_vector_len: Some(self.max_move_vector_len()),
2043            max_back_edges_per_function,
2044            max_back_edges_per_module,
2045            max_basic_blocks_in_script: None,
2046            max_identifier_len: self.max_move_identifier_len_as_option(), /* Before protocol
2047                                                                           * version 9, there was
2048                                                                           * no limit */
2049            bytecode_version: self.move_binary_format_version(),
2050            max_variants_in_enum: self.max_move_enum_variants_as_option(),
2051        }
2052    }
2053
2054    /// Override one or more settings in the config, for testing.
2055    /// This must be called at the beginning of the test, before
2056    /// get_for_(min|max)_version is called, since those functions cache
2057    /// their return value.
2058    pub fn apply_overrides_for_testing(
2059        override_fn: impl Fn(ProtocolVersion, Self) -> Self + Send + Sync + 'static,
2060    ) -> OverrideGuard {
2061        CONFIG_OVERRIDE.with(|ovr| {
2062            let mut cur = ovr.borrow_mut();
2063            assert!(cur.is_none(), "config override already present");
2064            *cur = Some(Box::new(override_fn));
2065            OverrideGuard
2066        })
2067    }
2068}
2069
2070// Setters for tests.
2071// This is only needed for feature_flags. Please suffix each setter with
2072// `_for_testing`. Non-feature_flags should already have test setters defined
2073// through macros.
2074impl ProtocolConfig {
2075    pub fn set_zklogin_auth_for_testing(&mut self, val: bool) {
2076        self.feature_flags.zklogin_auth = val
2077    }
2078    pub fn set_enable_jwk_consensus_updates_for_testing(&mut self, val: bool) {
2079        self.feature_flags.enable_jwk_consensus_updates = val
2080    }
2081
2082    pub fn set_accept_zklogin_in_multisig_for_testing(&mut self, val: bool) {
2083        self.feature_flags.accept_zklogin_in_multisig = val
2084    }
2085
2086    pub fn set_per_object_congestion_control_mode_for_testing(
2087        &mut self,
2088        val: PerObjectCongestionControlMode,
2089    ) {
2090        self.feature_flags.per_object_congestion_control_mode = val;
2091    }
2092
2093    pub fn set_consensus_choice_for_testing(&mut self, val: ConsensusChoice) {
2094        self.feature_flags.consensus_choice = val;
2095    }
2096
2097    pub fn set_consensus_network_for_testing(&mut self, val: ConsensusNetwork) {
2098        self.feature_flags.consensus_network = val;
2099    }
2100
2101    pub fn set_zklogin_max_epoch_upper_bound_delta_for_testing(&mut self, val: Option<u64>) {
2102        self.feature_flags.zklogin_max_epoch_upper_bound_delta = val
2103    }
2104
2105    pub fn set_passkey_auth_for_testing(&mut self, val: bool) {
2106        self.feature_flags.passkey_auth = val
2107    }
2108
2109    pub fn set_disallow_new_modules_in_deps_only_packages_for_testing(&mut self, val: bool) {
2110        self.feature_flags
2111            .disallow_new_modules_in_deps_only_packages = val;
2112    }
2113
2114    pub fn set_consensus_round_prober_for_testing(&mut self, val: bool) {
2115        self.feature_flags.consensus_round_prober = val;
2116    }
2117
2118    pub fn set_consensus_distributed_vote_scoring_strategy_for_testing(&mut self, val: bool) {
2119        self.feature_flags
2120            .consensus_distributed_vote_scoring_strategy = val;
2121    }
2122
2123    pub fn set_gc_depth_for_testing(&mut self, val: u32) {
2124        self.consensus_gc_depth = Some(val);
2125    }
2126
2127    pub fn set_consensus_linearize_subdag_v2_for_testing(&mut self, val: bool) {
2128        self.feature_flags.consensus_linearize_subdag_v2 = val;
2129    }
2130
2131    pub fn set_consensus_round_prober_probe_accepted_rounds(&mut self, val: bool) {
2132        self.feature_flags
2133            .consensus_round_prober_probe_accepted_rounds = val;
2134    }
2135
2136    pub fn set_accept_passkey_in_multisig_for_testing(&mut self, val: bool) {
2137        self.feature_flags.accept_passkey_in_multisig = val;
2138    }
2139
2140    pub fn set_consensus_smart_ancestor_selection_for_testing(&mut self, val: bool) {
2141        self.feature_flags.consensus_smart_ancestor_selection = val;
2142    }
2143}
2144
2145type OverrideFn = dyn Fn(ProtocolVersion, ProtocolConfig) -> ProtocolConfig + Send + Sync;
2146
2147thread_local! {
2148    static CONFIG_OVERRIDE: RefCell<Option<Box<OverrideFn>>> = const { RefCell::new(None) };
2149}
2150
2151#[must_use]
2152pub struct OverrideGuard;
2153
2154impl Drop for OverrideGuard {
2155    fn drop(&mut self) {
2156        info!("restoring override fn");
2157        CONFIG_OVERRIDE.with(|ovr| {
2158            *ovr.borrow_mut() = None;
2159        });
2160    }
2161}
2162
2163/// Defines which limit got crossed.
2164/// The value which crossed the limit and value of the limit crossed are
2165/// embedded
2166#[derive(PartialEq, Eq)]
2167pub enum LimitThresholdCrossed {
2168    None,
2169    Soft(u128, u128),
2170    Hard(u128, u128),
2171}
2172
2173/// Convenience function for comparing limit ranges
2174/// V::MAX must be at >= U::MAX and T::MAX
2175pub fn check_limit_in_range<T: Into<V>, U: Into<V>, V: PartialOrd + Into<u128>>(
2176    x: T,
2177    soft_limit: U,
2178    hard_limit: V,
2179) -> LimitThresholdCrossed {
2180    let x: V = x.into();
2181    let soft_limit: V = soft_limit.into();
2182
2183    debug_assert!(soft_limit <= hard_limit);
2184
2185    // It is important to preserve this comparison order because if soft_limit ==
2186    // hard_limit we want LimitThresholdCrossed::Hard
2187    if x >= hard_limit {
2188        LimitThresholdCrossed::Hard(x.into(), hard_limit.into())
2189    } else if x < soft_limit {
2190        LimitThresholdCrossed::None
2191    } else {
2192        LimitThresholdCrossed::Soft(x.into(), soft_limit.into())
2193    }
2194}
2195
2196#[macro_export]
2197macro_rules! check_limit {
2198    ($x:expr, $hard:expr) => {
2199        check_limit!($x, $hard, $hard)
2200    };
2201    ($x:expr, $soft:expr, $hard:expr) => {
2202        check_limit_in_range($x as u64, $soft, $hard)
2203    };
2204}
2205
2206/// Used to check which limits were crossed if the TX is metered (not system tx)
2207/// Args are: is_metered, value_to_check, metered_limit, unmetered_limit
2208/// metered_limit is always less than or equal to unmetered_hard_limit
2209#[macro_export]
2210macro_rules! check_limit_by_meter {
2211    ($is_metered:expr, $x:expr, $metered_limit:expr, $unmetered_hard_limit:expr, $metric:expr) => {{
2212        // If this is metered, we use the metered_limit limit as the upper bound
2213        let (h, metered_str) = if $is_metered {
2214            ($metered_limit, "metered")
2215        } else {
2216            // Unmetered gets more headroom
2217            ($unmetered_hard_limit, "unmetered")
2218        };
2219        use iota_protocol_config::check_limit_in_range;
2220        let result = check_limit_in_range($x as u64, $metered_limit, h);
2221        match result {
2222            LimitThresholdCrossed::None => {}
2223            LimitThresholdCrossed::Soft(_, _) => {
2224                $metric.with_label_values(&[metered_str, "soft"]).inc();
2225            }
2226            LimitThresholdCrossed::Hard(_, _) => {
2227                $metric.with_label_values(&[metered_str, "hard"]).inc();
2228            }
2229        };
2230        result
2231    }};
2232}
2233
2234#[cfg(all(test, not(msim)))]
2235mod test {
2236    use insta::assert_yaml_snapshot;
2237
2238    use super::*;
2239
2240    #[test]
2241    fn snapshot_tests() {
2242        println!("\n============================================================================");
2243        println!("!                                                                          !");
2244        println!("! IMPORTANT: never update snapshots from this test. only add new versions! !");
2245        println!("!                                                                          !");
2246        println!("============================================================================\n");
2247        for chain_id in &[Chain::Unknown, Chain::Mainnet, Chain::Testnet] {
2248            // make Chain::Unknown snapshots compatible with pre-chain-id snapshots so that
2249            // we don't break the release-time compatibility tests. Once Chain
2250            // Id configs have been released everywhere, we can remove this and
2251            // only test Mainnet and Testnet
2252            let chain_str = match chain_id {
2253                Chain::Unknown => "".to_string(),
2254                _ => format!("{:?}_", chain_id),
2255            };
2256            for i in MIN_PROTOCOL_VERSION..=MAX_PROTOCOL_VERSION {
2257                let cur = ProtocolVersion::new(i);
2258                assert_yaml_snapshot!(
2259                    format!("{}version_{}", chain_str, cur.as_u64()),
2260                    ProtocolConfig::get_for_version(cur, *chain_id)
2261                );
2262            }
2263        }
2264    }
2265
2266    #[test]
2267    fn test_getters() {
2268        let prot: ProtocolConfig =
2269            ProtocolConfig::get_for_version(ProtocolVersion::new(1), Chain::Unknown);
2270        assert_eq!(
2271            prot.max_arguments(),
2272            prot.max_arguments_as_option().unwrap()
2273        );
2274    }
2275
2276    #[test]
2277    fn test_setters() {
2278        let mut prot: ProtocolConfig =
2279            ProtocolConfig::get_for_version(ProtocolVersion::new(1), Chain::Unknown);
2280        prot.set_max_arguments_for_testing(123);
2281        assert_eq!(prot.max_arguments(), 123);
2282
2283        prot.set_max_arguments_from_str_for_testing("321".to_string());
2284        assert_eq!(prot.max_arguments(), 321);
2285
2286        prot.disable_max_arguments_for_testing();
2287        assert_eq!(prot.max_arguments_as_option(), None);
2288
2289        prot.set_attr_for_testing("max_arguments".to_string(), "456".to_string());
2290        assert_eq!(prot.max_arguments(), 456);
2291    }
2292
2293    #[test]
2294    #[should_panic(expected = "unsupported version")]
2295    fn max_version_test() {
2296        // When this does not panic, version higher than MAX_PROTOCOL_VERSION exists.
2297        // To fix, bump MAX_PROTOCOL_VERSION or disable this check for the version.
2298        let _ = ProtocolConfig::get_for_version_impl(
2299            ProtocolVersion::new(MAX_PROTOCOL_VERSION + 1),
2300            Chain::Unknown,
2301        );
2302    }
2303
2304    #[test]
2305    fn lookup_by_string_test() {
2306        let prot: ProtocolConfig =
2307            ProtocolConfig::get_for_version(ProtocolVersion::new(1), Chain::Mainnet);
2308        // Does not exist
2309        assert!(prot.lookup_attr("some random string".to_string()).is_none());
2310
2311        assert!(
2312            prot.lookup_attr("max_arguments".to_string())
2313                == Some(ProtocolConfigValue::u32(prot.max_arguments())),
2314        );
2315
2316        // We didnt have this in version 1 on Mainnet
2317        assert!(
2318            prot.lookup_attr("poseidon_bn254_cost_base".to_string())
2319                .is_none()
2320        );
2321        assert!(
2322            prot.attr_map()
2323                .get("poseidon_bn254_cost_base")
2324                .unwrap()
2325                .is_none()
2326        );
2327
2328        // But we did in version 1 on Devnet
2329        let prot: ProtocolConfig =
2330            ProtocolConfig::get_for_version(ProtocolVersion::new(1), Chain::Unknown);
2331
2332        assert!(
2333            prot.lookup_attr("poseidon_bn254_cost_base".to_string())
2334                == Some(ProtocolConfigValue::u64(prot.poseidon_bn254_cost_base()))
2335        );
2336        assert!(
2337            prot.attr_map().get("poseidon_bn254_cost_base").unwrap()
2338                == &Some(ProtocolConfigValue::u64(prot.poseidon_bn254_cost_base()))
2339        );
2340
2341        // Check feature flags
2342        let prot: ProtocolConfig =
2343            ProtocolConfig::get_for_version(ProtocolVersion::new(1), Chain::Mainnet);
2344        // Does not exist
2345        assert!(
2346            prot.feature_flags
2347                .lookup_attr("some random string".to_owned())
2348                .is_none()
2349        );
2350        assert!(
2351            !prot
2352                .feature_flags
2353                .attr_map()
2354                .contains_key("some random string")
2355        );
2356
2357        // Was false in v1 on Mainnet
2358        assert!(prot.feature_flags.lookup_attr("enable_poseidon".to_owned()) == Some(false));
2359        assert!(
2360            prot.feature_flags
2361                .attr_map()
2362                .get("enable_poseidon")
2363                .unwrap()
2364                == &false
2365        );
2366        let prot: ProtocolConfig =
2367            ProtocolConfig::get_for_version(ProtocolVersion::new(1), Chain::Unknown);
2368        // Was true from v1 and up on Devnet
2369        assert!(prot.feature_flags.lookup_attr("enable_poseidon".to_owned()) == Some(true));
2370        assert!(
2371            prot.feature_flags
2372                .attr_map()
2373                .get("enable_poseidon")
2374                .unwrap()
2375                == &true
2376        );
2377    }
2378
2379    #[test]
2380    fn limit_range_fn_test() {
2381        let low = 100u32;
2382        let high = 10000u64;
2383
2384        assert!(check_limit!(1u8, low, high) == LimitThresholdCrossed::None);
2385        assert!(matches!(
2386            check_limit!(255u16, low, high),
2387            LimitThresholdCrossed::Soft(255u128, 100)
2388        ));
2389        // This wont compile because lossy
2390        // assert!(check_limit!(100000000u128, low, high) ==
2391        // LimitThresholdCrossed::None); This wont compile because lossy
2392        // assert!(check_limit!(100000000usize, low, high) ==
2393        // LimitThresholdCrossed::None);
2394
2395        assert!(matches!(
2396            check_limit!(2550000u64, low, high),
2397            LimitThresholdCrossed::Hard(2550000, 10000)
2398        ));
2399
2400        assert!(matches!(
2401            check_limit!(2550000u64, high, high),
2402            LimitThresholdCrossed::Hard(2550000, 10000)
2403        ));
2404
2405        assert!(matches!(
2406            check_limit!(1u8, high),
2407            LimitThresholdCrossed::None
2408        ));
2409
2410        assert!(check_limit!(255u16, high) == LimitThresholdCrossed::None);
2411
2412        assert!(matches!(
2413            check_limit!(2550000u64, high),
2414            LimitThresholdCrossed::Hard(2550000, 10000)
2415        ));
2416    }
2417}