Skip to main content

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::{MeterConfig, 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 = 40;
23
24/// Protocol version that IIP8 took effect.
25pub const PROTOCOL_VERSION_IIP8: u64 = 20;
26// Record history of protocol version allocations here:
27//
28// Version 1:  Original version.
29// Version 2:  Don't redistribute slashed staking rewards, fix computation of
30//             SystemEpochInfoEventV1.
31// Version 3:  Set the `relocate_event_module` to be true so that the module
32//             that is associated as the "sending module" for an event is
33//             relocated by linkage.
34//             Add `Clock` based unlock to `Timelock` objects.
35// Version 4:  Introduce the `max_type_to_layout_nodes` config that sets the
36//             maximal nodes which are allowed when converting to a type layout.
37// Version 5:  Introduce fixed protocol-defined base fee, IotaSystemStateV2 and
38//             SystemEpochInfoEventV2.
39//             Disallow adding new modules in `deps-only` packages.
40//             Improve gas/wall time efficiency of some Move stdlib vector
41//             functions.
42//             Add new gas model version to update charging of functions.
43//             Enable proper conversion of certain type argument errors in the
44//             execution layer.
45// Version 6:  Bound size of values created in the adapter.
46// Version 7:  Improve handling of stake withdrawal from candidate validators.
47// Version 8:  Variants as type nodes.
48//             Enable smart ancestor selection for testnet.
49//             Enable probing for accepted rounds in round prober for testnet.
50//             Switch to distributed vote scoring in consensus in testnet.
51//             Enable zstd compression for consensus tonic network in testnet.
52//             Enable consensus garbage collection for testnet
53//             Enable the new consensus commit rule for testnet.
54//             Enable min_free_execution_slot for the shared object congestion
55//             tracker in devnet.
56// Version 9:  Disable smart ancestor selection for the testnet.
57//             Enable zstd compression for consensus tonic network in mainnet.
58//             Enable passkey auth in multisig for devnet.
59//             Remove the iota-bridge from the framework.
60// Version 10: Enable min_free_execution_slot for the shared object congestion
61//             tracker in all networks.
62//             Increase the committee size to 80 on all networks.
63//             Enable round prober in consensus for mainnet.
64//             Enable probing for accepted rounds in round prober for mainnet.
65//             Switch to distributed vote scoring in consensus for mainnet.
66//             Enable the new consensus commit rule for mainnet.
67//             Enable consensus garbage collection for mainnet with GC depth set
68//             to 60 rounds.
69//             Enable batching in synchronizer for testnet
70//             Enable the gas price feedback mechanism in devnet.
71//             Enable Identifier input validation.
72//             Removes unnecessary child object mutations
73//             Add additional signature checks
74//             Add additional linkage checks
75// Version 11: Framework fix regarding candidate validator commission rate.
76// Version 12: Enable the gas price feedback mechanism in all networks.
77//             Enable the normalization of PTB arguments.
78// Version 13: Introduce logic to allow the committee to be selected from a set
79//             of eligible active validators.
80//             Enable processing and tracking AuthorityCapabilitiesV1 from
81//             non-committee validators in the devnet.
82// Version 14: Switches the consensus protocol to Starfish in devnet.
83//             Enable median-based commit timestamp calculation in consensus,
84//             and enforce checkpoint timestamp monotonicity for testnet.
85//             Enable batched block sync for mainnet.
86//             Enable selecting committee only from active validators that
87//             support the next epoch's version and issued valid
88//             AuthorityCapabilities notification in testnet.
89// Version 15: Enable shared object transaction bursts of 10 times average load
90//             on devnet.
91// Version 16: Enable selecting committee only from active validators that
92//             support the next epoch's version and issued valid
93//             AuthorityCapabilities notification.
94//             Enable committing transactions only for traversed headers in
95//             Starfish.
96// Version 17: Increase the committee size to 100 on all networks.
97// Version 18: Enable passkey authentication support in testnet.
98// Version 19: Enable congestion limit overshoot in the gas price feedback
99//             mechanism on devnet.
100//             Enable a separate gas price feedback mechanism for transactions
101//             using randomness on devnet.
102//             Allow metadata bytes indexed with a dedicated key in compiled
103//             Move modules in devnet.
104//             Enable publishing package metadata v1 along with the package in
105//             devnet.
106//             Enable Move-based account authentication in devnet.
107//             Increase the base cost for transfer receive object in devnet.
108//             Switch consensus protocol to Starfish in testnet.
109//             Enable passkey authentication support in mainnet.
110//             Change epoch transaction will contain validator scores.
111//             Enable validator scoring on testnet and enable adjustment of
112//             validator rewards based on scores on Devnet.
113// Version 20: Supports the calculation of validator scores while still passing
114//             a default score value to the advance_epoch call. Enables this
115//             decoupling on Testnet; Devnet and Mainnet behavior remain the
116//             same.
117//             Introduce Dynamic Minimum Commission (IIP-8) on all networks.
118// Version 21: Enable overshoot of 100 in congestion control on testnet.
119//             Enable congestion limit overshoot in the gas price feedback
120//             mechanism on testnet.
121//             Enable a separate gas price feedback mechanism for transactions
122//             using randomness on testnet.
123//             Enable fast commit syncer for faster recovery in devnet.
124//             Add auth_context_tx native functions costs.
125//             Reduce max_auth_gas in Devnet.
126// Version 22: Enable overshoot of 100 in congestion control on all networks.
127//             Enable congestion limit overshoot in the gas price feedback
128//             mechanism on all networks.
129//             Enable a separate gas price feedback mechanism for transactions
130//             using randomness on all networks.
131//             Enable Move-based account authentication in testnet.
132//             Enable fast commit syncer for faster recovery on testnet.
133// Version 23: Enable Move native context (TxContext via native functions) in
134//             all networks. TxContext fields are read via native functions
135//             instead of being deserialized from a BCS-encoded struct.
136//             Enables sponsor, rgp, gas_price, and gas_budget to be exposed to
137//             Move.
138// Version 24: Switch consensus protocol to Starfish in all networks.
139//             Enable Move-based sponsor account authentication in devnet.
140//             Add AuthContext native functions cost for reading tx_data_bytes.
141//             Enable additional borrow checks.
142// Version 25: Deprecate zkLogin related parameters since zkLogin is no longer
143//             supported.
144// Version 26: Introduce a module to allow Move code to query protocol feature
145//             flags at runtime.
146// Version 27: Only sponsor Move authentication is performed pre-consensus in
147//             devnet.
148//             Enable consensus block restrictions on testnet and devnet:
149//             bound block-header size to O(committee_size) and enable
150//             garbage collection in the block manager.
151// Version 28: Move authenticator contracts can now inspect which authenticator
152//             function the sender and sponsor used during transaction execution
153//             via new AuthContext accessors.
154//             Enable Move-based account authentication in mainnet.
155//             Enable Move-based sponsor account authentication in testnet.
156// Version 29: Keep advancing the random beacon DKG state machine on every
157//             commit while it is still pending -- regardless of whether new DKG
158//             messages or confirmations arrived that commit -- so DKG resolves
159//             from persisted state (completing, or failing once the timeout
160//             round passes) even with no fresh inbound traffic, e.g. after a
161//             validator restart. Without this it can stay pending forever and
162//             block epoch close.
163//             Enable median-based commit timestamp calculation in consensus,
164//             and enforce checkpoint timestamp monotonicity for mainnet.
165//             Enable fast commit syncer for faster recovery on all networks.
166//             Enable consensus block restrictions on all networks:
167//             bound block-header size to O(committee_size) and enable
168//             garbage collection in the block manager.
169// Version 30: Extend the protocol_config framework module with a generic
170//             `get_attr<T>` native that lets Move code read any numeric or
171//             boolean protocol parameter by name, returning T directly and
172//             aborting on error.
173//             Expose `is_feature_enabled` and `get_attr<T>` natives to the
174//             iota_system package via a new iota_system::protocol_config
175//             module.
176// Version 31: Rebuild the framework binaries for the latest iota_system
177//             validator set changes.
178//             Enable validator metadata verification v2.
179//             Amortize the minimum checkpoint interval over a sliding window
180//             on non-Mainnet/Testnet chains.
181//             Start publishing package metadata using module metadata as a
182//             dynamic field.
183//             Report a failure of the Move authentication with a distinct
184//             `MoveAuthentication` execution error.
185//             Enable the optimistic commit rule (StarfishSpeed) in Starfish
186//             consensus on devnet.
187// Version 32: Move validator count limits (min/max validator count) and
188//             stake thresholds (joining stake, low/very low stake
189//             thresholds, grace period) into the protocol config.
190//             Enable the optimistic commit rule (StarfishSpeed) in Starfish
191//             consensus on testnet.
192//             Amortize the minimum checkpoint interval over a sliding window
193//             on testnet.
194//             Start publishing package metadata using module metadata as a
195//             dynamic field on testnet.
196//             Enable the redesigned leader schedule (sliding-window reputation
197//             scoring and absolute-score bad-node selection) in Starfish
198//             consensus on devnet.
199//             Enable Move-based sponsor account authentication on mainnet.
200//             Only sponsor Move authentication is performed pre-consensus on
201//             mainnet.
202//             Enable the P-COOL flow on devnet.
203// Version 33: Amortize the minimum checkpoint interval over a sliding window
204//             on mainnet.
205//             Enable the sliding-window reputation scoring and absolute-score
206//             bad-node selection on testnet
207// Version 34: Bump the scorer version to 2 on devnet: misbehavior reports
208//             carry a dedicated counter for invalid bundle parts, previously
209//             folded into the unprovable block-fault counter.
210//             Add the `iota::transaction_deny_rules` framework module and its
211//             reserved object ID 0xDE9 (dormant until deny-rule governance
212//             activates).
213//             Stop locking immutable objects in post-consensus conflict
214//             resolution.
215//             Disable Move-based sponsor account authentication on mainnet.
216// Version 35: Scale the PTB value size limit by the value's type.
217//             Allow objects created or mutated by system transactions to exceed
218//             the max object size limit.
219//             Enable the optimistic commit rule (StarfishSpeed) in Starfish
220//             consensus on mainnet.
221//             Meter the packages a transaction publishes with the protocol
222//             config's verifier limits in post-consensus validation, and set
223//             those limits to the node config's defaults on all chains
224//             (inert where the P-COOL flow is off).
225//             Start publishing package metadata using module metadata as a
226//             dynamic field on mainnet.
227//             Enable the redesigned leader schedule (sliding-window reputation
228//             scoring and absolute-score bad-node selection) in Starfish
229//             consensus on mainnet.
230// Version 36: Reject a transaction whose sender or sponsor is authenticated by
231//             a `MoveAuthenticator` with an immutable account object.
232// Version 37: Reject a transaction that names an object version in the range
233//             assigned to canceled transactions, or one below it, from the
234//             transaction bytes, before any object is loaded.
235//             Reject `<SELF>` as an identifier in published modules.
236//             Make the enum variant count limit explicit in the protocol
237//             config.
238//             Check the package that holds a `MoveAuthenticator`'s
239//             authenticate function, and that package's dependencies, against
240//             the package deny list.
241//             Require the version field of a published module header to be the
242//             encoding the serializer produces for that version, rejecting a
243//             non-zero flavor byte below binary format version 7.
244//             Reject the randomness state object as a `MoveAuthenticator`
245//             input.
246//             Traverse the module graph when checking a published module for
247//             cyclic dependencies, instead of stopping at its immediate
248//             dependencies.
249// Version 38: Bound system Move packages by `max_move_system_package_size`
250//             rather than the limit that applies to user packages.
251//             Abort `iota::account::create_immutable_account_v1`, so no new
252//             immutable account object can be created.
253//             Validate PTB indices at signing time.
254// Version 39: Allow random beacon DKG to complete after its timeout on devnet
255//             and testnet.
256//             The consensus handler's processed-transaction cache holds only
257//             messages recorded as processed, so a cache hit gives the same
258//             answer as the processed-message table on every validator. A
259//             user transaction from an authority that has sent EndOfPublish
260//             no longer makes a later transaction with the same key in the
261//             same commit be skipped as a duplicate.
262//             Raise the minimum validator joining stake to 6M IOTA, the low
263//             stake threshold to 5.5M IOTA and the very low stake threshold to
264//             5M IOTA on all chains.
265//             Reject a multisig whose committee mixes Ed25519 with other key
266//             schemes unless every committee member has signed.
267//             Enable Groth16 verifying key input length checks before deserialization.
268//             Reject the deprecated global storage instructions and non-empty
269//             `acquires` lists when execution deserializes a module, and
270//             verify modules without the acquires pass and with vector element
271//             borrows checked by the call rule.
272// Version 40: Post-consensus validation takes the instantiation-loop graph
273//             edge limit, and whether the instantiation-loop check is
274//             metered, from the protocol config.
275//             Make the packages named by a `MoveAuthenticator`'s type
276//             arguments inputs of that authenticator.
277//             Limit the struct, enum and vector values in Move-call
278//             arguments, per call and per transaction.
279//             Reject `<SELF>` as an identifier in transactions, at signing,
280//             after consensus and in block verification. Block verification
281//             also rejects a block that carries a system transaction kind in
282//             a user transaction or certificate.
283#[derive(Copy, Clone, Debug, Hash, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
284pub struct ProtocolVersion(u64);
285
286impl ProtocolVersion {
287    // The minimum and maximum protocol version supported by this binary.
288    // Counterintuitively, this constant may change over time as support for old
289    // protocol versions is removed from the source. This ensures that when a
290    // new network (such as a testnet) is created, its genesis committee will
291    // use a protocol version that is actually supported by the binary.
292    pub const MIN: Self = Self(MIN_PROTOCOL_VERSION);
293
294    pub const MAX: Self = Self(MAX_PROTOCOL_VERSION);
295
296    #[cfg(not(msim))]
297    const MAX_ALLOWED: Self = Self::MAX;
298
299    // We create one additional "fake" version in simulator builds so that we can
300    // test upgrades.
301    #[cfg(msim)]
302    pub const MAX_ALLOWED: Self = Self(MAX_PROTOCOL_VERSION + 1);
303
304    pub fn new(v: u64) -> Self {
305        Self(v)
306    }
307
308    pub const fn as_u64(&self) -> u64 {
309        self.0
310    }
311
312    // For serde deserialization - we don't define a Default impl because there
313    // isn't a single universally appropriate default value.
314    pub fn max() -> Self {
315        Self::MAX
316    }
317}
318
319impl From<u64> for ProtocolVersion {
320    fn from(v: u64) -> Self {
321        Self::new(v)
322    }
323}
324
325impl std::ops::Sub<u64> for ProtocolVersion {
326    type Output = Self;
327    fn sub(self, rhs: u64) -> Self::Output {
328        Self::new(self.0 - rhs)
329    }
330}
331
332impl std::ops::Add<u64> for ProtocolVersion {
333    type Output = Self;
334    fn add(self, rhs: u64) -> Self::Output {
335        Self::new(self.0 + rhs)
336    }
337}
338
339#[derive(
340    Clone, Serialize, Deserialize, Debug, PartialEq, Copy, PartialOrd, Ord, Eq, ValueEnum, Default,
341)]
342pub enum Chain {
343    Mainnet,
344    Testnet,
345    #[default]
346    Unknown,
347}
348
349impl Chain {
350    pub fn as_str(self) -> &'static str {
351        match self {
352            Chain::Mainnet => "mainnet",
353            Chain::Testnet => "testnet",
354            Chain::Unknown => "unknown",
355        }
356    }
357}
358
359pub struct Error(pub String);
360
361// TODO: There are quite a few non boolean values in the feature flags. We
362// should move them out.
363/// Records on/off feature flags that may vary at each protocol version.
364#[derive(
365    Default,
366    Clone,
367    Serialize,
368    Deserialize,
369    Debug,
370    ProtocolConfigFeatureFlagsGetters,
371    ProtocolConfigOverride,
372)]
373struct FeatureFlags {
374    // Add feature flags here, e.g.:
375    // new_protocol_feature: bool,
376
377    // Disables unnecessary invariant check in the Move VM when swapping the value out of a local
378    // This flag is used to provide the correct MoveVM configuration for clients.
379    #[serde(skip_serializing_if = "is_true")]
380    disable_invariant_violation_check_in_swap_loc: bool,
381
382    // If true, checks no extra bytes in a compiled module
383    // This flag is used to provide the correct MoveVM configuration for clients.
384    #[serde(skip_serializing_if = "is_true")]
385    no_extraneous_module_bytes: bool,
386
387    // How we order transactions coming out of consensus before sending to execution.
388    #[serde(skip_serializing_if = "ConsensusTransactionOrdering::is_none")]
389    consensus_transaction_ordering: ConsensusTransactionOrdering,
390
391    // If true, use the hardened OTW check
392    // This flag is used to provide the correct MoveVM configuration for clients.
393    #[serde(skip_serializing_if = "is_true")]
394    hardened_otw_check: bool,
395
396    // Enable the poseidon hash function
397    #[serde(skip_serializing_if = "is_false")]
398    enable_poseidon: bool,
399
400    // Enable native function for msm.
401    #[serde(skip_serializing_if = "is_false")]
402    enable_group_ops_native_function_msm: bool,
403
404    // Controls the behavior of per object congestion control in consensus handler.
405    #[serde(skip_serializing_if = "PerObjectCongestionControlMode::is_none")]
406    per_object_congestion_control_mode: PerObjectCongestionControlMode,
407
408    // The consensus protocol to be used for the epoch.
409    #[serde(
410        default = "ConsensusChoice::mysticeti_deprecated",
411        skip_serializing_if = "ConsensusChoice::is_mysticeti_deprecated"
412    )]
413    consensus_choice: ConsensusChoice,
414
415    // Consensus network to use.
416    #[serde(skip_serializing_if = "ConsensusNetwork::is_tonic")]
417    consensus_network: ConsensusNetwork,
418
419    // Set the upper bound allowed for max_epoch in zklogin signature.
420    #[deprecated]
421    #[serde(skip_serializing_if = "Option::is_none")]
422    zklogin_max_epoch_upper_bound_delta: Option<u64>,
423
424    // Enable VDF
425    #[serde(skip_serializing_if = "is_false")]
426    enable_vdf: bool,
427
428    // Enable passkey auth (SIP-9)
429    #[serde(skip_serializing_if = "is_false")]
430    passkey_auth: bool,
431
432    // Rethrow type layout errors during serialization instead of trying to convert them.
433    // This flag is used to provide the correct MoveVM configuration for clients.
434    #[serde(skip_serializing_if = "is_true")]
435    rethrow_serialization_type_layout_errors: bool,
436
437    // Makes the event's sending module version-aware.
438    #[serde(skip_serializing_if = "is_false")]
439    relocate_event_module: bool,
440
441    // Enable a protocol-defined base gas price for all transactions.
442    #[serde(skip_serializing_if = "is_false")]
443    protocol_defined_base_fee: bool,
444
445    // Enable uncompressed group elements in BLS123-81 G1
446    #[serde(skip_serializing_if = "is_false")]
447    uncompressed_g1_group_elements: bool,
448
449    // Disallow adding new modules in `deps-only` packages.
450    #[serde(skip_serializing_if = "is_false")]
451    disallow_new_modules_in_deps_only_packages: bool,
452
453    // Enable v2 native charging for natives.
454    #[serde(skip_serializing_if = "is_false")]
455    native_charging_v2: bool,
456
457    // Properly convert certain type argument errors in the execution layer.
458    #[serde(skip_serializing_if = "is_false")]
459    convert_type_argument_error: bool,
460
461    // Probe rounds received by peers from every authority.
462    #[serde(skip_serializing_if = "is_false")]
463    consensus_round_prober: bool,
464
465    // Use distributed vote leader scoring strategy in consensus.
466    #[serde(skip_serializing_if = "is_false")]
467    consensus_distributed_vote_scoring_strategy: bool,
468
469    // Enables the new logic for collecting the subdag in the consensus linearizer. The new logic
470    // does not stop the recursion at the highest committed round for each authority, but
471    // allows to commit uncommitted blocks up to gc round (excluded) for that authority.
472    #[serde(skip_serializing_if = "is_false")]
473    consensus_linearize_subdag_v2: bool,
474
475    // Variants count as nodes
476    #[serde(skip_serializing_if = "is_false")]
477    variant_nodes: bool,
478
479    // Use smart ancestor selection in consensus.
480    #[serde(skip_serializing_if = "is_false")]
481    consensus_smart_ancestor_selection: bool,
482
483    // Probe accepted rounds in round prober.
484    #[serde(skip_serializing_if = "is_false")]
485    consensus_round_prober_probe_accepted_rounds: bool,
486
487    // If true, enable zstd compression for consensus tonic network.
488    #[serde(skip_serializing_if = "is_false")]
489    consensus_zstd_compression: bool,
490
491    // Use the minimum free execution slot to schedule execution of a transaction in the shared
492    // object congestion tracker.
493    #[serde(skip_serializing_if = "is_false")]
494    congestion_control_min_free_execution_slot: bool,
495
496    // If true, multisig containing passkey sig is accepted.
497    #[serde(skip_serializing_if = "is_false")]
498    accept_passkey_in_multisig: bool,
499
500    // If true, enabled batched block sync in consensus.
501    #[serde(skip_serializing_if = "is_false")]
502    consensus_batched_block_sync: bool,
503
504    // To enable/disable the gas price feedback mechanism used for transactions
505    // cancelled due to shared object congestion
506    #[serde(skip_serializing_if = "is_false")]
507    congestion_control_gas_price_feedback_mechanism: bool,
508
509    // Validate identifier inputs separately
510    #[serde(skip_serializing_if = "is_false")]
511    validate_identifier_inputs: bool,
512
513    // If true, enables the optimizations for child object mutations, removing unnecessary
514    // mutations
515    #[serde(skip_serializing_if = "is_false")]
516    minimize_child_object_mutations: bool,
517
518    // If true enable additional linkage checks.
519    #[serde(skip_serializing_if = "is_false")]
520    dependency_linkage_error: bool,
521
522    // If true enable additional multisig checks.
523    #[serde(skip_serializing_if = "is_false")]
524    additional_multisig_checks: bool,
525
526    // If true, enables the normalization of PTB arguments but does not yet enable splatting
527    // `Result`s of length not equal to 1
528    #[serde(skip_serializing_if = "is_false")]
529    normalize_ptb_arguments: bool,
530
531    // If true, use ChangeEpochV3 for epoch change to pass an additional eligible_active_validators
532    // parameter to IotaSystem's advance_epoch call. This should only be enabled when on-chain
533    // IotaSystem objects are updated as well.
534    #[serde(skip_serializing_if = "is_false")]
535    select_committee_from_eligible_validators: bool,
536
537    // If true, non-committee active validators will sign and send AuthorityCapabilitiesV1 to the
538    // committee. Once the committee reaches consensus over the AuthorityCapabilitiesV1, it is
539    // recorded and possible to use in the committee selection if
540    // select_validators_supporting_next_epoch_version is enabled. This flag does not change the
541    // way that eligible_validators vector is created - still all active validators are used for
542    // selecting the committee.
543    #[serde(skip_serializing_if = "is_false")]
544    track_non_committee_eligible_validators: bool,
545
546    // The committee be selected from active_validators who support the next protocol version AND
547    // have issued a correct AuthorityCapabilities notification. This flag should only be enabled
548    // if both select_committee_from_eligible_validators and
549    // track_non_committee_eligible_validators are enabled. If this is disabled, then all
550    // active validators are used for selecting the committee (default behavior).
551    #[serde(skip_serializing_if = "is_false")]
552    select_committee_supporting_next_epoch_version: bool,
553
554    // If true, then it (1) will not enforce monotonicity checks for a block's ancestors, (2)
555    // calculates the commit's timestamp based on the weighted by stake median timestamp of the
556    // leader's ancestors, and (3) enforces checkpoint timestamps are non-decreasing.
557    #[serde(skip_serializing_if = "is_false")]
558    consensus_median_timestamp_with_checkpoint_enforcement: bool,
559
560    // If true, then transactions are committed only for traversed headers
561    #[serde(skip_serializing_if = "is_false")]
562    consensus_commit_transactions_only_for_traversed_headers: bool,
563
564    // To enable/disable congestion limit overshoot in the gas price feedback mechanism.
565    #[serde(skip_serializing_if = "is_false")]
566    congestion_limit_overshoot_in_gas_price_feedback_mechanism: bool,
567
568    // To enable/disable a separate gas price feedback mechanism for transactions using
569    // randomness.
570    #[serde(skip_serializing_if = "is_false")]
571    separate_gas_price_feedback_mechanism_for_randomness: bool,
572
573    // If true, it allows metadata bytes indexed with a dedicated key in a compiled module.
574    // This flag is used to provide the correct MoveVM configuration for clients.
575    #[serde(skip_serializing_if = "is_false")]
576    metadata_in_module_bytes: bool,
577
578    // If true, enables publishing package metadata v1 along with the package.
579    #[serde(skip_serializing_if = "is_false")]
580    publish_package_metadata: bool,
581
582    // If true, enables the authentication of account using Move code.
583    #[serde(skip_serializing_if = "is_false")]
584    enable_move_authentication: bool,
585
586    // If true, enables the authentication of a sponsor account using Move code.
587    #[serde(skip_serializing_if = "is_false")]
588    enable_move_authentication_for_sponsor: bool,
589
590    // If true, the change epoch transaction will contain validator scores.
591    #[serde(skip_serializing_if = "is_false")]
592    pass_validator_scores_to_advance_epoch: bool,
593
594    // If true, enables calculation of validator scores.
595    #[serde(skip_serializing_if = "is_false")]
596    calculate_validator_scores: bool,
597
598    // If true, validators will use the committee's score to adjust rewards.
599    #[serde(skip_serializing_if = "is_false")]
600    adjust_rewards_by_score: bool,
601
602    // If true, the change epoch transaction will contain the locally calculated validator scores.
603    // If false, a default score (MAX_SCORE) is passed
604    #[serde(skip_serializing_if = "is_false")]
605    pass_calculated_validator_scores_to_advance_epoch: bool,
606
607    // If true, enables the fast commit syncer in Starfish consensus for faster recovery
608    // from large commit gaps. Also controls whether TransactionRef is used in commits
609    // instead of BlockRef, and enables the associated gRPC endpoints for fetching
610    // commits and transactions.
611    #[serde(skip_serializing_if = "is_false")]
612    consensus_fast_commit_sync: bool,
613
614    // If true, enables consensus block restrictions: bounds the block header size for
615    // a given committee size.
616    #[serde(skip_serializing_if = "is_false")]
617    consensus_block_restrictions: bool,
618
619    // If true, enable `TxContext` Move API to go native.
620    #[serde(skip_serializing_if = "is_false")]
621    move_native_tx_context: bool,
622
623    // If true, perform additional borrow checks
624    #[serde(skip_serializing_if = "is_false")]
625    additional_borrow_checks: bool,
626
627    // If true, only sponsor Move authentication is performed pre-consensus.
628    #[serde(skip_serializing_if = "is_false")]
629    pre_consensus_sponsor_only_move_authentication: bool,
630
631    // If true, enables the optimistic commit rule (StarfishSpeed) in Starfish consensus.
632    #[serde(skip_serializing_if = "is_false")]
633    consensus_starfish_speed: bool,
634
635    // If true, keep advancing the random beacon DKG state machine on every
636    // consensus commit while DKG is still pending, even when no new messages or
637    // confirmations were processed that commit. This lets a validator resolve
638    // DKG from already-persisted state (completing, or failing once the timeout
639    // round passes) with no fresh inbound traffic -- e.g. after a restart --
640    // instead of staying pending forever.
641    #[serde(skip_serializing_if = "is_false")]
642    always_advance_dkg_to_resolution: bool,
643
644    // If true, enables the P-COOL (post-consensus owned-object locking) flow:
645    // transactions bypass pre-consensus certification and owned-object locking,
646    // and conflicts are resolved deterministically post-consensus (white-flag
647    // conflict resolution) using persistent locks. Post-consensus deny checks
648    // use a consensus-governed deny rule set instead of each validator's local
649    // `TransactionDenyConfig`: validators announce proposed rules, and the
650    // active set is their stake-weighted aggregate. The active set is mirrored
651    // into the on-chain `TransactionDenyRules` object, which is created at the
652    // end of the first epoch with the flow and updated by system transactions
653    // when the active set changes.
654    //
655    // Post-consensus validation is deterministic: it reads object state as of
656    // `pcool_deterministic_validation_horizon_distance` commits below the
657    // commit it validates, and checks the sender against the coin deny list
658    // for the coin types of its inputs there, with changes made this epoch
659    // counting; execution no longer checks inputs against it. A committee
660    // validator does not execute state-synced checkpoints while its epoch is
661    // running: it waits for its own checkpoint builder and takes only
662    // randomness signatures from state sync. Once the certified last
663    // checkpoint of the epoch is known, it executes the rest of the epoch from
664    // state sync and stops processing consensus commits.
665    //
666    // From protocol version 39 requires `max_meter_ticks_regex_reference_safety`,
667    // `consensus_dedup_only_recorded_messages`, a positive
668    // `pcool_deterministic_validation_horizon_distance` and
669    // `deny_rule_update_max_entries_per_tx`, and excludes
670    // `pre_consensus_sponsor_only_move_authentication`.
671    #[serde(skip_serializing_if = "is_false")]
672    enable_pcool_flow: bool,
673
674    // No longer read: post-consensus validation never locks immutable inputs.
675    // Kept because shipped protocol versions set it.
676    #[serde(skip_serializing_if = "is_false")]
677    pcool_skip_immutable_object_locks: bool,
678
679    // No longer read: post-consensus validation always meters published
680    // packages with the verifier limits from this config. Kept because
681    // shipped protocol versions set it.
682    #[serde(skip_serializing_if = "is_false")]
683    pcool_verifier_limits_from_protocol_config: bool,
684
685    // If true perform consistent verification of metadata
686    #[serde(skip_serializing_if = "is_false")]
687    validator_metadata_verify_v2: bool,
688
689    // If true, the package holding a `MoveAuthenticator`'s authenticate function,
690    // together with that package's dependencies, is checked against the package
691    // deny list.
692    #[serde(skip_serializing_if = "is_false")]
693    deny_authenticator_packages: bool,
694
695    // If true, package metadata can be published with ModuleMetadata as a dynamic
696    // field.
697    #[serde(skip_serializing_if = "is_false")]
698    package_metadata_with_dynamic_module_metadata: bool,
699
700    // If true, a failure of the Move authentication is reported with a distinct
701    // `MoveAuthentication` execution error.
702    #[serde(skip_serializing_if = "is_false")]
703    report_move_authentication_error: bool,
704
705    // If true, the Starfish leader schedule scores reputation over a sliding
706    // window and rebuilds the swap table every `consensus_commits_per_schedule`
707    // commits with a uniform base election; when false, V2 snapshot scoring +
708    // stake-weighted base election is used.
709    #[serde(skip_serializing_if = "is_false")]
710    consensus_enable_sliding_window_leader_schedule: bool,
711
712    // If true, Starfish selects "bad" leader-schedule nodes by absolute
713    // normalized reputation score: exclude validators below a low threshold,
714    // capped at a maximum number of validators, and keep a minimum-size good
715    // (swap-in) pool; when false, the fixed stake cut by rank is used.
716    #[serde(skip_serializing_if = "is_false")]
717    consensus_enable_absolute_score_leader_schedule: bool,
718
719    // If true, enables better errors and bounds for max ptb values
720    #[serde(skip_serializing_if = "is_false")]
721    max_ptb_value_size_v2: bool,
722
723    // Allow objects created or mutated in system transactions to exceed the max object size limit.
724    #[serde(skip_serializing_if = "is_false")]
725    allow_unbounded_system_objects: bool,
726
727    // If true, transaction validation rejects a `MoveAuthenticator` whose
728    // account object is immutable.
729    #[serde(skip_serializing_if = "is_false")]
730    reject_immutable_account_objects: bool,
731
732    // If true, `iota::account::create_immutable_account_v1` aborts, so no new
733    // immutable account object can be created.
734    #[serde(skip_serializing_if = "is_false")]
735    reject_immutable_account_creation: bool,
736
737    // If true, `validity_check` rejects a transaction that names an object
738    // version at or above `Version::MAX_VALID_EXCL`, the range assigned to the
739    // objects of canceled transactions, or right below it, from the transaction
740    // bytes alone. Version assignment increments the largest input version and
741    // halts the node when the result is not a valid version.
742    #[serde(skip_serializing_if = "is_false")]
743    validate_input_object_versions: bool,
744
745    // Disallow self identifier
746    #[serde(skip_serializing_if = "is_false")]
747    disallow_self_identifier: bool,
748
749    // Reject a transaction whose type arguments, Move call module or function
750    // name, or Move authenticator type arguments carry an identifier that
751    // move-core rejects (`<SELF>`), at signing, after consensus and in block
752    // verification.
753    #[serde(skip_serializing_if = "is_false")]
754    disallow_self_identifier_in_transactions: bool,
755
756    // If true, the version field of a published module header must be the encoding
757    // the serializer produces for the version it decodes to. Below binary format
758    // version 7 the flavor byte is not part of the header, and without this check
759    // a non-zero flavor byte is masked off instead of rejected.
760    #[serde(skip_serializing_if = "is_false")]
761    check_canonical_module_version_header: bool,
762
763    // If true, `validity_check` rejects a `MoveAuthenticator` that names the
764    // randomness state object among its inputs. An authenticate function cannot
765    // derive randomness from it, but naming it schedules the transaction as
766    // randomness-using and defers it to a randomness round for nothing.
767    #[serde(skip_serializing_if = "is_false")]
768    disallow_randomness_in_move_authenticator: bool,
769
770    // If true, the cyclic dependency check traverses the module graph. Without it
771    // the traversal descends only into modules it has already visited, so it stops
772    // at the immediate dependencies and never reports a cycle.
773    #[serde(skip_serializing_if = "is_false")]
774    check_cyclic_dependencies: bool,
775
776    // Validate PTB input and result indices before signing.
777    #[serde(skip_serializing_if = "is_false")]
778    validate_ptb_argument_indices: bool,
779
780    // If true, keep DKG pending after its timeout so that it can complete later
781    // in the epoch.
782    #[serde(skip_serializing_if = "is_false")]
783    allow_dkg_completion_after_timeout: bool,
784
785    // If true, a consensus message is skipped as a duplicate of an earlier message with the same
786    // key that was recorded as processed or passed verification in the same commit:
787    // - The consensus handler adds a message to its processed-transaction cache only after the
788    //   epoch store recorded it as processed. Otherwise the cache also holds messages that were
789    //   dropped without being recorded, and since it differs between validators and after a
790    //   restart, skipping on a cache hit lets validators disagree about a later message with the
791    //   same key.
792    // - A user transaction from an authority that has sent EndOfPublish fails verification, so it
793    //   does not make a later transaction with the same key in its commit be skipped.
794    #[serde(skip_serializing_if = "is_false")]
795    consensus_dedup_only_recorded_messages: bool,
796
797    // If true, a multisig whose committee mixes Ed25519 with other key schemes
798    // is only accepted when every committee member has signed. Ed25519 members
799    // carry no flag byte in the multisig address preimage, so two different
800    // mixed committees can derive the same address.
801    #[serde(skip_serializing_if = "is_false")]
802    reject_partially_signed_mixed_ed25519_multisig: bool,
803
804    // If true, groth16::prepare_verifying_key checks that the verifying key has
805    // no more than MAX_PUBLIC_INPUTS public inputs.
806    #[serde(skip_serializing_if = "is_false")]
807    limit_groth16_pvk_inputs: bool,
808
809    // If true, groth16::verify_groth16_proof checks that the prepared verifying
810    // key has the length implied by the number of public inputs, and aborts
811    // with EInvalidVerifyingKey if it does not.
812    #[serde(skip_serializing_if = "is_false")]
813    check_groth16_pvk_length: bool,
814
815    // If true, deprecate global storage ops everywhere. A module that uses the
816    // deprecated global storage instructions, or has a non-empty `acquires`
817    // list, fails to deserialize. The verifier skips the acquires pass, checks
818    // vector element borrows with the same rule as calls, and fails if a
819    // deprecated instruction reaches it. This applies to every module the VM
820    // verifies, including published packages it loads. Signing always runs
821    // with it on; post-consensus validation follows this flag.
822    #[serde(skip_serializing_if = "is_false")]
823    deprecate_global_storage_ops: bool,
824
825    // If true, post-consensus validation meters the instantiation-loop check
826    // of the bytecode verifier. Signing always meters it.
827    #[serde(skip_serializing_if = "is_false")]
828    meter_instantiation_loops: bool,
829
830    // If true, the packages named by a `MoveAuthenticator`'s type arguments are
831    // inputs of that authenticator, as those of a `MoveCall` are. Without it no
832    // node waits for them, so a node that has not executed such a package's
833    // publish yet fails an authentication that the others pass.
834    #[serde(skip_serializing_if = "is_false")]
835    move_authenticator_type_arg_packages_as_inputs: bool,
836}
837
838fn is_true(b: &bool) -> bool {
839    *b
840}
841
842fn is_false(b: &bool) -> bool {
843    !b
844}
845
846/// Ordering mechanism for transactions in one consensus output.
847#[derive(Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
848pub enum ConsensusTransactionOrdering {
849    /// No ordering. Transactions are processed in the order they appear in the
850    /// consensus output.
851    #[default]
852    None,
853    /// Order transactions by gas price, highest first.
854    ByGasPrice,
855}
856
857impl ConsensusTransactionOrdering {
858    pub fn is_none(&self) -> bool {
859        matches!(self, ConsensusTransactionOrdering::None)
860    }
861}
862
863// The config for per object congestion control in consensus handler.
864#[derive(Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
865pub enum PerObjectCongestionControlMode {
866    #[default]
867    None, // No congestion control.
868    TotalGasBudget, // Use txn gas budget as execution cost.
869    TotalTxCount,   // Use total txn count as execution cost.
870}
871
872impl PerObjectCongestionControlMode {
873    pub fn is_none(&self) -> bool {
874        matches!(self, PerObjectCongestionControlMode::None)
875    }
876}
877
878// Configuration options for consensus algorithm.
879#[derive(Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
880pub enum ConsensusChoice {
881    /// Kept only so protocol-config serialization of historical epochs stays
882    /// bit-for-bit identical; no runtime code branches on it.
883    #[deprecated(note = "Mysticeti was replaced by Starfish")]
884    MysticetiDeprecated,
885    #[default]
886    Starfish,
887}
888
889#[expect(deprecated)]
890impl ConsensusChoice {
891    /// serde deserialization default: an absent `consensus_choice` field in a
892    /// historical snapshot deserializes to `MysticetiDeprecated` so that
893    /// re-serialization stays byte-identical (the skip condition below also
894    /// triggers on that variant). Decoupled from the Rust `Default` impl,
895    /// which returns `Starfish` to reflect that Starfish is the current
896    /// consensus protocol.
897    fn mysticeti_deprecated() -> Self {
898        ConsensusChoice::MysticetiDeprecated
899    }
900
901    pub fn is_mysticeti_deprecated(&self) -> bool {
902        matches!(self, ConsensusChoice::MysticetiDeprecated)
903    }
904    pub fn is_starfish(&self) -> bool {
905        matches!(self, ConsensusChoice::Starfish)
906    }
907}
908
909// Configuration options for consensus network.
910#[derive(Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
911pub enum ConsensusNetwork {
912    #[default]
913    Tonic,
914}
915
916impl ConsensusNetwork {
917    pub fn is_tonic(&self) -> bool {
918        matches!(self, ConsensusNetwork::Tonic)
919    }
920}
921
922/// Constants that change the behavior of the protocol.
923///
924/// The value of each constant here must be fixed for a given protocol version.
925/// To change the value of a constant, advance the protocol version, and add
926/// support for it in `get_for_version` under the new version number.
927/// (below).
928///
929/// To add a new field to this struct, use the following procedure:
930/// - Advance the protocol version.
931/// - Add the field as a private `Option<T>` to the struct.
932/// - Initialize the field to `None` in prior protocol versions.
933/// - Initialize the field to `Some(val)` for your new protocol version.
934/// - Add a public getter that simply unwraps the field.
935/// - Two public getters of the form `field(&self) -> field_type` and `field_as_option(&self) ->
936///   Option<field_type>` will be automatically generated for you.
937/// Example for a field: `new_constant: Option<u64>`
938/// ```rust,ignore
939///      pub fn new_constant(&self) -> u64 {
940///         self.new_constant.expect(Self::CONSTANT_ERR_MSG)
941///     }
942///      pub fn new_constant_as_option(&self) -> Option<u64> {
943///         self.new_constant.expect(Self::CONSTANT_ERR_MSG)
944///     }
945/// ```
946/// With `pub fn new_constant(&self) -> u64`, if the constant is accessed in a
947/// protocol version in which it is not defined, the validator will crash.
948/// (Crashing is necessary because this type of error would almost always result
949/// in forking if not prevented here). If you don't want the validator to crash,
950/// you can use the `pub fn new_constant_as_option(&self) -> Option<u64>`
951/// getter, which will return `None` if the field is not defined at that
952/// version.
953/// - If you want a customized getter, you can add a method in the impl.
954#[skip_serializing_none]
955#[derive(Clone, Serialize, Debug, ProtocolConfigAccessors, ProtocolConfigOverride)]
956pub struct ProtocolConfig {
957    pub version: ProtocolVersion,
958
959    feature_flags: FeatureFlags,
960
961    // ==== Transaction input limits ====
962
963    //
964    /// Maximum serialized size of a transaction (in bytes).
965    max_tx_size_bytes: Option<u64>,
966
967    /// Maximum number of input objects to a transaction. Enforced by the
968    /// transaction input checker. Pure inputs do not count towards it; all
969    /// inputs together cannot exceed
970    /// `iota_types::transaction::MAX_PROGRAMMABLE_TX_INPUTS`.
971    max_input_objects: Option<u64>,
972
973    /// Max size of objects a transaction can write to disk after completion.
974    /// Enforce by the IOTA adapter. This is the sum of the serialized size
975    /// of all objects written to disk. The max size of individual objects
976    /// on the other hand is `max_move_object_size`.
977    max_size_written_objects: Option<u64>,
978    /// Max size of objects a system transaction can write to disk after
979    /// completion. Enforce by the IOTA adapter. Similar to
980    /// `max_size_written_objects` but for system transactions.
981    max_size_written_objects_system_tx: Option<u64>,
982
983    /// Maximum size of serialized transaction effects.
984    max_serialized_tx_effects_size_bytes: Option<u64>,
985
986    /// Maximum size of serialized transaction effects for system transactions.
987    max_serialized_tx_effects_size_bytes_system_tx: Option<u64>,
988
989    /// Maximum number of gas payment objects for a transaction.
990    max_gas_payment_objects: Option<u32>,
991
992    /// Maximum number of modules in a Publish transaction.
993    max_modules_in_publish: Option<u32>,
994
995    /// Maximum number of transitive dependencies in a package when publishing.
996    max_package_dependencies: Option<u32>,
997
998    /// Maximum number of arguments in a move call or a
999    /// ProgrammableTransaction's TransferObjects command.
1000    max_arguments: Option<u32>,
1001
1002    /// Maximum number of total type arguments, computed recursively.
1003    max_type_arguments: Option<u32>,
1004
1005    /// Maximum depth of an individual type argument.
1006    max_type_argument_depth: Option<u32>,
1007
1008    /// Maximum size of a Pure CallArg.
1009    max_pure_argument_size: Option<u32>,
1010
1011    /// Maximum number of Commands in a ProgrammableTransaction.
1012    max_programmable_tx_commands: Option<u32>,
1013
1014    // ==== Move VM, Move bytecode verifier, and execution limits ===
1015
1016    //
1017    /// Maximum Move bytecode version the VM understands. All older versions are
1018    /// accepted.
1019    move_binary_format_version: Option<u32>,
1020    min_move_binary_format_version: Option<u32>,
1021
1022    /// Configuration controlling binary tables size.
1023    binary_module_handles: Option<u16>,
1024    binary_struct_handles: Option<u16>,
1025    binary_function_handles: Option<u16>,
1026    binary_function_instantiations: Option<u16>,
1027    binary_signatures: Option<u16>,
1028    binary_constant_pool: Option<u16>,
1029    binary_identifiers: Option<u16>,
1030    binary_address_identifiers: Option<u16>,
1031    binary_struct_defs: Option<u16>,
1032    binary_struct_def_instantiations: Option<u16>,
1033    binary_function_defs: Option<u16>,
1034    binary_field_handles: Option<u16>,
1035    binary_field_instantiations: Option<u16>,
1036    binary_friend_decls: Option<u16>,
1037    binary_enum_defs: Option<u16>,
1038    binary_enum_def_instantiations: Option<u16>,
1039    binary_variant_handles: Option<u16>,
1040    binary_variant_instantiation_handles: Option<u16>,
1041
1042    /// Maximum size of the `contents` part of an object, in bytes. Enforced by
1043    /// the IOTA adapter when effects are produced.
1044    max_move_object_size: Option<u64>,
1045
1046    // TODO: Option<increase to 500 KB. currently, publishing a package > 500 KB exceeds the max
1047    // computation gas cost
1048    /// Maximum size of a Move package object, in bytes. Enforced by the IOTA
1049    /// adapter at the end of a publish transaction.
1050    max_move_package_size: Option<u64>,
1051
1052    /// Max number of publish or upgrade commands allowed in a programmable
1053    /// transaction block.
1054    max_publish_or_upgrade_per_ptb: Option<u64>,
1055
1056    /// Maximum gas budget in NANOS that a transaction can use.
1057    max_tx_gas: Option<u64>,
1058
1059    /// Maximum gas budget in NANOS that a authentication transaction can use.
1060    max_auth_gas: Option<u64>,
1061
1062    /// Maximum amount of the proposed gas price in NANOS (defined in the
1063    /// transaction).
1064    max_gas_price: Option<u64>,
1065
1066    /// The max computation bucket for gas. This is the max that can be charged
1067    /// for computation.
1068    max_gas_computation_bucket: Option<u64>,
1069
1070    // Define the value used to round up computation gas charges
1071    gas_rounding_step: Option<u64>,
1072
1073    /// Maximum number of nested loops. Enforced by the Move bytecode verifier.
1074    max_loop_depth: Option<u64>,
1075
1076    /// Maximum number of type arguments that can be bound to generic type
1077    /// parameters. Enforced by the Move bytecode verifier.
1078    max_generic_instantiation_length: Option<u64>,
1079
1080    /// Maximum number of parameters that a Move function can have. Enforced by
1081    /// the Move bytecode verifier.
1082    max_function_parameters: Option<u64>,
1083
1084    /// Maximum number of basic blocks that a Move function can have. Enforced
1085    /// by the Move bytecode verifier.
1086    max_basic_blocks: Option<u64>,
1087
1088    /// Maximum stack size value. Enforced by the Move bytecode verifier.
1089    max_value_stack_size: Option<u64>,
1090
1091    /// Maximum number of "type nodes", a metric for how big a SignatureToken
1092    /// will be when expanded into a fully qualified type. Enforced by the Move
1093    /// bytecode verifier.
1094    max_type_nodes: Option<u64>,
1095
1096    /// Maximum number of push instructions in one function. Enforced by the
1097    /// Move bytecode verifier.
1098    max_push_size: Option<u64>,
1099
1100    /// Maximum number of struct definitions in a module. Enforced by the Move
1101    /// bytecode verifier.
1102    max_struct_definitions: Option<u64>,
1103
1104    /// Maximum number of function definitions in a module. Enforced by the Move
1105    /// bytecode verifier.
1106    max_function_definitions: Option<u64>,
1107
1108    /// Maximum number of fields allowed in a struct definition. Enforced by the
1109    /// Move bytecode verifier.
1110    max_fields_in_struct: Option<u64>,
1111
1112    /// Maximum dependency depth. Enforced by the Move linker when loading
1113    /// dependent modules.
1114    max_dependency_depth: Option<u64>,
1115
1116    /// Maximum number of Move events that a single transaction can emit.
1117    /// Enforced by the VM during execution.
1118    max_num_event_emit: Option<u64>,
1119
1120    /// Maximum number of new IDs that a single transaction can create. Enforced
1121    /// by the VM during execution.
1122    max_num_new_move_object_ids: Option<u64>,
1123
1124    /// Maximum number of new IDs that a single system transaction can create.
1125    /// Enforced by the VM during execution.
1126    max_num_new_move_object_ids_system_tx: Option<u64>,
1127
1128    /// Maximum number of IDs that a single transaction can delete. Enforced by
1129    /// the VM during execution.
1130    max_num_deleted_move_object_ids: Option<u64>,
1131
1132    /// Maximum number of IDs that a single system transaction can delete.
1133    /// Enforced by the VM during execution.
1134    max_num_deleted_move_object_ids_system_tx: Option<u64>,
1135
1136    /// Maximum number of IDs that a single transaction can transfer. Enforced
1137    /// by the VM during execution.
1138    max_num_transferred_move_object_ids: Option<u64>,
1139
1140    /// Maximum number of IDs that a single system transaction can transfer.
1141    /// Enforced by the VM during execution.
1142    max_num_transferred_move_object_ids_system_tx: Option<u64>,
1143
1144    /// Maximum size of a Move user event. Enforced by the VM during execution.
1145    max_event_emit_size: Option<u64>,
1146
1147    /// Maximum size of a Move user event. Enforced by the VM during execution.
1148    max_event_emit_size_total: Option<u64>,
1149
1150    /// Maximum length of a vector in Move. Enforced by the VM during execution,
1151    /// and for constants, by the verifier.
1152    max_move_vector_len: Option<u64>,
1153
1154    /// Maximum length of an `Identifier` in Move. Enforced by the bytecode
1155    /// verifier at signing.
1156    max_move_identifier_len: Option<u64>,
1157
1158    /// Maximum depth of a Move value within the VM.
1159    max_move_value_depth: Option<u64>,
1160
1161    /// Maximum number of struct, enum and vector values in the arguments of
1162    /// one Move call.
1163    max_move_call_argument_nodes: Option<u64>,
1164
1165    /// Maximum number of struct, enum and vector values in the arguments of
1166    /// all Move calls of one programmable transaction.
1167    max_move_call_argument_nodes_total: Option<u64>,
1168
1169    /// Maximum number of variants in an enum. Enforced by the bytecode verifier
1170    /// at signing.
1171    max_move_enum_variants: Option<u64>,
1172
1173    // === Metered bytecode verifier limits ===
1174    // Enforced on the packages a transaction publishes when post-consensus
1175    // validation checks them.
1176    // Signing, admission and simulation are validator-local decisions and use
1177    // each validator's own `VerifierSigningConfig` instead.
1178
1179    //
1180    /// Maximum number of back edges in a Move function.
1181    max_back_edges_per_function: Option<u64>,
1182
1183    /// Maximum number of back edges in a Move module.
1184    max_back_edges_per_module: Option<u64>,
1185
1186    /// Maximum number of meter `ticks` spent verifying a Move function.
1187    max_verifier_meter_ticks_per_function: Option<u64>,
1188
1189    /// Maximum number of meter `ticks` spent verifying a Move module.
1190    max_meter_ticks_per_module: Option<u64>,
1191
1192    /// Maximum number of meter `ticks` spent verifying a Move package.
1193    max_meter_ticks_per_package: Option<u64>,
1194
1195    /// Maximum number of meter `ticks` the regex-based reference safety check
1196    /// may spend per function, module and package. The check rejects a module
1197    /// it cannot finish within the limit.
1198    max_meter_ticks_regex_reference_safety: Option<u64>,
1199
1200    /// Maximum number of edges in the instantiation-loop graph of a Move
1201    /// module, checked only by post-consensus validation. Signing uses a limit
1202    /// set in the binary instead, and execution does not check it.
1203    max_instantiation_loop_graph_edges: Option<u64>,
1204
1205    // === Object runtime internal operation limits ====
1206    // These affect dynamic fields
1207
1208    //
1209    /// Maximum number of cached objects in the object runtime ObjectStore.
1210    /// Enforced by object runtime during execution
1211    object_runtime_max_num_cached_objects: Option<u64>,
1212
1213    /// Maximum number of cached objects in the object runtime ObjectStore in
1214    /// system transaction. Enforced by object runtime during execution
1215    object_runtime_max_num_cached_objects_system_tx: Option<u64>,
1216
1217    /// Maximum number of stored objects accessed by object runtime ObjectStore.
1218    /// Enforced by object runtime during execution
1219    object_runtime_max_num_store_entries: Option<u64>,
1220
1221    /// Maximum number of stored objects accessed by object runtime ObjectStore
1222    /// in system transaction. Enforced by object runtime during execution
1223    object_runtime_max_num_store_entries_system_tx: Option<u64>,
1224
1225    // === Execution gas costs ====
1226
1227    //
1228    /// Base cost for any IOTA transaction
1229    base_tx_cost_fixed: Option<u64>,
1230
1231    /// Additional cost for a transaction that publishes a package
1232    /// i.e., the base cost of such a transaction is base_tx_cost_fixed +
1233    /// package_publish_cost_fixed
1234    package_publish_cost_fixed: Option<u64>,
1235
1236    /// Cost per byte of a Move call transaction
1237    /// i.e., the cost of such a transaction is base_cost +
1238    /// (base_tx_cost_per_byte * size)
1239    base_tx_cost_per_byte: Option<u64>,
1240
1241    /// Cost per byte for a transaction that publishes a package
1242    package_publish_cost_per_byte: Option<u64>,
1243
1244    // Per-byte cost of reading an object during transaction execution
1245    obj_access_cost_read_per_byte: Option<u64>,
1246
1247    // Per-byte cost of writing an object during transaction execution
1248    obj_access_cost_mutate_per_byte: Option<u64>,
1249
1250    // Per-byte cost of deleting an object during transaction execution
1251    obj_access_cost_delete_per_byte: Option<u64>,
1252
1253    /// Per-byte cost charged for each input object to a transaction.
1254    /// Meant to approximate the cost of checking locks for each object
1255    // TODO: Option<I'm not sure that this cost makes sense. Checking locks is "free"
1256    // in the sense that an invalid tx that can never be committed/pay gas can
1257    // force validators to check an arbitrary number of locks. If those checks are
1258    // "free" for invalid transactions, why charge for them in valid transactions
1259    // TODO: Option<if we keep this, I think we probably want it to be a fixed cost rather
1260    // than a per-byte cost. checking an object lock should not require loading an
1261    // entire object, just consulting an ID -> tx digest map
1262    obj_access_cost_verify_per_byte: Option<u64>,
1263
1264    // Maximal nodes which are allowed when converting to a type layout.
1265    max_type_to_layout_nodes: Option<u64>,
1266
1267    // Maximal size in bytes that a PTB value can be
1268    max_ptb_value_size: Option<u64>,
1269
1270    // === Gas version. gas model ===
1271
1272    //
1273    /// Gas model version, what code we are using to charge gas
1274    gas_model_version: Option<u64>,
1275
1276    // === Storage gas costs ===
1277
1278    //
1279    /// Per-byte cost of storing an object in the IOTA global object store. Some
1280    /// of this cost may be refundable if the object is later freed
1281    obj_data_cost_refundable: Option<u64>,
1282
1283    // Per-byte cost of storing an object in the IOTA transaction log (e.g., in
1284    // CertifiedTransactionEffects) This depends on the size of various fields including the
1285    // effects TODO: Option<I don't fully understand this^ and more details would be useful
1286    obj_metadata_cost_non_refundable: Option<u64>,
1287
1288    // === Tokenomics ===
1289
1290    // TODO: Option<this should be changed to u64.
1291    /// Sender of a txn that touches an object will get this percent of the
1292    /// storage rebate back. In basis point.
1293    storage_rebate_rate: Option<u64>,
1294
1295    /// The share of rewards that will be slashed and redistributed is 50%.
1296    /// In basis point.
1297    reward_slashing_rate: Option<u64>,
1298
1299    /// Unit storage gas price, Nanos per internal gas unit.
1300    storage_gas_price: Option<u64>,
1301
1302    // Base gas price for computation gas, nanos per computation unit.
1303    base_gas_price: Option<u64>,
1304
1305    /// The number of tokens minted as a validator subsidy per epoch.
1306    validator_target_reward: Option<u64>,
1307
1308    // === Core Protocol ===
1309
1310    //
1311    /// Max number of transactions per checkpoint.
1312    /// Note that this is a protocol constant and not a config as validators
1313    /// must have this set to the same value, otherwise they *will* fork.
1314    max_transactions_per_checkpoint: Option<u64>,
1315
1316    /// Max size of a checkpoint in bytes.
1317    /// Note that this is a protocol constant and not a config as validators
1318    /// must have this set to the same value, otherwise they *will* fork.
1319    max_checkpoint_size_bytes: Option<u64>,
1320
1321    /// A protocol upgrade always requires 2f+1 stake to agree. We support a
1322    /// buffer of additional stake (as a fraction of f, expressed in basis
1323    /// points) that is required before an upgrade can happen automatically.
1324    /// 10000bps would indicate that complete unanimity is required (all
1325    /// 3f+1 must vote), while 0bps would indicate that 2f+1 is sufficient.
1326    buffer_stake_for_protocol_upgrade_bps: Option<u64>,
1327
1328    // === Native Function Costs ===
1329
1330    // `address` module
1331    // Cost params for the Move native function `address::from_bytes(bytes: vector<u8>)`
1332    address_from_bytes_cost_base: Option<u64>,
1333    // Cost params for the Move native function `address::to_u256(address): u256`
1334    address_to_u256_cost_base: Option<u64>,
1335    // Cost params for the Move native function `address::from_u256(u256): address`
1336    address_from_u256_cost_base: Option<u64>,
1337
1338    // `config` module
1339    // Cost params for the Move native function `read_setting_impl<Name: copy + drop + store,
1340    // SettingValue: key + store, SettingDataValue: store, Value: copy + drop + store,
1341    // >(config: address, name: address, current_epoch: u64): Option<Value>`
1342    config_read_setting_impl_cost_base: Option<u64>,
1343    config_read_setting_impl_cost_per_byte: Option<u64>,
1344
1345    // `dynamic_field` module
1346    // Cost params for the Move native function `hash_type_and_key<K: copy + drop + store>(parent:
1347    // address, k: K): address`
1348    dynamic_field_hash_type_and_key_cost_base: Option<u64>,
1349    dynamic_field_hash_type_and_key_type_cost_per_byte: Option<u64>,
1350    dynamic_field_hash_type_and_key_value_cost_per_byte: Option<u64>,
1351    dynamic_field_hash_type_and_key_type_tag_cost_per_byte: Option<u64>,
1352    // Cost params for the Move native function `add_child_object<Child: key>(parent: address,
1353    // child: Child)`
1354    dynamic_field_add_child_object_cost_base: Option<u64>,
1355    dynamic_field_add_child_object_type_cost_per_byte: Option<u64>,
1356    dynamic_field_add_child_object_value_cost_per_byte: Option<u64>,
1357    dynamic_field_add_child_object_struct_tag_cost_per_byte: Option<u64>,
1358    // Cost params for the Move native function `borrow_child_object_mut<Child: key>(parent: &mut
1359    // UID, id: address): &mut Child`
1360    dynamic_field_borrow_child_object_cost_base: Option<u64>,
1361    dynamic_field_borrow_child_object_child_ref_cost_per_byte: Option<u64>,
1362    dynamic_field_borrow_child_object_type_cost_per_byte: Option<u64>,
1363    // Cost params for the Move native function `remove_child_object<Child: key>(parent: address,
1364    // id: address): Child`
1365    dynamic_field_remove_child_object_cost_base: Option<u64>,
1366    dynamic_field_remove_child_object_child_cost_per_byte: Option<u64>,
1367    dynamic_field_remove_child_object_type_cost_per_byte: Option<u64>,
1368    // Cost params for the Move native function `has_child_object(parent: address, id: address):
1369    // bool`
1370    dynamic_field_has_child_object_cost_base: Option<u64>,
1371    // Cost params for the Move native function `has_child_object_with_ty<Child: key>(parent:
1372    // address, id: address): bool`
1373    dynamic_field_has_child_object_with_ty_cost_base: Option<u64>,
1374    dynamic_field_has_child_object_with_ty_type_cost_per_byte: Option<u64>,
1375    dynamic_field_has_child_object_with_ty_type_tag_cost_per_byte: Option<u64>,
1376
1377    // `event` module
1378    // Cost params for the Move native function `event::emit<T: copy + drop>(event: T)`
1379    event_emit_cost_base: Option<u64>,
1380    event_emit_value_size_derivation_cost_per_byte: Option<u64>,
1381    event_emit_tag_size_derivation_cost_per_byte: Option<u64>,
1382    event_emit_output_cost_per_byte: Option<u64>,
1383
1384    //  `object` module
1385    // Cost params for the Move native function `borrow_uid<T: key>(obj: &T): &UID`
1386    object_borrow_uid_cost_base: Option<u64>,
1387    // Cost params for the Move native function `delete_impl(id: address)`
1388    object_delete_impl_cost_base: Option<u64>,
1389    // Cost params for the Move native function `record_new_uid(id: address)`
1390    object_record_new_uid_cost_base: Option<u64>,
1391
1392    // Transfer
1393    // Cost params for the Move native function `transfer_impl<T: key>(obj: T, recipient: address)`
1394    transfer_transfer_internal_cost_base: Option<u64>,
1395    // Cost params for the Move native function `freeze_object<T: key>(obj: T)`
1396    transfer_freeze_object_cost_base: Option<u64>,
1397    // Cost params for the Move native function `share_object<T: key>(obj: T)`
1398    transfer_share_object_cost_base: Option<u64>,
1399    // Cost params for the Move native function
1400    // `receive_object<T: key>(p: &mut UID, recv: Receiving<T>T)`
1401    transfer_receive_object_cost_base: Option<u64>,
1402
1403    // TxContext
1404    // Cost params for the Move native function `transfer_impl<T: key>(obj: T, recipient: address)`
1405    tx_context_derive_id_cost_base: Option<u64>,
1406    tx_context_fresh_id_cost_base: Option<u64>,
1407    tx_context_sender_cost_base: Option<u64>,
1408    tx_context_digest_cost_base: Option<u64>,
1409    tx_context_epoch_cost_base: Option<u64>,
1410    tx_context_epoch_timestamp_ms_cost_base: Option<u64>,
1411    tx_context_sponsor_cost_base: Option<u64>,
1412    tx_context_rgp_cost_base: Option<u64>,
1413    tx_context_gas_price_cost_base: Option<u64>,
1414    tx_context_gas_budget_cost_base: Option<u64>,
1415    tx_context_ids_created_cost_base: Option<u64>,
1416    tx_context_replace_cost_base: Option<u64>,
1417
1418    // Types
1419    // Cost params for the Move native function `is_one_time_witness<T: drop>(_: &T): bool`
1420    types_is_one_time_witness_cost_base: Option<u64>,
1421    types_is_one_time_witness_type_tag_cost_per_byte: Option<u64>,
1422    types_is_one_time_witness_type_cost_per_byte: Option<u64>,
1423
1424    // Validator
1425    // Cost params for the Move native function `validate_metadata_bcs(metadata: vector<u8>)`
1426    validator_validate_metadata_cost_base: Option<u64>,
1427    validator_validate_metadata_data_cost_per_byte: Option<u64>,
1428
1429    // Crypto natives
1430    crypto_invalid_arguments_cost: Option<u64>,
1431    // bls12381::bls12381_min_sig_verify
1432    bls12381_bls12381_min_sig_verify_cost_base: Option<u64>,
1433    bls12381_bls12381_min_sig_verify_msg_cost_per_byte: Option<u64>,
1434    bls12381_bls12381_min_sig_verify_msg_cost_per_block: Option<u64>,
1435
1436    // bls12381::bls12381_min_pk_verify
1437    bls12381_bls12381_min_pk_verify_cost_base: Option<u64>,
1438    bls12381_bls12381_min_pk_verify_msg_cost_per_byte: Option<u64>,
1439    bls12381_bls12381_min_pk_verify_msg_cost_per_block: Option<u64>,
1440
1441    // ecdsa_k1::ecrecover
1442    ecdsa_k1_ecrecover_keccak256_cost_base: Option<u64>,
1443    ecdsa_k1_ecrecover_keccak256_msg_cost_per_byte: Option<u64>,
1444    ecdsa_k1_ecrecover_keccak256_msg_cost_per_block: Option<u64>,
1445    ecdsa_k1_ecrecover_sha256_cost_base: Option<u64>,
1446    ecdsa_k1_ecrecover_sha256_msg_cost_per_byte: Option<u64>,
1447    ecdsa_k1_ecrecover_sha256_msg_cost_per_block: Option<u64>,
1448
1449    // ecdsa_k1::decompress_pubkey
1450    ecdsa_k1_decompress_pubkey_cost_base: Option<u64>,
1451
1452    // ecdsa_k1::secp256k1_verify
1453    ecdsa_k1_secp256k1_verify_keccak256_cost_base: Option<u64>,
1454    ecdsa_k1_secp256k1_verify_keccak256_msg_cost_per_byte: Option<u64>,
1455    ecdsa_k1_secp256k1_verify_keccak256_msg_cost_per_block: Option<u64>,
1456    ecdsa_k1_secp256k1_verify_sha256_cost_base: Option<u64>,
1457    ecdsa_k1_secp256k1_verify_sha256_msg_cost_per_byte: Option<u64>,
1458    ecdsa_k1_secp256k1_verify_sha256_msg_cost_per_block: Option<u64>,
1459
1460    // ecdsa_r1::ecrecover
1461    ecdsa_r1_ecrecover_keccak256_cost_base: Option<u64>,
1462    ecdsa_r1_ecrecover_keccak256_msg_cost_per_byte: Option<u64>,
1463    ecdsa_r1_ecrecover_keccak256_msg_cost_per_block: Option<u64>,
1464    ecdsa_r1_ecrecover_sha256_cost_base: Option<u64>,
1465    ecdsa_r1_ecrecover_sha256_msg_cost_per_byte: Option<u64>,
1466    ecdsa_r1_ecrecover_sha256_msg_cost_per_block: Option<u64>,
1467
1468    // ecdsa_r1::secp256k1_verify
1469    ecdsa_r1_secp256r1_verify_keccak256_cost_base: Option<u64>,
1470    ecdsa_r1_secp256r1_verify_keccak256_msg_cost_per_byte: Option<u64>,
1471    ecdsa_r1_secp256r1_verify_keccak256_msg_cost_per_block: Option<u64>,
1472    ecdsa_r1_secp256r1_verify_sha256_cost_base: Option<u64>,
1473    ecdsa_r1_secp256r1_verify_sha256_msg_cost_per_byte: Option<u64>,
1474    ecdsa_r1_secp256r1_verify_sha256_msg_cost_per_block: Option<u64>,
1475
1476    // ecvrf::verify
1477    ecvrf_ecvrf_verify_cost_base: Option<u64>,
1478    ecvrf_ecvrf_verify_alpha_string_cost_per_byte: Option<u64>,
1479    ecvrf_ecvrf_verify_alpha_string_cost_per_block: Option<u64>,
1480
1481    // ed25519
1482    ed25519_ed25519_verify_cost_base: Option<u64>,
1483    ed25519_ed25519_verify_msg_cost_per_byte: Option<u64>,
1484    ed25519_ed25519_verify_msg_cost_per_block: Option<u64>,
1485
1486    // groth16::prepare_verifying_key
1487    groth16_prepare_verifying_key_bls12381_cost_base: Option<u64>,
1488    groth16_prepare_verifying_key_bn254_cost_base: Option<u64>,
1489
1490    // groth16::verify_groth16_proof_internal
1491    groth16_verify_groth16_proof_internal_bls12381_cost_base: Option<u64>,
1492    groth16_verify_groth16_proof_internal_bls12381_cost_per_public_input: Option<u64>,
1493    groth16_verify_groth16_proof_internal_bn254_cost_base: Option<u64>,
1494    groth16_verify_groth16_proof_internal_bn254_cost_per_public_input: Option<u64>,
1495    groth16_verify_groth16_proof_internal_public_input_cost_per_byte: Option<u64>,
1496
1497    // hash::blake2b256
1498    hash_blake2b256_cost_base: Option<u64>,
1499    hash_blake2b256_data_cost_per_byte: Option<u64>,
1500    hash_blake2b256_data_cost_per_block: Option<u64>,
1501
1502    // hash::keccak256
1503    hash_keccak256_cost_base: Option<u64>,
1504    hash_keccak256_data_cost_per_byte: Option<u64>,
1505    hash_keccak256_data_cost_per_block: Option<u64>,
1506
1507    // poseidon::poseidon_bn254
1508    poseidon_bn254_cost_base: Option<u64>,
1509    poseidon_bn254_cost_per_block: Option<u64>,
1510
1511    // group_ops
1512    group_ops_bls12381_decode_scalar_cost: Option<u64>,
1513    group_ops_bls12381_decode_g1_cost: Option<u64>,
1514    group_ops_bls12381_decode_g2_cost: Option<u64>,
1515    group_ops_bls12381_decode_gt_cost: Option<u64>,
1516    group_ops_bls12381_scalar_add_cost: Option<u64>,
1517    group_ops_bls12381_g1_add_cost: Option<u64>,
1518    group_ops_bls12381_g2_add_cost: Option<u64>,
1519    group_ops_bls12381_gt_add_cost: Option<u64>,
1520    group_ops_bls12381_scalar_sub_cost: Option<u64>,
1521    group_ops_bls12381_g1_sub_cost: Option<u64>,
1522    group_ops_bls12381_g2_sub_cost: Option<u64>,
1523    group_ops_bls12381_gt_sub_cost: Option<u64>,
1524    group_ops_bls12381_scalar_mul_cost: Option<u64>,
1525    group_ops_bls12381_g1_mul_cost: Option<u64>,
1526    group_ops_bls12381_g2_mul_cost: Option<u64>,
1527    group_ops_bls12381_gt_mul_cost: Option<u64>,
1528    group_ops_bls12381_scalar_div_cost: Option<u64>,
1529    group_ops_bls12381_g1_div_cost: Option<u64>,
1530    group_ops_bls12381_g2_div_cost: Option<u64>,
1531    group_ops_bls12381_gt_div_cost: Option<u64>,
1532    group_ops_bls12381_g1_hash_to_base_cost: Option<u64>,
1533    group_ops_bls12381_g2_hash_to_base_cost: Option<u64>,
1534    group_ops_bls12381_g1_hash_to_cost_per_byte: Option<u64>,
1535    group_ops_bls12381_g2_hash_to_cost_per_byte: Option<u64>,
1536    group_ops_bls12381_g1_msm_base_cost: Option<u64>,
1537    group_ops_bls12381_g2_msm_base_cost: Option<u64>,
1538    group_ops_bls12381_g1_msm_base_cost_per_input: Option<u64>,
1539    group_ops_bls12381_g2_msm_base_cost_per_input: Option<u64>,
1540    group_ops_bls12381_msm_max_len: Option<u32>,
1541    group_ops_bls12381_pairing_cost: Option<u64>,
1542    group_ops_bls12381_g1_to_uncompressed_g1_cost: Option<u64>,
1543    group_ops_bls12381_uncompressed_g1_to_g1_cost: Option<u64>,
1544    group_ops_bls12381_uncompressed_g1_sum_base_cost: Option<u64>,
1545    group_ops_bls12381_uncompressed_g1_sum_cost_per_term: Option<u64>,
1546    group_ops_bls12381_uncompressed_g1_sum_max_terms: Option<u64>,
1547
1548    // hmac::hmac_sha3_256
1549    hmac_hmac_sha3_256_cost_base: Option<u64>,
1550    hmac_hmac_sha3_256_input_cost_per_byte: Option<u64>,
1551    hmac_hmac_sha3_256_input_cost_per_block: Option<u64>,
1552
1553    // zklogin::check_zklogin_id
1554    #[deprecated]
1555    check_zklogin_id_cost_base: Option<u64>,
1556    // zklogin::check_zklogin_issuer
1557    #[deprecated]
1558    check_zklogin_issuer_cost_base: Option<u64>,
1559
1560    vdf_verify_vdf_cost: Option<u64>,
1561    vdf_hash_to_input_cost: Option<u64>,
1562
1563    // Stdlib costs
1564    bcs_per_byte_serialized_cost: Option<u64>,
1565    bcs_legacy_min_output_size_cost: Option<u64>,
1566    bcs_failure_cost: Option<u64>,
1567
1568    hash_sha2_256_base_cost: Option<u64>,
1569    hash_sha2_256_per_byte_cost: Option<u64>,
1570    hash_sha2_256_legacy_min_input_len_cost: Option<u64>,
1571    hash_sha3_256_base_cost: Option<u64>,
1572    hash_sha3_256_per_byte_cost: Option<u64>,
1573    hash_sha3_256_legacy_min_input_len_cost: Option<u64>,
1574    type_name_get_base_cost: Option<u64>,
1575    type_name_get_per_byte_cost: Option<u64>,
1576
1577    string_check_utf8_base_cost: Option<u64>,
1578    string_check_utf8_per_byte_cost: Option<u64>,
1579    string_is_char_boundary_base_cost: Option<u64>,
1580    string_sub_string_base_cost: Option<u64>,
1581    string_sub_string_per_byte_cost: Option<u64>,
1582    string_index_of_base_cost: Option<u64>,
1583    string_index_of_per_byte_pattern_cost: Option<u64>,
1584    string_index_of_per_byte_searched_cost: Option<u64>,
1585
1586    vector_empty_base_cost: Option<u64>,
1587    vector_length_base_cost: Option<u64>,
1588    vector_push_back_base_cost: Option<u64>,
1589    vector_push_back_legacy_per_abstract_memory_unit_cost: Option<u64>,
1590    vector_borrow_base_cost: Option<u64>,
1591    vector_pop_back_base_cost: Option<u64>,
1592    vector_destroy_empty_base_cost: Option<u64>,
1593    vector_swap_base_cost: Option<u64>,
1594    debug_print_base_cost: Option<u64>,
1595    debug_print_stack_trace_base_cost: Option<u64>,
1596
1597    // === Execution Version ===
1598    execution_version: Option<u64>,
1599
1600    // Dictates the threshold (percentage of stake) that is used to calculate the "bad" nodes to be
1601    // swapped when creating the consensus schedule. The values should be of the range [0 - 33].
1602    // Anything above 33 (f) will not be allowed.
1603    consensus_bad_nodes_stake_threshold: Option<u64>,
1604
1605    #[deprecated]
1606    max_jwk_votes_per_validator_per_epoch: Option<u64>,
1607    // The maximum age of a JWK in epochs before it is removed from the AuthenticatorState object.
1608    // Applied at the end of an epoch as a delta from the new epoch value, so setting this to 1
1609    // will cause the new epoch to start with JWKs from the previous epoch still valid.
1610    #[deprecated]
1611    max_age_of_jwk_in_epochs: Option<u64>,
1612
1613    // === random beacon ===
1614    /// Maximum allowed precision loss when reducing voting weights for the
1615    /// random beacon protocol.
1616    random_beacon_reduction_allowed_delta: Option<u16>,
1617
1618    /// Minimum number of shares below which voting weights will not be reduced
1619    /// for the random beacon protocol.
1620    random_beacon_reduction_lower_bound: Option<u32>,
1621
1622    /// Consensus Round after which DKG should be aborted and randomness
1623    /// disabled for the epoch, if it hasn't already completed.
1624    random_beacon_dkg_timeout_round: Option<u32>,
1625
1626    /// Minimum interval between consecutive rounds of generated randomness.
1627    random_beacon_min_round_interval_ms: Option<u64>,
1628
1629    /// Version of the random beacon DKG protocol.
1630    /// 0 was deprecated (and currently not supported), 1 is the default
1631    /// version.
1632    random_beacon_dkg_version: Option<u64>,
1633
1634    /// The maximum serialized transaction size (in bytes) accepted by
1635    /// consensus. `consensus_max_transaction_size_bytes` should include
1636    /// space for additional metadata, on top of the `max_tx_size_bytes`
1637    /// value.
1638    consensus_max_transaction_size_bytes: Option<u64>,
1639    /// The maximum size of transactions included in a consensus block.
1640    consensus_max_transactions_in_block_bytes: Option<u64>,
1641    /// The maximum number of transactions included in a consensus block.
1642    consensus_max_num_transactions_in_block: Option<u64>,
1643
1644    /// The max number of consensus rounds a transaction can be deferred due to
1645    /// shared object congestion. Transactions will be cancelled after this
1646    /// many rounds.
1647    max_deferral_rounds_for_congestion_control: Option<u64>,
1648
1649    /// Minimum interval of commit timestamps between consecutive checkpoints.
1650    min_checkpoint_interval_ms: Option<u64>,
1651
1652    /// Number of recent checkpoints over which `min_checkpoint_interval_ms`
1653    /// may be amortized. When set, a checkpoint is built once the full
1654    /// interval elapsed since the previous checkpoint, or once the checkpoint
1655    /// this many back in the current epoch is at least that many intervals
1656    /// older. The windowed arm recycles the slack that discrete commit
1657    /// timestamps add to the strict arm, holding the sustained rate at the
1658    /// ceiling, while the strict arm keeps quiet gaps within one interval.
1659    /// The window does not cross epoch boundaries; before it fills — and
1660    /// always when unset — only the strict adjacent check applies.
1661    checkpoint_rate_window_size: Option<u64>,
1662
1663    /// Version number to use for version_specific_data in `CheckpointSummary`.
1664    checkpoint_summary_version_specific_data: Option<u64>,
1665
1666    /// The max number of transactions that can be included in a single Soft
1667    /// Bundle.
1668    max_soft_bundle_size: Option<u64>,
1669
1670    /// Deprecated because of bridge removal.
1671    /// Whether to try to form bridge committee
1672    // Note: this is not a feature flag because we want to distinguish between
1673    // `None` and `Some(false)`, as committee was already finalized on Testnet.
1674    bridge_should_try_to_finalize_committee: Option<bool>,
1675
1676    /// The max accumulated txn execution cost per object in a mysticeti commit.
1677    /// Transactions in a commit will be deferred once their touch shared
1678    /// objects hit this limit. Note that if
1679    /// `max_congestion_limit_overshoot_per_commit` is set, this may be overshot
1680    /// within a single commit, but the limit will be enforced in the long run.
1681    max_accumulated_txn_cost_per_object_in_mysticeti_commit: Option<u64>,
1682
1683    /// Maximum number of committee (validators taking part in consensus)
1684    /// validators at any moment. We do not allow the number of committee
1685    /// validators in any epoch to go above this.
1686    max_committee_members_count: Option<u64>,
1687
1688    /// Maximum number of added plus removed entries one injected
1689    /// `TransactionDenyRulesUpdate` transaction may carry; a larger diff is
1690    /// split into multiple transactions in the same commit. Required by
1691    /// `enable_pcool_flow` from protocol version 39.
1692    deny_rule_update_max_entries_per_tx: Option<u64>,
1693
1694    /// Configures the garbage collection depth for consensus. When is unset or
1695    /// `0` then the garbage collection is disabled.
1696    consensus_gc_depth: Option<u32>,
1697
1698    /// Configures the maximum number of acknowledgments to be included in a
1699    /// block. It must be reasonably larger than the number of validators
1700    /// because not all validators create their blocks at the same pace.
1701    /// Default value set to 400. (5 x expected committee size (80)).
1702    /// Applicable only to `starfish` consensus.
1703    consensus_max_acknowledgments_per_block: Option<u32>,
1704
1705    /// The maximum amount that is allowed to overshoot the congestion limit
1706    /// specified by 'max_accumulated_txn_cost_per_object_in_mysticeti_commit'
1707    /// for any single commit. Any overshoot is tracked as a debt that must
1708    /// be accounted for in subsequent commits.
1709    max_congestion_limit_overshoot_per_commit: Option<u64>,
1710
1711    /// Maximum number of transactions from a single consensus commit that may
1712    /// be scheduled to execute concurrently (the execution-worker pool size).
1713    /// `Some` activates execution-worker congestion control, under which
1714    /// owned-object-only transactions are also scheduled, deferred and shed
1715    /// by the congestion tracker; `None` disables it. Must be positive when
1716    /// set. Requires `enable_pcool_flow`.
1717    max_concurrent_execution_workers: Option<u16>,
1718
1719    /// How many consensus commits back post-consensus validation reads object
1720    /// state. Validating a transaction in commit C reads object state as of
1721    /// commit C - K, where K is this distance; that commit is the horizon of
1722    /// C, and it must be fully executed before C is validated. Set on Devnet
1723    /// from protocol version 39. Required by `enable_pcool_flow` from that
1724    /// version.
1725    pcool_deterministic_validation_horizon_distance: Option<u64>,
1726
1727    /// Scorer version. When set to `None`, MisbehaviorReports are not sent nor
1728    /// considered valid. When set to `Some(version)`, scores are included in
1729    /// the MisbehaviorReports messages, where `version` determines the scoring
1730    /// formulas and metrics to be used. Even if set to None, the Scorer
1731    /// component is created, having access to metrics and being able to expose
1732    /// validator scores. Also gates the wire format of the
1733    /// `MisbehaviorReport` consensus transaction — scorer and report bump
1734    /// together.
1735    scorer_version: Option<u16>,
1736
1737    // `auth_context` module
1738    // Cost params for the Move native function `native_digest(): vector<u8>`
1739    auth_context_digest_cost_base: Option<u64>,
1740    // Cost params for the Move native function `native_tx_data_bytes(): &vector<u8>`
1741    auth_context_tx_data_bytes_cost_base: Option<u64>,
1742    auth_context_tx_data_bytes_cost_per_byte: Option<u64>,
1743    // Cost params for the Move native function `native_tx_commands<C>(): vector<C>`
1744    auth_context_tx_commands_cost_base: Option<u64>,
1745    auth_context_tx_commands_cost_per_byte: Option<u64>,
1746    // Cost params for the Move native function `native_tx_inputs<I>(): vector<I>`
1747    auth_context_tx_inputs_cost_base: Option<u64>,
1748    auth_context_tx_inputs_cost_per_byte: Option<u64>,
1749    // Cost params for the Move native function `fun native_replace<I, C>(auth_digest: vector<u8>,
1750    // tx_inputs: vector<I>, tx_commands: vector<C>, tx_data_bytes: vector<u8>)`
1751    auth_context_replace_cost_base: Option<u64>,
1752    auth_context_replace_cost_per_byte: Option<u64>,
1753    // Cost params for the Move native functions
1754    // `fun native_sender_authenticator_function_info_v1<F>(): &Option<F>`
1755    // `fun native_sponsor_authenticator_function_info_v1<F>(): &Option<F>`
1756    auth_context_authenticator_function_info_v1_cost_base: Option<u64>,
1757
1758    /// Number of committed subdags between leader-schedule recomputations.
1759    /// When unset, defaults to 300.
1760    consensus_commits_per_schedule: Option<u32>,
1761
1762    /// Minimum number of active validators at any moment.
1763    /// Supersedes `SystemParametersV1::min_validator_count`.
1764    min_validator_count: Option<u64>,
1765
1766    /// Maximum number of active validators at any moment. The number of
1767    /// validators in any epoch is not allowed to go above this.
1768    /// Supersedes `SystemParametersV1::max_validator_count`.
1769    max_validator_count: Option<u64>,
1770
1771    /// Minimum stake, in nanos, a validator candidate needs to join the
1772    /// active set. Supersedes
1773    /// `SystemParametersV1::min_validator_joining_stake`.
1774    min_validator_joining_stake: Option<u64>,
1775
1776    /// Active validators with stake, in nanos, below this threshold are
1777    /// considered at risk and are removed after
1778    /// `validator_low_stake_grace_period` consecutive epochs below it.
1779    /// Supersedes `SystemParametersV1::validator_low_stake_threshold`.
1780    validator_low_stake_threshold: Option<u64>,
1781
1782    /// Active validators with stake, in nanos, below this threshold are
1783    /// removed at the next epoch boundary without a grace period.
1784    /// Supersedes `SystemParametersV1::validator_very_low_stake_threshold`.
1785    validator_very_low_stake_threshold: Option<u64>,
1786
1787    /// Number of consecutive epochs a validator may stay below
1788    /// `validator_low_stake_threshold` before being removed.
1789    /// Supersedes `SystemParametersV1::validator_low_stake_grace_period`.
1790    validator_low_stake_grace_period: Option<u64>,
1791
1792    /// Number of committed subdags the sliding-window leader scorer aggregates
1793    /// over (the scoring depth). When unset, defaults to 600. Consulted only
1794    /// when `consensus_enable_sliding_window_leader_schedule` is set.
1795    consensus_leader_schedule_window_size: Option<u32>,
1796
1797    /// Maximum size of a system Move package object, in bytes. System packages
1798    /// are published by the network rather than by users, so they are held to a
1799    /// larger bound than `max_move_package_size`. When unset, system packages
1800    /// are bound by `max_move_package_size` like any other package.
1801    max_move_system_package_size: Option<u64>,
1802}
1803
1804// feature flags
1805impl ProtocolConfig {
1806    // Add checks for feature flag support here, e.g.:
1807    // pub fn check_new_protocol_feature_supported(&self) -> Result<(), Error> {
1808    //     if self.feature_flags.new_protocol_feature_supported {
1809    //         Ok(())
1810    //     } else {
1811    //         Err(Error(format!(
1812    //             "new_protocol_feature is not supported at {:?}",
1813    //             self.version
1814    //         )))
1815    //     }
1816    // }
1817
1818    pub fn disable_invariant_violation_check_in_swap_loc(&self) -> bool {
1819        self.feature_flags
1820            .disable_invariant_violation_check_in_swap_loc
1821    }
1822
1823    pub fn no_extraneous_module_bytes(&self) -> bool {
1824        self.feature_flags.no_extraneous_module_bytes
1825    }
1826
1827    pub fn consensus_transaction_ordering(&self) -> ConsensusTransactionOrdering {
1828        self.feature_flags.consensus_transaction_ordering
1829    }
1830
1831    pub fn dkg_version(&self) -> u64 {
1832        // Version 0 was deprecated and removed, the default is 1 if not set.
1833        self.random_beacon_dkg_version.unwrap_or(1)
1834    }
1835
1836    pub fn hardened_otw_check(&self) -> bool {
1837        self.feature_flags.hardened_otw_check
1838    }
1839
1840    pub fn enable_poseidon(&self) -> bool {
1841        self.feature_flags.enable_poseidon
1842    }
1843
1844    pub fn enable_group_ops_native_function_msm(&self) -> bool {
1845        self.feature_flags.enable_group_ops_native_function_msm
1846    }
1847
1848    pub fn per_object_congestion_control_mode(&self) -> PerObjectCongestionControlMode {
1849        self.feature_flags.per_object_congestion_control_mode
1850    }
1851
1852    pub fn consensus_choice(&self) -> ConsensusChoice {
1853        self.feature_flags.consensus_choice
1854    }
1855
1856    pub fn consensus_network(&self) -> ConsensusNetwork {
1857        self.feature_flags.consensus_network
1858    }
1859
1860    pub fn enable_vdf(&self) -> bool {
1861        self.feature_flags.enable_vdf
1862    }
1863
1864    pub fn passkey_auth(&self) -> bool {
1865        self.feature_flags.passkey_auth
1866    }
1867
1868    pub fn max_transaction_size_bytes(&self) -> u64 {
1869        // Provide a default value if protocol config version is too low.
1870        self.consensus_max_transaction_size_bytes
1871            .unwrap_or(256 * 1024)
1872    }
1873
1874    pub fn max_transactions_in_block_bytes(&self) -> u64 {
1875        if cfg!(msim) {
1876            256 * 1024
1877        } else {
1878            self.consensus_max_transactions_in_block_bytes
1879                .unwrap_or(512 * 1024)
1880        }
1881    }
1882
1883    pub fn max_num_transactions_in_block(&self) -> u64 {
1884        if cfg!(msim) {
1885            8
1886        } else {
1887            self.consensus_max_num_transactions_in_block.unwrap_or(512)
1888        }
1889    }
1890
1891    pub fn rethrow_serialization_type_layout_errors(&self) -> bool {
1892        self.feature_flags.rethrow_serialization_type_layout_errors
1893    }
1894
1895    pub fn relocate_event_module(&self) -> bool {
1896        self.feature_flags.relocate_event_module
1897    }
1898
1899    pub fn protocol_defined_base_fee(&self) -> bool {
1900        self.feature_flags.protocol_defined_base_fee
1901    }
1902
1903    pub fn uncompressed_g1_group_elements(&self) -> bool {
1904        self.feature_flags.uncompressed_g1_group_elements
1905    }
1906
1907    pub fn disallow_new_modules_in_deps_only_packages(&self) -> bool {
1908        self.feature_flags
1909            .disallow_new_modules_in_deps_only_packages
1910    }
1911
1912    pub fn native_charging_v2(&self) -> bool {
1913        self.feature_flags.native_charging_v2
1914    }
1915
1916    pub fn consensus_round_prober(&self) -> bool {
1917        self.feature_flags.consensus_round_prober
1918    }
1919
1920    pub fn consensus_distributed_vote_scoring_strategy(&self) -> bool {
1921        self.feature_flags
1922            .consensus_distributed_vote_scoring_strategy
1923    }
1924
1925    pub fn gc_depth(&self) -> u32 {
1926        if cfg!(msim) {
1927            // exercise a very low gc_depth
1928            min(5, self.consensus_gc_depth.unwrap_or(0))
1929        } else {
1930            self.consensus_gc_depth.unwrap_or(0)
1931        }
1932    }
1933
1934    pub fn consensus_linearize_subdag_v2(&self) -> bool {
1935        let res = self.feature_flags.consensus_linearize_subdag_v2;
1936        assert!(
1937            !res || self.gc_depth() > 0,
1938            "The consensus linearize sub dag V2 requires GC to be enabled"
1939        );
1940        res
1941    }
1942
1943    pub fn consensus_max_acknowledgments_per_block_or_default(&self) -> u32 {
1944        self.consensus_max_acknowledgments_per_block.unwrap_or(400)
1945    }
1946
1947    pub fn max_acknowledgments_per_block(&self, committee_size: usize) -> usize {
1948        2 * committee_size
1949    }
1950
1951    pub fn max_commit_votes_per_block(&self, committee_size: usize) -> usize {
1952        committee_size
1953    }
1954
1955    pub fn variant_nodes(&self) -> bool {
1956        self.feature_flags.variant_nodes
1957    }
1958
1959    pub fn consensus_smart_ancestor_selection(&self) -> bool {
1960        self.feature_flags.consensus_smart_ancestor_selection
1961    }
1962
1963    pub fn consensus_round_prober_probe_accepted_rounds(&self) -> bool {
1964        self.feature_flags
1965            .consensus_round_prober_probe_accepted_rounds
1966    }
1967
1968    pub fn consensus_zstd_compression(&self) -> bool {
1969        self.feature_flags.consensus_zstd_compression
1970    }
1971
1972    pub fn congestion_control_min_free_execution_slot(&self) -> bool {
1973        self.feature_flags
1974            .congestion_control_min_free_execution_slot
1975    }
1976
1977    pub fn accept_passkey_in_multisig(&self) -> bool {
1978        self.feature_flags.accept_passkey_in_multisig
1979    }
1980
1981    pub fn consensus_batched_block_sync(&self) -> bool {
1982        self.feature_flags.consensus_batched_block_sync
1983    }
1984
1985    /// Check if the gas price feedback mechanism (which is used for
1986    /// transactions cancelled due to shared object congestion) is enabled
1987    pub fn congestion_control_gas_price_feedback_mechanism(&self) -> bool {
1988        self.feature_flags
1989            .congestion_control_gas_price_feedback_mechanism
1990    }
1991
1992    pub fn validate_identifier_inputs(&self) -> bool {
1993        self.feature_flags.validate_identifier_inputs
1994    }
1995
1996    pub fn minimize_child_object_mutations(&self) -> bool {
1997        self.feature_flags.minimize_child_object_mutations
1998    }
1999
2000    pub fn dependency_linkage_error(&self) -> bool {
2001        self.feature_flags.dependency_linkage_error
2002    }
2003
2004    pub fn additional_multisig_checks(&self) -> bool {
2005        self.feature_flags.additional_multisig_checks
2006    }
2007
2008    pub fn consensus_num_requested_prior_commits_at_startup(&self) -> u32 {
2009        // TODO: this will eventually be the max of some number of other
2010        // parameters.
2011        0
2012    }
2013
2014    pub fn normalize_ptb_arguments(&self) -> bool {
2015        self.feature_flags.normalize_ptb_arguments
2016    }
2017
2018    pub fn select_committee_from_eligible_validators(&self) -> bool {
2019        let res = self.feature_flags.select_committee_from_eligible_validators;
2020        assert!(
2021            !res || (self.protocol_defined_base_fee()
2022                && self.max_committee_members_count_as_option().is_some()),
2023            "select_committee_from_eligible_validators requires protocol_defined_base_fee and max_committee_members_count to be set"
2024        );
2025        res
2026    }
2027
2028    pub fn track_non_committee_eligible_validators(&self) -> bool {
2029        self.feature_flags.track_non_committee_eligible_validators
2030    }
2031
2032    pub fn select_committee_supporting_next_epoch_version(&self) -> bool {
2033        let res = self
2034            .feature_flags
2035            .select_committee_supporting_next_epoch_version;
2036        assert!(
2037            !res || (self.track_non_committee_eligible_validators()
2038                && self.select_committee_from_eligible_validators()),
2039            "select_committee_supporting_next_epoch_version requires select_committee_from_eligible_validators to be set"
2040        );
2041        res
2042    }
2043
2044    pub fn consensus_median_timestamp_with_checkpoint_enforcement(&self) -> bool {
2045        let res = self
2046            .feature_flags
2047            .consensus_median_timestamp_with_checkpoint_enforcement;
2048        assert!(
2049            !res || self.gc_depth() > 0,
2050            "The consensus median timestamp with checkpoint enforcement requires GC to be enabled"
2051        );
2052        res
2053    }
2054
2055    pub fn consensus_commit_transactions_only_for_traversed_headers(&self) -> bool {
2056        self.feature_flags
2057            .consensus_commit_transactions_only_for_traversed_headers
2058    }
2059
2060    /// Check whether congestion limit overshoot is enabled in the gas price
2061    /// feedback mechanism.
2062    pub fn congestion_limit_overshoot_in_gas_price_feedback_mechanism(&self) -> bool {
2063        self.feature_flags
2064            .congestion_limit_overshoot_in_gas_price_feedback_mechanism
2065    }
2066
2067    /// Check whether a separate gas price feedback mechanism is used for
2068    /// randomness transactions.
2069    pub fn separate_gas_price_feedback_mechanism_for_randomness(&self) -> bool {
2070        self.feature_flags
2071            .separate_gas_price_feedback_mechanism_for_randomness
2072    }
2073
2074    pub fn metadata_in_module_bytes(&self) -> bool {
2075        self.feature_flags.metadata_in_module_bytes
2076    }
2077
2078    pub fn publish_package_metadata(&self) -> bool {
2079        self.feature_flags.publish_package_metadata
2080    }
2081
2082    pub fn enable_move_authentication(&self) -> bool {
2083        self.feature_flags.enable_move_authentication
2084    }
2085
2086    pub fn additional_borrow_checks(&self) -> bool {
2087        self.feature_flags.additional_borrow_checks
2088    }
2089
2090    pub fn enable_move_authentication_for_sponsor(&self) -> bool {
2091        let enable_move_authentication_for_sponsor =
2092            self.feature_flags.enable_move_authentication_for_sponsor;
2093        assert!(
2094            !enable_move_authentication_for_sponsor || self.enable_move_authentication(),
2095            "enable_move_authentication_for_sponsor requires enable_move_authentication to be set"
2096        );
2097        enable_move_authentication_for_sponsor
2098    }
2099
2100    pub fn pass_validator_scores_to_advance_epoch(&self) -> bool {
2101        self.feature_flags.pass_validator_scores_to_advance_epoch
2102    }
2103
2104    pub fn calculate_validator_scores(&self) -> bool {
2105        let calculate_validator_scores = self.feature_flags.calculate_validator_scores;
2106        assert!(
2107            !calculate_validator_scores || self.scorer_version.is_some(),
2108            "calculate_validator_scores requires scorer_version to be set"
2109        );
2110        calculate_validator_scores
2111    }
2112
2113    pub fn adjust_rewards_by_score(&self) -> bool {
2114        let adjust = self.feature_flags.adjust_rewards_by_score;
2115        assert!(
2116            !adjust || (self.scorer_version.is_some() && self.calculate_validator_scores()),
2117            "adjust_rewards_by_score requires scorer_version to be set"
2118        );
2119        adjust
2120    }
2121
2122    pub fn pass_calculated_validator_scores_to_advance_epoch(&self) -> bool {
2123        let pass = self
2124            .feature_flags
2125            .pass_calculated_validator_scores_to_advance_epoch;
2126        assert!(
2127            !pass
2128                || (self.pass_validator_scores_to_advance_epoch()
2129                    && self.calculate_validator_scores()),
2130            "pass_calculated_validator_scores_to_advance_epoch requires pass_validator_scores_to_advance_epoch and calculate_validator_scores to be enabled"
2131        );
2132        pass
2133    }
2134    pub fn consensus_fast_commit_sync(&self) -> bool {
2135        let res = self.feature_flags.consensus_fast_commit_sync;
2136        assert!(
2137            !res || self.consensus_commit_transactions_only_for_traversed_headers(),
2138            "consensus_fast_commit_sync requires consensus_commit_transactions_only_for_traversed_headers to be enabled"
2139        );
2140        res
2141    }
2142
2143    pub fn consensus_block_restrictions(&self) -> bool {
2144        self.feature_flags.consensus_block_restrictions
2145    }
2146
2147    pub fn move_native_tx_context(&self) -> bool {
2148        self.feature_flags.move_native_tx_context
2149    }
2150
2151    pub fn pre_consensus_sponsor_only_move_authentication(&self) -> bool {
2152        let pre_consensus_sponsor_only_move_authentication = self
2153            .feature_flags
2154            .pre_consensus_sponsor_only_move_authentication;
2155        if pre_consensus_sponsor_only_move_authentication {
2156            assert!(
2157                self.enable_move_authentication(),
2158                "pre_consensus_sponsor_only_move_authentication requires enable_move_authentication to be set"
2159            );
2160            assert!(
2161                self.enable_move_authentication_for_sponsor(),
2162                "pre_consensus_sponsor_only_move_authentication requires enable_move_authentication_for_sponsor to be set"
2163            );
2164        }
2165        pre_consensus_sponsor_only_move_authentication
2166    }
2167
2168    pub fn consensus_starfish_speed(&self) -> bool {
2169        let res = self.feature_flags.consensus_starfish_speed;
2170        assert!(
2171            !res || self.consensus_fast_commit_sync(),
2172            "consensus_starfish_speed requires consensus_fast_commit_sync to be enabled"
2173        );
2174        res
2175    }
2176
2177    pub fn always_advance_dkg_to_resolution(&self) -> bool {
2178        self.feature_flags.always_advance_dkg_to_resolution
2179    }
2180
2181    pub fn enable_pcool_flow(&self) -> bool {
2182        self.feature_flags.enable_pcool_flow
2183    }
2184
2185    pub fn validator_metadata_verify_v2(&self) -> bool {
2186        self.feature_flags.validator_metadata_verify_v2
2187    }
2188
2189    pub fn commits_per_schedule(&self) -> u32 {
2190        let commits_per_schedule = if cfg!(msim) {
2191            // Exercise faster leader-schedule rotation in simtests.
2192            min(10, self.consensus_commits_per_schedule.unwrap_or(300))
2193        } else {
2194            self.consensus_commits_per_schedule.unwrap_or(300)
2195        };
2196        assert!(
2197            commits_per_schedule > 0,
2198            "consensus_commits_per_schedule must be greater than 0"
2199        );
2200        commits_per_schedule
2201    }
2202
2203    pub fn leader_schedule_window_size(&self) -> u32 {
2204        if cfg!(msim) {
2205            // Keep the scoring window commensurate with the msim-scaled
2206            // commit sync parameters.
2207            min(
2208                20,
2209                self.consensus_leader_schedule_window_size.unwrap_or(600),
2210            )
2211        } else {
2212            self.consensus_leader_schedule_window_size.unwrap_or(600)
2213        }
2214    }
2215
2216    pub fn consensus_enable_sliding_window_leader_schedule(&self) -> bool {
2217        let res = self
2218            .feature_flags
2219            .consensus_enable_sliding_window_leader_schedule;
2220        assert!(
2221            !res || self.leader_schedule_window_size() >= self.commits_per_schedule(),
2222            "consensus_enable_sliding_window_leader_schedule requires window_size >= commits_per_schedule"
2223        );
2224        res
2225    }
2226
2227    pub fn consensus_enable_absolute_score_leader_schedule(&self) -> bool {
2228        self.feature_flags
2229            .consensus_enable_absolute_score_leader_schedule
2230    }
2231
2232    pub fn max_ptb_value_size_v2(&self) -> bool {
2233        self.feature_flags.max_ptb_value_size_v2
2234    }
2235
2236    pub fn deny_authenticator_packages(&self) -> bool {
2237        self.feature_flags.deny_authenticator_packages
2238    }
2239
2240    pub fn package_metadata_with_dynamic_module_metadata(&self) -> bool {
2241        let res = self
2242            .feature_flags
2243            .package_metadata_with_dynamic_module_metadata;
2244        assert!(
2245            !res || self.publish_package_metadata(),
2246            "package_metadata_with_dynamic_module_metadata requires publish_package_metadata to be enabled"
2247        );
2248        res
2249    }
2250
2251    pub fn report_move_authentication_error(&self) -> bool {
2252        let report_move_authentication_error = self.feature_flags.report_move_authentication_error;
2253        assert!(
2254            !report_move_authentication_error || self.enable_move_authentication(),
2255            "report_move_authentication_error requires enable_move_authentication to be set"
2256        );
2257        report_move_authentication_error
2258    }
2259
2260    /// Named to avoid colliding with the derive-generated
2261    /// `max_concurrent_execution_workers[_as_option]()`, which bypass the
2262    /// checks below — always read the parameter through this getter.
2263    pub fn concurrent_execution_workers(&self) -> Option<u16> {
2264        let res = self.max_concurrent_execution_workers;
2265        assert!(
2266            res.is_none() || self.enable_pcool_flow(),
2267            "max_concurrent_execution_workers requires enable_pcool_flow to be enabled"
2268        );
2269        assert!(
2270            res.is_none()
2271                || self
2272                    .max_accumulated_txn_cost_per_object_in_mysticeti_commit
2273                    .is_some(),
2274            "max_concurrent_execution_workers requires per-object congestion control \
2275                (max_accumulated_txn_cost_per_object_in_mysticeti_commit) to be enabled"
2276        );
2277        assert!(
2278            res.is_none() || self.congestion_control_gas_price_feedback_mechanism(),
2279            "max_concurrent_execution_workers requires the gas price feedback mechanism \
2280                (congestion_control_gas_price_feedback_mechanism), which carries the suggested \
2281                gas price of an execution-worker congestion cancellation"
2282        );
2283        assert!(
2284            res.is_none() || !self.separate_gas_price_feedback_mechanism_for_randomness(),
2285            "max_concurrent_execution_workers implies a single congestion tracker and suggested \
2286                gas price calculator for all transactions, which is incompatible with \
2287                separate_gas_price_feedback_mechanism_for_randomness"
2288        );
2289        assert!(
2290            res != Some(0),
2291            "max_concurrent_execution_workers must be positive when set"
2292        );
2293        res
2294    }
2295
2296    pub fn allow_unbounded_system_objects(&self) -> bool {
2297        self.feature_flags.allow_unbounded_system_objects
2298    }
2299
2300    pub fn reject_immutable_account_objects(&self) -> bool {
2301        let reject_immutable_account_objects = self.feature_flags.reject_immutable_account_objects;
2302        assert!(
2303            !reject_immutable_account_objects || self.enable_move_authentication(),
2304            "reject_immutable_account_objects requires enable_move_authentication to be set"
2305        );
2306        reject_immutable_account_objects
2307    }
2308
2309    pub fn reject_immutable_account_creation(&self) -> bool {
2310        let reject_immutable_account_creation =
2311            self.feature_flags.reject_immutable_account_creation;
2312        assert!(
2313            !reject_immutable_account_creation || self.reject_immutable_account_objects(),
2314            "reject_immutable_account_creation requires reject_immutable_account_objects to be set"
2315        );
2316        reject_immutable_account_creation
2317    }
2318
2319    pub fn validate_input_object_versions(&self) -> bool {
2320        self.feature_flags.validate_input_object_versions
2321    }
2322
2323    pub fn check_canonical_module_version_header(&self) -> bool {
2324        self.feature_flags.check_canonical_module_version_header
2325    }
2326
2327    pub fn disallow_randomness_in_move_authenticator(&self) -> bool {
2328        self.feature_flags.disallow_randomness_in_move_authenticator
2329    }
2330
2331    pub fn check_cyclic_dependencies(&self) -> bool {
2332        self.feature_flags.check_cyclic_dependencies
2333    }
2334
2335    pub fn validate_ptb_argument_indices(&self) -> bool {
2336        self.feature_flags.validate_ptb_argument_indices
2337    }
2338
2339    pub fn allow_dkg_completion_after_timeout(&self) -> bool {
2340        self.feature_flags.allow_dkg_completion_after_timeout
2341    }
2342
2343    pub fn disallow_self_identifier_in_transactions(&self) -> bool {
2344        self.feature_flags.disallow_self_identifier_in_transactions
2345    }
2346
2347    pub fn consensus_dedup_only_recorded_messages(&self) -> bool {
2348        self.feature_flags.consensus_dedup_only_recorded_messages
2349    }
2350
2351    pub fn reject_partially_signed_mixed_ed25519_multisig(&self) -> bool {
2352        self.feature_flags
2353            .reject_partially_signed_mixed_ed25519_multisig
2354    }
2355
2356    pub fn limit_groth16_pvk_inputs(&self) -> bool {
2357        self.feature_flags.limit_groth16_pvk_inputs
2358    }
2359
2360    pub fn check_groth16_pvk_length(&self) -> bool {
2361        self.feature_flags.check_groth16_pvk_length
2362    }
2363
2364    pub fn deprecate_global_storage_ops(&self) -> bool {
2365        self.feature_flags.deprecate_global_storage_ops
2366    }
2367
2368    pub fn meter_instantiation_loops(&self) -> bool {
2369        self.feature_flags.meter_instantiation_loops
2370    }
2371
2372    pub fn move_authenticator_type_arg_packages_as_inputs(&self) -> bool {
2373        self.feature_flags
2374            .move_authenticator_type_arg_packages_as_inputs
2375    }
2376}
2377
2378#[cfg(not(msim))]
2379static POISON_VERSION_METHODS: AtomicBool = const { AtomicBool::new(false) };
2380
2381// Use a thread local in sim tests for test isolation.
2382#[cfg(msim)]
2383thread_local! {
2384    static POISON_VERSION_METHODS: AtomicBool = const { AtomicBool::new(false) };
2385}
2386
2387// Instantiations for each protocol version.
2388impl ProtocolConfig {
2389    /// Get the value ProtocolConfig that are in effect during the given
2390    /// protocol version.
2391    pub fn get_for_version(version: ProtocolVersion, chain: Chain) -> Self {
2392        // ProtocolVersion can be deserialized so we need to check it here as well.
2393        assert!(
2394            version >= ProtocolVersion::MIN,
2395            "Network protocol version is {:?}, but the minimum supported version by the binary is {:?}. Please upgrade the binary.",
2396            version,
2397            ProtocolVersion::MIN.0,
2398        );
2399        assert!(
2400            version <= ProtocolVersion::MAX_ALLOWED,
2401            "Network protocol version is {:?}, but the maximum supported version by the binary is {:?}. Please upgrade the binary.",
2402            version,
2403            ProtocolVersion::MAX_ALLOWED.0,
2404        );
2405
2406        let mut ret = Self::get_for_version_impl(version, chain);
2407        ret.version = version;
2408
2409        ret = CONFIG_OVERRIDE.with(|ovr| {
2410            if let Some(override_fn) = &*ovr.borrow() {
2411                warn!(
2412                    "overriding ProtocolConfig settings with custom settings (you should not see this log outside of tests)"
2413                );
2414                override_fn(version, ret)
2415            } else {
2416                ret
2417            }
2418        });
2419
2420        if std::env::var("IOTA_PROTOCOL_CONFIG_OVERRIDE_ENABLE").is_ok() {
2421            warn!(
2422                "overriding ProtocolConfig settings with custom settings; this may break non-local networks"
2423            );
2424
2425            // First, deserialize the top-level ProtocolConfig fields
2426            let overrides: ProtocolConfigOptional =
2427                serde_env::from_env_with_prefix("IOTA_PROTOCOL_CONFIG_OVERRIDE")
2428                    .expect("failed to parse ProtocolConfig override env variables");
2429            overrides.apply_to(&mut ret);
2430
2431            // Then, separately deserialize FeatureFlags fields
2432            let feature_flag_overrides: FeatureFlagsOptional =
2433                serde_env::from_env_with_prefix("IOTA_PROTOCOL_CONFIG_FEATURE_FLAGS_OVERRIDE")
2434                    .expect("failed to parse ProtocolConfig feature flags override env variables");
2435
2436            feature_flag_overrides.apply_to(&mut ret.feature_flags);
2437        }
2438
2439        // Devnet runs the P-COOL flow from version 32, before the settings it
2440        // requires exist; only versions from 39 on are checked for them. A test
2441        // override can return the config of another version, so the check
2442        // reads the version of the config returned.
2443        let pcool_requirements_apply =
2444            ret.feature_flags.enable_pcool_flow && ret.version >= ProtocolVersion::new(39);
2445        // Post-consensus validation meters published packages with the
2446        // verifier limits from this config, and reads the regex check budget
2447        // through the panicking accessor.
2448        assert!(
2449            !pcool_requirements_apply || ret.max_meter_ticks_regex_reference_safety.is_some(),
2450            "enable_pcool_flow requires max_meter_ticks_regex_reference_safety"
2451        );
2452        // For the same reason, the consensus handler must not skip a message
2453        // as a duplicate of one that was dropped without being recorded, as
2454        // its cache of such messages differs between validators.
2455        assert!(
2456            !pcool_requirements_apply || ret.feature_flags.consensus_dedup_only_recorded_messages,
2457            "enable_pcool_flow requires consensus_dedup_only_recorded_messages"
2458        );
2459        // With a distance of 0, the consensus handler processing commit C
2460        // would wait for C itself to be fully executed, which cannot happen
2461        // before the handler finishes processing C.
2462        assert!(
2463            !pcool_requirements_apply
2464                || ret
2465                    .pcool_deterministic_validation_horizon_distance
2466                    .is_some_and(|distance| distance > 0),
2467            "enable_pcool_flow requires a positive pcool_deterministic_validation_horizon_distance"
2468        );
2469        // Without the sender's authenticator run before consensus, a sponsor
2470        // alone could get a transaction sequenced that locks a Move account's
2471        // owned objects.
2472        assert!(
2473            !pcool_requirements_apply
2474                || !ret
2475                    .feature_flags
2476                    .pre_consensus_sponsor_only_move_authentication,
2477            "enable_pcool_flow excludes pre_consensus_sponsor_only_move_authentication"
2478        );
2479        // The injection cannot chunk updates without its limit.
2480        assert!(
2481            !pcool_requirements_apply || ret.deny_rule_update_max_entries_per_tx.is_some(),
2482            "enable_pcool_flow requires deny_rule_update_max_entries_per_tx"
2483        );
2484        // A deny-rule update chunk must always execute, or the object falls
2485        // permanently behind the mirrored state on every validator at once.
2486        // The binding limits are `max_event_emit_size` (the update event
2487        // carries every entry, ~32 bytes each) and the object-runtime store
2488        // entries touched when removals re-link `LinkedTable` nodes — neither
2489        // expressible as an entry count here, so the constant keeps a wide
2490        // margin below them (tightest is roughly 5000 entries).
2491        const DENY_RULE_UPDATE_MAX_ENTRIES_PER_TX_CEILING: u64 = 2048;
2492        assert!(
2493            ret.deny_rule_update_max_entries_per_tx
2494                .is_none_or(|max_entries| {
2495                    max_entries > 0
2496                        && max_entries <= DENY_RULE_UPDATE_MAX_ENTRIES_PER_TX_CEILING
2497                        && [
2498                            ret.max_num_new_move_object_ids_system_tx,
2499                            ret.max_num_deleted_move_object_ids_system_tx,
2500                            ret.object_runtime_max_num_cached_objects_system_tx,
2501                            ret.object_runtime_max_num_store_entries_system_tx,
2502                        ]
2503                        .iter()
2504                        .all(|limit| limit.is_none_or(|limit| max_entries <= limit))
2505                }),
2506            "deny_rule_update_max_entries_per_tx must be positive, at most {DENY_RULE_UPDATE_MAX_ENTRIES_PER_TX_CEILING}, and within the system transaction object limits"
2507        );
2508
2509        ret
2510    }
2511
2512    /// Get the value ProtocolConfig that are in effect during the given
2513    /// protocol version. Or none if the version is not supported.
2514    pub fn get_for_version_if_supported(version: ProtocolVersion, chain: Chain) -> Option<Self> {
2515        if version.0 >= ProtocolVersion::MIN.0 && version.0 <= ProtocolVersion::MAX_ALLOWED.0 {
2516            let mut ret = Self::get_for_version_impl(version, chain);
2517            ret.version = version;
2518            Some(ret)
2519        } else {
2520            None
2521        }
2522    }
2523
2524    #[cfg(not(msim))]
2525    pub fn poison_get_for_min_version() {
2526        POISON_VERSION_METHODS.store(true, Ordering::Relaxed);
2527    }
2528
2529    #[cfg(not(msim))]
2530    fn load_poison_get_for_min_version() -> bool {
2531        POISON_VERSION_METHODS.load(Ordering::Relaxed)
2532    }
2533
2534    #[cfg(msim)]
2535    pub fn poison_get_for_min_version() {
2536        POISON_VERSION_METHODS.with(|p| p.store(true, Ordering::Relaxed));
2537    }
2538
2539    #[cfg(msim)]
2540    fn load_poison_get_for_min_version() -> bool {
2541        POISON_VERSION_METHODS.with(|p| p.load(Ordering::Relaxed))
2542    }
2543
2544    pub fn convert_type_argument_error(&self) -> bool {
2545        self.feature_flags.convert_type_argument_error
2546    }
2547
2548    /// Convenience to get the constants at the current minimum supported
2549    /// version. Mainly used by client code that may not yet be
2550    /// protocol-version aware.
2551    pub fn get_for_min_version() -> Self {
2552        if Self::load_poison_get_for_min_version() {
2553            panic!("get_for_min_version called on validator");
2554        }
2555        ProtocolConfig::get_for_version(ProtocolVersion::MIN, Chain::Unknown)
2556    }
2557
2558    /// CAREFUL! - You probably want to use `get_for_version` instead.
2559    ///
2560    /// Convenience to get the constants at the current maximum supported
2561    /// version. Mainly used by genesis. Note well that this function uses
2562    /// the max version supported locally by the node, which is not
2563    /// necessarily the current version of the network. ALSO, this function
2564    /// disregards chain specific config (by using Chain::Unknown), thereby
2565    /// potentially returning a protocol config that is incorrect for some
2566    /// feature flags. Definitely safe for testing and for protocol version
2567    /// 11 and prior.
2568    #[expect(non_snake_case)]
2569    pub fn get_for_max_version_UNSAFE() -> Self {
2570        if Self::load_poison_get_for_min_version() {
2571            panic!("get_for_max_version_UNSAFE called on validator");
2572        }
2573        ProtocolConfig::get_for_version(ProtocolVersion::MAX, Chain::Unknown)
2574    }
2575
2576    fn get_for_version_impl(version: ProtocolVersion, chain: Chain) -> Self {
2577        #[cfg(msim)]
2578        {
2579            // populate the fake simulator version # with a different base tx cost.
2580            if version > ProtocolVersion::MAX {
2581                let mut config = Self::get_for_version_impl(ProtocolVersion::MAX, Chain::Unknown);
2582                config.base_tx_cost_fixed = Some(config.base_tx_cost_fixed() + 1000);
2583                return config;
2584            }
2585        }
2586
2587        // IMPORTANT: Never modify the value of any constant for a pre-existing protocol
2588        // version. To change the values here you must create a new protocol
2589        // version with the new values!
2590        let mut cfg = Self {
2591            version,
2592
2593            feature_flags: Default::default(),
2594
2595            max_tx_size_bytes: Some(128 * 1024),
2596            // We need this number to be at least 100x less than
2597            // `max_serialized_tx_effects_size_bytes`otherwise effects can be huge
2598            max_input_objects: Some(2048),
2599            max_serialized_tx_effects_size_bytes: Some(512 * 1024),
2600            max_serialized_tx_effects_size_bytes_system_tx: Some(512 * 1024 * 16),
2601            max_gas_payment_objects: Some(256),
2602            max_modules_in_publish: Some(64),
2603            max_package_dependencies: Some(32),
2604            max_arguments: Some(512),
2605            max_type_arguments: Some(16),
2606            max_type_argument_depth: Some(16),
2607            max_pure_argument_size: Some(16 * 1024),
2608            max_programmable_tx_commands: Some(1024),
2609            move_binary_format_version: Some(7),
2610            min_move_binary_format_version: Some(6),
2611            binary_module_handles: Some(100),
2612            binary_struct_handles: Some(300),
2613            binary_function_handles: Some(1500),
2614            binary_function_instantiations: Some(750),
2615            binary_signatures: Some(1000),
2616            binary_constant_pool: Some(4000),
2617            binary_identifiers: Some(10000),
2618            binary_address_identifiers: Some(100),
2619            binary_struct_defs: Some(200),
2620            binary_struct_def_instantiations: Some(100),
2621            binary_function_defs: Some(1000),
2622            binary_field_handles: Some(500),
2623            binary_field_instantiations: Some(250),
2624            binary_friend_decls: Some(100),
2625            binary_enum_defs: None,
2626            binary_enum_def_instantiations: None,
2627            binary_variant_handles: None,
2628            binary_variant_instantiation_handles: None,
2629            max_move_object_size: Some(250 * 1024),
2630            max_move_package_size: Some(100 * 1024),
2631            max_publish_or_upgrade_per_ptb: Some(5),
2632            // max gas budget for an authentication is in NANOS
2633            max_auth_gas: None,
2634            // max gas budget is in NANOS and an absolute value 50IOTA
2635            max_tx_gas: Some(50_000_000_000),
2636            max_gas_price: Some(100_000),
2637            max_gas_computation_bucket: Some(5_000_000),
2638            max_loop_depth: Some(5),
2639            max_generic_instantiation_length: Some(32),
2640            max_function_parameters: Some(128),
2641            max_basic_blocks: Some(1024),
2642            max_value_stack_size: Some(1024),
2643            max_type_nodes: Some(256),
2644            max_push_size: Some(10000),
2645            max_struct_definitions: Some(200),
2646            max_function_definitions: Some(1000),
2647            max_fields_in_struct: Some(32),
2648            max_dependency_depth: Some(100),
2649            max_num_event_emit: Some(1024),
2650            max_num_new_move_object_ids: Some(2048),
2651            max_num_new_move_object_ids_system_tx: Some(2048 * 16),
2652            max_num_deleted_move_object_ids: Some(2048),
2653            max_num_deleted_move_object_ids_system_tx: Some(2048 * 16),
2654            max_num_transferred_move_object_ids: Some(2048),
2655            max_num_transferred_move_object_ids_system_tx: Some(2048 * 16),
2656            max_event_emit_size: Some(250 * 1024),
2657            max_move_vector_len: Some(256 * 1024),
2658            max_type_to_layout_nodes: None,
2659            max_ptb_value_size: None,
2660
2661            max_back_edges_per_function: Some(10_000),
2662            max_back_edges_per_module: Some(10_000),
2663
2664            max_verifier_meter_ticks_per_function: Some(16_000_000),
2665
2666            max_meter_ticks_per_module: Some(16_000_000),
2667            max_meter_ticks_per_package: Some(16_000_000),
2668            max_meter_ticks_regex_reference_safety: None,
2669            max_instantiation_loop_graph_edges: None,
2670
2671            object_runtime_max_num_cached_objects: Some(1000),
2672            object_runtime_max_num_cached_objects_system_tx: Some(1000 * 16),
2673            object_runtime_max_num_store_entries: Some(1000),
2674            object_runtime_max_num_store_entries_system_tx: Some(1000 * 16),
2675            // min gas budget is in NANOS and an absolute value 1000 NANOS or 0.000001IOTA
2676            base_tx_cost_fixed: Some(1_000),
2677            package_publish_cost_fixed: Some(1_000),
2678            base_tx_cost_per_byte: Some(0),
2679            package_publish_cost_per_byte: Some(80),
2680            obj_access_cost_read_per_byte: Some(15),
2681            obj_access_cost_mutate_per_byte: Some(40),
2682            obj_access_cost_delete_per_byte: Some(40),
2683            obj_access_cost_verify_per_byte: Some(200),
2684            obj_data_cost_refundable: Some(100),
2685            obj_metadata_cost_non_refundable: Some(50),
2686            gas_model_version: Some(1),
2687            storage_rebate_rate: Some(10000),
2688            // Change reward slashing rate to 100%.
2689            reward_slashing_rate: Some(10000),
2690            storage_gas_price: Some(76),
2691            base_gas_price: None,
2692            // The initial subsidy (target reward) for validators per epoch.
2693            // Refer to the IOTA tokenomics for the origin of this value.
2694            validator_target_reward: Some(767_000 * 1_000_000_000),
2695            max_transactions_per_checkpoint: Some(10_000),
2696            max_checkpoint_size_bytes: Some(30 * 1024 * 1024),
2697
2698            // For now, perform upgrades with a bare quorum of validators.
2699            buffer_stake_for_protocol_upgrade_bps: Some(5000),
2700
2701            // === Native Function Costs ===
2702            // `address` module
2703            // Cost params for the Move native function `address::from_bytes(bytes: vector<u8>)`
2704            address_from_bytes_cost_base: Some(52),
2705            // Cost params for the Move native function `address::to_u256(address): u256`
2706            address_to_u256_cost_base: Some(52),
2707            // Cost params for the Move native function `address::from_u256(u256): address`
2708            address_from_u256_cost_base: Some(52),
2709
2710            // `config` module
2711            // Cost params for the Move native function `read_setting_impl``
2712            config_read_setting_impl_cost_base: Some(100),
2713            config_read_setting_impl_cost_per_byte: Some(40),
2714
2715            // `dynamic_field` module
2716            // Cost params for the Move native function `hash_type_and_key<K: copy + drop +
2717            // store>(parent: address, k: K): address`
2718            dynamic_field_hash_type_and_key_cost_base: Some(100),
2719            dynamic_field_hash_type_and_key_type_cost_per_byte: Some(2),
2720            dynamic_field_hash_type_and_key_value_cost_per_byte: Some(2),
2721            dynamic_field_hash_type_and_key_type_tag_cost_per_byte: Some(2),
2722            // Cost params for the Move native function `add_child_object<Child: key>(parent:
2723            // address, child: Child)`
2724            dynamic_field_add_child_object_cost_base: Some(100),
2725            dynamic_field_add_child_object_type_cost_per_byte: Some(10),
2726            dynamic_field_add_child_object_value_cost_per_byte: Some(10),
2727            dynamic_field_add_child_object_struct_tag_cost_per_byte: Some(10),
2728            // Cost params for the Move native function `borrow_child_object_mut<Child: key>(parent:
2729            // &mut UID, id: address): &mut Child`
2730            dynamic_field_borrow_child_object_cost_base: Some(100),
2731            dynamic_field_borrow_child_object_child_ref_cost_per_byte: Some(10),
2732            dynamic_field_borrow_child_object_type_cost_per_byte: Some(10),
2733            // Cost params for the Move native function `remove_child_object<Child: key>(parent:
2734            // address, id: address): Child`
2735            dynamic_field_remove_child_object_cost_base: Some(100),
2736            dynamic_field_remove_child_object_child_cost_per_byte: Some(2),
2737            dynamic_field_remove_child_object_type_cost_per_byte: Some(2),
2738            // Cost params for the Move native function `has_child_object(parent: address, id:
2739            // address): bool`
2740            dynamic_field_has_child_object_cost_base: Some(100),
2741            // Cost params for the Move native function `has_child_object_with_ty<Child:
2742            // key>(parent: address, id: address): bool`
2743            dynamic_field_has_child_object_with_ty_cost_base: Some(100),
2744            dynamic_field_has_child_object_with_ty_type_cost_per_byte: Some(2),
2745            dynamic_field_has_child_object_with_ty_type_tag_cost_per_byte: Some(2),
2746
2747            // `event` module
2748            // Cost params for the Move native function `event::emit<T: copy + drop>(event: T)`
2749            event_emit_cost_base: Some(52),
2750            event_emit_value_size_derivation_cost_per_byte: Some(2),
2751            event_emit_tag_size_derivation_cost_per_byte: Some(5),
2752            event_emit_output_cost_per_byte: Some(10),
2753
2754            //  `object` module
2755            // Cost params for the Move native function `borrow_uid<T: key>(obj: &T): &UID`
2756            object_borrow_uid_cost_base: Some(52),
2757            // Cost params for the Move native function `delete_impl(id: address)`
2758            object_delete_impl_cost_base: Some(52),
2759            // Cost params for the Move native function `record_new_uid(id: address)`
2760            object_record_new_uid_cost_base: Some(52),
2761
2762            // `transfer` module
2763            // Cost params for the Move native function `transfer_impl<T: key>(obj: T, recipient:
2764            // address)`
2765            transfer_transfer_internal_cost_base: Some(52),
2766            // Cost params for the Move native function `freeze_object<T: key>(obj: T)`
2767            transfer_freeze_object_cost_base: Some(52),
2768            // Cost params for the Move native function `share_object<T: key>(obj: T)`
2769            transfer_share_object_cost_base: Some(52),
2770            transfer_receive_object_cost_base: Some(52),
2771
2772            // `tx_context` module
2773            // Cost params for the Move native function `transfer_impl<T: key>(obj: T, recipient:
2774            // address)`
2775            tx_context_derive_id_cost_base: Some(52),
2776            tx_context_fresh_id_cost_base: None,
2777            tx_context_sender_cost_base: None,
2778            tx_context_digest_cost_base: None,
2779            tx_context_epoch_cost_base: None,
2780            tx_context_epoch_timestamp_ms_cost_base: None,
2781            tx_context_sponsor_cost_base: None,
2782            tx_context_rgp_cost_base: None,
2783            tx_context_gas_price_cost_base: None,
2784            tx_context_gas_budget_cost_base: None,
2785            tx_context_ids_created_cost_base: None,
2786            tx_context_replace_cost_base: None,
2787
2788            // `types` module
2789            // Cost params for the Move native function `is_one_time_witness<T: drop>(_: &T): bool`
2790            types_is_one_time_witness_cost_base: Some(52),
2791            types_is_one_time_witness_type_tag_cost_per_byte: Some(2),
2792            types_is_one_time_witness_type_cost_per_byte: Some(2),
2793
2794            // `validator` module
2795            // Cost params for the Move native function `validate_metadata_bcs(metadata:
2796            // vector<u8>)`
2797            validator_validate_metadata_cost_base: Some(52),
2798            validator_validate_metadata_data_cost_per_byte: Some(2),
2799
2800            // Crypto
2801            crypto_invalid_arguments_cost: Some(100),
2802            // bls12381::bls12381_min_pk_verify
2803            bls12381_bls12381_min_sig_verify_cost_base: Some(52),
2804            bls12381_bls12381_min_sig_verify_msg_cost_per_byte: Some(2),
2805            bls12381_bls12381_min_sig_verify_msg_cost_per_block: Some(2),
2806
2807            // bls12381::bls12381_min_pk_verify
2808            bls12381_bls12381_min_pk_verify_cost_base: Some(52),
2809            bls12381_bls12381_min_pk_verify_msg_cost_per_byte: Some(2),
2810            bls12381_bls12381_min_pk_verify_msg_cost_per_block: Some(2),
2811
2812            // ecdsa_k1::ecrecover
2813            ecdsa_k1_ecrecover_keccak256_cost_base: Some(52),
2814            ecdsa_k1_ecrecover_keccak256_msg_cost_per_byte: Some(2),
2815            ecdsa_k1_ecrecover_keccak256_msg_cost_per_block: Some(2),
2816            ecdsa_k1_ecrecover_sha256_cost_base: Some(52),
2817            ecdsa_k1_ecrecover_sha256_msg_cost_per_byte: Some(2),
2818            ecdsa_k1_ecrecover_sha256_msg_cost_per_block: Some(2),
2819
2820            // ecdsa_k1::decompress_pubkey
2821            ecdsa_k1_decompress_pubkey_cost_base: Some(52),
2822
2823            // ecdsa_k1::secp256k1_verify
2824            ecdsa_k1_secp256k1_verify_keccak256_cost_base: Some(52),
2825            ecdsa_k1_secp256k1_verify_keccak256_msg_cost_per_byte: Some(2),
2826            ecdsa_k1_secp256k1_verify_keccak256_msg_cost_per_block: Some(2),
2827            ecdsa_k1_secp256k1_verify_sha256_cost_base: Some(52),
2828            ecdsa_k1_secp256k1_verify_sha256_msg_cost_per_byte: Some(2),
2829            ecdsa_k1_secp256k1_verify_sha256_msg_cost_per_block: Some(2),
2830
2831            // ecdsa_r1::ecrecover
2832            ecdsa_r1_ecrecover_keccak256_cost_base: Some(52),
2833            ecdsa_r1_ecrecover_keccak256_msg_cost_per_byte: Some(2),
2834            ecdsa_r1_ecrecover_keccak256_msg_cost_per_block: Some(2),
2835            ecdsa_r1_ecrecover_sha256_cost_base: Some(52),
2836            ecdsa_r1_ecrecover_sha256_msg_cost_per_byte: Some(2),
2837            ecdsa_r1_ecrecover_sha256_msg_cost_per_block: Some(2),
2838
2839            // ecdsa_r1::secp256k1_verify
2840            ecdsa_r1_secp256r1_verify_keccak256_cost_base: Some(52),
2841            ecdsa_r1_secp256r1_verify_keccak256_msg_cost_per_byte: Some(2),
2842            ecdsa_r1_secp256r1_verify_keccak256_msg_cost_per_block: Some(2),
2843            ecdsa_r1_secp256r1_verify_sha256_cost_base: Some(52),
2844            ecdsa_r1_secp256r1_verify_sha256_msg_cost_per_byte: Some(2),
2845            ecdsa_r1_secp256r1_verify_sha256_msg_cost_per_block: Some(2),
2846
2847            // ecvrf::verify
2848            ecvrf_ecvrf_verify_cost_base: Some(52),
2849            ecvrf_ecvrf_verify_alpha_string_cost_per_byte: Some(2),
2850            ecvrf_ecvrf_verify_alpha_string_cost_per_block: Some(2),
2851
2852            // ed25519
2853            ed25519_ed25519_verify_cost_base: Some(52),
2854            ed25519_ed25519_verify_msg_cost_per_byte: Some(2),
2855            ed25519_ed25519_verify_msg_cost_per_block: Some(2),
2856
2857            // groth16::prepare_verifying_key
2858            groth16_prepare_verifying_key_bls12381_cost_base: Some(52),
2859            groth16_prepare_verifying_key_bn254_cost_base: Some(52),
2860
2861            // groth16::verify_groth16_proof_internal
2862            groth16_verify_groth16_proof_internal_bls12381_cost_base: Some(52),
2863            groth16_verify_groth16_proof_internal_bls12381_cost_per_public_input: Some(2),
2864            groth16_verify_groth16_proof_internal_bn254_cost_base: Some(52),
2865            groth16_verify_groth16_proof_internal_bn254_cost_per_public_input: Some(2),
2866            groth16_verify_groth16_proof_internal_public_input_cost_per_byte: Some(2),
2867
2868            // hash::blake2b256
2869            hash_blake2b256_cost_base: Some(52),
2870            hash_blake2b256_data_cost_per_byte: Some(2),
2871            hash_blake2b256_data_cost_per_block: Some(2),
2872            // hash::keccak256
2873            hash_keccak256_cost_base: Some(52),
2874            hash_keccak256_data_cost_per_byte: Some(2),
2875            hash_keccak256_data_cost_per_block: Some(2),
2876
2877            poseidon_bn254_cost_base: None,
2878            poseidon_bn254_cost_per_block: None,
2879
2880            // hmac::hmac_sha3_256
2881            hmac_hmac_sha3_256_cost_base: Some(52),
2882            hmac_hmac_sha3_256_input_cost_per_byte: Some(2),
2883            hmac_hmac_sha3_256_input_cost_per_block: Some(2),
2884
2885            // group ops
2886            group_ops_bls12381_decode_scalar_cost: Some(52),
2887            group_ops_bls12381_decode_g1_cost: Some(52),
2888            group_ops_bls12381_decode_g2_cost: Some(52),
2889            group_ops_bls12381_decode_gt_cost: Some(52),
2890            group_ops_bls12381_scalar_add_cost: Some(52),
2891            group_ops_bls12381_g1_add_cost: Some(52),
2892            group_ops_bls12381_g2_add_cost: Some(52),
2893            group_ops_bls12381_gt_add_cost: Some(52),
2894            group_ops_bls12381_scalar_sub_cost: Some(52),
2895            group_ops_bls12381_g1_sub_cost: Some(52),
2896            group_ops_bls12381_g2_sub_cost: Some(52),
2897            group_ops_bls12381_gt_sub_cost: Some(52),
2898            group_ops_bls12381_scalar_mul_cost: Some(52),
2899            group_ops_bls12381_g1_mul_cost: Some(52),
2900            group_ops_bls12381_g2_mul_cost: Some(52),
2901            group_ops_bls12381_gt_mul_cost: Some(52),
2902            group_ops_bls12381_scalar_div_cost: Some(52),
2903            group_ops_bls12381_g1_div_cost: Some(52),
2904            group_ops_bls12381_g2_div_cost: Some(52),
2905            group_ops_bls12381_gt_div_cost: Some(52),
2906            group_ops_bls12381_g1_hash_to_base_cost: Some(52),
2907            group_ops_bls12381_g2_hash_to_base_cost: Some(52),
2908            group_ops_bls12381_g1_hash_to_cost_per_byte: Some(2),
2909            group_ops_bls12381_g2_hash_to_cost_per_byte: Some(2),
2910            group_ops_bls12381_g1_msm_base_cost: Some(52),
2911            group_ops_bls12381_g2_msm_base_cost: Some(52),
2912            group_ops_bls12381_g1_msm_base_cost_per_input: Some(52),
2913            group_ops_bls12381_g2_msm_base_cost_per_input: Some(52),
2914            group_ops_bls12381_msm_max_len: Some(32),
2915            group_ops_bls12381_pairing_cost: Some(52),
2916            group_ops_bls12381_g1_to_uncompressed_g1_cost: None,
2917            group_ops_bls12381_uncompressed_g1_to_g1_cost: None,
2918            group_ops_bls12381_uncompressed_g1_sum_base_cost: None,
2919            group_ops_bls12381_uncompressed_g1_sum_cost_per_term: None,
2920            group_ops_bls12381_uncompressed_g1_sum_max_terms: None,
2921
2922            // zklogin::check_zklogin_id
2923            #[allow(deprecated)]
2924            check_zklogin_id_cost_base: Some(200),
2925            #[allow(deprecated)]
2926            // zklogin::check_zklogin_issuer
2927            check_zklogin_issuer_cost_base: Some(200),
2928
2929            vdf_verify_vdf_cost: None,
2930            vdf_hash_to_input_cost: None,
2931
2932            bcs_per_byte_serialized_cost: Some(2),
2933            bcs_legacy_min_output_size_cost: Some(1),
2934            bcs_failure_cost: Some(52),
2935            hash_sha2_256_base_cost: Some(52),
2936            hash_sha2_256_per_byte_cost: Some(2),
2937            hash_sha2_256_legacy_min_input_len_cost: Some(1),
2938            hash_sha3_256_base_cost: Some(52),
2939            hash_sha3_256_per_byte_cost: Some(2),
2940            hash_sha3_256_legacy_min_input_len_cost: Some(1),
2941            type_name_get_base_cost: Some(52),
2942            type_name_get_per_byte_cost: Some(2),
2943            string_check_utf8_base_cost: Some(52),
2944            string_check_utf8_per_byte_cost: Some(2),
2945            string_is_char_boundary_base_cost: Some(52),
2946            string_sub_string_base_cost: Some(52),
2947            string_sub_string_per_byte_cost: Some(2),
2948            string_index_of_base_cost: Some(52),
2949            string_index_of_per_byte_pattern_cost: Some(2),
2950            string_index_of_per_byte_searched_cost: Some(2),
2951            vector_empty_base_cost: Some(52),
2952            vector_length_base_cost: Some(52),
2953            vector_push_back_base_cost: Some(52),
2954            vector_push_back_legacy_per_abstract_memory_unit_cost: Some(2),
2955            vector_borrow_base_cost: Some(52),
2956            vector_pop_back_base_cost: Some(52),
2957            vector_destroy_empty_base_cost: Some(52),
2958            vector_swap_base_cost: Some(52),
2959            debug_print_base_cost: Some(52),
2960            debug_print_stack_trace_base_cost: Some(52),
2961
2962            max_size_written_objects: Some(5 * 1000 * 1000),
2963            // max size of written objects during a system TXn to allow for larger writes
2964            // akin to `max_size_written_objects` but for system TXns
2965            max_size_written_objects_system_tx: Some(50 * 1000 * 1000),
2966
2967            // Limits the length of a Move identifier
2968            max_move_identifier_len: Some(128),
2969            max_move_value_depth: Some(128),
2970            max_move_call_argument_nodes: None,
2971            max_move_call_argument_nodes_total: None,
2972            max_move_enum_variants: None,
2973
2974            gas_rounding_step: Some(1_000),
2975
2976            execution_version: Some(1),
2977
2978            // We maintain the same total size limit for events, but increase the number of
2979            // events that can be emitted.
2980            max_event_emit_size_total: Some(
2981                256 /* former event count limit */ * 250 * 1024, // size limit per event
2982            ),
2983
2984            // Taking a baby step approach, we consider only 20% by stake as bad nodes so we
2985            // have a 80% by stake of nodes participating in the leader committee. That
2986            // allow us for more redundancy in case we have validators
2987            // under performing - since the responsibility is shared
2988            // amongst more nodes. We can increase that once we do have
2989            // higher confidence.
2990            consensus_bad_nodes_stake_threshold: Some(20),
2991
2992            // Max of 10 votes per hour.
2993            #[allow(deprecated)]
2994            max_jwk_votes_per_validator_per_epoch: Some(240),
2995
2996            #[allow(deprecated)]
2997            max_age_of_jwk_in_epochs: Some(1),
2998
2999            consensus_max_transaction_size_bytes: Some(256 * 1024), // 256KB
3000
3001            // Assume 1KB per transaction and 500 transactions per block.
3002            consensus_max_transactions_in_block_bytes: Some(512 * 1024),
3003
3004            random_beacon_reduction_allowed_delta: Some(800),
3005
3006            random_beacon_reduction_lower_bound: Some(1000),
3007            random_beacon_dkg_timeout_round: Some(3000),
3008            random_beacon_min_round_interval_ms: Some(500),
3009
3010            random_beacon_dkg_version: Some(1),
3011
3012            // Assume 20_000 TPS * 5% max stake per validator / (minimum) 4 blocks per round
3013            // = 250 transactions per block maximum Using a higher limit
3014            // that is 512, to account for bursty traffic and system transactions.
3015            consensus_max_num_transactions_in_block: Some(512),
3016
3017            max_deferral_rounds_for_congestion_control: Some(10),
3018
3019            min_checkpoint_interval_ms: Some(200),
3020
3021            checkpoint_rate_window_size: None,
3022
3023            checkpoint_summary_version_specific_data: Some(1),
3024
3025            max_soft_bundle_size: Some(5),
3026
3027            bridge_should_try_to_finalize_committee: None,
3028
3029            max_accumulated_txn_cost_per_object_in_mysticeti_commit: Some(10),
3030
3031            max_committee_members_count: None,
3032            deny_rule_update_max_entries_per_tx: None,
3033
3034            consensus_gc_depth: None,
3035
3036            consensus_max_acknowledgments_per_block: None,
3037
3038            max_congestion_limit_overshoot_per_commit: None,
3039
3040            max_concurrent_execution_workers: None,
3041
3042            pcool_deterministic_validation_horizon_distance: None,
3043
3044            scorer_version: None,
3045
3046            // `auth_context` module
3047            auth_context_digest_cost_base: None,
3048            auth_context_tx_data_bytes_cost_base: None,
3049            auth_context_tx_data_bytes_cost_per_byte: None,
3050            auth_context_tx_commands_cost_base: None,
3051            auth_context_tx_commands_cost_per_byte: None,
3052            auth_context_tx_inputs_cost_base: None,
3053            auth_context_tx_inputs_cost_per_byte: None,
3054            auth_context_replace_cost_base: None,
3055            auth_context_replace_cost_per_byte: None,
3056            auth_context_authenticator_function_info_v1_cost_base: None,
3057            consensus_commits_per_schedule: None,
3058            min_validator_count: None,
3059            max_validator_count: None,
3060            min_validator_joining_stake: None,
3061            validator_low_stake_threshold: None,
3062            validator_very_low_stake_threshold: None,
3063            validator_low_stake_grace_period: None,
3064            consensus_leader_schedule_window_size: None,
3065
3066            max_move_system_package_size: None,
3067            // When adding a new constant, set it to None in the earliest version, like this:
3068            // new_constant: None,
3069        };
3070
3071        cfg.feature_flags.consensus_transaction_ordering = ConsensusTransactionOrdering::ByGasPrice;
3072
3073        // MoveVM related flags
3074        {
3075            cfg.feature_flags
3076                .disable_invariant_violation_check_in_swap_loc = true;
3077            cfg.feature_flags.no_extraneous_module_bytes = true;
3078            cfg.feature_flags.hardened_otw_check = true;
3079            cfg.feature_flags.rethrow_serialization_type_layout_errors = true;
3080        }
3081
3082        // zkLogin related flags
3083        {
3084            #[allow(deprecated)]
3085            {
3086                cfg.feature_flags.zklogin_max_epoch_upper_bound_delta = Some(30);
3087            }
3088        }
3089
3090        // Historical default: Mysticeti. Kept explicitly to match the
3091        // serialized form of pre-v14/v19/v24 configs. No runtime behavior
3092        // depends on this — Starfish is the only consensus protocol.
3093        #[expect(deprecated)]
3094        {
3095            cfg.feature_flags.consensus_choice = ConsensusChoice::MysticetiDeprecated;
3096        }
3097        // Use tonic networking for consensus.
3098        cfg.feature_flags.consensus_network = ConsensusNetwork::Tonic;
3099
3100        cfg.feature_flags.per_object_congestion_control_mode =
3101            PerObjectCongestionControlMode::TotalTxCount;
3102
3103        // Do not allow bridge committee to finalize on mainnet.
3104        cfg.bridge_should_try_to_finalize_committee = Some(chain != Chain::Mainnet);
3105
3106        // Devnet
3107        if chain != Chain::Mainnet && chain != Chain::Testnet {
3108            cfg.feature_flags.enable_poseidon = true;
3109            cfg.poseidon_bn254_cost_base = Some(260);
3110            cfg.poseidon_bn254_cost_per_block = Some(10);
3111
3112            cfg.feature_flags.enable_group_ops_native_function_msm = true;
3113
3114            cfg.feature_flags.enable_vdf = true;
3115            // Set to 30x and 2x the cost of a signature verification for now. This
3116            // should be updated along with other native crypto functions.
3117            cfg.vdf_verify_vdf_cost = Some(1500);
3118            cfg.vdf_hash_to_input_cost = Some(100);
3119
3120            cfg.feature_flags.passkey_auth = true;
3121        }
3122
3123        for cur in 2..=version.0 {
3124            match cur {
3125                1 => unreachable!(),
3126                // version 2 is a new framework version but with no config changes
3127                2 => {}
3128                3 => {
3129                    cfg.feature_flags.relocate_event_module = true;
3130                }
3131                4 => {
3132                    cfg.max_type_to_layout_nodes = Some(512);
3133                }
3134                5 => {
3135                    cfg.feature_flags.protocol_defined_base_fee = true;
3136                    cfg.base_gas_price = Some(1000);
3137
3138                    cfg.feature_flags.disallow_new_modules_in_deps_only_packages = true;
3139                    cfg.feature_flags.convert_type_argument_error = true;
3140                    cfg.feature_flags.native_charging_v2 = true;
3141
3142                    if chain != Chain::Mainnet && chain != Chain::Testnet {
3143                        cfg.feature_flags.uncompressed_g1_group_elements = true;
3144                    }
3145
3146                    cfg.gas_model_version = Some(2);
3147
3148                    cfg.poseidon_bn254_cost_per_block = Some(388);
3149
3150                    cfg.bls12381_bls12381_min_sig_verify_cost_base = Some(44064);
3151                    cfg.bls12381_bls12381_min_pk_verify_cost_base = Some(49282);
3152                    cfg.ecdsa_k1_secp256k1_verify_keccak256_cost_base = Some(1470);
3153                    cfg.ecdsa_k1_secp256k1_verify_sha256_cost_base = Some(1470);
3154                    cfg.ecdsa_r1_secp256r1_verify_sha256_cost_base = Some(4225);
3155                    cfg.ecdsa_r1_secp256r1_verify_keccak256_cost_base = Some(4225);
3156                    cfg.ecvrf_ecvrf_verify_cost_base = Some(4848);
3157                    cfg.ed25519_ed25519_verify_cost_base = Some(1802);
3158
3159                    // Manually changed to be "under cost"
3160                    cfg.ecdsa_r1_ecrecover_keccak256_cost_base = Some(1173);
3161                    cfg.ecdsa_r1_ecrecover_sha256_cost_base = Some(1173);
3162                    cfg.ecdsa_k1_ecrecover_keccak256_cost_base = Some(500);
3163                    cfg.ecdsa_k1_ecrecover_sha256_cost_base = Some(500);
3164
3165                    cfg.groth16_prepare_verifying_key_bls12381_cost_base = Some(53838);
3166                    cfg.groth16_prepare_verifying_key_bn254_cost_base = Some(82010);
3167                    cfg.groth16_verify_groth16_proof_internal_bls12381_cost_base = Some(72090);
3168                    cfg.groth16_verify_groth16_proof_internal_bls12381_cost_per_public_input =
3169                        Some(8213);
3170                    cfg.groth16_verify_groth16_proof_internal_bn254_cost_base = Some(115502);
3171                    cfg.groth16_verify_groth16_proof_internal_bn254_cost_per_public_input =
3172                        Some(9484);
3173
3174                    cfg.hash_keccak256_cost_base = Some(10);
3175                    cfg.hash_blake2b256_cost_base = Some(10);
3176
3177                    // group ops
3178                    cfg.group_ops_bls12381_decode_scalar_cost = Some(7);
3179                    cfg.group_ops_bls12381_decode_g1_cost = Some(2848);
3180                    cfg.group_ops_bls12381_decode_g2_cost = Some(3770);
3181                    cfg.group_ops_bls12381_decode_gt_cost = Some(3068);
3182
3183                    cfg.group_ops_bls12381_scalar_add_cost = Some(10);
3184                    cfg.group_ops_bls12381_g1_add_cost = Some(1556);
3185                    cfg.group_ops_bls12381_g2_add_cost = Some(3048);
3186                    cfg.group_ops_bls12381_gt_add_cost = Some(188);
3187
3188                    cfg.group_ops_bls12381_scalar_sub_cost = Some(10);
3189                    cfg.group_ops_bls12381_g1_sub_cost = Some(1550);
3190                    cfg.group_ops_bls12381_g2_sub_cost = Some(3019);
3191                    cfg.group_ops_bls12381_gt_sub_cost = Some(497);
3192
3193                    cfg.group_ops_bls12381_scalar_mul_cost = Some(11);
3194                    cfg.group_ops_bls12381_g1_mul_cost = Some(4842);
3195                    cfg.group_ops_bls12381_g2_mul_cost = Some(9108);
3196                    cfg.group_ops_bls12381_gt_mul_cost = Some(27490);
3197
3198                    cfg.group_ops_bls12381_scalar_div_cost = Some(91);
3199                    cfg.group_ops_bls12381_g1_div_cost = Some(5091);
3200                    cfg.group_ops_bls12381_g2_div_cost = Some(9206);
3201                    cfg.group_ops_bls12381_gt_div_cost = Some(27804);
3202
3203                    cfg.group_ops_bls12381_g1_hash_to_base_cost = Some(2962);
3204                    cfg.group_ops_bls12381_g2_hash_to_base_cost = Some(8688);
3205
3206                    cfg.group_ops_bls12381_g1_msm_base_cost = Some(62648);
3207                    cfg.group_ops_bls12381_g2_msm_base_cost = Some(131192);
3208                    cfg.group_ops_bls12381_g1_msm_base_cost_per_input = Some(1333);
3209                    cfg.group_ops_bls12381_g2_msm_base_cost_per_input = Some(3216);
3210
3211                    cfg.group_ops_bls12381_uncompressed_g1_to_g1_cost = Some(677);
3212                    cfg.group_ops_bls12381_g1_to_uncompressed_g1_cost = Some(2099);
3213                    cfg.group_ops_bls12381_uncompressed_g1_sum_base_cost = Some(77);
3214                    cfg.group_ops_bls12381_uncompressed_g1_sum_cost_per_term = Some(26);
3215                    cfg.group_ops_bls12381_uncompressed_g1_sum_max_terms = Some(1200);
3216
3217                    cfg.group_ops_bls12381_pairing_cost = Some(26897);
3218
3219                    cfg.validator_validate_metadata_cost_base = Some(20000);
3220
3221                    cfg.max_committee_members_count = Some(50);
3222                }
3223                6 => {
3224                    cfg.max_ptb_value_size = Some(1024 * 1024);
3225                }
3226                7 => {
3227                    // version 7 is a new framework version but with no config
3228                    // changes
3229                }
3230                8 => {
3231                    cfg.feature_flags.variant_nodes = true;
3232
3233                    if chain != Chain::Mainnet {
3234                        // Enable round prober in consensus.
3235                        cfg.feature_flags.consensus_round_prober = true;
3236                        // Enable distributed vote scoring.
3237                        cfg.feature_flags
3238                            .consensus_distributed_vote_scoring_strategy = true;
3239                        cfg.feature_flags.consensus_linearize_subdag_v2 = true;
3240                        // Enable smart ancestor selection for testnet
3241                        cfg.feature_flags.consensus_smart_ancestor_selection = true;
3242                        // Enable probing for accepted rounds in round prober for testnet
3243                        cfg.feature_flags
3244                            .consensus_round_prober_probe_accepted_rounds = true;
3245                        // Enable zstd compression for consensus in testnet
3246                        cfg.feature_flags.consensus_zstd_compression = true;
3247                        // Assuming a round rate of max 15/sec, then using a gc depth of 60 allow
3248                        // blocks within a window of ~4 seconds
3249                        // to be included before be considered garbage collected.
3250                        cfg.consensus_gc_depth = Some(60);
3251                    }
3252
3253                    // Enable min_free_execution_slot for the shared object congestion tracker in
3254                    // devnet.
3255                    if chain != Chain::Testnet && chain != Chain::Mainnet {
3256                        cfg.feature_flags.congestion_control_min_free_execution_slot = true;
3257                    }
3258                }
3259                9 => {
3260                    if chain != Chain::Mainnet {
3261                        // Disable smart ancestor selection in the testnet and devnet.
3262                        cfg.feature_flags.consensus_smart_ancestor_selection = false;
3263                    }
3264
3265                    // Enable zstd compression for consensus
3266                    cfg.feature_flags.consensus_zstd_compression = true;
3267
3268                    // Enable passkey in multisig in devnet.
3269                    if chain != Chain::Testnet && chain != Chain::Mainnet {
3270                        cfg.feature_flags.accept_passkey_in_multisig = true;
3271                    }
3272
3273                    // this flag is now deprecated because of the bridge removal.
3274                    cfg.bridge_should_try_to_finalize_committee = None;
3275                }
3276                10 => {
3277                    // Enable min_free_execution_slot for the shared object congestion tracker in
3278                    // all networks.
3279                    cfg.feature_flags.congestion_control_min_free_execution_slot = true;
3280
3281                    // Increase the committee size to 80 on all networks.
3282                    cfg.max_committee_members_count = Some(80);
3283
3284                    // Enable round prober in consensus.
3285                    cfg.feature_flags.consensus_round_prober = true;
3286                    // Enable probing for accepted rounds in round.
3287                    cfg.feature_flags
3288                        .consensus_round_prober_probe_accepted_rounds = true;
3289                    // Enable distributed vote scoring.
3290                    cfg.feature_flags
3291                        .consensus_distributed_vote_scoring_strategy = true;
3292                    // Enable the new consensus commit rule.
3293                    cfg.feature_flags.consensus_linearize_subdag_v2 = true;
3294
3295                    // Enable consensus garbage collection
3296                    // Assuming a round rate of max 15/sec, then using a gc depth of 60 allow
3297                    // blocks within a window of ~4 seconds
3298                    // to be included before be considered garbage collected.
3299                    cfg.consensus_gc_depth = Some(60);
3300
3301                    // Enable minimized child object mutation counting.
3302                    cfg.feature_flags.minimize_child_object_mutations = true;
3303
3304                    if chain != Chain::Mainnet {
3305                        // Enable batched block sync in devnet and testnet.
3306                        cfg.feature_flags.consensus_batched_block_sync = true;
3307                    }
3308
3309                    if chain != Chain::Testnet && chain != Chain::Mainnet {
3310                        // Enable the gas price feedback mechanism (which is used for
3311                        // transactions cancelled due to shared object congestion) in devnet
3312                        cfg.feature_flags
3313                            .congestion_control_gas_price_feedback_mechanism = true;
3314                    }
3315
3316                    cfg.feature_flags.validate_identifier_inputs = true;
3317                    cfg.feature_flags.dependency_linkage_error = true;
3318                    cfg.feature_flags.additional_multisig_checks = true;
3319                }
3320                11 => {
3321                    // version 11 is a new framework version but with no config
3322                    // changes
3323                }
3324                12 => {
3325                    // Enable the gas price feedback mechanism for transactions
3326                    // cancelled due to congestion in all networks
3327                    cfg.feature_flags
3328                        .congestion_control_gas_price_feedback_mechanism = true;
3329
3330                    // Enable normalization of PTB arguments in all networks.
3331                    cfg.feature_flags.normalize_ptb_arguments = true;
3332                }
3333                13 => {
3334                    // Enable selecting committee based on eligible active validators on all
3335                    // networks.
3336                    cfg.feature_flags.select_committee_from_eligible_validators = true;
3337                    // Enable tracking non-committee eligible active
3338                    // validators on all networks.
3339                    cfg.feature_flags.track_non_committee_eligible_validators = true;
3340
3341                    if chain != Chain::Testnet && chain != Chain::Mainnet {
3342                        // Enable selecting committee only from active validators that next epoch
3343                        // version and issued valid AuthorityCapabilities notification in devnet.
3344                        cfg.feature_flags
3345                            .select_committee_supporting_next_epoch_version = true;
3346                    }
3347                }
3348                14 => {
3349                    // Enable batched block sync for mainnet.
3350                    cfg.feature_flags.consensus_batched_block_sync = true;
3351
3352                    if chain != Chain::Mainnet {
3353                        // Enable median-based commit timestamp calculation in consensus and
3354                        // enforce checkpoint timestamp monotonicity for testnet.
3355                        cfg.feature_flags
3356                            .consensus_median_timestamp_with_checkpoint_enforcement = true;
3357                        // Enable selecting committee only from active validators that support the
3358                        // next epoch's version and issued valid AuthorityCapabilities notification
3359                        // in testnet.
3360                        cfg.feature_flags
3361                            .select_committee_supporting_next_epoch_version = true;
3362                    }
3363                    if chain != Chain::Testnet && chain != Chain::Mainnet {
3364                        // Switch consensus protocol to Starfish in devnet
3365                        cfg.feature_flags.consensus_choice = ConsensusChoice::Starfish;
3366                    }
3367                }
3368                15 => {
3369                    if chain != Chain::Mainnet && chain != Chain::Testnet {
3370                        // Enable overshoot of 100 in congestion control. This allows bursts of
3371                        // shared object transactions up to 10 times the average allowable
3372                        // load set by `max_accumulated_txn_cost_per_object_in_mysticeti_commit`.
3373                        cfg.max_congestion_limit_overshoot_per_commit = Some(100);
3374                    }
3375                }
3376                16 => {
3377                    // Enable selecting committee only from active validators that support the
3378                    // next epoch's version and issued valid AuthorityCapabilities notification.
3379                    cfg.feature_flags
3380                        .select_committee_supporting_next_epoch_version = true;
3381                    // Enable committing transactions only for traversed headers in Starfish
3382                    cfg.feature_flags
3383                        .consensus_commit_transactions_only_for_traversed_headers = true;
3384                }
3385                17 => {
3386                    // Increase the committee size to 100 on all networks.
3387                    cfg.max_committee_members_count = Some(100);
3388                }
3389                18 => {
3390                    if chain != Chain::Mainnet {
3391                        // Enable passkey authentication support in testnet.
3392                        cfg.feature_flags.passkey_auth = true;
3393                    }
3394                }
3395                19 => {
3396                    if chain != Chain::Testnet && chain != Chain::Mainnet {
3397                        // Enable congestion limit overshoot in the gas price feedback
3398                        // mechanism on devnet.
3399                        cfg.feature_flags
3400                            .congestion_limit_overshoot_in_gas_price_feedback_mechanism = true;
3401                        // Enable a separate gas price feedback mechanism for transactions using
3402                        // randomness on devnet.
3403                        cfg.feature_flags
3404                            .separate_gas_price_feedback_mechanism_for_randomness = true;
3405                        // Enable storing metadata in module bytes and then
3406                        // publishing package metadata in devnet
3407                        cfg.feature_flags.metadata_in_module_bytes = true;
3408                        cfg.feature_flags.publish_package_metadata = true;
3409                        // Enable Move authentication in devnet
3410                        cfg.feature_flags.enable_move_authentication = true;
3411                        // Max auth gas budget is in NANOS and an absolute value 0.25 IOTA
3412                        cfg.max_auth_gas = Some(250_000_000);
3413                        // Increase the base cost for transfer receive object in devnet, since the
3414                        // implementation now does check if parent is not an account.
3415                        cfg.transfer_receive_object_cost_base = Some(100);
3416                        // Enable adjustment of validator rewards based on score in devnet.
3417                        cfg.feature_flags.adjust_rewards_by_score = true;
3418                    }
3419
3420                    if chain != Chain::Mainnet {
3421                        // Switch consensus protocol to Starfish in testnet.
3422                        cfg.feature_flags.consensus_choice = ConsensusChoice::Starfish;
3423
3424                        // Enable validator score calculation on testnet
3425                        cfg.feature_flags.calculate_validator_scores = true;
3426                        cfg.scorer_version = Some(1);
3427                    }
3428
3429                    // Change epoch transaction will contain validator scores
3430                    cfg.feature_flags.pass_validator_scores_to_advance_epoch = true;
3431
3432                    // Enable passkey authentication support in mainnet
3433                    cfg.feature_flags.passkey_auth = true;
3434                }
3435                20 => {
3436                    if chain != Chain::Testnet && chain != Chain::Mainnet {
3437                        // Passes the calculated validator scores to advance epoch only on Devnet
3438                        cfg.feature_flags
3439                            .pass_calculated_validator_scores_to_advance_epoch = true;
3440                    }
3441                }
3442                21 => {
3443                    if chain != Chain::Testnet && chain != Chain::Mainnet {
3444                        // Enable fast commit syncer for faster recovery in devnet.
3445                        cfg.feature_flags.consensus_fast_commit_sync = true;
3446                    }
3447                    if chain != Chain::Mainnet {
3448                        // Enable overshoot of 100 in congestion control on testnet.
3449                        // This allows bursts of shared-object transactions
3450                        // up to 10 times the average allowable load set by
3451                        // `max_accumulated_txn_cost_per_object_in_mysticeti_commit`.
3452                        cfg.max_congestion_limit_overshoot_per_commit = Some(100);
3453                        // Enable congestion limit overshoot in the gas price feedback
3454                        // mechanism on testnet.
3455                        cfg.feature_flags
3456                            .congestion_limit_overshoot_in_gas_price_feedback_mechanism = true;
3457                        // Enable a separate gas price feedback mechanism for transactions using
3458                        // randomness on testnet.
3459                        cfg.feature_flags
3460                            .separate_gas_price_feedback_mechanism_for_randomness = true;
3461                    }
3462
3463                    cfg.auth_context_digest_cost_base = Some(30);
3464                    cfg.auth_context_tx_commands_cost_base = Some(30);
3465                    cfg.auth_context_tx_commands_cost_per_byte = Some(2);
3466                    cfg.auth_context_tx_inputs_cost_base = Some(30);
3467                    cfg.auth_context_tx_inputs_cost_per_byte = Some(2);
3468                    cfg.auth_context_replace_cost_base = Some(30);
3469                    cfg.auth_context_replace_cost_per_byte = Some(2);
3470
3471                    if chain != Chain::Testnet && chain != Chain::Mainnet {
3472                        // Decrease max_auth_gas to 0.00025 IOTA
3473                        cfg.max_auth_gas = Some(250_000);
3474                    }
3475                }
3476                22 => {
3477                    // Enable overshoot of 100 in congestion control on all networks.
3478                    // This allows bursts of shared-object transactions
3479                    // up to 10 times the average allowable load set by
3480                    // `max_accumulated_txn_cost_per_object_in_mysticeti_commit`.
3481                    cfg.max_congestion_limit_overshoot_per_commit = Some(100);
3482                    // Enable congestion limit overshoot in the gas price feedback
3483                    // mechanism on all networks.
3484                    cfg.feature_flags
3485                        .congestion_limit_overshoot_in_gas_price_feedback_mechanism = true;
3486                    // Enable a separate gas price feedback mechanism for transactions using
3487                    // randomness on all networks.
3488                    cfg.feature_flags
3489                        .separate_gas_price_feedback_mechanism_for_randomness = true;
3490
3491                    if chain != Chain::Mainnet {
3492                        // Enable storing metadata in module bytes and then
3493                        // publishing package metadata in testnet
3494                        cfg.feature_flags.metadata_in_module_bytes = true;
3495                        cfg.feature_flags.publish_package_metadata = true;
3496                        // Enable Move authentication in testnet
3497                        cfg.feature_flags.enable_move_authentication = true;
3498                        // Max_auth_gas is 0.00025 IOTA
3499                        cfg.max_auth_gas = Some(250_000);
3500                        // Increase the base cost for transfer receive object in testnet, since the
3501                        // implementation now does check if parent is not an account.
3502                        cfg.transfer_receive_object_cost_base = Some(100);
3503                    }
3504
3505                    if chain != Chain::Mainnet {
3506                        // Enable fast commit syncer for faster recovery on testnet.
3507                        cfg.feature_flags.consensus_fast_commit_sync = true;
3508                    }
3509                }
3510                23 => {
3511                    // Enable Move native context (TxContext via native functions) in all networks.
3512                    cfg.feature_flags.move_native_tx_context = true;
3513                    cfg.tx_context_fresh_id_cost_base = Some(52);
3514                    cfg.tx_context_sender_cost_base = Some(30);
3515                    cfg.tx_context_digest_cost_base = Some(30);
3516                    cfg.tx_context_epoch_cost_base = Some(30);
3517                    cfg.tx_context_epoch_timestamp_ms_cost_base = Some(30);
3518                    cfg.tx_context_sponsor_cost_base = Some(30);
3519                    cfg.tx_context_rgp_cost_base = Some(30);
3520                    cfg.tx_context_gas_price_cost_base = Some(30);
3521                    cfg.tx_context_gas_budget_cost_base = Some(30);
3522                    cfg.tx_context_ids_created_cost_base = Some(30);
3523                    cfg.tx_context_replace_cost_base = Some(30);
3524                }
3525                24 => {
3526                    // Switch consensus protocol to Starfish in all networks.
3527                    cfg.feature_flags.consensus_choice = ConsensusChoice::Starfish;
3528
3529                    if chain != Chain::Testnet && chain != Chain::Mainnet {
3530                        // Enable Move-based sponsor account authentication in devnet.
3531                        cfg.feature_flags.enable_move_authentication_for_sponsor = true;
3532                    }
3533
3534                    // Add tx_data_bytes to AuthContext for intent-based signature
3535                    // verification in account abstraction.
3536                    cfg.auth_context_tx_data_bytes_cost_base = Some(30);
3537                    cfg.auth_context_tx_data_bytes_cost_per_byte = Some(2);
3538
3539                    // Enable additional borrow checks.
3540                    cfg.feature_flags.additional_borrow_checks = true;
3541                }
3542                #[allow(deprecated)]
3543                25 => {
3544                    // Deprecate zkLogin related parameters since zkLogin is deprecated and was
3545                    // never enabled on IOTA.
3546                    cfg.feature_flags.zklogin_max_epoch_upper_bound_delta = None;
3547                    cfg.check_zklogin_id_cost_base = None;
3548                    cfg.check_zklogin_issuer_cost_base = None;
3549                    cfg.max_jwk_votes_per_validator_per_epoch = None;
3550                    cfg.max_age_of_jwk_in_epochs = None;
3551                }
3552                26 => {
3553                    // Introduce a module to allow Move code to query protocol
3554                    // feature flags at runtime.
3555                }
3556                27 => {
3557                    if chain != Chain::Mainnet {
3558                        // Enable consensus block restrictions on testnet/devnet to bound
3559                        // header size by committee size.
3560                        cfg.feature_flags.consensus_block_restrictions = true;
3561                    }
3562
3563                    if chain != Chain::Testnet && chain != Chain::Mainnet {
3564                        // Only sponsor Move authentication is performed pre-consensus in devnet.
3565                        cfg.feature_flags
3566                            .pre_consensus_sponsor_only_move_authentication = true;
3567                    }
3568                }
3569                28 => {
3570                    // AuthenticatorFunctionInfoV1 max BCS size:
3571                    // package (32) + module_name (128) + function_name (128) = 288 bytes = 9 ×
3572                    // digest. auth_context_digest_cost_base = 30 for 32 bytes →
3573                    // 9 × 30 = 270.
3574                    cfg.auth_context_authenticator_function_info_v1_cost_base = Some(270);
3575
3576                    // Enable storing metadata in module bytes and then
3577                    // publishing package metadata in mainnet.
3578                    cfg.feature_flags.metadata_in_module_bytes = true;
3579                    cfg.feature_flags.publish_package_metadata = true;
3580                    // Enable Move authentication in mainnet.
3581                    cfg.feature_flags.enable_move_authentication = true;
3582                    // Increase the base cost for transfer receive object in mainnet, since the
3583                    // implementation now does check if parent is not an account.
3584                    cfg.transfer_receive_object_cost_base = Some(100);
3585
3586                    if chain != Chain::Unknown {
3587                        // max_auth_gas is 0.00002 IOTA in testnet and mainnet.
3588                        cfg.max_auth_gas = Some(20_000);
3589                    }
3590
3591                    if chain != Chain::Mainnet {
3592                        // Enable Move-based sponsor account authentication in testnet.
3593                        cfg.feature_flags.enable_move_authentication_for_sponsor = true;
3594                        // Only sponsor Move authentication is performed pre-consensus in testnet.
3595                        cfg.feature_flags
3596                            .pre_consensus_sponsor_only_move_authentication = true;
3597                    }
3598                }
3599                29 => {
3600                    // Keep advancing the random beacon DKG state machine on every commit
3601                    // while it is still pending so DKG resolves from persisted state
3602                    // (completing, or failing once the timeout round passes) even with no
3603                    // fresh inbound traffic -- e.g. after a validator restart -- instead of
3604                    // staying pending forever and blocking epoch close.
3605                    cfg.feature_flags.always_advance_dkg_to_resolution = true;
3606
3607                    // Enable median-based commit timestamp calculation in consensus and
3608                    // enforce checkpoint timestamp monotonicity for mainnet.
3609                    cfg.feature_flags
3610                        .consensus_median_timestamp_with_checkpoint_enforcement = true;
3611
3612                    // Enable fast commit syncer for faster recovery on all networks.
3613                    cfg.feature_flags.consensus_fast_commit_sync = true;
3614                    // Enable consensus block restrictions on all networks to bound
3615                    // header size by committee size and garbage-collect the block
3616                    // manager.
3617                    cfg.feature_flags.consensus_block_restrictions = true;
3618                }
3619                30 => {
3620                    // Extend the protocol_config framework module with
3621                    // `get_attr<T>`, a generic native that lets Move code
3622                    // read any numeric or boolean protocol parameter by name,
3623                    // returning T directly and aborting on error.
3624                    // Also expose `is_feature_enabled` and `get_attr<T>` to
3625                    // iota_system via a new iota_system::protocol_config
3626                    // module.
3627                }
3628                31 => {
3629                    cfg.feature_flags.validator_metadata_verify_v2 = true;
3630
3631                    if chain != Chain::Mainnet && chain != Chain::Testnet {
3632                        // Amortize the minimum checkpoint interval over a sliding
3633                        // window so the checkpoint rate holds at the ceiling.
3634                        cfg.checkpoint_rate_window_size = Some(20);
3635                        // Publish package metadata with the module metadata stored as a
3636                        // dynamic field.
3637                        cfg.feature_flags
3638                            .package_metadata_with_dynamic_module_metadata = true;
3639                        // Enable the optimistic commit rule (StarfishSpeed) in
3640                        // Starfish consensus.
3641                        cfg.feature_flags.consensus_starfish_speed = true;
3642                    }
3643
3644                    cfg.feature_flags.report_move_authentication_error = true;
3645                }
3646                32 => {
3647                    // Identical to the genesis SystemParametersV1 values on
3648                    // all existing networks; enforcement moves from on-chain
3649                    // state to the protocol config.
3650                    cfg.min_validator_count = Some(4);
3651                    cfg.max_validator_count = Some(150);
3652                    cfg.min_validator_joining_stake = Some(2_000_000_000_000_000);
3653                    cfg.validator_low_stake_threshold = Some(1_500_000_000_000_000);
3654                    cfg.validator_very_low_stake_threshold = Some(1_000_000_000_000_000);
3655                    cfg.validator_low_stake_grace_period = Some(7);
3656
3657                    // Enable Move-based sponsor account authentication in mainnet.
3658                    cfg.feature_flags.enable_move_authentication_for_sponsor = true;
3659                    // Only sponsor Move authentication is performed pre-consensus in mainnet.
3660                    cfg.feature_flags
3661                        .pre_consensus_sponsor_only_move_authentication = true;
3662
3663                    if chain != Chain::Mainnet {
3664                        // Enable the optimistic commit rule (StarfishSpeed) in
3665                        // Starfish consensus.
3666                        cfg.feature_flags.consensus_starfish_speed = true;
3667                        // Amortize the minimum checkpoint interval over a sliding
3668                        // window so the checkpoint rate holds at the ceiling.
3669                        cfg.checkpoint_rate_window_size = Some(20);
3670                        // Publish package metadata with the module metadata stored as a
3671                        // dynamic field.
3672                        cfg.feature_flags
3673                            .package_metadata_with_dynamic_module_metadata = true;
3674                    }
3675
3676                    if chain != Chain::Mainnet && chain != Chain::Testnet {
3677                        // Enable the redesigned leader schedule: sliding-window
3678                        // reputation scoring and absolute-score bad-node
3679                        // selection.
3680                        cfg.feature_flags
3681                            .consensus_enable_sliding_window_leader_schedule = true;
3682                        cfg.feature_flags
3683                            .consensus_enable_absolute_score_leader_schedule = true;
3684                        // Enable the P-COOL flow: transactions skip
3685                        // pre-consensus certification and owned-object locking,
3686                        // and conflicts are resolved after consensus.
3687                        cfg.feature_flags.enable_pcool_flow = true;
3688                    }
3689                }
3690                33 => {
3691                    // Amortize the minimum checkpoint interval over a sliding
3692                    // window so the checkpoint rate holds at the ceiling.
3693                    cfg.checkpoint_rate_window_size = Some(20);
3694                    // Enable the redesigned leader schedule: sliding-window
3695                    // reputation scoring and absolute-score bad-node
3696                    // selection.
3697                    if chain != Chain::Mainnet {
3698                        cfg.feature_flags
3699                            .consensus_enable_sliding_window_leader_schedule = true;
3700                        cfg.feature_flags
3701                            .consensus_enable_absolute_score_leader_schedule = true;
3702                    }
3703                }
3704                34 => {
3705                    if chain != Chain::Testnet && chain != Chain::Mainnet {
3706                        // Misbehavior reports carry a dedicated counter for
3707                        // invalid bundle parts, previously folded into the
3708                        // unprovable block-fault counter.
3709                        cfg.scorer_version = Some(2);
3710                    }
3711                    // Stop locking immutable objects in post-consensus conflict
3712                    // resolution. Set on all chains; inert where the P-COOL flow
3713                    // is off.
3714                    cfg.feature_flags.pcool_skip_immutable_object_locks = true;
3715
3716                    if chain == Chain::Mainnet {
3717                        // Disable Move-based sponsor account authentication.
3718                        cfg.feature_flags.enable_move_authentication_for_sponsor = false;
3719                        // The pre-consensus sponsor-only flag requires
3720                        // `enable_move_authentication_for_sponsor`, so clear it too.
3721                        cfg.feature_flags
3722                            .pre_consensus_sponsor_only_move_authentication = false;
3723                    }
3724                }
3725                35 => {
3726                    // Scale the PTB value size limit by the value's type.
3727                    cfg.feature_flags.max_ptb_value_size_v2 = true;
3728                    // Let system objects grow past the per-object size bound.
3729                    cfg.feature_flags.allow_unbounded_system_objects = true;
3730
3731                    // Enable the optimistic commit rule (StarfishSpeed) in
3732                    // Starfish consensus.
3733                    cfg.feature_flags.consensus_starfish_speed = true;
3734
3735                    // Post-consensus validation meters published packages with
3736                    // the limits below instead of each validator's own
3737                    // `VerifierSigningConfig`. The values are that config's
3738                    // defaults, so a validator that leaves it alone reaches
3739                    // the same result at admission and post-consensus. Set on
3740                    // all chains; inert where the P-COOL flow is off.
3741                    cfg.max_verifier_meter_ticks_per_function = Some(2_200_000);
3742                    cfg.max_meter_ticks_per_module = Some(2_200_000);
3743                    cfg.max_meter_ticks_per_package = Some(2_200_000);
3744                    cfg.max_meter_ticks_regex_reference_safety = Some(2_200_000);
3745                    cfg.feature_flags.pcool_verifier_limits_from_protocol_config = true;
3746                    // Publish package metadata with the module metadata stored as a
3747                    // dynamic field.
3748                    cfg.feature_flags
3749                        .package_metadata_with_dynamic_module_metadata = true;
3750                    // Enable the redesigned leader schedule: sliding-window
3751                    // reputation scoring and absolute-score bad-node
3752                    // selection.
3753                    cfg.feature_flags
3754                        .consensus_enable_sliding_window_leader_schedule = true;
3755                    cfg.feature_flags
3756                        .consensus_enable_absolute_score_leader_schedule = true;
3757
3758                    // Enable Move-based sponsor account authentication on all
3759                    // networks.
3760                    cfg.feature_flags.enable_move_authentication_for_sponsor = true;
3761                    // Run every `MoveAuthenticator` pre-consensus again, not
3762                    // just the sponsor's, on all networks.
3763                    cfg.feature_flags
3764                        .pre_consensus_sponsor_only_move_authentication = false;
3765                }
3766                36 => {
3767                    // No immutable account object can authenticate a sender or
3768                    // a sponsor.
3769                    cfg.feature_flags.reject_immutable_account_objects = true;
3770                }
3771                37 => {
3772                    // Refuse object versions in, or right below, the range
3773                    // assigned to canceled transactions before any object is
3774                    // loaded, by consulting the transaction bytes only.
3775                    cfg.feature_flags.validate_input_object_versions = true;
3776                    cfg.feature_flags.disallow_self_identifier = true;
3777                    cfg.max_move_enum_variants = Some(move_core_types::VARIANT_COUNT_MAX);
3778                    // Apply the package deny list to the package that holds a
3779                    // `MoveAuthenticator`'s authenticate function.
3780                    cfg.feature_flags.deny_authenticator_packages = true;
3781                    // Require a published module header to carry the canonical
3782                    // encoding of its binary format version.
3783                    cfg.feature_flags.check_canonical_module_version_header = true;
3784                    // An authenticate function cannot read randomness, so the
3785                    // randomness state object is refused as an authenticator
3786                    // input instead of scheduling the transaction as
3787                    // randomness-using for nothing.
3788                    cfg.feature_flags.disallow_randomness_in_move_authenticator = true;
3789                    // Traverse the module graph when checking for cyclic
3790                    // dependencies.
3791                    cfg.feature_flags.check_cyclic_dependencies = true;
3792                }
3793                38 => {
3794                    // A system package is published by the network, not by a
3795                    // user, so the user-package bound was never meant to apply
3796                    // to it: an existing system package is already exempt when
3797                    // it is upgraded at an epoch change, and only a first
3798                    // publish (genesis, or a newly added system package) is
3799                    // checked against it.
3800                    cfg.max_move_system_package_size = Some(200 * 1024);
3801                    // An immutable account object cannot authenticate anything
3802                    // since version 36, so stop creating new ones.
3803                    cfg.feature_flags.reject_immutable_account_creation = true;
3804
3805                    cfg.feature_flags.validate_ptb_argument_indices = true;
3806                }
3807                39 => {
3808                    // Keep random beacon DKG running after its timeout round, so
3809                    // randomness is enabled again mid-epoch if DKG completes late.
3810                    if chain != Chain::Mainnet {
3811                        cfg.feature_flags.allow_dkg_completion_after_timeout = true;
3812                    }
3813                    cfg.feature_flags.consensus_dedup_only_recorded_messages = true;
3814
3815                    // Raise the minimum validator joining stake to 6M IOTA, the low
3816                    // stake threshold to 5.5M IOTA and the very low stake threshold to
3817                    // 5M IOTA on all chains.
3818                    cfg.min_validator_joining_stake = Some(6_000_000_000_000_000);
3819                    cfg.validator_low_stake_threshold = Some(5_500_000_000_000_000);
3820                    cfg.validator_very_low_stake_threshold = Some(5_000_000_000_000_000);
3821
3822                    // Reject a multisig whose committee mixes Ed25519 with other key
3823                    // schemes unless every committee member has signed.
3824                    cfg.feature_flags
3825                        .reject_partially_signed_mixed_ed25519_multisig = true;
3826
3827                    if chain != Chain::Mainnet && chain != Chain::Testnet {
3828                        // Post-consensus validation reads object state as of
3829                        // 4 commits below the one it validates.
3830                        cfg.pcool_deterministic_validation_horizon_distance = Some(4);
3831                        // Mirror the governed deny rules into the on-chain
3832                        // object in chunks of at most 1000 entries.
3833                        cfg.deny_rule_update_max_entries_per_tx = Some(1000);
3834                    }
3835
3836                    // Reject Groth16 verifying keys whose size does not match the
3837                    // number of public inputs before deserializing them.
3838                    cfg.feature_flags.limit_groth16_pvk_inputs = true;
3839                    cfg.feature_flags.check_groth16_pvk_length = true;
3840
3841                    // At execution too, not only at signing: reject the
3842                    // deprecated global storage instructions and non-empty
3843                    // `acquires` lists when deserializing a module, and verify
3844                    // modules without the acquires pass and with vector element
3845                    // borrows checked by the call rule.
3846                    cfg.feature_flags.deprecate_global_storage_ops = true;
3847                }
3848                40 => {
3849                    // Post-consensus validation meters the instantiation-loop
3850                    // check and caps its graph with these values, which signing
3851                    // also uses.
3852                    cfg.feature_flags.meter_instantiation_loops = true;
3853                    cfg.max_instantiation_loop_graph_edges = Some(100_000);
3854
3855                    // Make the packages named by a `MoveAuthenticator`'s type
3856                    // arguments inputs of that authenticator.
3857                    cfg.feature_flags
3858                        .move_authenticator_type_arg_packages_as_inputs = true;
3859
3860                    // Limit the struct, enum and vector values in Move-call
3861                    // arguments.
3862                    cfg.max_move_call_argument_nodes = Some(2_097_152);
3863                    cfg.max_move_call_argument_nodes_total = Some(16_777_216);
3864
3865                    // Reject `<SELF>` as an identifier in transactions, at
3866                    // signing, after consensus and in block verification.
3867                    cfg.feature_flags.disallow_self_identifier_in_transactions = true;
3868                }
3869                // Use this template when making changes:
3870                //
3871                //     // modify an existing constant.
3872                //     move_binary_format_version: Some(7),
3873                //
3874                //     // Add a new constant (which is set to None in prior versions).
3875                //     new_constant: Some(new_value),
3876                //
3877                //     // Remove a constant (ensure that it is never accessed during this version).
3878                //     max_move_object_size: None,
3879                _ => panic!("unsupported version {version:?}"),
3880            }
3881        }
3882        cfg
3883    }
3884
3885    // Extract the bytecode verifier config from this protocol config.
3886    // If used during signing, `signing_limits` should be set.
3887    // The third limit configures`sanity_check_with_regex_reference_safety`,
3888    // which runs the new regex-based reference safety check to check that it is
3889    // strictly more permissive than the current implementation.
3890    pub fn verifier_config(&self, signing_limits: Option<(usize, usize, usize)>) -> VerifierConfig {
3891        let (
3892            max_back_edges_per_function,
3893            max_back_edges_per_module,
3894            sanity_check_with_regex_reference_safety,
3895        ) = if let Some((
3896            max_back_edges_per_function,
3897            max_back_edges_per_module,
3898            sanity_check_with_regex_reference_safety,
3899        )) = signing_limits
3900        {
3901            (
3902                Some(max_back_edges_per_function),
3903                Some(max_back_edges_per_module),
3904                Some(sanity_check_with_regex_reference_safety),
3905            )
3906        } else {
3907            (None, None, None)
3908        };
3909
3910        let additional_borrow_checks = if signing_limits.is_some() {
3911            // Always apply additional borrow checks during signing regardless of
3912            // protocol version, to prevent accepting potentially unsafe bytecode.
3913            true
3914        } else {
3915            self.additional_borrow_checks()
3916        };
3917        let deprecate_global_storage_ops = if signing_limits.is_some() {
3918            // Always on during signing, regardless of protocol version: reject
3919            // the deprecated global storage instructions, skip the acquires
3920            // pass and check vector element borrows with the call rule.
3921            true
3922        } else {
3923            self.deprecate_global_storage_ops()
3924        };
3925
3926        // Far above the largest instantiation-loop graph in the system packages
3927        // and examples.
3928        const MAX_INSTANTIATION_LOOP_GRAPH_EDGES_AT_SIGNING: usize = 100_000;
3929
3930        // Applied with the signing limits only: execution verifies without a
3931        // meter. Both fail with PROGRAM_TOO_COMPLEX, which signing rejects.
3932        // Post-consensus validation takes them from the protocol config, see
3933        // `post_consensus_verifier_config`.
3934        let (meter_instantiation_loops, max_instantiation_loop_graph_edges) =
3935            if signing_limits.is_some() {
3936                (true, Some(MAX_INSTANTIATION_LOOP_GRAPH_EDGES_AT_SIGNING))
3937            } else {
3938                (false, None)
3939            };
3940
3941        VerifierConfig {
3942            max_loop_depth: Some(self.max_loop_depth() as usize),
3943            max_generic_instantiation_length: Some(self.max_generic_instantiation_length() as usize),
3944            max_function_parameters: Some(self.max_function_parameters() as usize),
3945            max_basic_blocks: Some(self.max_basic_blocks() as usize),
3946            max_value_stack_size: self.max_value_stack_size() as usize,
3947            max_type_nodes: Some(self.max_type_nodes() as usize),
3948            max_push_size: Some(self.max_push_size() as usize),
3949            max_dependency_depth: Some(self.max_dependency_depth() as usize),
3950            max_fields_in_struct: Some(self.max_fields_in_struct() as usize),
3951            max_function_definitions: Some(self.max_function_definitions() as usize),
3952            max_data_definitions: Some(self.max_struct_definitions() as usize),
3953            max_constant_vector_len: Some(self.max_move_vector_len()),
3954            max_back_edges_per_function,
3955            max_back_edges_per_module,
3956            max_basic_blocks_in_script: None,
3957            max_identifier_len: self.max_move_identifier_len_as_option(), /* Before protocol
3958                                                                           * version 9, there was
3959                                                                           * no limit */
3960            disallow_self_identifier: self.feature_flags.disallow_self_identifier,
3961            bytecode_version: self.move_binary_format_version(),
3962            max_variants_in_enum: self.max_move_enum_variants_as_option(),
3963            additional_borrow_checks,
3964            sanity_check_with_regex_reference_safety: sanity_check_with_regex_reference_safety
3965                .map(|limit| limit as u128),
3966            check_cyclic_dependencies: self.feature_flags.check_cyclic_dependencies,
3967            meter_instantiation_loops,
3968            max_instantiation_loop_graph_edges,
3969            deprecate_global_storage_ops,
3970        }
3971    }
3972
3973    /// The bytecode verifier config for post-consensus validation: the
3974    /// protocol's sign-time limits, with `deprecate_global_storage_ops`, the
3975    /// instantiation-loop graph edge limit and the metering of that check
3976    /// taken from the protocol config rather than set as at signing.
3977    ///
3978    /// # Panics
3979    ///
3980    /// Panics before protocol version 35, which has no
3981    /// `max_meter_ticks_regex_reference_safety`.
3982    pub fn post_consensus_verifier_config(&self) -> VerifierConfig {
3983        // Before protocol version 40, the check is metered and capped at
3984        // 100,000 edges, the values signing used then.
3985        let (meter_instantiation_loops, max_instantiation_loop_graph_edges) =
3986            if self.version < ProtocolVersion::new(40) {
3987                (true, Some(100_000))
3988            } else {
3989                (
3990                    self.meter_instantiation_loops(),
3991                    self.max_instantiation_loop_graph_edges_as_option()
3992                        .map(|edges| edges as usize),
3993                )
3994            };
3995        VerifierConfig {
3996            deprecate_global_storage_ops: self.deprecate_global_storage_ops(),
3997            meter_instantiation_loops,
3998            max_instantiation_loop_graph_edges,
3999            ..self.verifier_config(Some(self.verifier_signing_limits()))
4000        }
4001    }
4002
4003    /// The sign-time verifier limits as protocol parameters, in the shape
4004    /// `verifier_config` takes: back edges per function, back edges per module,
4005    /// and the meter limit of the regex-based reference safety check.
4006    /// `VerifierSigningConfig::limits_for_signing` is the validator-local
4007    /// counterpart. Defined from protocol version 35, which sets
4008    /// `max_meter_ticks_regex_reference_safety`.
4009    pub fn verifier_signing_limits(&self) -> (usize, usize, usize) {
4010        (
4011            self.max_back_edges_per_function() as usize,
4012            self.max_back_edges_per_module() as usize,
4013            self.max_meter_ticks_regex_reference_safety() as usize,
4014        )
4015    }
4016
4017    /// The meter limits for verifying the packages a transaction publishes, as
4018    /// protocol parameters. `VerifierSigningConfig::meter_config_for_signing`
4019    /// is the validator-local counterpart.
4020    pub fn meter_config(&self) -> MeterConfig {
4021        MeterConfig {
4022            max_per_fun_meter_units: Some(self.max_verifier_meter_ticks_per_function() as u128),
4023            max_per_mod_meter_units: Some(self.max_meter_ticks_per_module() as u128),
4024            max_per_pkg_meter_units: Some(self.max_meter_ticks_per_package() as u128),
4025        }
4026    }
4027
4028    /// Override one or more settings in the config, for testing.
4029    /// This must be called at the beginning of the test, before
4030    /// get_for_(min|max)_version is called, since those functions cache
4031    /// their return value.
4032    pub fn apply_overrides_for_testing(
4033        override_fn: impl Fn(ProtocolVersion, Self) -> Self + Send + Sync + 'static,
4034    ) -> OverrideGuard {
4035        CONFIG_OVERRIDE.with(|ovr| {
4036            let mut cur = ovr.borrow_mut();
4037            assert!(cur.is_none(), "config override already present");
4038            *cur = Some(Box::new(override_fn));
4039            OverrideGuard
4040        })
4041    }
4042}
4043
4044// Setters for tests.
4045// This is only needed for feature_flags. Please suffix each setter with
4046// `_for_testing`. Non-feature_flags should already have test setters defined
4047// through macros.
4048impl ProtocolConfig {
4049    pub fn set_per_object_congestion_control_mode_for_testing(
4050        &mut self,
4051        val: PerObjectCongestionControlMode,
4052    ) {
4053        self.feature_flags.per_object_congestion_control_mode = val;
4054    }
4055
4056    pub fn set_consensus_choice_for_testing(&mut self, val: ConsensusChoice) {
4057        self.feature_flags.consensus_choice = val;
4058    }
4059
4060    pub fn set_consensus_network_for_testing(&mut self, val: ConsensusNetwork) {
4061        self.feature_flags.consensus_network = val;
4062    }
4063
4064    pub fn set_passkey_auth_for_testing(&mut self, val: bool) {
4065        self.feature_flags.passkey_auth = val
4066    }
4067
4068    pub fn set_disallow_new_modules_in_deps_only_packages_for_testing(&mut self, val: bool) {
4069        self.feature_flags
4070            .disallow_new_modules_in_deps_only_packages = val;
4071    }
4072
4073    pub fn set_check_canonical_module_version_header_for_testing(&mut self, val: bool) {
4074        self.feature_flags.check_canonical_module_version_header = val;
4075    }
4076
4077    pub fn set_deprecate_global_storage_ops_for_testing(&mut self, val: bool) {
4078        self.feature_flags.deprecate_global_storage_ops = val;
4079    }
4080
4081    pub fn set_meter_instantiation_loops_for_testing(&mut self, val: bool) {
4082        self.feature_flags.meter_instantiation_loops = val;
4083    }
4084
4085    pub fn set_consensus_round_prober_for_testing(&mut self, val: bool) {
4086        self.feature_flags.consensus_round_prober = val;
4087    }
4088
4089    pub fn set_consensus_distributed_vote_scoring_strategy_for_testing(&mut self, val: bool) {
4090        self.feature_flags
4091            .consensus_distributed_vote_scoring_strategy = val;
4092    }
4093
4094    pub fn set_gc_depth_for_testing(&mut self, val: u32) {
4095        self.consensus_gc_depth = Some(val);
4096    }
4097
4098    pub fn set_consensus_linearize_subdag_v2_for_testing(&mut self, val: bool) {
4099        self.feature_flags.consensus_linearize_subdag_v2 = val;
4100    }
4101
4102    pub fn set_consensus_round_prober_probe_accepted_rounds(&mut self, val: bool) {
4103        self.feature_flags
4104            .consensus_round_prober_probe_accepted_rounds = val;
4105    }
4106
4107    pub fn set_accept_passkey_in_multisig_for_testing(&mut self, val: bool) {
4108        self.feature_flags.accept_passkey_in_multisig = val;
4109    }
4110
4111    pub fn set_consensus_smart_ancestor_selection_for_testing(&mut self, val: bool) {
4112        self.feature_flags.consensus_smart_ancestor_selection = val;
4113    }
4114
4115    pub fn set_consensus_batched_block_sync_for_testing(&mut self, val: bool) {
4116        self.feature_flags.consensus_batched_block_sync = val;
4117    }
4118
4119    pub fn set_congestion_control_min_free_execution_slot_for_testing(&mut self, val: bool) {
4120        self.feature_flags
4121            .congestion_control_min_free_execution_slot = val;
4122    }
4123
4124    pub fn set_congestion_control_gas_price_feedback_mechanism_for_testing(&mut self, val: bool) {
4125        self.feature_flags
4126            .congestion_control_gas_price_feedback_mechanism = val;
4127    }
4128
4129    pub fn set_select_committee_from_eligible_validators_for_testing(&mut self, val: bool) {
4130        self.feature_flags.select_committee_from_eligible_validators = val;
4131    }
4132
4133    pub fn set_track_non_committee_eligible_validators_for_testing(&mut self, val: bool) {
4134        self.feature_flags.track_non_committee_eligible_validators = val;
4135    }
4136
4137    pub fn set_select_committee_supporting_next_epoch_version(&mut self, val: bool) {
4138        self.feature_flags
4139            .select_committee_supporting_next_epoch_version = val;
4140    }
4141
4142    pub fn set_consensus_median_timestamp_with_checkpoint_enforcement_for_testing(
4143        &mut self,
4144        val: bool,
4145    ) {
4146        self.feature_flags
4147            .consensus_median_timestamp_with_checkpoint_enforcement = val;
4148    }
4149
4150    pub fn set_consensus_commit_transactions_only_for_traversed_headers_for_testing(
4151        &mut self,
4152        val: bool,
4153    ) {
4154        self.feature_flags
4155            .consensus_commit_transactions_only_for_traversed_headers = val;
4156    }
4157
4158    pub fn set_congestion_limit_overshoot_in_gas_price_feedback_mechanism_for_testing(
4159        &mut self,
4160        val: bool,
4161    ) {
4162        self.feature_flags
4163            .congestion_limit_overshoot_in_gas_price_feedback_mechanism = val;
4164    }
4165
4166    pub fn set_separate_gas_price_feedback_mechanism_for_randomness_for_testing(
4167        &mut self,
4168        val: bool,
4169    ) {
4170        self.feature_flags
4171            .separate_gas_price_feedback_mechanism_for_randomness = val;
4172    }
4173
4174    pub fn set_metadata_in_module_bytes_for_testing(&mut self, val: bool) {
4175        self.feature_flags.metadata_in_module_bytes = val;
4176    }
4177
4178    pub fn set_publish_package_metadata_for_testing(&mut self, val: bool) {
4179        self.feature_flags.publish_package_metadata = val;
4180    }
4181
4182    pub fn set_enable_move_authentication_for_testing(&mut self, val: bool) {
4183        self.feature_flags.enable_move_authentication = val;
4184    }
4185
4186    pub fn set_enable_move_authentication_for_sponsor_for_testing(&mut self, val: bool) {
4187        self.feature_flags.enable_move_authentication_for_sponsor = val;
4188    }
4189
4190    pub fn set_consensus_fast_commit_sync_for_testing(&mut self, val: bool) {
4191        self.feature_flags.consensus_fast_commit_sync = val;
4192    }
4193
4194    pub fn set_consensus_block_restrictions_for_testing(&mut self, val: bool) {
4195        self.feature_flags.consensus_block_restrictions = val;
4196    }
4197
4198    pub fn set_pre_consensus_sponsor_only_move_authentication_for_testing(&mut self, val: bool) {
4199        self.feature_flags
4200            .pre_consensus_sponsor_only_move_authentication = val;
4201    }
4202
4203    pub fn set_consensus_starfish_speed_for_testing(&mut self, val: bool) {
4204        self.feature_flags.consensus_starfish_speed = val;
4205    }
4206
4207    pub fn set_always_advance_dkg_to_resolution_for_testing(&mut self, val: bool) {
4208        self.feature_flags.always_advance_dkg_to_resolution = val;
4209    }
4210
4211    /// Turning the flow on also turns on the flags it requires, turns off
4212    /// `pre_consensus_sponsor_only_move_authentication`, which it excludes, and
4213    /// fills in the settings it requires when unset, whatever the version.
4214    pub fn set_enable_pcool_flow_for_testing(&mut self, val: bool) {
4215        self.feature_flags.enable_pcool_flow = val;
4216        if val {
4217            self.feature_flags
4218                .pre_consensus_sponsor_only_move_authentication = false;
4219            // Post-consensus validation reads this budget; versions before 35
4220            // leave it unset.
4221            self.max_meter_ticks_regex_reference_safety
4222                .get_or_insert(2_200_000);
4223            self.feature_flags.consensus_dedup_only_recorded_messages = true;
4224            self.pcool_deterministic_validation_horizon_distance
4225                .get_or_insert(4);
4226            self.deny_rule_update_max_entries_per_tx.get_or_insert(1000);
4227        }
4228    }
4229
4230    pub fn set_reject_immutable_account_objects_for_testing(&mut self, val: bool) {
4231        self.feature_flags.reject_immutable_account_objects = val;
4232    }
4233
4234    pub fn set_reject_immutable_account_creation_for_testing(&mut self, val: bool) {
4235        self.feature_flags.reject_immutable_account_creation = val;
4236    }
4237
4238    pub fn set_validate_input_object_versions_for_testing(&mut self, val: bool) {
4239        self.feature_flags.validate_input_object_versions = val;
4240    }
4241
4242    pub fn set_disallow_randomness_in_move_authenticator_for_testing(&mut self, val: bool) {
4243        self.feature_flags.disallow_randomness_in_move_authenticator = val;
4244    }
4245
4246    pub fn set_move_authenticator_type_arg_packages_as_inputs_for_testing(&mut self, val: bool) {
4247        self.feature_flags
4248            .move_authenticator_type_arg_packages_as_inputs = val;
4249    }
4250
4251    pub fn set_disallow_self_identifier_in_transactions_for_testing(&mut self, val: bool) {
4252        self.feature_flags.disallow_self_identifier_in_transactions = val;
4253    }
4254
4255    pub fn set_commits_per_schedule_for_testing(&mut self, val: u32) {
4256        self.consensus_commits_per_schedule = Some(val);
4257    }
4258
4259    pub fn set_deny_authenticator_packages_for_testing(&mut self, val: bool) {
4260        self.feature_flags.deny_authenticator_packages = val;
4261    }
4262
4263    /// Keeps the config consistent with the getters that assert on this flag:
4264    /// enabling fills in `scorer_version` when unset, disabling also switches
4265    /// off `adjust_rewards_by_score` and
4266    /// `pass_calculated_validator_scores_to_advance_epoch`.
4267    pub fn set_calculate_validator_scores_for_testing(&mut self, val: bool) {
4268        self.feature_flags.calculate_validator_scores = val;
4269        if val {
4270            self.scorer_version.get_or_insert(1);
4271        } else {
4272            self.feature_flags.adjust_rewards_by_score = false;
4273            self.feature_flags
4274                .pass_calculated_validator_scores_to_advance_epoch = false;
4275        }
4276    }
4277
4278    pub fn set_package_metadata_with_dynamic_module_metadata_for_testing(&mut self, val: bool) {
4279        self.feature_flags
4280            .package_metadata_with_dynamic_module_metadata = val;
4281    }
4282
4283    pub fn set_report_move_authentication_error_for_testing(&mut self, val: bool) {
4284        self.feature_flags.report_move_authentication_error = val;
4285    }
4286
4287    pub fn set_leader_schedule_window_size_for_testing(&mut self, val: u32) {
4288        self.consensus_leader_schedule_window_size = Some(val);
4289    }
4290
4291    pub fn set_consensus_enable_sliding_window_leader_schedule_for_testing(&mut self, val: bool) {
4292        self.feature_flags
4293            .consensus_enable_sliding_window_leader_schedule = val;
4294    }
4295
4296    pub fn set_consensus_enable_absolute_score_leader_schedule_for_testing(&mut self, val: bool) {
4297        self.feature_flags
4298            .consensus_enable_absolute_score_leader_schedule = val;
4299    }
4300
4301    pub fn set_allow_dkg_completion_after_timeout_for_testing(&mut self, val: bool) {
4302        self.feature_flags.allow_dkg_completion_after_timeout = val;
4303    }
4304
4305    /// Turning the flag off also turns off `enable_pcool_flow`, which requires
4306    /// it.
4307    pub fn set_consensus_dedup_only_recorded_messages_for_testing(&mut self, val: bool) {
4308        self.feature_flags.consensus_dedup_only_recorded_messages = val;
4309        if !val {
4310            self.feature_flags.enable_pcool_flow = false;
4311        }
4312    }
4313}
4314
4315type OverrideFn = dyn Fn(ProtocolVersion, ProtocolConfig) -> ProtocolConfig + Send + Sync;
4316
4317thread_local! {
4318    static CONFIG_OVERRIDE: RefCell<Option<Box<OverrideFn>>> = const { RefCell::new(None) };
4319}
4320
4321#[must_use]
4322pub struct OverrideGuard;
4323
4324impl Drop for OverrideGuard {
4325    fn drop(&mut self) {
4326        info!("restoring override fn");
4327        CONFIG_OVERRIDE.with(|ovr| {
4328            *ovr.borrow_mut() = None;
4329        });
4330    }
4331}
4332
4333/// Defines which limit got crossed.
4334/// The value which crossed the limit and value of the limit crossed are
4335/// embedded
4336#[derive(PartialEq, Eq)]
4337pub enum LimitThresholdCrossed {
4338    None,
4339    Soft(u128, u128),
4340    Hard(u128, u128),
4341}
4342
4343/// Convenience function for comparing limit ranges
4344/// V::MAX must be at >= U::MAX and T::MAX
4345pub fn check_limit_in_range<T: Into<V>, U: Into<V>, V: PartialOrd + Into<u128>>(
4346    x: T,
4347    soft_limit: U,
4348    hard_limit: V,
4349) -> LimitThresholdCrossed {
4350    let x: V = x.into();
4351    let soft_limit: V = soft_limit.into();
4352
4353    debug_assert!(soft_limit <= hard_limit);
4354
4355    // It is important to preserve this comparison order because if soft_limit ==
4356    // hard_limit we want LimitThresholdCrossed::Hard
4357    if x >= hard_limit {
4358        LimitThresholdCrossed::Hard(x.into(), hard_limit.into())
4359    } else if x < soft_limit {
4360        LimitThresholdCrossed::None
4361    } else {
4362        LimitThresholdCrossed::Soft(x.into(), soft_limit.into())
4363    }
4364}
4365
4366#[macro_export]
4367macro_rules! check_limit {
4368    ($x:expr, $hard:expr) => {
4369        check_limit!($x, $hard, $hard)
4370    };
4371    ($x:expr, $soft:expr, $hard:expr) => {
4372        check_limit_in_range($x as u64, $soft, $hard)
4373    };
4374}
4375
4376/// Used to check which limits were crossed if the TX is metered (not system tx)
4377/// Args are: is_metered, value_to_check, metered_limit, unmetered_limit
4378/// metered_limit is always less than or equal to unmetered_hard_limit
4379#[macro_export]
4380macro_rules! check_limit_by_meter {
4381    ($is_metered:expr, $x:expr, $metered_limit:expr, $unmetered_hard_limit:expr, $metric:expr) => {{
4382        // If this is metered, we use the metered_limit limit as the upper bound
4383        let (h, metered_str) = if $is_metered {
4384            ($metered_limit, "metered")
4385        } else {
4386            // Unmetered gets more headroom
4387            ($unmetered_hard_limit, "unmetered")
4388        };
4389        use iota_protocol_config::check_limit_in_range;
4390        let result = check_limit_in_range($x as u64, $metered_limit, h);
4391        match result {
4392            LimitThresholdCrossed::None => {}
4393            LimitThresholdCrossed::Soft(_, _) => {
4394                $metric.with_label_values(&[metered_str, "soft"]).inc();
4395            }
4396            LimitThresholdCrossed::Hard(_, _) => {
4397                $metric.with_label_values(&[metered_str, "hard"]).inc();
4398            }
4399        };
4400        result
4401    }};
4402}
4403
4404#[cfg(all(test, not(msim)))]
4405mod test {
4406    use insta::assert_yaml_snapshot;
4407
4408    use super::*;
4409
4410    #[test]
4411    fn snapshot_tests() {
4412        println!("\n============================================================================");
4413        println!("!                                                                          !");
4414        println!("! IMPORTANT: never update snapshots from this test. only add new versions! !");
4415        println!("!                                                                          !");
4416        println!("============================================================================\n");
4417        for chain_id in &[Chain::Unknown, Chain::Mainnet, Chain::Testnet] {
4418            // make Chain::Unknown snapshots compatible with pre-chain-id snapshots so that
4419            // we don't break the release-time compatibility tests. Once Chain
4420            // Id configs have been released everywhere, we can remove this and
4421            // only test Mainnet and Testnet
4422            let chain_str = match chain_id {
4423                Chain::Unknown => "".to_string(),
4424                _ => format!("{chain_id:?}_"),
4425            };
4426            for i in MIN_PROTOCOL_VERSION..=MAX_PROTOCOL_VERSION {
4427                let cur = ProtocolVersion::new(i);
4428                assert_yaml_snapshot!(
4429                    format!("{}version_{}", chain_str, cur.as_u64()),
4430                    ProtocolConfig::get_for_version(cur, *chain_id)
4431                );
4432            }
4433        }
4434    }
4435
4436    #[test]
4437    fn test_getters() {
4438        let prot: ProtocolConfig =
4439            ProtocolConfig::get_for_version(ProtocolVersion::new(1), Chain::Unknown);
4440        assert_eq!(
4441            prot.max_arguments(),
4442            prot.max_arguments_as_option().unwrap()
4443        );
4444    }
4445
4446    #[test]
4447    fn only_signing_bounds_the_instantiation_loop_checker() {
4448        let prot = ProtocolConfig::get_for_max_version_UNSAFE();
4449
4450        let signing = prot.verifier_config(Some((0, 0, 0)));
4451        assert!(signing.max_instantiation_loop_graph_edges.is_some());
4452        assert!(signing.meter_instantiation_loops);
4453
4454        let execution = prot.verifier_config(None);
4455        assert_eq!(execution.max_instantiation_loop_graph_edges, None);
4456        assert!(!execution.meter_instantiation_loops);
4457    }
4458
4459    #[test]
4460    fn post_consensus_verifier_config_follows_deprecate_global_storage_ops() {
4461        let mut prot = ProtocolConfig::get_for_max_version_UNSAFE();
4462        prot.set_deprecate_global_storage_ops_for_testing(false);
4463
4464        assert!(
4465            prot.verifier_config(Some((0, 0, 0)))
4466                .deprecate_global_storage_ops
4467        );
4468        let post_consensus = prot.post_consensus_verifier_config();
4469        assert!(!post_consensus.deprecate_global_storage_ops);
4470        assert_eq!(
4471            post_consensus.max_back_edges_per_function,
4472            Some(prot.max_back_edges_per_function() as usize)
4473        );
4474
4475        prot.set_deprecate_global_storage_ops_for_testing(true);
4476        assert!(
4477            prot.post_consensus_verifier_config()
4478                .deprecate_global_storage_ops
4479        );
4480    }
4481
4482    #[test]
4483    fn post_consensus_verifier_config_bounds_the_instantiation_loop_checker() {
4484        let before = ProtocolConfig::get_for_version(ProtocolVersion::new(39), Chain::Unknown);
4485        let config = before.post_consensus_verifier_config();
4486        assert!(config.meter_instantiation_loops);
4487        assert_eq!(config.max_instantiation_loop_graph_edges, Some(100_000));
4488
4489        let mut prot = ProtocolConfig::get_for_version(ProtocolVersion::new(40), Chain::Unknown);
4490        prot.set_max_instantiation_loop_graph_edges_for_testing(7);
4491        prot.set_meter_instantiation_loops_for_testing(false);
4492        let config = prot.post_consensus_verifier_config();
4493        assert!(!config.meter_instantiation_loops);
4494        assert_eq!(config.max_instantiation_loop_graph_edges, Some(7));
4495
4496        // The node's signing config keeps its own values.
4497        let signing = prot.verifier_config(Some((0, 0, 0)));
4498        assert!(signing.meter_instantiation_loops);
4499        assert_eq!(signing.max_instantiation_loop_graph_edges, Some(100_000));
4500    }
4501
4502    #[test]
4503    fn signing_and_post_consensus_instantiation_loop_limits_match() {
4504        let prot = ProtocolConfig::get_for_max_version_UNSAFE();
4505        let signing = prot.verifier_config(Some(prot.verifier_signing_limits()));
4506        let post_consensus = prot.post_consensus_verifier_config();
4507
4508        assert_eq!(
4509            signing.meter_instantiation_loops,
4510            post_consensus.meter_instantiation_loops
4511        );
4512        assert_eq!(
4513            signing.max_instantiation_loop_graph_edges,
4514            post_consensus.max_instantiation_loop_graph_edges
4515        );
4516    }
4517
4518    #[test]
4519    fn test_setters() {
4520        let mut prot: ProtocolConfig =
4521            ProtocolConfig::get_for_version(ProtocolVersion::new(1), Chain::Unknown);
4522        prot.set_max_arguments_for_testing(123);
4523        assert_eq!(prot.max_arguments(), 123);
4524
4525        prot.set_max_arguments_from_str_for_testing("321".to_string());
4526        assert_eq!(prot.max_arguments(), 321);
4527
4528        prot.disable_max_arguments_for_testing();
4529        assert_eq!(prot.max_arguments_as_option(), None);
4530
4531        prot.set_attr_for_testing("max_arguments".to_string(), "456".to_string());
4532        assert_eq!(prot.max_arguments(), 456);
4533    }
4534
4535    #[test]
4536    fn reject_immutable_account_creation_implies_rejecting_the_objects() {
4537        for chain in [Chain::Unknown, Chain::Mainnet, Chain::Testnet] {
4538            for version in MIN_PROTOCOL_VERSION..=MAX_PROTOCOL_VERSION {
4539                // The getter asserts the dependency on
4540                // `reject_immutable_account_objects`.
4541                ProtocolConfig::get_for_version(ProtocolVersion::new(version), chain)
4542                    .reject_immutable_account_creation();
4543            }
4544        }
4545    }
4546
4547    #[test]
4548    #[should_panic(expected = "unsupported version")]
4549    fn max_version_test() {
4550        // When this does not panic, version higher than MAX_PROTOCOL_VERSION exists.
4551        // To fix, bump MAX_PROTOCOL_VERSION or disable this check for the version.
4552        let _ = ProtocolConfig::get_for_version_impl(
4553            ProtocolVersion::new(MAX_PROTOCOL_VERSION + 1),
4554            Chain::Unknown,
4555        );
4556    }
4557
4558    #[test]
4559    fn lookup_by_string_test() {
4560        let prot: ProtocolConfig =
4561            ProtocolConfig::get_for_version(ProtocolVersion::new(1), Chain::Mainnet);
4562        // Does not exist
4563        assert!(prot.lookup_attr("some random string".to_string()).is_none());
4564
4565        assert!(
4566            prot.lookup_attr("max_arguments".to_string())
4567                == Some(ProtocolConfigValue::u32(prot.max_arguments())),
4568        );
4569
4570        // We didnt have this in version 1 on Mainnet
4571        assert!(
4572            prot.lookup_attr("poseidon_bn254_cost_base".to_string())
4573                .is_none()
4574        );
4575        assert!(
4576            prot.attr_map()
4577                .get("poseidon_bn254_cost_base")
4578                .unwrap()
4579                .is_none()
4580        );
4581
4582        // But we did in version 1 on Devnet
4583        let prot: ProtocolConfig =
4584            ProtocolConfig::get_for_version(ProtocolVersion::new(1), Chain::Unknown);
4585
4586        assert!(
4587            prot.lookup_attr("poseidon_bn254_cost_base".to_string())
4588                == Some(ProtocolConfigValue::u64(prot.poseidon_bn254_cost_base()))
4589        );
4590        assert!(
4591            prot.attr_map().get("poseidon_bn254_cost_base").unwrap()
4592                == &Some(ProtocolConfigValue::u64(prot.poseidon_bn254_cost_base()))
4593        );
4594
4595        // Check feature flags
4596        let prot: ProtocolConfig =
4597            ProtocolConfig::get_for_version(ProtocolVersion::new(1), Chain::Mainnet);
4598        // Does not exist
4599        assert!(
4600            prot.feature_flags
4601                .lookup_attr("some random string".to_owned())
4602                .is_none()
4603        );
4604        assert!(
4605            !prot
4606                .feature_flags
4607                .attr_map()
4608                .contains_key("some random string")
4609        );
4610
4611        // Was false in v1 on Mainnet
4612        assert!(prot.feature_flags.lookup_attr("enable_poseidon".to_owned()) == Some(false));
4613        assert!(
4614            prot.feature_flags
4615                .attr_map()
4616                .get("enable_poseidon")
4617                .unwrap()
4618                == &false
4619        );
4620        let prot: ProtocolConfig =
4621            ProtocolConfig::get_for_version(ProtocolVersion::new(1), Chain::Unknown);
4622        // Was true from v1 and up on Devnet
4623        assert!(prot.feature_flags.lookup_attr("enable_poseidon".to_owned()) == Some(true));
4624        assert!(
4625            prot.feature_flags
4626                .attr_map()
4627                .get("enable_poseidon")
4628                .unwrap()
4629                == &true
4630        );
4631    }
4632
4633    /// A chunk limit above the executability ceiling would fail execution on
4634    /// every validator at once, so the configuration is rejected at startup
4635    /// rather than at the flip.
4636    #[test]
4637    #[should_panic(expected = "deny_rule_update_max_entries_per_tx must be positive")]
4638    fn deny_rule_chunk_limit_above_the_ceiling_is_rejected() {
4639        let _guard = ProtocolConfig::apply_overrides_for_testing(|_, mut config| {
4640            config.set_enable_pcool_flow_for_testing(true);
4641            config.set_deny_rule_update_max_entries_per_tx_for_testing(2048 + 1);
4642            config
4643        });
4644        let _ = ProtocolConfig::get_for_version(ProtocolVersion::max(), Chain::Unknown);
4645    }
4646
4647    /// A zero chunk limit would make every delta unsplittable; the pure
4648    /// chunking function clamps it, but the configuration is still invalid.
4649    #[test]
4650    #[should_panic(expected = "deny_rule_update_max_entries_per_tx must be positive")]
4651    fn deny_rule_chunk_limit_of_zero_is_rejected() {
4652        let _guard = ProtocolConfig::apply_overrides_for_testing(|_, mut config| {
4653            config.set_enable_pcool_flow_for_testing(true);
4654            config.set_deny_rule_update_max_entries_per_tx_for_testing(0);
4655            config
4656        });
4657        let _ = ProtocolConfig::get_for_version(ProtocolVersion::max(), Chain::Unknown);
4658    }
4659
4660    /// The value the flip is expected to ship stays inside the limits.
4661    #[test]
4662    fn deny_rule_chunk_limit_within_system_tx_object_id_limit_is_accepted() {
4663        let _guard = ProtocolConfig::apply_overrides_for_testing(|_, mut config| {
4664            config.set_enable_pcool_flow_for_testing(true);
4665            config.set_deny_rule_update_max_entries_per_tx_for_testing(1000);
4666            config
4667        });
4668        let config = ProtocolConfig::get_for_version(ProtocolVersion::max(), Chain::Unknown);
4669        assert_eq!(config.deny_rule_update_max_entries_per_tx(), 1000);
4670    }
4671
4672    /// From version 39 the P-COOL flow requires the deny rule settings, which
4673    /// mirror the governed deny rules into the on-chain object.
4674    #[test]
4675    #[should_panic(expected = "enable_pcool_flow requires deny_rule_update_max_entries_per_tx")]
4676    fn pcool_flow_without_the_deny_rule_settings_is_rejected() {
4677        let _guard = ProtocolConfig::apply_overrides_for_testing(|_, mut config| {
4678            config.set_enable_pcool_flow_for_testing(true);
4679            config.disable_deny_rule_update_max_entries_per_tx_for_testing();
4680            config
4681        });
4682        let _ = ProtocolConfig::get_for_version(ProtocolVersion::new(39), Chain::Unknown);
4683    }
4684
4685    /// Devnet runs the P-COOL flow from version 32, before the settings it
4686    /// requires exist. Those versions are not checked for them.
4687    #[test]
4688    fn devnet_versions_before_39_run_the_pcool_flow_without_its_settings() {
4689        for version in 32..39 {
4690            let config =
4691                ProtocolConfig::get_for_version(ProtocolVersion::new(version), Chain::Unknown);
4692            assert!(config.enable_pcool_flow(), "version {version}");
4693            assert_eq!(
4694                config.deny_rule_update_max_entries_per_tx_as_option(),
4695                None,
4696                "version {version}"
4697            );
4698        }
4699    }
4700
4701    /// Devnet sets the horizon distance from version 39 on; Mainnet, Testnet
4702    /// and earlier versions leave it unset. An override still wins.
4703    #[test]
4704    fn horizon_distance_is_set_on_devnet_from_version_39() {
4705        let config = ProtocolConfig::get_for_version(ProtocolVersion::new(39), Chain::Unknown);
4706        assert_eq!(config.pcool_deterministic_validation_horizon_distance(), 4);
4707        for (version, chain) in [
4708            (38, Chain::Unknown),
4709            (39, Chain::Mainnet),
4710            (39, Chain::Testnet),
4711        ] {
4712            let config = ProtocolConfig::get_for_version(ProtocolVersion::new(version), chain);
4713            assert_eq!(
4714                config.pcool_deterministic_validation_horizon_distance_as_option(),
4715                None,
4716                "version {version} on {chain:?}"
4717            );
4718        }
4719
4720        let _guard = ProtocolConfig::apply_overrides_for_testing(|_, mut config| {
4721            config.set_pcool_deterministic_validation_horizon_distance_for_testing(5);
4722            config
4723        });
4724        let config = ProtocolConfig::get_for_version(ProtocolVersion::max(), Chain::Unknown);
4725        assert_eq!(config.pcool_deterministic_validation_horizon_distance(), 5);
4726    }
4727
4728    /// The P-COOL flow has no horizon distance to fall back on.
4729    #[test]
4730    #[should_panic(expected = "pcool_deterministic_validation_horizon_distance")]
4731    fn pcool_flow_without_a_horizon_distance_is_rejected() {
4732        let _guard = ProtocolConfig::apply_overrides_for_testing(|_, mut config| {
4733            config.set_enable_pcool_flow_for_testing(true);
4734            config.disable_pcool_deterministic_validation_horizon_distance_for_testing();
4735            config
4736        });
4737        let _ = ProtocolConfig::get_for_version(ProtocolVersion::max(), Chain::Unknown);
4738    }
4739
4740    /// With a horizon distance of 0, the consensus handler processing commit C
4741    /// would wait for C itself to be fully executed, which cannot happen before
4742    /// the handler finishes processing C, so the network would halt. The
4743    /// configuration is rejected at startup.
4744    #[test]
4745    #[should_panic(expected = "pcool_deterministic_validation_horizon_distance")]
4746    fn horizon_distance_of_zero_with_the_pcool_flow_is_rejected() {
4747        let _guard = ProtocolConfig::apply_overrides_for_testing(|_, mut config| {
4748            config.set_enable_pcool_flow_for_testing(true);
4749            config.set_pcool_deterministic_validation_horizon_distance_for_testing(0);
4750            config
4751        });
4752        let _ = ProtocolConfig::get_for_version(ProtocolVersion::max(), Chain::Unknown);
4753    }
4754
4755    /// Every version from 39 and chain that turns the P-COOL flow on sets a
4756    /// positive horizon distance and the verifier limits post-consensus
4757    /// validation meters published packages with.
4758    #[test]
4759    fn every_version_with_the_pcool_flow_sets_its_requirements() {
4760        for chain in [Chain::Unknown, Chain::Mainnet, Chain::Testnet] {
4761            for version in 39..=MAX_PROTOCOL_VERSION {
4762                let config = ProtocolConfig::get_for_version(ProtocolVersion::new(version), chain);
4763                if config.enable_pcool_flow() {
4764                    assert!(
4765                        config
4766                            .pcool_deterministic_validation_horizon_distance_as_option()
4767                            .is_some_and(|distance| distance > 0),
4768                        "version {version} on {chain:?} runs the P-COOL flow without a positive \
4769                         horizon distance"
4770                    );
4771                    assert!(
4772                        config
4773                            .max_meter_ticks_regex_reference_safety_as_option()
4774                            .is_some(),
4775                        "version {version} on {chain:?} runs the P-COOL flow without the \
4776                         regex reference safety budget"
4777                    );
4778                }
4779            }
4780        }
4781    }
4782
4783    /// Turning the P-COOL flow on for a test also turns on what it requires,
4784    /// as a version that turns it on must, whatever the version the test
4785    /// starts from.
4786    #[test]
4787    fn enabling_the_pcool_flow_for_testing_enables_its_requirements() {
4788        let mut config = ProtocolConfig::get_for_version(
4789            ProtocolVersion::new(MIN_PROTOCOL_VERSION),
4790            Chain::Unknown,
4791        );
4792        assert!(
4793            config
4794                .max_meter_ticks_regex_reference_safety_as_option()
4795                .is_none()
4796        );
4797        config.set_enable_pcool_flow_for_testing(true);
4798        assert!(config.enable_pcool_flow());
4799        assert_eq!(config.max_meter_ticks_regex_reference_safety(), 2_200_000);
4800        assert!(config.consensus_dedup_only_recorded_messages());
4801        assert_eq!(config.pcool_deterministic_validation_horizon_distance(), 4);
4802        assert_eq!(config.deny_rule_update_max_entries_per_tx(), 1000);
4803    }
4804
4805    /// An override that returns an older version's config for every version
4806    /// asked for, as `TestAuthorityBuilder` installs, is checked against the
4807    /// version of that config, which runs the P-COOL flow on Devnet before the
4808    /// settings it requires exist.
4809    #[test]
4810    fn an_override_returning_an_older_config_is_checked_against_its_version() {
4811        let older = ProtocolConfig::get_for_version(ProtocolVersion::new(37), Chain::Unknown);
4812        assert!(older.enable_pcool_flow());
4813        assert!(!older.consensus_dedup_only_recorded_messages());
4814        let _guard = ProtocolConfig::apply_overrides_for_testing(move |_, _| older.clone());
4815        let config = ProtocolConfig::get_for_version(ProtocolVersion::max(), Chain::Unknown);
4816        assert_eq!(config.version, ProtocolVersion::new(37));
4817    }
4818
4819    /// Without `consensus_dedup_only_recorded_messages` the consensus handler
4820    /// could skip a message as a duplicate of one only some validators saw
4821    /// dropped, so the combination is rejected at startup.
4822    #[test]
4823    #[should_panic(expected = "enable_pcool_flow requires consensus_dedup_only_recorded_messages")]
4824    fn pcool_flow_without_dedup_of_recorded_messages_is_rejected() {
4825        let _guard = ProtocolConfig::apply_overrides_for_testing(|_, mut config| {
4826            config.feature_flags.consensus_dedup_only_recorded_messages = false;
4827            config
4828        });
4829        let _ = ProtocolConfig::get_for_version(ProtocolVersion::max(), Chain::Unknown);
4830    }
4831
4832    /// With sponsor-only pre-consensus authentication, a sponsor alone could get
4833    /// a transaction sequenced that locks a Move account's owned objects, so
4834    /// the P-COOL flow excludes it.
4835    #[test]
4836    #[should_panic(
4837        expected = "enable_pcool_flow excludes pre_consensus_sponsor_only_move_authentication"
4838    )]
4839    fn pcool_flow_with_sponsor_only_pre_consensus_authentication_is_rejected() {
4840        let _guard = ProtocolConfig::apply_overrides_for_testing(|_, mut config| {
4841            config
4842                .feature_flags
4843                .pre_consensus_sponsor_only_move_authentication = true;
4844            config
4845        });
4846        let _ = ProtocolConfig::get_for_version(ProtocolVersion::max(), Chain::Unknown);
4847    }
4848
4849    /// Turning the P-COOL flow on for testing turns sponsor-only pre-consensus
4850    /// authentication off, which Testnet's version 34 has on.
4851    #[test]
4852    fn turning_the_pcool_flow_on_turns_sponsor_only_authentication_off() {
4853        let mut config = ProtocolConfig::get_for_version(ProtocolVersion::new(34), Chain::Testnet);
4854        assert!(config.pre_consensus_sponsor_only_move_authentication());
4855        config.set_enable_pcool_flow_for_testing(true);
4856        assert!(!config.pre_consensus_sponsor_only_move_authentication());
4857    }
4858
4859    /// A test that turns a requirement off keeps a valid config instead of
4860    /// tripping the startup check.
4861    #[test]
4862    fn disabling_a_requirement_for_testing_disables_the_pcool_flow() {
4863        let _guard = ProtocolConfig::apply_overrides_for_testing(|_, mut config| {
4864            config.set_consensus_dedup_only_recorded_messages_for_testing(false);
4865            config
4866        });
4867        let config = ProtocolConfig::get_for_version(ProtocolVersion::max(), Chain::Unknown);
4868        assert!(!config.enable_pcool_flow());
4869    }
4870
4871    #[test]
4872    fn limit_range_fn_test() {
4873        let low = 100u32;
4874        let high = 10000u64;
4875
4876        assert!(check_limit!(1u8, low, high) == LimitThresholdCrossed::None);
4877        assert!(matches!(
4878            check_limit!(255u16, low, high),
4879            LimitThresholdCrossed::Soft(255u128, 100)
4880        ));
4881        // This wont compile because lossy
4882        // assert!(check_limit!(100000000u128, low, high) ==
4883        // LimitThresholdCrossed::None); This wont compile because lossy
4884        // assert!(check_limit!(100000000usize, low, high) ==
4885        // LimitThresholdCrossed::None);
4886
4887        assert!(matches!(
4888            check_limit!(2550000u64, low, high),
4889            LimitThresholdCrossed::Hard(2550000, 10000)
4890        ));
4891
4892        assert!(matches!(
4893            check_limit!(2550000u64, high, high),
4894            LimitThresholdCrossed::Hard(2550000, 10000)
4895        ));
4896
4897        assert!(matches!(
4898            check_limit!(1u8, high),
4899            LimitThresholdCrossed::None
4900        ));
4901
4902        assert!(check_limit!(255u16, high) == LimitThresholdCrossed::None);
4903
4904        assert!(matches!(
4905            check_limit!(2550000u64, high),
4906            LimitThresholdCrossed::Hard(2550000, 10000)
4907        ));
4908    }
4909}