diff --git a/crates/iota-core/src/authority.rs b/crates/iota-core/src/authority.rs index ea62b573629..433966c099b 100644 --- a/crates/iota-core/src/authority.rs +++ b/crates/iota-core/src/authority.rs @@ -54,6 +54,7 @@ use iota_types::committee::CommitteeTrait; use iota_types::{ IOTA_SYSTEM_ADDRESS, TypeTag, authenticator_state::get_authenticator_state, + balance::Balance, base_types::*, committee::{Committee, EpochId, ProtocolVersion}, crypto::{AuthoritySignInfo, AuthoritySignature, RandomnessRound, Signer, default_hash}, @@ -71,6 +72,8 @@ use iota_types::{ execution_status::ExecutionStatus, fp_ensure, gas::{GasCostSummary, IotaGasStatus}, + gas_coin::GAS, + governance::StakedIota, inner_temporary_store::{ InnerTemporaryStore, ObjectMap, PackageStoreWithFallback, TemporaryModuleResolver, TxCoins, WrittenObjects, @@ -100,6 +103,7 @@ use iota_types::{ BackingPackageStore, BackingStore, ObjectKey, ObjectOrTombstone, ObjectStore, WriteKind, }, supported_protocol_versions::{ProtocolConfig, SupportedProtocolVersions}, + timelock::{timelock::TimeLock, timelocked_staked_iota::TimelockedStakedIota}, transaction::*, }; use itertools::Itertools; @@ -4490,6 +4494,73 @@ impl AuthorityState { Some(tx) } + #[instrument(level = "debug", skip_all)] + fn create_system_display_txs( + &self, + epoch_store: &Arc, + ) -> Option { + let txs = [ + self.create_staked_iota_display_tx_v1(epoch_store), + self.create_staked_timelocked_iota_display_tx_v1(epoch_store), + self.create_timelocked_iota_display_tx_v1(epoch_store), + ] + .iter() + .filter_map(|f| f.clone()) + .collect::>(); + + if txs.is_empty() { + return None; + } + + info!("Creating system display transactions"); + Some(EndOfEpochTransactionKind::system_display(txs)) + } + + #[instrument(level = "debug", skip_all)] + fn create_staked_iota_display_tx_v1( + &self, + epoch_store: &Arc, + ) -> Option { + let tag = StakedIota::type_(); + + if epoch_store.is_system_display_object_created(tag, 1) { + return None; + } + + info!("Creating `StakedIota` system display v1 transaction"); + Some(SystemDisplayTransactionKind::StakedIotaV1) + } + + #[instrument(level = "debug", skip_all)] + fn create_staked_timelocked_iota_display_tx_v1( + &self, + epoch_store: &Arc, + ) -> Option { + let tag = TimelockedStakedIota::type_(); + + if epoch_store.is_system_display_object_created(tag, 1) { + return None; + } + + info!("Creating `TimelockedStakedIota` system display v1 transaction"); + Some(SystemDisplayTransactionKind::TimelockedStakedIotaV1) + } + + #[instrument(level = "debug", skip_all)] + fn create_timelocked_iota_display_tx_v1( + &self, + epoch_store: &Arc, + ) -> Option { + let tag = TimeLock::::type_(Balance::type_(GAS::type_().into()).into()); + + if epoch_store.is_system_display_object_created(tag, 1) { + return None; + } + + info!("Creating `TimeLock>` system display v1 transaction"); + Some(SystemDisplayTransactionKind::TimelockedIotaV1) + } + /// Creates and execute the advance epoch transaction to effects without /// committing it to the database. The effects of the change epoch tx /// are only written to the database after a certified checkpoint has been @@ -4525,6 +4596,9 @@ impl AuthorityState { if let Some(tx) = self.init_bridge_committee_tx(epoch_store) { txns.push(tx); } + if let Some(tx) = self.create_system_display_txs(epoch_store) { + txns.push(tx); + } let next_epoch = epoch_store.epoch() + 1; diff --git a/crates/iota-core/src/authority/authority_per_epoch_store.rs b/crates/iota-core/src/authority/authority_per_epoch_store.rs index cc6340a840e..6aa963eb5c8 100644 --- a/crates/iota-core/src/authority/authority_per_epoch_store.rs +++ b/crates/iota-core/src/authority/authority_per_epoch_store.rs @@ -41,8 +41,9 @@ use iota_types::{ effects::TransactionEffects, error::{IotaError, IotaResult}, executable_transaction::{TrustedExecutableTransaction, VerifiedExecutableTransaction}, - iota_system_state::epoch_start_iota_system_state::{ - EpochStartSystemState, EpochStartSystemStateTrait, + iota_system_state::{ + epoch_start_iota_system_state::{EpochStartSystemState, EpochStartSystemStateTrait}, + system_display_object_key, }, message_envelope::TrustedEnvelope, messages_checkpoint::{ @@ -62,6 +63,7 @@ use iota_types::{ }; use itertools::{Itertools, izip}; use move_bytecode_utils::module_cache::SyncModuleCache; +use move_core_types::language_storage::StructTag; use parking_lot::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard}; use prometheus::IntCounter; use serde::{Deserialize, Serialize}; @@ -959,6 +961,21 @@ impl AuthorityPerEpochStore { self.epoch_start_configuration.bridge_committee_initiated() } + pub fn is_system_display_object_created(&self, tag: StructTag, version: u16) -> bool { + let key = system_display_object_key(tag); + + let object_version = self + .epoch_start_configuration + .system_display_object_version(&key) + .cloned(); + + let Some(object_version) = object_version else { + return false; + }; + + version <= object_version + } + pub fn get_parent_path(&self) -> PathBuf { self.parent_path.clone() } diff --git a/crates/iota-core/src/authority/epoch_start_configuration.rs b/crates/iota-core/src/authority/epoch_start_configuration.rs index 7ae6446577a..c496cddb139 100644 --- a/crates/iota-core/src/authority/epoch_start_configuration.rs +++ b/crates/iota-core/src/authority/epoch_start_configuration.rs @@ -2,7 +2,7 @@ // Modifications Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -use std::fmt; +use std::{collections::HashMap, fmt}; use enum_dispatch::enum_dispatch; use iota_config::{ExecutionCacheConfig, NodeConfig}; @@ -13,8 +13,9 @@ use iota_types::{ deny_list_v1::get_deny_list_obj_initial_shared_version, epoch_data::EpochData, error::IotaResult, - iota_system_state::epoch_start_iota_system_state::{ - EpochStartSystemState, EpochStartSystemStateTrait, + iota_system_state::{ + epoch_start_iota_system_state::{EpochStartSystemState, EpochStartSystemStateTrait}, + get_system_display_objects, }, messages_checkpoint::{CheckpointDigest, CheckpointTimestamp}, randomness_state::get_randomness_state_obj_initial_shared_version, @@ -34,6 +35,8 @@ pub trait EpochStartConfigTrait { fn coin_deny_list_obj_initial_shared_version(&self) -> SequenceNumber; fn bridge_obj_initial_shared_version(&self) -> Option; fn bridge_committee_initiated(&self) -> bool; + fn system_display_object_versions(&self) -> impl Iterator; + fn system_display_object_version(&self, key: &str) -> Option<&u16>; fn execution_cache_type(&self) -> ExecutionCacheConfigType { if self.flags().contains(&EpochFlag::WritebackCacheEnabled) { @@ -115,6 +118,10 @@ impl EpochStartConfiguration { let bridge_obj_initial_shared_version = get_bridge_obj_initial_shared_version(object_store)?; let bridge_committee_initiated = is_bridge_committee_initiated(object_store)?; + let system_display_object_versions = get_system_display_objects(object_store)? + .into_iter() + .map(|(key, display)| (key, display.version)) + .collect(); Ok(Self::V1(EpochStartConfigurationV1 { system_state, epoch_digest, @@ -124,6 +131,7 @@ impl EpochStartConfiguration { coin_deny_list_obj_initial_shared_version, bridge_obj_initial_shared_version, bridge_committee_initiated, + system_display_object_versions, })) } @@ -143,6 +151,7 @@ impl EpochStartConfiguration { .coin_deny_list_obj_initial_shared_version, bridge_obj_initial_shared_version: config.bridge_obj_initial_shared_version, bridge_committee_initiated: config.bridge_committee_initiated, + system_display_object_versions: config.system_display_object_versions.clone(), }), _ => panic!( "This function is only implemented for the latest version of EpochStartConfiguration" @@ -174,6 +183,7 @@ pub struct EpochStartConfigurationV1 { coin_deny_list_obj_initial_shared_version: SequenceNumber, bridge_obj_initial_shared_version: Option, bridge_committee_initiated: bool, + system_display_object_versions: HashMap, } impl EpochStartConfigTrait for EpochStartConfigurationV1 { @@ -208,4 +218,12 @@ impl EpochStartConfigTrait for EpochStartConfigurationV1 { fn bridge_committee_initiated(&self) -> bool { self.bridge_committee_initiated } + + fn system_display_object_versions(&self) -> impl Iterator { + self.system_display_object_versions.iter() + } + + fn system_display_object_version(&self, key: &str) -> Option<&u16> { + self.system_display_object_versions.get(key) + } } diff --git a/crates/iota-core/src/generate_format.rs b/crates/iota-core/src/generate_format.rs index 1f0ff6e1ee5..07ce5e9057f 100644 --- a/crates/iota-core/src/generate_format.rs +++ b/crates/iota-core/src/generate_format.rs @@ -33,8 +33,8 @@ use iota_types::{ signature::GenericSignature, storage::DeleteKind, transaction::{ - Argument, CallArg, Command, EndOfEpochTransactionKind, ObjectArg, TransactionExpiration, - TransactionKind, + Argument, CallArg, Command, EndOfEpochTransactionKind, ObjectArg, + SystemDisplayTransactionKind, TransactionExpiration, TransactionKind, }, utils::DEFAULT_ADDRESS_SEED, }; @@ -172,6 +172,7 @@ fn get_registry() -> Result { tracer.trace_type::(&samples)?; tracer.trace_type::(&samples)?; tracer.trace_type::(&samples)?; + tracer.trace_type::(&samples)?; tracer.trace_type::(&samples)?; tracer.trace_type::(&samples)?; diff --git a/crates/iota-framework/packages/iota-framework/sources/display.move b/crates/iota-framework/packages/iota-framework/sources/display.move index bf6cc92765a..037889fcacf 100644 --- a/crates/iota-framework/packages/iota-framework/sources/display.move +++ b/crates/iota-framework/packages/iota-framework/sources/display.move @@ -2,35 +2,37 @@ // Modifications Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -/// Defines a Display struct which defines the way an Object +/// Defines a `Display` struct which defines the way an Object /// should be displayed. The intention is to keep data as independent /// from its display as possible, protecting the development process /// and keeping it separate from the ecosystem agreements. /// -/// Each of the fields of the Display object should allow for pattern -/// substitution and filling-in the pieces using the data from the object T. +/// Each of the fields of the `Display` object should allow for pattern +/// substitution and filling-in the pieces using the data from the object `T`. /// /// More entry functions might be added in the future depending on the use cases. module iota::display { + use std::string::String; + + use iota::event; use iota::package::Publisher; + use iota::system_admin_cap::IotaSystemAdminCap; use iota::vec_map::{Self, VecMap}; - use iota::event; - use std::string::String; - /// For when T does not belong to the package `Publisher`. + /// For when `T` does not belong to the package `Publisher`. const ENotOwner: u64 = 0; /// For when vectors passed into one of the multiple insert functions /// don't match in their lengths. const EVecLengthMismatch: u64 = 1; - /// The Display object. Defines the way a T instance should be - /// displayed. Display object can only be created and modified with - /// a PublisherCap, making sure that the rules are set by the owner - /// of the type. + /// The `Display` object. Defines the way a `T` instance should be + /// displayed. `Display` object can only be created and modified with + /// ether a `Publisher` cap or `IotaSystemAdminCap`, making sure that + /// the rules are set by the owner of the type or the system object. /// /// Each of the display properties should support patterns outside - /// of the system, making it simpler to customize Display based + /// of the system, making it simpler to customize `Display` based /// on the property values of an Object. /// ``` /// // Example of a display object @@ -43,28 +45,28 @@ module iota::display { /// } /// ``` /// - /// Uses only String type due to external-facing nature of the object, + /// Uses only `String` type due to external-facing nature of the object, /// the property names have a priority over their types. public struct Display has key, store { id: UID, /// Contains fields for display. Currently supported /// fields are: name, link, image and description. fields: VecMap, - /// Version that can only be updated manually by the Publisher. + /// Version that can only be updated manually by the `Publisher`. version: u16 } - /// Event: emitted when a new Display object has been created for type T. + /// Event: emitted when a new `Display` object has been created for type `T`. /// Type signature of the event corresponds to the type while id serves for /// the discovery. /// - /// Since Iota RPC supports querying events by type, finding a Display for the T + /// Since Iota RPC supports querying events by type, finding a `Display` for the `T` /// would be as simple as looking for the first event with `Display`. public struct DisplayCreated has copy, drop { id: ID } - /// Version of Display got updated - + /// Version of `Display` got updated. public struct VersionUpdated has copy, drop { id: ID, version: u16, @@ -73,34 +75,39 @@ module iota::display { // === Initializer Methods === - /// Create an empty Display object. It can either be shared empty or filled - /// with data right away via cheaper `set_owned` method. + /// Create an empty `Display` object with `Publisher`. public fun new(pub: &Publisher, ctx: &mut TxContext): Display { assert!(is_authorized(pub), ENotOwner); create_internal(ctx) } - /// Create a new Display object with a set of fields. + /// Create a new `Display` object with a set of fields using `Publisher`. public fun new_with_fields( pub: &Publisher, fields: vector, values: vector, ctx: &mut TxContext ): Display { - let len = fields.length(); - assert!(len == values.length(), EVecLengthMismatch); - - let mut i = 0; let mut display = new(pub, ctx); - while (i < len) { - display.add_internal(fields[i], values[i]); - i = i + 1; - }; + add_multiple(&mut display, fields, values); + display + } + + /// Create an empty `Display` object with `IotaSystemAdminCap`. + public fun system_new(_: &IotaSystemAdminCap, ctx: &mut TxContext): Display { + create_internal(ctx) + } + /// Create a new Display object with a set of fields using `IotaSystemAdminCap`. + public fun system_new_with_fields( + cap: &IotaSystemAdminCap, fields: vector, values: vector, ctx: &mut TxContext + ): Display { + let mut display = system_new(cap, ctx); + add_multiple(&mut display, fields, values); display } // === Entry functions: Create === #[allow(lint(self_transfer))] - /// Create a new empty Display object and keep it. + /// Create a new empty `Display` object and keep it. entry public fun create_and_keep(pub: &Publisher, ctx: &mut TxContext) { transfer::public_transfer(new(pub, ctx), ctx.sender()) } @@ -145,18 +152,23 @@ module iota::display { self.add_internal(name, value) } - /// Remove the key from the Display. + /// Remove the key from the `Display`. entry public fun remove(self: &mut Display, name: String) { self.fields.remove(&name); } // === Access fields === - /// Authorization check; can be performed externally to implement protection rules for Display. + /// Authorization check; can be performed externally to implement protection rules for `Display`. public fun is_authorized(pub: &Publisher): bool { pub.from_package() } + /// Read the `id` field. + public fun id(d: &Display): &ID { + d.id.uid_as_inner() + } + /// Read the `version` field. public fun version(d: &Display): u16 { d.version @@ -192,10 +204,14 @@ module iota::display { #[test_only] module iota::display_tests { - use iota::test_scenario as test; use std::string::String; - use iota::package; + use iota::display; + use iota::package; + use iota::system_admin_cap; + + use iota::test_scenario as test; + use iota::test_utils; #[allow(unused_field)] /// An example object. @@ -225,4 +241,23 @@ module iota::display_tests { transfer::public_transfer(display, @0x2); test.end(); } + + #[test] + fun nft_test_sys_init() { + let mut test = test::begin(@0x2); + let cap = system_admin_cap::new_system_admin_cap_for_testing(); + + // create a new display object + let mut display = display::system_new(&cap, test.ctx()); + + display.add(b"name".to_string(), b"IOTEST Nft {name}".to_string()); + display.add(b"link".to_string(), b"https://iotestnft.com/nft/{id}".to_string()); + display.add(b"image".to_string(), b"https://api.iotestnft.com/nft/{id}/svg".to_string()); + display.add(b"description".to_string(), b"One of many Iotest Nfts".to_string()); + + transfer::public_transfer(display, @0x2); + + test_utils::destroy(cap); + test.end(); + } } diff --git a/crates/iota-framework/packages/iota-framework/sources/system_admin_cap.move b/crates/iota-framework/packages/iota-framework/sources/system_admin_cap.move index 2483ca4927a..97a696bddb1 100644 --- a/crates/iota-framework/packages/iota-framework/sources/system_admin_cap.move +++ b/crates/iota-framework/packages/iota-framework/sources/system_admin_cap.move @@ -10,7 +10,8 @@ module iota::system_admin_cap { const ENotSystemAddress: u64 = 1; /// `IotaSystemAdminCap` allows to perform privileged IOTA system operations. - /// For example, packing and unpacking `TimeLock`s during staking, etc. + /// For example, packing and unpacking `TimeLock`s during staking, + /// creating `Display` objects without `Publisher`, etc. public struct IotaSystemAdminCap has store {} #[allow(unused_function)] diff --git a/crates/iota-framework/packages/iota-system/sources/iota_system.move b/crates/iota-framework/packages/iota-system/sources/iota_system.move index 573ffddb165..b125488a991 100644 --- a/crates/iota-framework/packages/iota-system/sources/iota_system.move +++ b/crates/iota-framework/packages/iota-system/sources/iota_system.move @@ -41,19 +41,21 @@ module iota_system::iota_system { use iota::balance::Balance; + use std::string::String; use iota::coin::Coin; - use iota_system::staking_pool::StakedIota; + use iota::display::Display; use iota::iota::{IOTA, IotaTreasuryCap}; use iota::table::Table; use iota::system_admin_cap::IotaSystemAdminCap; - use iota_system::validator::ValidatorV1; - use iota_system::validator_cap::UnverifiedValidatorOperationCap; - use iota_system::iota_system_state_inner::{Self, SystemParametersV1, IotaSystemStateV1}; - use iota_system::staking_pool::PoolTokenExchangeRate; use iota::dynamic_field; use iota::vec_map::VecMap; + use iota_system::iota_system_state_inner::{Self, SystemParametersV1, IotaSystemStateV1, IotaSystemStateV2}; + use iota_system::staking_pool::{PoolTokenExchangeRate, StakedIota}; + use iota_system::validator::ValidatorV1; + use iota_system::validator_cap::UnverifiedValidatorOperationCap; + #[test_only] use iota::balance; #[test_only] use iota_system::validator_set::ValidatorSetV1; #[test_only] use iota::vec_set::VecSet; @@ -505,6 +507,53 @@ module iota_system::iota_system { self.load_system_state().iota_system_admin_cap() } + /// Create an empty system `Display` object with `IotaSystemAdminCap`. + public(package) fun new_system_display( + wrapper: &mut IotaSystemState, + ctx: &mut TxContext, + ): Display { + let self = wrapper.load_system_state(); + self.new_system_display(ctx) + } + + /// Create a new system `Display` object with a set of fields using `IotaSystemAdminCap`. + public(package) fun new_system_display_with_fields( + wrapper: &mut IotaSystemState, + fields: vector, + values: vector, + ctx: &mut TxContext, + ): Display { + let self = wrapper.load_system_state(); + self.new_system_display_with_fields(fields, values, ctx) + } + + /// Insert a system display object. + public(package) fun insert_system_display_object( + wrapper: &mut IotaSystemState, + display: Display, + ) { + let self = wrapper.load_system_state_mut(); + self.insert_system_display_object(display); + } + + /// Borrow an immutable system display object. + public(package) fun borrow_system_display_object(wrapper: &mut IotaSystemState): &Display { + let self = wrapper.load_system_state(); + self.borrow_system_display_object() + } + + /// Borrow a mutable system display object. + public(package) fun borrow_system_display_object_mut(wrapper: &mut IotaSystemState): &mut Display { + let self = wrapper.load_system_state_mut(); + self.borrow_system_display_object_mut() + } + + /// Returns true if the related system display object exists. + public(package) fun contains_system_display_object(wrapper: &mut IotaSystemState): bool { + let self = wrapper.load_system_state(); + self.contains_system_display_object() + } + #[allow(unused_function)] /// This function should be called at the end of an epoch, and advances the system to the next epoch. /// It does the following things: @@ -548,16 +597,23 @@ module iota_system::iota_system { storage_rebate } - fun load_system_state(self: &mut IotaSystemState): &IotaSystemStateV1 { + fun load_system_state(self: &mut IotaSystemState): &IotaSystemStateV2 { load_inner_maybe_upgrade(self) } - fun load_system_state_mut(self: &mut IotaSystemState): &mut IotaSystemStateV1 { + fun load_system_state_mut(self: &mut IotaSystemState): &mut IotaSystemStateV2 { load_inner_maybe_upgrade(self) } - fun load_inner_maybe_upgrade(self: &mut IotaSystemState): &mut IotaSystemStateV1 { - let inner: &mut IotaSystemStateV1 = dynamic_field::borrow_mut( + fun load_inner_maybe_upgrade(self: &mut IotaSystemState): &mut IotaSystemStateV2 { + if (self.version == 1) { + let v1: IotaSystemStateV1 = dynamic_field::remove(&mut self.id, self.version); + let v2 = v1.v1_to_v2(); + self.version = 2; + dynamic_field::add(&mut self.id, self.version, v2); + }; + + let inner: &mut IotaSystemStateV2 = dynamic_field::borrow_mut( &mut self.id, self.version ); diff --git a/crates/iota-framework/packages/iota-system/sources/iota_system_state_inner.move b/crates/iota-framework/packages/iota-system/sources/iota_system_state_inner.move index 5e701a31961..68baf6c068d 100644 --- a/crates/iota-framework/packages/iota-system/sources/iota_system_state_inner.move +++ b/crates/iota-framework/packages/iota-system/sources/iota_system_state_inner.move @@ -3,21 +3,24 @@ // SPDX-License-Identifier: Apache-2.0 module iota_system::iota_system_state_inner { + use std::string::{Self, String}; + use iota::balance::{Self, Balance}; use iota::coin::Coin; + use iota::display::{Self, Display}; use iota::iota::{IOTA, IotaTreasuryCap}; use iota::system_admin_cap::IotaSystemAdminCap; + use iota::vec_map::{Self, VecMap}; + use iota::vec_set::{Self, VecSet}; + use iota::event; + use iota::table::Table; + use iota::bag::{Self, Bag}; + use iota_system::validator::{Self, ValidatorV1}; use iota_system::validator_set::{Self, ValidatorSetV1}; use iota_system::validator_cap::{UnverifiedValidatorOperationCap, ValidatorOperationCap}; use iota_system::storage_fund::{Self, StorageFundV1}; use iota_system::staking_pool::{PoolTokenExchangeRate, StakedIota}; - use iota::vec_map::{Self, VecMap}; - use iota::vec_set::{Self, VecSet}; - use iota::event; - use iota::table::Table; - use iota::bag::Bag; - use iota::bag; // same as in validator_set const ACTIVE_VALIDATOR_ONLY: u8 = 1; @@ -104,6 +107,61 @@ module iota_system::iota_system_state_inner { /// Unix timestamp of the current epoch start epoch_start_timestamp_ms: u64, + + /// Any extra fields that's not defined statically. + extra_fields: Bag, + } + + /// The top-level object containing all information of the Iota system. + public struct IotaSystemStateV2 has store { + /// The current epoch ID, starting from 0. + epoch: u64, + /// The current protocol version, starting from 1. + protocol_version: u64, + /// The current version of the system state data structure type. + /// This is always the same as IotaSystemState.version. Keeping a copy here so that + /// we know what version it is by inspecting IotaSystemStateV2 as well. + system_state_version: u64, + /// The IOTA's TreasuryCap. + iota_treasury_cap: IotaTreasuryCap, + /// Contains all information about the validators. + validators: ValidatorSetV1, + /// The storage fund. + storage_fund: StorageFundV1, + /// A list of system config parameters. + parameters: SystemParametersV1, + /// A capability allows to perform privileged IOTA system operations. + iota_system_admin_cap: IotaSystemAdminCap, + /// The reference gas price for the current epoch. + reference_gas_price: u64, + /// A map storing the records of validator reporting each other. + /// There is an entry in the map for each validator that has been reported + /// at least once. The entry VecSet contains all the validators that reported + /// them. If a validator has never been reported they don't have an entry in this map. + /// This map persists across epoch: a peer continues being in a reported state until the + /// reporter doesn't explicitly remove their report. + /// Note that in case we want to support validator address change in future, + /// the reports should be based on validator ids + validator_report_records: VecMap>, + + /// Whether the system is running in a downgraded safe mode due to a non-recoverable bug. + /// This is set whenever we failed to execute advance_epoch, and ended up executing advance_epoch_safe_mode. + /// It can be reset once we are able to successfully execute advance_epoch. + /// The rest of the fields starting with `safe_mode_` are accmulated during safe mode + /// when advance_epoch_safe_mode is executed. They will eventually be processed once we + /// are out of safe mode. + safe_mode: bool, + safe_mode_storage_charges: Balance, + safe_mode_computation_rewards: Balance, + safe_mode_storage_rebates: u64, + safe_mode_non_refundable_storage_fee: u64, + + /// Unix timestamp of the current epoch start + epoch_start_timestamp_ms: u64, + + /// A map contains the system display object IDs stored in the extra fields. + system_display_objects: VecMap, + /// Any extra fields that's not defined statically. extra_fields: Bag, } @@ -199,6 +257,49 @@ module iota_system::iota_system_state_inner { } } + public(package) fun v1_to_v2(self: IotaSystemStateV1): IotaSystemStateV2 { + let IotaSystemStateV1 { + epoch, + protocol_version, + system_state_version: _, + iota_treasury_cap, + validators, + storage_fund, + parameters, + iota_system_admin_cap, + reference_gas_price, + validator_report_records, + safe_mode, + safe_mode_storage_charges, + safe_mode_computation_rewards, + safe_mode_storage_rebates, + safe_mode_non_refundable_storage_fee, + epoch_start_timestamp_ms, + extra_fields, + } = self; + + IotaSystemStateV2 { + epoch, + protocol_version, + system_state_version: 2, + iota_treasury_cap, + validators, + storage_fund, + parameters, + iota_system_admin_cap, + reference_gas_price, + validator_report_records, + safe_mode, + safe_mode_storage_charges, + safe_mode_computation_rewards, + safe_mode_storage_rebates, + safe_mode_non_refundable_storage_fee, + epoch_start_timestamp_ms, + system_display_objects: vec_map::empty(), + extra_fields, + } + } + // ==== public(package) functions ==== /// Can be called by anyone who wishes to become a validator candidate and starts accuring delegated @@ -208,7 +309,7 @@ module iota_system::iota_system_state_inner { /// Note: `proof_of_possession` MUST be a valid signature using iota_address and authority_pubkey_bytes. /// To produce a valid PoP, run [fn test_proof_of_possession]. public(package) fun request_add_validator_candidate( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, authority_pubkey_bytes: vector, network_pubkey_bytes: vector, protocol_pubkey_bytes: vector, @@ -248,7 +349,7 @@ module iota_system::iota_system_state_inner { /// Called by a validator candidate to remove themselves from the candidacy. After this call /// their staking pool becomes deactivate. public(package) fun request_remove_validator_candidate( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, ctx: &mut TxContext, ) { self.validators.request_remove_validator_candidate(ctx); @@ -259,7 +360,7 @@ module iota_system::iota_system_state_inner { /// stake the validator has doesn't meet the min threshold, or if the number of new validators for the next /// epoch has already reached the maximum. public(package) fun request_add_validator( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, ctx: &TxContext, ) { assert!( @@ -276,7 +377,7 @@ module iota_system::iota_system_state_inner { /// At the end of the epoch, the `validator` object will be returned to the iota_address /// of the validator. public(package) fun request_remove_validator( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, ctx: &TxContext, ) { // Only check min validator condition if the current number of validators satisfy the constraint. @@ -295,7 +396,7 @@ module iota_system::iota_system_state_inner { /// A validator can call this function to submit a new gas price quote, to be /// used for the reference gas price calculation at the end of the epoch. public(package) fun request_set_gas_price( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, cap: &UnverifiedValidatorOperationCap, new_gas_price: u64, ) { @@ -308,7 +409,7 @@ module iota_system::iota_system_state_inner { /// This function is used to set new gas price for candidate validators public(package) fun set_candidate_validator_gas_price( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, cap: &UnverifiedValidatorOperationCap, new_gas_price: u64, ) { @@ -321,7 +422,7 @@ module iota_system::iota_system_state_inner { /// A validator can call this function to set a new commission rate, updated at the end of /// the epoch. public(package) fun request_set_commission_rate( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, new_commission_rate: u64, ctx: &TxContext, ) { @@ -333,7 +434,7 @@ module iota_system::iota_system_state_inner { /// This function is used to set new commission rate for candidate validators public(package) fun set_candidate_validator_commission_rate( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, new_commission_rate: u64, ctx: &TxContext, ) { @@ -343,7 +444,7 @@ module iota_system::iota_system_state_inner { /// Add stake to a validator's staking pool. public(package) fun request_add_stake( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, stake: Coin, validator_address: address, ctx: &mut TxContext, @@ -357,7 +458,7 @@ module iota_system::iota_system_state_inner { /// Add stake to a validator's staking pool using multiple coins. public(package) fun request_add_stake_mul_coin( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, stakes: vector>, stake_amount: option::Option, validator_address: address, @@ -369,7 +470,7 @@ module iota_system::iota_system_state_inner { /// Withdraw some portion of a stake from a validator's staking pool. public(package) fun request_withdraw_stake( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, staked_iota: StakedIota, ctx: &TxContext, ) : Balance { @@ -383,7 +484,7 @@ module iota_system::iota_system_state_inner { /// 3. the cap object is still valid. /// This function is idempotent. public(package) fun report_validator( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, cap: &UnverifiedValidatorOperationCap, reportee_addr: address, ) { @@ -400,7 +501,7 @@ module iota_system::iota_system_state_inner { /// 2. the sender has not previously reported the `reportee_addr`, or /// 3. the cap is not valid public(package) fun undo_report_validator( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, cap: &UnverifiedValidatorOperationCap, reportee_addr: address, ) { @@ -442,12 +543,83 @@ module iota_system::iota_system_state_inner { } } + /// Create an empty system `Display` object with `IotaSystemAdminCap`. + public(package) fun new_system_display( + self: &IotaSystemStateV2, + ctx: &mut TxContext, + ): Display { + display::system_new(&self.iota_system_admin_cap, ctx) + } + + /// Create a new system `Display` object with a set of fields using `IotaSystemAdminCap`. + public(package) fun new_system_display_with_fields( + self: &IotaSystemStateV2, + fields: vector, + values: vector, + ctx: &mut TxContext, + ): Display { + display::system_new_with_fields(&self.iota_system_admin_cap, fields, values, ctx) + } + + /// Insert a system display object. + public(package) fun insert_system_display_object( + self: &mut IotaSystemStateV2, + display: Display, + ) { + // Get a display object unique key. + let key = system_display_object_key(); + let display_id = *display.id(); + + // Store the display object. + self.system_display_objects.insert(key, display_id); + self.extra_fields.add(display_id, display); + } + + /// Borrow an immutable system display object. + public(package) fun borrow_system_display_object(self: &IotaSystemStateV2): &Display { + // Get a display object unique key. + let key = system_display_object_key(); + + // Get the id. + let display_id = *self.system_display_objects.get(&key); + + // Borrow the display object. + self.extra_fields.borrow(display_id) + } + + /// Borrow a mutable system display object. + public(package) fun borrow_system_display_object_mut(self: &mut IotaSystemStateV2): &mut Display { + // Get a display object unique key. + let key = system_display_object_key(); + + // Get the id. + let display_id = *self.system_display_objects.get(&key); + + // Borrow the display object. + self.extra_fields.borrow_mut(display_id) + } + + /// Returns true if the related system display object exists. + public(package) fun contains_system_display_object(self: &IotaSystemStateV2): bool { + // Get a display object unique key. + let key = system_display_object_key(); + + // Check if the related display object exists. + self.system_display_objects.contains(&key) + } + + /// Return a fully qualified type name with the original package IDs + /// that is used as a display object key. + fun system_display_object_key(): String { + string::from_ascii(std::type_name::get_with_original_ids().into_string()) + } + // ==== validator metadata management functions ==== /// Create a new `UnverifiedValidatorOperationCap`, transfer it to the /// validator and registers it. The original object is thus revoked. public(package) fun rotate_operation_cap( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, ctx: &mut TxContext, ) { let validator = self.validators.get_validator_mut_with_ctx_including_candidates(ctx); @@ -456,7 +628,7 @@ module iota_system::iota_system_state_inner { /// Update a validator's name. public(package) fun update_validator_name( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, name: vector, ctx: &TxContext, ) { @@ -467,7 +639,7 @@ module iota_system::iota_system_state_inner { /// Update a validator's description public(package) fun update_validator_description( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, description: vector, ctx: &TxContext, ) { @@ -477,7 +649,7 @@ module iota_system::iota_system_state_inner { /// Update a validator's image url public(package) fun update_validator_image_url( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, image_url: vector, ctx: &TxContext, ) { @@ -487,7 +659,7 @@ module iota_system::iota_system_state_inner { /// Update a validator's project url public(package) fun update_validator_project_url( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, project_url: vector, ctx: &TxContext, ) { @@ -498,7 +670,7 @@ module iota_system::iota_system_state_inner { /// Update a validator's network address. /// The change will only take effects starting from the next epoch. public(package) fun update_validator_next_epoch_network_address( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, network_address: vector, ctx: &TxContext, ) { @@ -510,7 +682,7 @@ module iota_system::iota_system_state_inner { /// Update candidate validator's network address. public(package) fun update_candidate_validator_network_address( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, network_address: vector, ctx: &TxContext, ) { @@ -521,7 +693,7 @@ module iota_system::iota_system_state_inner { /// Update a validator's p2p address. /// The change will only take effects starting from the next epoch. public(package) fun update_validator_next_epoch_p2p_address( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, p2p_address: vector, ctx: &TxContext, ) { @@ -533,7 +705,7 @@ module iota_system::iota_system_state_inner { /// Update candidate validator's p2p address. public(package) fun update_candidate_validator_p2p_address( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, p2p_address: vector, ctx: &TxContext, ) { @@ -544,7 +716,7 @@ module iota_system::iota_system_state_inner { /// Update a validator's primary address. /// The change will only take effects starting from the next epoch. public(package) fun update_validator_next_epoch_primary_address( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, primary_address: vector, ctx: &TxContext, ) { @@ -554,7 +726,7 @@ module iota_system::iota_system_state_inner { /// Update candidate validator's primary address. public(package) fun update_candidate_validator_primary_address( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, primary_address: vector, ctx: &TxContext, ) { @@ -565,7 +737,7 @@ module iota_system::iota_system_state_inner { /// Update a validator's public key of authority key and proof of possession. /// The change will only take effects starting from the next epoch. public(package) fun update_validator_next_epoch_authority_pubkey( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, authority_pubkey: vector, proof_of_possession: vector, ctx: &TxContext, @@ -578,7 +750,7 @@ module iota_system::iota_system_state_inner { /// Update candidate validator's public key of authority key and proof of possession. public(package) fun update_candidate_validator_authority_pubkey( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, authority_pubkey: vector, proof_of_possession: vector, ctx: &TxContext, @@ -590,7 +762,7 @@ module iota_system::iota_system_state_inner { /// Update a validator's public key of protocol key. /// The change will only take effects starting from the next epoch. public(package) fun update_validator_next_epoch_protocol_pubkey( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, protocol_pubkey: vector, ctx: &TxContext, ) { @@ -602,7 +774,7 @@ module iota_system::iota_system_state_inner { /// Update candidate validator's public key of protocol key. public(package) fun update_candidate_validator_protocol_pubkey( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, protocol_pubkey: vector, ctx: &TxContext, ) { @@ -613,7 +785,7 @@ module iota_system::iota_system_state_inner { /// Update a validator's public key of network key. /// The change will only take effects starting from the next epoch. public(package) fun update_validator_next_epoch_network_pubkey( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, network_pubkey: vector, ctx: &TxContext, ) { @@ -625,7 +797,7 @@ module iota_system::iota_system_state_inner { /// Update candidate validator's public key of network key. public(package) fun update_candidate_validator_network_pubkey( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, network_pubkey: vector, ctx: &TxContext, ) { @@ -644,7 +816,7 @@ module iota_system::iota_system_state_inner { /// 5. Burn any leftover rewards. /// 6. Update all validators. public(package) fun advance_epoch( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, new_epoch: u64, next_protocol_version: u64, validator_target_reward: u64, @@ -773,19 +945,19 @@ module iota_system::iota_system_state_inner { /// Return the current epoch number. Useful for applications that need a coarse-grained concept of time, /// since epochs are ever-increasing and epoch changes are intended to happen every 24 hours. - public(package) fun epoch(self: &IotaSystemStateV1): u64 { + public(package) fun epoch(self: &IotaSystemStateV2): u64 { self.epoch } - public(package) fun protocol_version(self: &IotaSystemStateV1): u64 { + public(package) fun protocol_version(self: &IotaSystemStateV2): u64 { self.protocol_version } - public(package) fun system_state_version(self: &IotaSystemStateV1): u64 { + public(package) fun system_state_version(self: &IotaSystemStateV2): u64 { self.system_state_version } - public(package) fun iota_system_admin_cap(self: &IotaSystemStateV1): &IotaSystemAdminCap { + public(package) fun iota_system_admin_cap(self: &IotaSystemStateV2): &IotaSystemAdminCap { &self.iota_system_admin_cap } @@ -796,19 +968,19 @@ module iota_system::iota_system_state_inner { } /// Returns unix timestamp of the start of current epoch - public(package) fun epoch_start_timestamp_ms(self: &IotaSystemStateV1): u64 { + public(package) fun epoch_start_timestamp_ms(self: &IotaSystemStateV2): u64 { self.epoch_start_timestamp_ms } /// Returns the total amount staked with `validator_addr`. /// Aborts if `validator_addr` is not an active validator. - public(package) fun validator_stake_amount(self: &IotaSystemStateV1, validator_addr: address): u64 { + public(package) fun validator_stake_amount(self: &IotaSystemStateV2, validator_addr: address): u64 { self.validators.validator_total_stake_amount(validator_addr) } /// Returns the voting power for `validator_addr`. /// Aborts if `validator_addr` is not an active validator. - public(package) fun active_validator_voting_powers(self: &IotaSystemStateV1): VecMap { + public(package) fun active_validator_voting_powers(self: &IotaSystemStateV2): VecMap { let mut active_validators = active_validator_addresses(self); let mut voting_powers = vec_map::empty(); while (!vector::is_empty(&active_validators)) { @@ -821,24 +993,24 @@ module iota_system::iota_system_state_inner { /// Returns the staking pool id of a given validator. /// Aborts if `validator_addr` is not an active validator. - public(package) fun validator_staking_pool_id(self: &IotaSystemStateV1, validator_addr: address): ID { + public(package) fun validator_staking_pool_id(self: &IotaSystemStateV2, validator_addr: address): ID { self.validators.validator_staking_pool_id(validator_addr) } /// Returns reference to the staking pool mappings that map pool ids to active validator addresses - public(package) fun validator_staking_pool_mappings(self: &IotaSystemStateV1): &Table { + public(package) fun validator_staking_pool_mappings(self: &IotaSystemStateV2): &Table { self.validators.staking_pool_mappings() } /// Returns the total iota supply. - public(package) fun get_total_iota_supply(self: &IotaSystemStateV1): u64 { + public(package) fun get_total_iota_supply(self: &IotaSystemStateV2): u64 { self.iota_treasury_cap.total_supply() } /// Returns all the validators who are currently reporting `addr` - public(package) fun get_reporters_of(self: &IotaSystemStateV1, addr: address): VecSet
{ + public(package) fun get_reporters_of(self: &IotaSystemStateV2, addr: address): VecSet
{ if (self.validator_report_records.contains(&addr)) { self.validator_report_records[&addr] @@ -847,23 +1019,23 @@ module iota_system::iota_system_state_inner { } } - public(package) fun get_storage_fund_total_balance(self: &IotaSystemStateV1): u64 { + public(package) fun get_storage_fund_total_balance(self: &IotaSystemStateV2): u64 { self.storage_fund.total_balance() } - public(package) fun get_storage_fund_object_rebates(self: &IotaSystemStateV1): u64 { + public(package) fun get_storage_fund_object_rebates(self: &IotaSystemStateV2): u64 { self.storage_fund.total_object_storage_rebates() } public(package) fun pool_exchange_rates( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, pool_id: &ID ): &Table { let validators = &mut self.validators; validators.pool_exchange_rates(pool_id) } - public(package) fun active_validator_addresses(self: &IotaSystemStateV1): vector
{ + public(package) fun active_validator_addresses(self: &IotaSystemStateV2): vector
{ let validator_set = &self.validators; validator_set.active_validator_addresses() } @@ -893,36 +1065,36 @@ module iota_system::iota_system_state_inner { #[test_only] /// Return the current validator set - public(package) fun validators(self: &IotaSystemStateV1): &ValidatorSetV1 { + public(package) fun validators(self: &IotaSystemStateV2): &ValidatorSetV1 { &self.validators } #[test_only] /// Return the currently active validator by address - public(package) fun active_validator_by_address(self: &IotaSystemStateV1, validator_address: address): &ValidatorV1 { + public(package) fun active_validator_by_address(self: &IotaSystemStateV2, validator_address: address): &ValidatorV1 { self.validators().get_active_validator_ref(validator_address) } #[test_only] /// Return the currently pending validator by address - public(package) fun pending_validator_by_address(self: &IotaSystemStateV1, validator_address: address): &ValidatorV1 { + public(package) fun pending_validator_by_address(self: &IotaSystemStateV2, validator_address: address): &ValidatorV1 { self.validators().get_pending_validator_ref(validator_address) } #[test_only] /// Return the currently candidate validator by address - public(package) fun candidate_validator_by_address(self: &IotaSystemStateV1, validator_address: address): &ValidatorV1 { + public(package) fun candidate_validator_by_address(self: &IotaSystemStateV2, validator_address: address): &ValidatorV1 { validators(self).get_candidate_validator_ref(validator_address) } #[test_only] - public(package) fun set_epoch_for_testing(self: &mut IotaSystemStateV1, epoch_num: u64) { + public(package) fun set_epoch_for_testing(self: &mut IotaSystemStateV2, epoch_num: u64) { self.epoch = epoch_num } #[test_only] public(package) fun request_add_validator_for_testing( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, min_joining_stake_for_testing: u64, ctx: &TxContext, ) { @@ -939,7 +1111,7 @@ module iota_system::iota_system_state_inner { // in the process. #[test_only] public(package) fun request_add_validator_candidate_for_testing( - self: &mut IotaSystemStateV1, + self: &mut IotaSystemStateV2, pubkey_bytes: vector, network_pubkey_bytes: vector, protocol_pubkey_bytes: vector, diff --git a/crates/iota-framework/packages/iota-system/sources/system_display.move b/crates/iota-framework/packages/iota-system/sources/system_display.move new file mode 100644 index 00000000000..96d00965a6d --- /dev/null +++ b/crates/iota-framework/packages/iota-system/sources/system_display.move @@ -0,0 +1,100 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +module iota_system::system_display { + + use std::string; + + use iota::balance::Balance; + use iota::iota::IOTA; + use iota::timelock::TimeLock; + + use iota_system::iota_system::IotaSystemState; + use iota_system::staking_pool::StakedIota; + use iota_system::timelocked_staking::TimelockedStakedIota; + + #[allow(unused_function)] + /// Create a `Display` object for the `StakedIota` type. + fun create_staked_iota_display_v1( + iota_system: &mut IotaSystemState, + ctx: &mut TxContext, + ) { + // A display object content. + let keys = vector[ + string::utf8(b"principal"), + string::utf8(b"stake_activation_epoch"), + ]; + + let values = vector[ + string::utf8(b"{principal}"), + string::utf8(b"{stake_activation_epoch}"), + ]; + + // Create a display object. + let mut display = iota_system.new_system_display_with_fields(keys, values, ctx); + + // Commit the display object to apply changes. + display.update_version(); + + // Store the display object. + iota_system.insert_system_display_object(display); + } + + #[allow(unused_function)] + /// Create a `Display` object for the `TimelockedStakedIota` type. + fun create_timelocked_staked_iota_display_v1( + iota_system: &mut IotaSystemState, + ctx: &mut TxContext, + ) { + // A display object content. + let keys = vector[ + string::utf8(b"principal"), + string::utf8(b"stake_activation_epoch"), + string::utf8(b"expiration_timestamp_ms"), + string::utf8(b"label"), + ]; + + let values = vector[ + string::utf8(b"{staked_iota.principal}"), + string::utf8(b"{staked_iota.stake_activation_epoch}"), + string::utf8(b"{expiration_timestamp_ms}"), + string::utf8(b"{label}"), + ]; + + // Create a display object. + let mut display = iota_system.new_system_display_with_fields(keys, values, ctx); + + // Commit the display object to apply changes. + display.update_version(); + + // Store the display object. + iota_system.insert_system_display_object(display); + } + + #[allow(unused_function)] + /// Create a `Display` object for the `TimeLock>` type. + fun create_timelocked_iota_display_v1( + iota_system: &mut IotaSystemState, + ctx: &mut TxContext, + ) { + // A display object content. + let keys = vector[ + string::utf8(b"locked"), + string::utf8(b"expiration_timestamp_ms"), + ]; + + let values = vector[ + string::utf8(b"{locked}"), + string::utf8(b"{expiration_timestamp_ms}"), + ]; + + // Create a display object. + let mut display = iota_system.new_system_display_with_fields>>(keys, values, ctx); + + // Commit the display object to apply changes. + display.update_version(); + + // Store the display object. + iota_system.insert_system_display_object(display); + } +} diff --git a/crates/iota-framework/packages_compiled/iota-framework b/crates/iota-framework/packages_compiled/iota-framework index b1dfb3584d4..e6ebfffe882 100644 Binary files a/crates/iota-framework/packages_compiled/iota-framework and b/crates/iota-framework/packages_compiled/iota-framework differ diff --git a/crates/iota-framework/packages_compiled/iota-system b/crates/iota-framework/packages_compiled/iota-system index 794306b9814..78c9afff440 100644 Binary files a/crates/iota-framework/packages_compiled/iota-system and b/crates/iota-framework/packages_compiled/iota-system differ diff --git a/crates/iota-framework/published_api.txt b/crates/iota-framework/published_api.txt index fc186af1667..abfd94b777a 100644 --- a/crates/iota-framework/published_api.txt +++ b/crates/iota-framework/published_api.txt @@ -619,6 +619,9 @@ SystemParametersV1 IotaSystemStateV1 public struct 0x3::iota_system_state_inner +IotaSystemStateV2 + public struct + 0x3::iota_system_state_inner SystemEpochInfoEventV1 public struct 0x3::iota_system_state_inner @@ -628,6 +631,9 @@ create create_system_parameters public(package) fun 0x3::iota_system_state_inner +v1_to_v2 + public(package) fun + 0x3::iota_system_state_inner request_add_validator_candidate public(package) fun 0x3::iota_system_state_inner @@ -673,6 +679,27 @@ report_validator_impl undo_report_validator_impl fun 0x3::iota_system_state_inner +new_system_display + public(package) fun + 0x3::iota_system_state_inner +new_system_display_with_fields + public(package) fun + 0x3::iota_system_state_inner +insert_system_display_object + public(package) fun + 0x3::iota_system_state_inner +borrow_system_display_object + public(package) fun + 0x3::iota_system_state_inner +borrow_system_display_object_mut + public(package) fun + 0x3::iota_system_state_inner +contains_system_display_object + public(package) fun + 0x3::iota_system_state_inner +system_display_object_key + fun + 0x3::iota_system_state_inner rotate_operation_cap public(package) fun 0x3::iota_system_state_inner @@ -892,6 +919,24 @@ active_validator_addresses load_iota_system_admin_cap public(package) fun 0x3::iota_system +new_system_display + public(package) fun + 0x3::iota_system +new_system_display_with_fields + public(package) fun + 0x3::iota_system +insert_system_display_object + public(package) fun + 0x3::iota_system +borrow_system_display_object + public(package) fun + 0x3::iota_system +borrow_system_display_object_mut + public(package) fun + 0x3::iota_system +contains_system_display_object + public(package) fun + 0x3::iota_system advance_epoch fun 0x3::iota_system @@ -1000,6 +1045,15 @@ allocate_tokens activate_validators fun 0x3::genesis +create_staked_iota_display_v1 + fun + 0x3::system_display +create_timelocked_staked_iota_display_v1 + fun + 0x3::system_display +create_timelocked_iota_display_v1 + fun + 0x3::system_display secp256k1_ecrecover public fun 0x2::ecdsa_k1 @@ -2230,6 +2284,12 @@ get_entry_by_idx_mut remove_entry_by_idx public fun 0x2::vec_map +IotaSystemAdminCap + public struct + 0x2::system_admin_cap +new_system_admin_cap + fun + 0x2::system_admin_cap Publisher public struct 0x2::package @@ -2329,6 +2389,12 @@ new new_with_fields public fun 0x2::display +system_new + public fun + 0x2::display +system_new_with_fields + public fun + 0x2::display create_and_keep public entry fun 0x2::display @@ -2350,6 +2416,9 @@ remove is_authorized public fun 0x2::display +id + public fun + 0x2::display version public fun 0x2::display @@ -2995,12 +3064,6 @@ generate_u8_in_range shuffle public fun 0x2::random -IotaSystemAdminCap - public struct - 0x2::system_admin_cap -new_system_admin_cap - fun - 0x2::system_admin_cap Table public struct 0x2::table diff --git a/crates/iota-genesis-builder/src/lib.rs b/crates/iota-genesis-builder/src/lib.rs index b3725eded9b..9c89f20257a 100644 --- a/crates/iota-genesis-builder/src/lib.rs +++ b/crates/iota-genesis-builder/src/lib.rs @@ -473,9 +473,8 @@ impl Builder { #[allow(clippy::infallible_destructuring_match)] let system_state = match unsigned_genesis.iota_system_object() { IotaSystemState::V1(inner) => inner, - #[cfg(msim)] _ => { - // Types other than V1 used in simtests do not need to be validated. + // Types other than V1 and used in simtests do not need to be validated. return; } }; diff --git a/crates/iota-graphql-rpc/src/types/transaction_block_kind/end_of_epoch.rs b/crates/iota-graphql-rpc/src/types/transaction_block_kind/end_of_epoch.rs index 45df35c47bd..89fe92df60f 100644 --- a/crates/iota-graphql-rpc/src/types/transaction_block_kind/end_of_epoch.rs +++ b/crates/iota-graphql-rpc/src/types/transaction_block_kind/end_of_epoch.rs @@ -287,6 +287,7 @@ impl EndOfEpochTransactionKind { checkpoint_viewed_at, }) } + N::SystemDisplay(_) => todo!(), } } } diff --git a/crates/iota-json-rpc-types/src/iota_transaction.rs b/crates/iota-json-rpc-types/src/iota_transaction.rs index 23e4cdfc8c0..42b1da949ec 100644 --- a/crates/iota-json-rpc-types/src/iota_transaction.rs +++ b/crates/iota-json-rpc-types/src/iota_transaction.rs @@ -37,7 +37,8 @@ use iota_types::{ transaction::{ Argument, CallArg, ChangeEpoch, Command, EndOfEpochTransactionKind, GenesisObject, InputObjectKind, ObjectArg, ProgrammableMoveCall, ProgrammableTransaction, - SenderSignedData, TransactionData, TransactionDataAPI, TransactionKind, + SenderSignedData, SystemDisplayTransactionKind, TransactionData, TransactionDataAPI, + TransactionKind, }, }; use move_binary_format::CompiledModule; @@ -528,6 +529,11 @@ impl IotaTransactionBlockKind { ) => IotaEndOfEpochTransactionKind::BridgeCommitteeUpdate( bridge_shared_version, ), + EndOfEpochTransactionKind::SystemDisplay(vec) => { + IotaEndOfEpochTransactionKind::SystemDisplay( + vec.into_iter().map(|t| t.into()).collect(), + ) + } }) .collect(), }) @@ -612,6 +618,11 @@ impl IotaTransactionBlockKind { EndOfEpochTransactionKind::BridgeCommitteeInit(seq) => { IotaEndOfEpochTransactionKind::BridgeCommitteeUpdate(seq) } + EndOfEpochTransactionKind::SystemDisplay(vec) => { + IotaEndOfEpochTransactionKind::SystemDisplay( + vec.into_iter().map(|t| t.into()).collect(), + ) + } }) .collect(), }) @@ -1607,6 +1618,30 @@ pub struct IotaEndOfEpochTransaction { pub transactions: Vec, } +#[serde_as] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +pub enum IotaSystemDisplayTransactionKind { + StakedIotaV1, + TimelockedStakedIotaV1, + TimelockedIotaV1, +} + +impl From for IotaSystemDisplayTransactionKind { + fn from(input: SystemDisplayTransactionKind) -> Self { + match input { + SystemDisplayTransactionKind::StakedIotaV1 => { + IotaSystemDisplayTransactionKind::StakedIotaV1 + } + SystemDisplayTransactionKind::TimelockedStakedIotaV1 => { + IotaSystemDisplayTransactionKind::TimelockedStakedIotaV1 + } + SystemDisplayTransactionKind::TimelockedIotaV1 => { + IotaSystemDisplayTransactionKind::TimelockedIotaV1 + } + } + } +} + #[serde_as] #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] pub enum IotaEndOfEpochTransactionKind { @@ -1615,6 +1650,7 @@ pub enum IotaEndOfEpochTransactionKind { AuthenticatorStateExpire(IotaAuthenticatorStateExpire), BridgeStateCreate(CheckpointDigest), BridgeCommitteeUpdate(SequenceNumber), + SystemDisplay(Vec), } #[serde_as] diff --git a/crates/iota-protocol-config/src/lib.rs b/crates/iota-protocol-config/src/lib.rs index 3ca28d34e66..e5b4a9b70b0 100644 --- a/crates/iota-protocol-config/src/lib.rs +++ b/crates/iota-protocol-config/src/lib.rs @@ -16,7 +16,7 @@ use tracing::{info, warn}; /// The minimum and maximum protocol versions supported by this build. const MIN_PROTOCOL_VERSION: u64 = 1; -pub const MAX_PROTOCOL_VERSION: u64 = 1; +pub const MAX_PROTOCOL_VERSION: u64 = 2; // Record history of protocol version allocations here: // @@ -180,6 +180,18 @@ struct FeatureFlags { // This flag is used to provide the correct MoveVM configuration for clients. #[serde(skip_serializing_if = "is_true")] rethrow_serialization_type_layout_errors: bool, + + // Enable the `StakedIota` display object V1. + #[serde(skip_serializing_if = "is_false")] + enable_staked_iota_display_v1: bool, + + // Enable the `TimelockedStakedIota` display object V1. + #[serde(skip_serializing_if = "is_false")] + enable_timelocked_staked_iota_display_v1: bool, + + // Enable the `Timelock>` display object V1. + #[serde(skip_serializing_if = "is_false")] + enable_timelocked_iota_display_v1: bool, } fn is_true(b: &bool) -> bool { @@ -1050,6 +1062,18 @@ impl ProtocolConfig { pub fn rethrow_serialization_type_layout_errors(&self) -> bool { self.feature_flags.rethrow_serialization_type_layout_errors } + + pub fn enable_staked_iota_display_v1(&self) -> bool { + self.feature_flags.enable_staked_iota_display_v1 + } + + pub fn enable_timelocked_staked_iota_display_v1(&self) -> bool { + self.feature_flags.enable_timelocked_staked_iota_display_v1 + } + + pub fn enable_timelocked_iota_display_v1(&self) -> bool { + self.feature_flags.enable_timelocked_iota_display_v1 + } } #[cfg(not(msim))] @@ -1630,13 +1654,16 @@ impl ProtocolConfig { } // Ignore this check for the fake versions for - // `test_choose_next_system_packages`. TODO: remove the never_loop - // attribute when the version 2 is added. - #[allow(clippy::never_loop)] + // `test_choose_next_system_packages`. #[cfg(not(msim))] for cur in 2..=version.0 { match cur { 1 => unreachable!(), + 2 => { + cfg.feature_flags.enable_staked_iota_display_v1 = true; + cfg.feature_flags.enable_timelocked_staked_iota_display_v1 = true; + cfg.feature_flags.enable_timelocked_iota_display_v1 = true; + } // Use this template when making changes: // diff --git a/crates/iota-protocol-config/src/snapshots/iota_protocol_config__test__Mainnet_version_2.snap b/crates/iota-protocol-config/src/snapshots/iota_protocol_config__test__Mainnet_version_2.snap new file mode 100644 index 00000000000..4f800ce47dd --- /dev/null +++ b/crates/iota-protocol-config/src/snapshots/iota_protocol_config__test__Mainnet_version_2.snap @@ -0,0 +1,272 @@ +--- +source: crates/iota-protocol-config/src/lib.rs +expression: "ProtocolConfig::get_for_version(cur, *chain_id)" +--- +version: 2 +feature_flags: + consensus_transaction_ordering: ByGasPrice + per_object_congestion_control_mode: TotalTxCount + zklogin_max_epoch_upper_bound_delta: 30 + enable_staked_iota_display_v1: true + enable_timelocked_staked_iota_display_v1: true + enable_timelocked_iota_display_v1: true +max_tx_size_bytes: 131072 +max_input_objects: 2048 +max_size_written_objects: 5000000 +max_size_written_objects_system_tx: 50000000 +max_serialized_tx_effects_size_bytes: 524288 +max_serialized_tx_effects_size_bytes_system_tx: 8388608 +max_gas_payment_objects: 256 +max_modules_in_publish: 64 +max_package_dependencies: 32 +max_arguments: 512 +max_type_arguments: 16 +max_type_argument_depth: 16 +max_pure_argument_size: 16384 +max_programmable_tx_commands: 1024 +move_binary_format_version: 7 +min_move_binary_format_version: 6 +binary_module_handles: 100 +binary_struct_handles: 300 +binary_function_handles: 1500 +binary_function_instantiations: 750 +binary_signatures: 1000 +binary_constant_pool: 4000 +binary_identifiers: 10000 +binary_address_identifiers: 100 +binary_struct_defs: 200 +binary_struct_def_instantiations: 100 +binary_function_defs: 1000 +binary_field_handles: 500 +binary_field_instantiations: 250 +binary_friend_decls: 100 +max_move_object_size: 256000 +max_move_package_size: 102400 +max_publish_or_upgrade_per_ptb: 5 +max_tx_gas: 50000000000 +max_gas_price: 100000 +max_gas_computation_bucket: 5000000 +gas_rounding_step: 1000 +max_loop_depth: 5 +max_generic_instantiation_length: 32 +max_function_parameters: 128 +max_basic_blocks: 1024 +max_value_stack_size: 1024 +max_type_nodes: 256 +max_push_size: 10000 +max_struct_definitions: 200 +max_function_definitions: 1000 +max_fields_in_struct: 32 +max_dependency_depth: 100 +max_num_event_emit: 1024 +max_num_new_move_object_ids: 2048 +max_num_new_move_object_ids_system_tx: 32768 +max_num_deleted_move_object_ids: 2048 +max_num_deleted_move_object_ids_system_tx: 32768 +max_num_transferred_move_object_ids: 2048 +max_num_transferred_move_object_ids_system_tx: 32768 +max_event_emit_size: 256000 +max_event_emit_size_total: 65536000 +max_move_vector_len: 262144 +max_move_identifier_len: 128 +max_move_value_depth: 128 +max_back_edges_per_function: 10000 +max_back_edges_per_module: 10000 +max_verifier_meter_ticks_per_function: 16000000 +max_meter_ticks_per_module: 16000000 +max_meter_ticks_per_package: 16000000 +object_runtime_max_num_cached_objects: 1000 +object_runtime_max_num_cached_objects_system_tx: 16000 +object_runtime_max_num_store_entries: 1000 +object_runtime_max_num_store_entries_system_tx: 16000 +base_tx_cost_fixed: 1000 +package_publish_cost_fixed: 1000 +base_tx_cost_per_byte: 0 +package_publish_cost_per_byte: 80 +obj_access_cost_read_per_byte: 15 +obj_access_cost_mutate_per_byte: 40 +obj_access_cost_delete_per_byte: 40 +obj_access_cost_verify_per_byte: 200 +gas_model_version: 1 +obj_data_cost_refundable: 100 +obj_metadata_cost_non_refundable: 50 +storage_rebate_rate: 10000 +reward_slashing_rate: 10000 +storage_gas_price: 76 +validator_target_reward: 767000000000000 +max_transactions_per_checkpoint: 10000 +max_checkpoint_size_bytes: 31457280 +buffer_stake_for_protocol_upgrade_bps: 5000 +address_from_bytes_cost_base: 52 +address_to_u256_cost_base: 52 +address_from_u256_cost_base: 52 +config_read_setting_impl_cost_base: 100 +config_read_setting_impl_cost_per_byte: 40 +dynamic_field_hash_type_and_key_cost_base: 100 +dynamic_field_hash_type_and_key_type_cost_per_byte: 2 +dynamic_field_hash_type_and_key_value_cost_per_byte: 2 +dynamic_field_hash_type_and_key_type_tag_cost_per_byte: 2 +dynamic_field_add_child_object_cost_base: 100 +dynamic_field_add_child_object_type_cost_per_byte: 10 +dynamic_field_add_child_object_value_cost_per_byte: 10 +dynamic_field_add_child_object_struct_tag_cost_per_byte: 10 +dynamic_field_borrow_child_object_cost_base: 100 +dynamic_field_borrow_child_object_child_ref_cost_per_byte: 10 +dynamic_field_borrow_child_object_type_cost_per_byte: 10 +dynamic_field_remove_child_object_cost_base: 100 +dynamic_field_remove_child_object_child_cost_per_byte: 2 +dynamic_field_remove_child_object_type_cost_per_byte: 2 +dynamic_field_has_child_object_cost_base: 100 +dynamic_field_has_child_object_with_ty_cost_base: 100 +dynamic_field_has_child_object_with_ty_type_cost_per_byte: 2 +dynamic_field_has_child_object_with_ty_type_tag_cost_per_byte: 2 +event_emit_cost_base: 52 +event_emit_value_size_derivation_cost_per_byte: 2 +event_emit_tag_size_derivation_cost_per_byte: 5 +event_emit_output_cost_per_byte: 10 +object_borrow_uid_cost_base: 52 +object_delete_impl_cost_base: 52 +object_record_new_uid_cost_base: 52 +transfer_transfer_internal_cost_base: 52 +transfer_freeze_object_cost_base: 52 +transfer_share_object_cost_base: 52 +transfer_receive_object_cost_base: 52 +tx_context_derive_id_cost_base: 52 +types_is_one_time_witness_cost_base: 52 +types_is_one_time_witness_type_tag_cost_per_byte: 2 +types_is_one_time_witness_type_cost_per_byte: 2 +validator_validate_metadata_cost_base: 52 +validator_validate_metadata_data_cost_per_byte: 2 +crypto_invalid_arguments_cost: 100 +bls12381_bls12381_min_sig_verify_cost_base: 52 +bls12381_bls12381_min_sig_verify_msg_cost_per_byte: 2 +bls12381_bls12381_min_sig_verify_msg_cost_per_block: 2 +bls12381_bls12381_min_pk_verify_cost_base: 52 +bls12381_bls12381_min_pk_verify_msg_cost_per_byte: 2 +bls12381_bls12381_min_pk_verify_msg_cost_per_block: 2 +ecdsa_k1_ecrecover_keccak256_cost_base: 52 +ecdsa_k1_ecrecover_keccak256_msg_cost_per_byte: 2 +ecdsa_k1_ecrecover_keccak256_msg_cost_per_block: 2 +ecdsa_k1_ecrecover_sha256_cost_base: 52 +ecdsa_k1_ecrecover_sha256_msg_cost_per_byte: 2 +ecdsa_k1_ecrecover_sha256_msg_cost_per_block: 2 +ecdsa_k1_decompress_pubkey_cost_base: 52 +ecdsa_k1_secp256k1_verify_keccak256_cost_base: 52 +ecdsa_k1_secp256k1_verify_keccak256_msg_cost_per_byte: 2 +ecdsa_k1_secp256k1_verify_keccak256_msg_cost_per_block: 2 +ecdsa_k1_secp256k1_verify_sha256_cost_base: 52 +ecdsa_k1_secp256k1_verify_sha256_msg_cost_per_byte: 2 +ecdsa_k1_secp256k1_verify_sha256_msg_cost_per_block: 2 +ecdsa_r1_ecrecover_keccak256_cost_base: 52 +ecdsa_r1_ecrecover_keccak256_msg_cost_per_byte: 2 +ecdsa_r1_ecrecover_keccak256_msg_cost_per_block: 2 +ecdsa_r1_ecrecover_sha256_cost_base: 52 +ecdsa_r1_ecrecover_sha256_msg_cost_per_byte: 2 +ecdsa_r1_ecrecover_sha256_msg_cost_per_block: 2 +ecdsa_r1_secp256r1_verify_keccak256_cost_base: 52 +ecdsa_r1_secp256r1_verify_keccak256_msg_cost_per_byte: 2 +ecdsa_r1_secp256r1_verify_keccak256_msg_cost_per_block: 2 +ecdsa_r1_secp256r1_verify_sha256_cost_base: 52 +ecdsa_r1_secp256r1_verify_sha256_msg_cost_per_byte: 2 +ecdsa_r1_secp256r1_verify_sha256_msg_cost_per_block: 2 +ecvrf_ecvrf_verify_cost_base: 52 +ecvrf_ecvrf_verify_alpha_string_cost_per_byte: 2 +ecvrf_ecvrf_verify_alpha_string_cost_per_block: 2 +ed25519_ed25519_verify_cost_base: 52 +ed25519_ed25519_verify_msg_cost_per_byte: 2 +ed25519_ed25519_verify_msg_cost_per_block: 2 +groth16_prepare_verifying_key_bls12381_cost_base: 52 +groth16_prepare_verifying_key_bn254_cost_base: 52 +groth16_verify_groth16_proof_internal_bls12381_cost_base: 52 +groth16_verify_groth16_proof_internal_bls12381_cost_per_public_input: 2 +groth16_verify_groth16_proof_internal_bn254_cost_base: 52 +groth16_verify_groth16_proof_internal_bn254_cost_per_public_input: 2 +groth16_verify_groth16_proof_internal_public_input_cost_per_byte: 2 +hash_blake2b256_cost_base: 52 +hash_blake2b256_data_cost_per_byte: 2 +hash_blake2b256_data_cost_per_block: 2 +hash_keccak256_cost_base: 52 +hash_keccak256_data_cost_per_byte: 2 +hash_keccak256_data_cost_per_block: 2 +group_ops_bls12381_decode_scalar_cost: 52 +group_ops_bls12381_decode_g1_cost: 52 +group_ops_bls12381_decode_g2_cost: 52 +group_ops_bls12381_decode_gt_cost: 52 +group_ops_bls12381_scalar_add_cost: 52 +group_ops_bls12381_g1_add_cost: 52 +group_ops_bls12381_g2_add_cost: 52 +group_ops_bls12381_gt_add_cost: 52 +group_ops_bls12381_scalar_sub_cost: 52 +group_ops_bls12381_g1_sub_cost: 52 +group_ops_bls12381_g2_sub_cost: 52 +group_ops_bls12381_gt_sub_cost: 52 +group_ops_bls12381_scalar_mul_cost: 52 +group_ops_bls12381_g1_mul_cost: 52 +group_ops_bls12381_g2_mul_cost: 52 +group_ops_bls12381_gt_mul_cost: 52 +group_ops_bls12381_scalar_div_cost: 52 +group_ops_bls12381_g1_div_cost: 52 +group_ops_bls12381_g2_div_cost: 52 +group_ops_bls12381_gt_div_cost: 52 +group_ops_bls12381_g1_hash_to_base_cost: 52 +group_ops_bls12381_g2_hash_to_base_cost: 52 +group_ops_bls12381_g1_hash_to_cost_per_byte: 2 +group_ops_bls12381_g2_hash_to_cost_per_byte: 2 +group_ops_bls12381_g1_msm_base_cost: 52 +group_ops_bls12381_g2_msm_base_cost: 52 +group_ops_bls12381_g1_msm_base_cost_per_input: 52 +group_ops_bls12381_g2_msm_base_cost_per_input: 52 +group_ops_bls12381_msm_max_len: 32 +group_ops_bls12381_pairing_cost: 52 +hmac_hmac_sha3_256_cost_base: 52 +hmac_hmac_sha3_256_input_cost_per_byte: 2 +hmac_hmac_sha3_256_input_cost_per_block: 2 +check_zklogin_id_cost_base: 200 +check_zklogin_issuer_cost_base: 200 +bcs_per_byte_serialized_cost: 2 +bcs_legacy_min_output_size_cost: 1 +bcs_failure_cost: 52 +hash_sha2_256_base_cost: 52 +hash_sha2_256_per_byte_cost: 2 +hash_sha2_256_legacy_min_input_len_cost: 1 +hash_sha3_256_base_cost: 52 +hash_sha3_256_per_byte_cost: 2 +hash_sha3_256_legacy_min_input_len_cost: 1 +type_name_get_base_cost: 52 +type_name_get_per_byte_cost: 2 +string_check_utf8_base_cost: 52 +string_check_utf8_per_byte_cost: 2 +string_is_char_boundary_base_cost: 52 +string_sub_string_base_cost: 52 +string_sub_string_per_byte_cost: 2 +string_index_of_base_cost: 52 +string_index_of_per_byte_pattern_cost: 2 +string_index_of_per_byte_searched_cost: 2 +vector_empty_base_cost: 52 +vector_length_base_cost: 52 +vector_push_back_base_cost: 52 +vector_push_back_legacy_per_abstract_memory_unit_cost: 2 +vector_borrow_base_cost: 52 +vector_pop_back_base_cost: 52 +vector_destroy_empty_base_cost: 52 +vector_swap_base_cost: 52 +debug_print_base_cost: 52 +debug_print_stack_trace_base_cost: 52 +execution_version: 1 +consensus_bad_nodes_stake_threshold: 20 +max_jwk_votes_per_validator_per_epoch: 240 +max_age_of_jwk_in_epochs: 1 +random_beacon_reduction_allowed_delta: 800 +random_beacon_reduction_lower_bound: 1000 +random_beacon_dkg_timeout_round: 3000 +random_beacon_min_round_interval_ms: 500 +random_beacon_dkg_version: 1 +consensus_max_transaction_size_bytes: 262144 +consensus_max_transactions_in_block_bytes: 524288 +consensus_max_num_transactions_in_block: 512 +max_deferral_rounds_for_congestion_control: 10 +min_checkpoint_interval_ms: 200 +checkpoint_summary_version_specific_data: 1 +max_soft_bundle_size: 5 +bridge_should_try_to_finalize_committee: false +max_accumulated_txn_cost_per_object_in_mysticeti_commit: 10 diff --git a/crates/iota-protocol-config/src/snapshots/iota_protocol_config__test__Testnet_version_2.snap b/crates/iota-protocol-config/src/snapshots/iota_protocol_config__test__Testnet_version_2.snap new file mode 100644 index 00000000000..9446a6cdf19 --- /dev/null +++ b/crates/iota-protocol-config/src/snapshots/iota_protocol_config__test__Testnet_version_2.snap @@ -0,0 +1,272 @@ +--- +source: crates/iota-protocol-config/src/lib.rs +expression: "ProtocolConfig::get_for_version(cur, *chain_id)" +--- +version: 2 +feature_flags: + consensus_transaction_ordering: ByGasPrice + per_object_congestion_control_mode: TotalTxCount + zklogin_max_epoch_upper_bound_delta: 30 + enable_staked_iota_display_v1: true + enable_timelocked_staked_iota_display_v1: true + enable_timelocked_iota_display_v1: true +max_tx_size_bytes: 131072 +max_input_objects: 2048 +max_size_written_objects: 5000000 +max_size_written_objects_system_tx: 50000000 +max_serialized_tx_effects_size_bytes: 524288 +max_serialized_tx_effects_size_bytes_system_tx: 8388608 +max_gas_payment_objects: 256 +max_modules_in_publish: 64 +max_package_dependencies: 32 +max_arguments: 512 +max_type_arguments: 16 +max_type_argument_depth: 16 +max_pure_argument_size: 16384 +max_programmable_tx_commands: 1024 +move_binary_format_version: 7 +min_move_binary_format_version: 6 +binary_module_handles: 100 +binary_struct_handles: 300 +binary_function_handles: 1500 +binary_function_instantiations: 750 +binary_signatures: 1000 +binary_constant_pool: 4000 +binary_identifiers: 10000 +binary_address_identifiers: 100 +binary_struct_defs: 200 +binary_struct_def_instantiations: 100 +binary_function_defs: 1000 +binary_field_handles: 500 +binary_field_instantiations: 250 +binary_friend_decls: 100 +max_move_object_size: 256000 +max_move_package_size: 102400 +max_publish_or_upgrade_per_ptb: 5 +max_tx_gas: 50000000000 +max_gas_price: 100000 +max_gas_computation_bucket: 5000000 +gas_rounding_step: 1000 +max_loop_depth: 5 +max_generic_instantiation_length: 32 +max_function_parameters: 128 +max_basic_blocks: 1024 +max_value_stack_size: 1024 +max_type_nodes: 256 +max_push_size: 10000 +max_struct_definitions: 200 +max_function_definitions: 1000 +max_fields_in_struct: 32 +max_dependency_depth: 100 +max_num_event_emit: 1024 +max_num_new_move_object_ids: 2048 +max_num_new_move_object_ids_system_tx: 32768 +max_num_deleted_move_object_ids: 2048 +max_num_deleted_move_object_ids_system_tx: 32768 +max_num_transferred_move_object_ids: 2048 +max_num_transferred_move_object_ids_system_tx: 32768 +max_event_emit_size: 256000 +max_event_emit_size_total: 65536000 +max_move_vector_len: 262144 +max_move_identifier_len: 128 +max_move_value_depth: 128 +max_back_edges_per_function: 10000 +max_back_edges_per_module: 10000 +max_verifier_meter_ticks_per_function: 16000000 +max_meter_ticks_per_module: 16000000 +max_meter_ticks_per_package: 16000000 +object_runtime_max_num_cached_objects: 1000 +object_runtime_max_num_cached_objects_system_tx: 16000 +object_runtime_max_num_store_entries: 1000 +object_runtime_max_num_store_entries_system_tx: 16000 +base_tx_cost_fixed: 1000 +package_publish_cost_fixed: 1000 +base_tx_cost_per_byte: 0 +package_publish_cost_per_byte: 80 +obj_access_cost_read_per_byte: 15 +obj_access_cost_mutate_per_byte: 40 +obj_access_cost_delete_per_byte: 40 +obj_access_cost_verify_per_byte: 200 +gas_model_version: 1 +obj_data_cost_refundable: 100 +obj_metadata_cost_non_refundable: 50 +storage_rebate_rate: 10000 +reward_slashing_rate: 10000 +storage_gas_price: 76 +validator_target_reward: 767000000000000 +max_transactions_per_checkpoint: 10000 +max_checkpoint_size_bytes: 31457280 +buffer_stake_for_protocol_upgrade_bps: 5000 +address_from_bytes_cost_base: 52 +address_to_u256_cost_base: 52 +address_from_u256_cost_base: 52 +config_read_setting_impl_cost_base: 100 +config_read_setting_impl_cost_per_byte: 40 +dynamic_field_hash_type_and_key_cost_base: 100 +dynamic_field_hash_type_and_key_type_cost_per_byte: 2 +dynamic_field_hash_type_and_key_value_cost_per_byte: 2 +dynamic_field_hash_type_and_key_type_tag_cost_per_byte: 2 +dynamic_field_add_child_object_cost_base: 100 +dynamic_field_add_child_object_type_cost_per_byte: 10 +dynamic_field_add_child_object_value_cost_per_byte: 10 +dynamic_field_add_child_object_struct_tag_cost_per_byte: 10 +dynamic_field_borrow_child_object_cost_base: 100 +dynamic_field_borrow_child_object_child_ref_cost_per_byte: 10 +dynamic_field_borrow_child_object_type_cost_per_byte: 10 +dynamic_field_remove_child_object_cost_base: 100 +dynamic_field_remove_child_object_child_cost_per_byte: 2 +dynamic_field_remove_child_object_type_cost_per_byte: 2 +dynamic_field_has_child_object_cost_base: 100 +dynamic_field_has_child_object_with_ty_cost_base: 100 +dynamic_field_has_child_object_with_ty_type_cost_per_byte: 2 +dynamic_field_has_child_object_with_ty_type_tag_cost_per_byte: 2 +event_emit_cost_base: 52 +event_emit_value_size_derivation_cost_per_byte: 2 +event_emit_tag_size_derivation_cost_per_byte: 5 +event_emit_output_cost_per_byte: 10 +object_borrow_uid_cost_base: 52 +object_delete_impl_cost_base: 52 +object_record_new_uid_cost_base: 52 +transfer_transfer_internal_cost_base: 52 +transfer_freeze_object_cost_base: 52 +transfer_share_object_cost_base: 52 +transfer_receive_object_cost_base: 52 +tx_context_derive_id_cost_base: 52 +types_is_one_time_witness_cost_base: 52 +types_is_one_time_witness_type_tag_cost_per_byte: 2 +types_is_one_time_witness_type_cost_per_byte: 2 +validator_validate_metadata_cost_base: 52 +validator_validate_metadata_data_cost_per_byte: 2 +crypto_invalid_arguments_cost: 100 +bls12381_bls12381_min_sig_verify_cost_base: 52 +bls12381_bls12381_min_sig_verify_msg_cost_per_byte: 2 +bls12381_bls12381_min_sig_verify_msg_cost_per_block: 2 +bls12381_bls12381_min_pk_verify_cost_base: 52 +bls12381_bls12381_min_pk_verify_msg_cost_per_byte: 2 +bls12381_bls12381_min_pk_verify_msg_cost_per_block: 2 +ecdsa_k1_ecrecover_keccak256_cost_base: 52 +ecdsa_k1_ecrecover_keccak256_msg_cost_per_byte: 2 +ecdsa_k1_ecrecover_keccak256_msg_cost_per_block: 2 +ecdsa_k1_ecrecover_sha256_cost_base: 52 +ecdsa_k1_ecrecover_sha256_msg_cost_per_byte: 2 +ecdsa_k1_ecrecover_sha256_msg_cost_per_block: 2 +ecdsa_k1_decompress_pubkey_cost_base: 52 +ecdsa_k1_secp256k1_verify_keccak256_cost_base: 52 +ecdsa_k1_secp256k1_verify_keccak256_msg_cost_per_byte: 2 +ecdsa_k1_secp256k1_verify_keccak256_msg_cost_per_block: 2 +ecdsa_k1_secp256k1_verify_sha256_cost_base: 52 +ecdsa_k1_secp256k1_verify_sha256_msg_cost_per_byte: 2 +ecdsa_k1_secp256k1_verify_sha256_msg_cost_per_block: 2 +ecdsa_r1_ecrecover_keccak256_cost_base: 52 +ecdsa_r1_ecrecover_keccak256_msg_cost_per_byte: 2 +ecdsa_r1_ecrecover_keccak256_msg_cost_per_block: 2 +ecdsa_r1_ecrecover_sha256_cost_base: 52 +ecdsa_r1_ecrecover_sha256_msg_cost_per_byte: 2 +ecdsa_r1_ecrecover_sha256_msg_cost_per_block: 2 +ecdsa_r1_secp256r1_verify_keccak256_cost_base: 52 +ecdsa_r1_secp256r1_verify_keccak256_msg_cost_per_byte: 2 +ecdsa_r1_secp256r1_verify_keccak256_msg_cost_per_block: 2 +ecdsa_r1_secp256r1_verify_sha256_cost_base: 52 +ecdsa_r1_secp256r1_verify_sha256_msg_cost_per_byte: 2 +ecdsa_r1_secp256r1_verify_sha256_msg_cost_per_block: 2 +ecvrf_ecvrf_verify_cost_base: 52 +ecvrf_ecvrf_verify_alpha_string_cost_per_byte: 2 +ecvrf_ecvrf_verify_alpha_string_cost_per_block: 2 +ed25519_ed25519_verify_cost_base: 52 +ed25519_ed25519_verify_msg_cost_per_byte: 2 +ed25519_ed25519_verify_msg_cost_per_block: 2 +groth16_prepare_verifying_key_bls12381_cost_base: 52 +groth16_prepare_verifying_key_bn254_cost_base: 52 +groth16_verify_groth16_proof_internal_bls12381_cost_base: 52 +groth16_verify_groth16_proof_internal_bls12381_cost_per_public_input: 2 +groth16_verify_groth16_proof_internal_bn254_cost_base: 52 +groth16_verify_groth16_proof_internal_bn254_cost_per_public_input: 2 +groth16_verify_groth16_proof_internal_public_input_cost_per_byte: 2 +hash_blake2b256_cost_base: 52 +hash_blake2b256_data_cost_per_byte: 2 +hash_blake2b256_data_cost_per_block: 2 +hash_keccak256_cost_base: 52 +hash_keccak256_data_cost_per_byte: 2 +hash_keccak256_data_cost_per_block: 2 +group_ops_bls12381_decode_scalar_cost: 52 +group_ops_bls12381_decode_g1_cost: 52 +group_ops_bls12381_decode_g2_cost: 52 +group_ops_bls12381_decode_gt_cost: 52 +group_ops_bls12381_scalar_add_cost: 52 +group_ops_bls12381_g1_add_cost: 52 +group_ops_bls12381_g2_add_cost: 52 +group_ops_bls12381_gt_add_cost: 52 +group_ops_bls12381_scalar_sub_cost: 52 +group_ops_bls12381_g1_sub_cost: 52 +group_ops_bls12381_g2_sub_cost: 52 +group_ops_bls12381_gt_sub_cost: 52 +group_ops_bls12381_scalar_mul_cost: 52 +group_ops_bls12381_g1_mul_cost: 52 +group_ops_bls12381_g2_mul_cost: 52 +group_ops_bls12381_gt_mul_cost: 52 +group_ops_bls12381_scalar_div_cost: 52 +group_ops_bls12381_g1_div_cost: 52 +group_ops_bls12381_g2_div_cost: 52 +group_ops_bls12381_gt_div_cost: 52 +group_ops_bls12381_g1_hash_to_base_cost: 52 +group_ops_bls12381_g2_hash_to_base_cost: 52 +group_ops_bls12381_g1_hash_to_cost_per_byte: 2 +group_ops_bls12381_g2_hash_to_cost_per_byte: 2 +group_ops_bls12381_g1_msm_base_cost: 52 +group_ops_bls12381_g2_msm_base_cost: 52 +group_ops_bls12381_g1_msm_base_cost_per_input: 52 +group_ops_bls12381_g2_msm_base_cost_per_input: 52 +group_ops_bls12381_msm_max_len: 32 +group_ops_bls12381_pairing_cost: 52 +hmac_hmac_sha3_256_cost_base: 52 +hmac_hmac_sha3_256_input_cost_per_byte: 2 +hmac_hmac_sha3_256_input_cost_per_block: 2 +check_zklogin_id_cost_base: 200 +check_zklogin_issuer_cost_base: 200 +bcs_per_byte_serialized_cost: 2 +bcs_legacy_min_output_size_cost: 1 +bcs_failure_cost: 52 +hash_sha2_256_base_cost: 52 +hash_sha2_256_per_byte_cost: 2 +hash_sha2_256_legacy_min_input_len_cost: 1 +hash_sha3_256_base_cost: 52 +hash_sha3_256_per_byte_cost: 2 +hash_sha3_256_legacy_min_input_len_cost: 1 +type_name_get_base_cost: 52 +type_name_get_per_byte_cost: 2 +string_check_utf8_base_cost: 52 +string_check_utf8_per_byte_cost: 2 +string_is_char_boundary_base_cost: 52 +string_sub_string_base_cost: 52 +string_sub_string_per_byte_cost: 2 +string_index_of_base_cost: 52 +string_index_of_per_byte_pattern_cost: 2 +string_index_of_per_byte_searched_cost: 2 +vector_empty_base_cost: 52 +vector_length_base_cost: 52 +vector_push_back_base_cost: 52 +vector_push_back_legacy_per_abstract_memory_unit_cost: 2 +vector_borrow_base_cost: 52 +vector_pop_back_base_cost: 52 +vector_destroy_empty_base_cost: 52 +vector_swap_base_cost: 52 +debug_print_base_cost: 52 +debug_print_stack_trace_base_cost: 52 +execution_version: 1 +consensus_bad_nodes_stake_threshold: 20 +max_jwk_votes_per_validator_per_epoch: 240 +max_age_of_jwk_in_epochs: 1 +random_beacon_reduction_allowed_delta: 800 +random_beacon_reduction_lower_bound: 1000 +random_beacon_dkg_timeout_round: 3000 +random_beacon_min_round_interval_ms: 500 +random_beacon_dkg_version: 1 +consensus_max_transaction_size_bytes: 262144 +consensus_max_transactions_in_block_bytes: 524288 +consensus_max_num_transactions_in_block: 512 +max_deferral_rounds_for_congestion_control: 10 +min_checkpoint_interval_ms: 200 +checkpoint_summary_version_specific_data: 1 +max_soft_bundle_size: 5 +bridge_should_try_to_finalize_committee: true +max_accumulated_txn_cost_per_object_in_mysticeti_commit: 10 diff --git a/crates/iota-protocol-config/src/snapshots/iota_protocol_config__test__version_2.snap b/crates/iota-protocol-config/src/snapshots/iota_protocol_config__test__version_2.snap new file mode 100644 index 00000000000..a9cb62bf643 --- /dev/null +++ b/crates/iota-protocol-config/src/snapshots/iota_protocol_config__test__version_2.snap @@ -0,0 +1,280 @@ +--- +source: crates/iota-protocol-config/src/lib.rs +expression: "ProtocolConfig::get_for_version(cur, *chain_id)" +--- +version: 2 +feature_flags: + consensus_transaction_ordering: ByGasPrice + enable_poseidon: true + enable_group_ops_native_function_msm: true + per_object_congestion_control_mode: TotalTxCount + zklogin_max_epoch_upper_bound_delta: 30 + enable_vdf: true + passkey_auth: true + enable_staked_iota_display_v1: true + enable_timelocked_staked_iota_display_v1: true + enable_timelocked_iota_display_v1: true +max_tx_size_bytes: 131072 +max_input_objects: 2048 +max_size_written_objects: 5000000 +max_size_written_objects_system_tx: 50000000 +max_serialized_tx_effects_size_bytes: 524288 +max_serialized_tx_effects_size_bytes_system_tx: 8388608 +max_gas_payment_objects: 256 +max_modules_in_publish: 64 +max_package_dependencies: 32 +max_arguments: 512 +max_type_arguments: 16 +max_type_argument_depth: 16 +max_pure_argument_size: 16384 +max_programmable_tx_commands: 1024 +move_binary_format_version: 7 +min_move_binary_format_version: 6 +binary_module_handles: 100 +binary_struct_handles: 300 +binary_function_handles: 1500 +binary_function_instantiations: 750 +binary_signatures: 1000 +binary_constant_pool: 4000 +binary_identifiers: 10000 +binary_address_identifiers: 100 +binary_struct_defs: 200 +binary_struct_def_instantiations: 100 +binary_function_defs: 1000 +binary_field_handles: 500 +binary_field_instantiations: 250 +binary_friend_decls: 100 +max_move_object_size: 256000 +max_move_package_size: 102400 +max_publish_or_upgrade_per_ptb: 5 +max_tx_gas: 50000000000 +max_gas_price: 100000 +max_gas_computation_bucket: 5000000 +gas_rounding_step: 1000 +max_loop_depth: 5 +max_generic_instantiation_length: 32 +max_function_parameters: 128 +max_basic_blocks: 1024 +max_value_stack_size: 1024 +max_type_nodes: 256 +max_push_size: 10000 +max_struct_definitions: 200 +max_function_definitions: 1000 +max_fields_in_struct: 32 +max_dependency_depth: 100 +max_num_event_emit: 1024 +max_num_new_move_object_ids: 2048 +max_num_new_move_object_ids_system_tx: 32768 +max_num_deleted_move_object_ids: 2048 +max_num_deleted_move_object_ids_system_tx: 32768 +max_num_transferred_move_object_ids: 2048 +max_num_transferred_move_object_ids_system_tx: 32768 +max_event_emit_size: 256000 +max_event_emit_size_total: 65536000 +max_move_vector_len: 262144 +max_move_identifier_len: 128 +max_move_value_depth: 128 +max_back_edges_per_function: 10000 +max_back_edges_per_module: 10000 +max_verifier_meter_ticks_per_function: 16000000 +max_meter_ticks_per_module: 16000000 +max_meter_ticks_per_package: 16000000 +object_runtime_max_num_cached_objects: 1000 +object_runtime_max_num_cached_objects_system_tx: 16000 +object_runtime_max_num_store_entries: 1000 +object_runtime_max_num_store_entries_system_tx: 16000 +base_tx_cost_fixed: 1000 +package_publish_cost_fixed: 1000 +base_tx_cost_per_byte: 0 +package_publish_cost_per_byte: 80 +obj_access_cost_read_per_byte: 15 +obj_access_cost_mutate_per_byte: 40 +obj_access_cost_delete_per_byte: 40 +obj_access_cost_verify_per_byte: 200 +gas_model_version: 1 +obj_data_cost_refundable: 100 +obj_metadata_cost_non_refundable: 50 +storage_rebate_rate: 10000 +reward_slashing_rate: 10000 +storage_gas_price: 76 +validator_target_reward: 767000000000000 +max_transactions_per_checkpoint: 10000 +max_checkpoint_size_bytes: 31457280 +buffer_stake_for_protocol_upgrade_bps: 5000 +address_from_bytes_cost_base: 52 +address_to_u256_cost_base: 52 +address_from_u256_cost_base: 52 +config_read_setting_impl_cost_base: 100 +config_read_setting_impl_cost_per_byte: 40 +dynamic_field_hash_type_and_key_cost_base: 100 +dynamic_field_hash_type_and_key_type_cost_per_byte: 2 +dynamic_field_hash_type_and_key_value_cost_per_byte: 2 +dynamic_field_hash_type_and_key_type_tag_cost_per_byte: 2 +dynamic_field_add_child_object_cost_base: 100 +dynamic_field_add_child_object_type_cost_per_byte: 10 +dynamic_field_add_child_object_value_cost_per_byte: 10 +dynamic_field_add_child_object_struct_tag_cost_per_byte: 10 +dynamic_field_borrow_child_object_cost_base: 100 +dynamic_field_borrow_child_object_child_ref_cost_per_byte: 10 +dynamic_field_borrow_child_object_type_cost_per_byte: 10 +dynamic_field_remove_child_object_cost_base: 100 +dynamic_field_remove_child_object_child_cost_per_byte: 2 +dynamic_field_remove_child_object_type_cost_per_byte: 2 +dynamic_field_has_child_object_cost_base: 100 +dynamic_field_has_child_object_with_ty_cost_base: 100 +dynamic_field_has_child_object_with_ty_type_cost_per_byte: 2 +dynamic_field_has_child_object_with_ty_type_tag_cost_per_byte: 2 +event_emit_cost_base: 52 +event_emit_value_size_derivation_cost_per_byte: 2 +event_emit_tag_size_derivation_cost_per_byte: 5 +event_emit_output_cost_per_byte: 10 +object_borrow_uid_cost_base: 52 +object_delete_impl_cost_base: 52 +object_record_new_uid_cost_base: 52 +transfer_transfer_internal_cost_base: 52 +transfer_freeze_object_cost_base: 52 +transfer_share_object_cost_base: 52 +transfer_receive_object_cost_base: 52 +tx_context_derive_id_cost_base: 52 +types_is_one_time_witness_cost_base: 52 +types_is_one_time_witness_type_tag_cost_per_byte: 2 +types_is_one_time_witness_type_cost_per_byte: 2 +validator_validate_metadata_cost_base: 52 +validator_validate_metadata_data_cost_per_byte: 2 +crypto_invalid_arguments_cost: 100 +bls12381_bls12381_min_sig_verify_cost_base: 52 +bls12381_bls12381_min_sig_verify_msg_cost_per_byte: 2 +bls12381_bls12381_min_sig_verify_msg_cost_per_block: 2 +bls12381_bls12381_min_pk_verify_cost_base: 52 +bls12381_bls12381_min_pk_verify_msg_cost_per_byte: 2 +bls12381_bls12381_min_pk_verify_msg_cost_per_block: 2 +ecdsa_k1_ecrecover_keccak256_cost_base: 52 +ecdsa_k1_ecrecover_keccak256_msg_cost_per_byte: 2 +ecdsa_k1_ecrecover_keccak256_msg_cost_per_block: 2 +ecdsa_k1_ecrecover_sha256_cost_base: 52 +ecdsa_k1_ecrecover_sha256_msg_cost_per_byte: 2 +ecdsa_k1_ecrecover_sha256_msg_cost_per_block: 2 +ecdsa_k1_decompress_pubkey_cost_base: 52 +ecdsa_k1_secp256k1_verify_keccak256_cost_base: 52 +ecdsa_k1_secp256k1_verify_keccak256_msg_cost_per_byte: 2 +ecdsa_k1_secp256k1_verify_keccak256_msg_cost_per_block: 2 +ecdsa_k1_secp256k1_verify_sha256_cost_base: 52 +ecdsa_k1_secp256k1_verify_sha256_msg_cost_per_byte: 2 +ecdsa_k1_secp256k1_verify_sha256_msg_cost_per_block: 2 +ecdsa_r1_ecrecover_keccak256_cost_base: 52 +ecdsa_r1_ecrecover_keccak256_msg_cost_per_byte: 2 +ecdsa_r1_ecrecover_keccak256_msg_cost_per_block: 2 +ecdsa_r1_ecrecover_sha256_cost_base: 52 +ecdsa_r1_ecrecover_sha256_msg_cost_per_byte: 2 +ecdsa_r1_ecrecover_sha256_msg_cost_per_block: 2 +ecdsa_r1_secp256r1_verify_keccak256_cost_base: 52 +ecdsa_r1_secp256r1_verify_keccak256_msg_cost_per_byte: 2 +ecdsa_r1_secp256r1_verify_keccak256_msg_cost_per_block: 2 +ecdsa_r1_secp256r1_verify_sha256_cost_base: 52 +ecdsa_r1_secp256r1_verify_sha256_msg_cost_per_byte: 2 +ecdsa_r1_secp256r1_verify_sha256_msg_cost_per_block: 2 +ecvrf_ecvrf_verify_cost_base: 52 +ecvrf_ecvrf_verify_alpha_string_cost_per_byte: 2 +ecvrf_ecvrf_verify_alpha_string_cost_per_block: 2 +ed25519_ed25519_verify_cost_base: 52 +ed25519_ed25519_verify_msg_cost_per_byte: 2 +ed25519_ed25519_verify_msg_cost_per_block: 2 +groth16_prepare_verifying_key_bls12381_cost_base: 52 +groth16_prepare_verifying_key_bn254_cost_base: 52 +groth16_verify_groth16_proof_internal_bls12381_cost_base: 52 +groth16_verify_groth16_proof_internal_bls12381_cost_per_public_input: 2 +groth16_verify_groth16_proof_internal_bn254_cost_base: 52 +groth16_verify_groth16_proof_internal_bn254_cost_per_public_input: 2 +groth16_verify_groth16_proof_internal_public_input_cost_per_byte: 2 +hash_blake2b256_cost_base: 52 +hash_blake2b256_data_cost_per_byte: 2 +hash_blake2b256_data_cost_per_block: 2 +hash_keccak256_cost_base: 52 +hash_keccak256_data_cost_per_byte: 2 +hash_keccak256_data_cost_per_block: 2 +poseidon_bn254_cost_base: 260 +poseidon_bn254_cost_per_block: 10 +group_ops_bls12381_decode_scalar_cost: 52 +group_ops_bls12381_decode_g1_cost: 52 +group_ops_bls12381_decode_g2_cost: 52 +group_ops_bls12381_decode_gt_cost: 52 +group_ops_bls12381_scalar_add_cost: 52 +group_ops_bls12381_g1_add_cost: 52 +group_ops_bls12381_g2_add_cost: 52 +group_ops_bls12381_gt_add_cost: 52 +group_ops_bls12381_scalar_sub_cost: 52 +group_ops_bls12381_g1_sub_cost: 52 +group_ops_bls12381_g2_sub_cost: 52 +group_ops_bls12381_gt_sub_cost: 52 +group_ops_bls12381_scalar_mul_cost: 52 +group_ops_bls12381_g1_mul_cost: 52 +group_ops_bls12381_g2_mul_cost: 52 +group_ops_bls12381_gt_mul_cost: 52 +group_ops_bls12381_scalar_div_cost: 52 +group_ops_bls12381_g1_div_cost: 52 +group_ops_bls12381_g2_div_cost: 52 +group_ops_bls12381_gt_div_cost: 52 +group_ops_bls12381_g1_hash_to_base_cost: 52 +group_ops_bls12381_g2_hash_to_base_cost: 52 +group_ops_bls12381_g1_hash_to_cost_per_byte: 2 +group_ops_bls12381_g2_hash_to_cost_per_byte: 2 +group_ops_bls12381_g1_msm_base_cost: 52 +group_ops_bls12381_g2_msm_base_cost: 52 +group_ops_bls12381_g1_msm_base_cost_per_input: 52 +group_ops_bls12381_g2_msm_base_cost_per_input: 52 +group_ops_bls12381_msm_max_len: 32 +group_ops_bls12381_pairing_cost: 52 +hmac_hmac_sha3_256_cost_base: 52 +hmac_hmac_sha3_256_input_cost_per_byte: 2 +hmac_hmac_sha3_256_input_cost_per_block: 2 +check_zklogin_id_cost_base: 200 +check_zklogin_issuer_cost_base: 200 +vdf_verify_vdf_cost: 1500 +vdf_hash_to_input_cost: 100 +bcs_per_byte_serialized_cost: 2 +bcs_legacy_min_output_size_cost: 1 +bcs_failure_cost: 52 +hash_sha2_256_base_cost: 52 +hash_sha2_256_per_byte_cost: 2 +hash_sha2_256_legacy_min_input_len_cost: 1 +hash_sha3_256_base_cost: 52 +hash_sha3_256_per_byte_cost: 2 +hash_sha3_256_legacy_min_input_len_cost: 1 +type_name_get_base_cost: 52 +type_name_get_per_byte_cost: 2 +string_check_utf8_base_cost: 52 +string_check_utf8_per_byte_cost: 2 +string_is_char_boundary_base_cost: 52 +string_sub_string_base_cost: 52 +string_sub_string_per_byte_cost: 2 +string_index_of_base_cost: 52 +string_index_of_per_byte_pattern_cost: 2 +string_index_of_per_byte_searched_cost: 2 +vector_empty_base_cost: 52 +vector_length_base_cost: 52 +vector_push_back_base_cost: 52 +vector_push_back_legacy_per_abstract_memory_unit_cost: 2 +vector_borrow_base_cost: 52 +vector_pop_back_base_cost: 52 +vector_destroy_empty_base_cost: 52 +vector_swap_base_cost: 52 +debug_print_base_cost: 52 +debug_print_stack_trace_base_cost: 52 +execution_version: 1 +consensus_bad_nodes_stake_threshold: 20 +max_jwk_votes_per_validator_per_epoch: 240 +max_age_of_jwk_in_epochs: 1 +random_beacon_reduction_allowed_delta: 800 +random_beacon_reduction_lower_bound: 1000 +random_beacon_dkg_timeout_round: 3000 +random_beacon_min_round_interval_ms: 500 +random_beacon_dkg_version: 1 +consensus_max_transaction_size_bytes: 262144 +consensus_max_transactions_in_block_bytes: 524288 +consensus_max_num_transactions_in_block: 512 +max_deferral_rounds_for_congestion_control: 10 +min_checkpoint_interval_ms: 200 +checkpoint_summary_version_specific_data: 1 +max_soft_bundle_size: 5 +bridge_should_try_to_finalize_committee: true +max_accumulated_txn_cost_per_object_in_mysticeti_commit: 10 diff --git a/crates/iota-types/src/display.rs b/crates/iota-types/src/display.rs index 09d796b2694..09d5bbbafcf 100644 --- a/crates/iota-types/src/display.rs +++ b/crates/iota-types/src/display.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 use move_core_types::{ident_str, identifier::IdentStr, language_storage::StructTag}; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use crate::{ IOTA_FRAMEWORK_ADDRESS, @@ -18,7 +18,7 @@ pub const DISPLAY_VERSION_UPDATED_EVENT_NAME: &IdentStr = ident_str!("VersionUpd // TODO: add tests to keep in sync /// Rust version of the Move iota::display::Display type -#[derive(Debug, Deserialize, Clone, Eq, PartialEq)] +#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)] pub struct DisplayObject { pub id: UID, pub fields: VecMap, diff --git a/crates/iota-types/src/iota_sdk2_conversions.rs b/crates/iota-types/src/iota_sdk2_conversions.rs index 4ca1631cc76..36190a8feae 100644 --- a/crates/iota-types/src/iota_sdk2_conversions.rs +++ b/crates/iota-types/src/iota_sdk2_conversions.rs @@ -534,6 +534,7 @@ impl From for EndOfEpochTransacti bridge_object_version: sequence_number.value(), } } + crate::transaction::EndOfEpochTransactionKind::SystemDisplay(_) => todo!(), } } } diff --git a/crates/iota-types/src/iota_system_state/iota_system_state_inner_v2.rs b/crates/iota-types/src/iota_system_state/iota_system_state_inner_v2.rs new file mode 100644 index 00000000000..e0b416645b8 --- /dev/null +++ b/crates/iota-types/src/iota_system_state/iota_system_state_inner_v2.rs @@ -0,0 +1,276 @@ +// Copyright (c) Mysten Labs, Inc. +// Modifications Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::Result; +use serde::{Deserialize, Serialize}; + +use super::{ + AdvanceEpochParams, IotaSystemStateTrait, + epoch_start_iota_system_state::EpochStartValidatorInfoV1, + get_validators_from_table_vec, + iota_system_state_inner_v1::{StorageFundV1, SystemParametersV1, ValidatorSetV1, ValidatorV1}, + iota_system_state_summary::{IotaSystemStateSummary, IotaValidatorSummary}, +}; +use crate::{ + balance::Balance, + base_types::IotaAddress, + collection_types::{Bag, Table, TableVec, VecMap, VecSet}, + committee::{CommitteeWithNetworkMetadata, NetworkMetadata}, + error::IotaError, + gas_coin::IotaTreasuryCap, + id::ID, + iota_system_state::epoch_start_iota_system_state::EpochStartSystemState, + storage::ObjectStore, + system_admin_cap::IotaSystemAdminCap, +}; + +/// Rust version of the Move iota_system::iota_system::IotaSystemStateV2 type +#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)] +pub struct IotaSystemStateV2 { + pub epoch: u64, + pub protocol_version: u64, + pub system_state_version: u64, + pub iota_treasury_cap: IotaTreasuryCap, + pub validators: ValidatorSetV1, + pub storage_fund: StorageFundV1, + pub parameters: SystemParametersV1, + pub iota_system_admin_cap: IotaSystemAdminCap, + pub reference_gas_price: u64, + pub validator_report_records: VecMap>, + pub safe_mode: bool, + pub safe_mode_storage_charges: Balance, + pub safe_mode_computation_rewards: Balance, + pub safe_mode_storage_rebates: u64, + pub safe_mode_non_refundable_storage_fee: u64, + pub epoch_start_timestamp_ms: u64, + pub system_display_objects: VecMap, + pub extra_fields: Bag, + // TODO: Use getters instead of all pub. +} + +impl IotaSystemStateTrait for IotaSystemStateV2 { + fn epoch(&self) -> u64 { + self.epoch + } + + fn reference_gas_price(&self) -> u64 { + self.reference_gas_price + } + + fn protocol_version(&self) -> u64 { + self.protocol_version + } + + fn system_state_version(&self) -> u64 { + self.system_state_version + } + + fn epoch_start_timestamp_ms(&self) -> u64 { + self.epoch_start_timestamp_ms + } + + fn epoch_duration_ms(&self) -> u64 { + self.parameters.epoch_duration_ms + } + + fn safe_mode(&self) -> bool { + self.safe_mode + } + + fn advance_epoch_safe_mode(&mut self, params: &AdvanceEpochParams) { + self.epoch = params.epoch; + self.safe_mode = true; + self.safe_mode_storage_charges + .deposit_for_safe_mode(params.storage_charge); + self.safe_mode_storage_rebates += params.storage_rebate; + self.safe_mode_computation_rewards + .deposit_for_safe_mode(params.computation_charge); + self.safe_mode_non_refundable_storage_fee += params.non_refundable_storage_fee; + self.epoch_start_timestamp_ms = params.epoch_start_timestamp_ms; + self.protocol_version = params.next_protocol_version.as_u64(); + } + + fn get_current_epoch_committee(&self) -> CommitteeWithNetworkMetadata { + let validators = self + .validators + .active_validators + .iter() + .map(|validator| { + let verified_metadata = validator.verified_metadata(); + let name = verified_metadata.iota_pubkey_bytes(); + ( + name, + (validator.voting_power, NetworkMetadata { + network_address: verified_metadata.net_address.clone(), + primary_address: verified_metadata.primary_address.clone(), + }), + ) + }) + .collect(); + CommitteeWithNetworkMetadata::new(self.epoch, validators) + } + + fn get_pending_active_validators( + &self, + object_store: &S, + ) -> Result, IotaError> { + let table_id = self.validators.pending_active_validators.contents.id; + let table_size = self.validators.pending_active_validators.contents.size; + let validators: Vec = + get_validators_from_table_vec(&object_store, table_id, table_size)?; + Ok(validators + .into_iter() + .map(|v| v.into_iota_validator_summary()) + .collect()) + } + + fn into_epoch_start_state(self) -> EpochStartSystemState { + EpochStartSystemState::new_v1( + self.epoch, + self.protocol_version, + self.reference_gas_price, + self.safe_mode, + self.epoch_start_timestamp_ms, + self.parameters.epoch_duration_ms, + self.validators + .active_validators + .iter() + .map(|validator| { + let metadata = validator.verified_metadata(); + EpochStartValidatorInfoV1 { + iota_address: metadata.iota_address, + authority_pubkey: metadata.authority_pubkey.clone(), + network_pubkey: metadata.network_pubkey.clone(), + protocol_pubkey: metadata.protocol_pubkey.clone(), + iota_net_address: metadata.net_address.clone(), + p2p_address: metadata.p2p_address.clone(), + primary_address: metadata.primary_address.clone(), + voting_power: validator.voting_power, + hostname: metadata.name.clone(), + } + }) + .collect(), + ) + } + + fn into_iota_system_state_summary(self) -> IotaSystemStateSummary { + // If you are making any changes to IotaSystemStateV2 or any of its dependent + // types before mainnet, please also update IotaSystemStateSummary and + // its corresponding TS type. Post-mainnet, we will need to introduce a + // new version. + let Self { + epoch, + protocol_version, + system_state_version, + iota_treasury_cap, + validators: + ValidatorSetV1 { + total_stake, + active_validators, + pending_active_validators: + TableVec { + contents: + Table { + id: pending_active_validators_id, + size: pending_active_validators_size, + }, + }, + pending_removals, + staking_pool_mappings: + Table { + id: staking_pool_mappings_id, + size: staking_pool_mappings_size, + }, + inactive_validators: + Table { + id: inactive_pools_id, + size: inactive_pools_size, + }, + validator_candidates: + Table { + id: validator_candidates_id, + size: validator_candidates_size, + }, + at_risk_validators: + VecMap { + contents: at_risk_validators, + }, + extra_fields: _, + }, + storage_fund, + parameters: + SystemParametersV1 { + epoch_duration_ms, + min_validator_count, + max_validator_count, + min_validator_joining_stake, + validator_low_stake_threshold, + validator_very_low_stake_threshold, + validator_low_stake_grace_period, + extra_fields: _, + }, + iota_system_admin_cap: _, + reference_gas_price, + validator_report_records: + VecMap { + contents: validator_report_records, + }, + safe_mode, + safe_mode_storage_charges, + safe_mode_computation_rewards, + safe_mode_storage_rebates, + safe_mode_non_refundable_storage_fee, + epoch_start_timestamp_ms, + system_display_objects: _, + extra_fields: _, + } = self; + IotaSystemStateSummary { + epoch, + protocol_version, + system_state_version, + iota_total_supply: iota_treasury_cap.total_supply().value, + iota_treasury_cap_id: iota_treasury_cap.id().to_owned(), + storage_fund_total_object_storage_rebates: storage_fund + .total_object_storage_rebates + .value(), + storage_fund_non_refundable_balance: storage_fund.non_refundable_balance.value(), + reference_gas_price, + safe_mode, + safe_mode_storage_charges: safe_mode_storage_charges.value(), + safe_mode_computation_rewards: safe_mode_computation_rewards.value(), + safe_mode_storage_rebates, + safe_mode_non_refundable_storage_fee, + epoch_start_timestamp_ms, + epoch_duration_ms, + total_stake, + active_validators: active_validators + .into_iter() + .map(|v| v.into_iota_validator_summary()) + .collect(), + pending_active_validators_id, + pending_active_validators_size, + pending_removals, + staking_pool_mappings_id, + staking_pool_mappings_size, + inactive_pools_id, + inactive_pools_size, + validator_candidates_id, + validator_candidates_size, + at_risk_validators: at_risk_validators + .into_iter() + .map(|e| (e.key, e.value)) + .collect(), + validator_report_records: validator_report_records + .into_iter() + .map(|e| (e.key, e.value.contents)) + .collect(), + min_validator_count, + max_validator_count, + min_validator_joining_stake, + validator_low_stake_threshold, + validator_very_low_stake_threshold, + validator_low_stake_grace_period, + } + } +} diff --git a/crates/iota-types/src/iota_system_state/mod.rs b/crates/iota-types/src/iota_system_state/mod.rs index 5e5634a53d5..f6e894ea44e 100644 --- a/crates/iota-types/src/iota_system_state/mod.rs +++ b/crates/iota-types/src/iota_system_state/mod.rs @@ -2,7 +2,7 @@ // Modifications Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -use std::fmt; +use std::{collections::HashMap, fmt}; use anyhow::Result; use enum_dispatch::enum_dispatch; @@ -12,12 +12,14 @@ use serde::{Deserialize, Serialize, de::DeserializeOwned}; use self::{ iota_system_state_inner_v1::{IotaSystemStateV1, ValidatorV1}, + iota_system_state_inner_v2::IotaSystemStateV2, iota_system_state_summary::{IotaSystemStateSummary, IotaValidatorSummary}, }; use crate::{ IOTA_SYSTEM_ADDRESS, IOTA_SYSTEM_STATE_OBJECT_ID, MoveTypeTagTrait, base_types::ObjectID, committee::CommitteeWithNetworkMetadata, + display::DisplayObject, dynamic_field::{Field, get_dynamic_field_from_store, get_dynamic_field_object_from_store}, error::IotaError, id::UID, @@ -29,6 +31,7 @@ use crate::{ pub mod epoch_start_iota_system_state; pub mod iota_system_state_inner_v1; +pub mod iota_system_state_inner_v2; pub mod iota_system_state_summary; #[cfg(msim)] @@ -45,6 +48,13 @@ pub const IOTA_SYSTEM_MODULE_NAME: &IdentStr = ident_str!("iota_system"); pub const ADVANCE_EPOCH_FUNCTION_NAME: &IdentStr = ident_str!("advance_epoch"); pub const ADVANCE_EPOCH_SAFE_MODE_FUNCTION_NAME: &IdentStr = ident_str!("advance_epoch_safe_mode"); +pub const IOTA_SYSTEM_DISPLAY_MODULE_NAME: &IdentStr = ident_str!("system_display"); +pub const CREATE_STAKED_IOTA_DISPLAY_V1: &IdentStr = ident_str!("create_staked_iota_display_v1"); +pub const CREATE_TIMELOCKED_STAKED_IOTA_DISPLAY_V1: &IdentStr = + ident_str!("create_timelocked_staked_iota_display_v1"); +pub const CREATE_TIMELOCKED_IOTA_DISPLAY_V1: &IdentStr = + ident_str!("create_timelocked_iota_display_v1"); + #[cfg(msim)] pub const IOTA_SYSTEM_STATE_SIM_TEST_V1: u64 = 18446744073709551605; // u64::MAX - 10 #[cfg(msim)] @@ -102,6 +112,13 @@ impl IotaSystemStateWrapper { protocol_config, ); } + 2 => { + Self::advance_epoch_safe_mode_impl::( + move_object, + params, + protocol_config, + ); + } #[cfg(msim)] IOTA_SYSTEM_STATE_SIM_TEST_V1 => { Self::advance_epoch_safe_mode_impl::( @@ -190,6 +207,7 @@ pub trait IotaSystemStateTrait { #[enum_dispatch(IotaSystemStateTrait)] pub enum IotaSystemState { V1(IotaSystemStateV1), + V2(IotaSystemStateV2), #[cfg(msim)] SimTestV1(SimTestIotaSystemStateV1), #[cfg(msim)] @@ -211,11 +229,8 @@ impl IotaSystemState { pub fn into_genesis_version_for_tooling(self) -> IotaSystemStateInnerGenesis { match self { IotaSystemState::V1(inner) => inner, - #[cfg(msim)] - _ => { - // Types other than V1 used in simtests should be unreachable - unreachable!() - } + // Types other than V1 and used in simtests should be unreachable + _ => unreachable!(), } } @@ -259,6 +274,18 @@ pub fn get_iota_system_state(object_store: &dyn ObjectStore) -> Result { + let result: IotaSystemStateV2 = + get_dynamic_field_from_store(object_store, id, &wrapper.version).map_err( + |err| { + IotaError::DynamicFieldRead(format!( + "Failed to load iota system state inner object with ID {:?} and version {:?}: {:?}", + id, wrapper.version, err + )) + }, + )?; + Ok(IotaSystemState::V2(result)) + } #[cfg(msim)] IOTA_SYSTEM_STATE_SIM_TEST_V1 => { let result: SimTestIotaSystemStateV1 = @@ -392,6 +419,48 @@ where Ok(validators) } +/// Get the system display objects stored in the system state. +pub fn get_system_display_objects( + object_store: &dyn ObjectStore, +) -> Result, IotaError> { + let system_state = get_iota_system_state(object_store)?; + + match system_state { + IotaSystemState::V1(_) => Ok(HashMap::new()), + IotaSystemState::V2(inner) => inner + .system_display_objects + .contents + .into_iter() + .map(|entry| { + let display_object_id = entry.value; + + let display_object: DisplayObject = get_dynamic_field_from_store( + object_store, + *inner.extra_fields.id.object_id(), + &display_object_id, + ) + .map_err(|err| { + IotaError::DynamicFieldRead(format!( + "Failed to load a system display object with ID {display_object_id:?}: {err}", + )) + })?; + + Ok((entry.key, display_object)) + }) + .collect::, _>>(), + #[cfg(msim)] + _ => unimplemented!("System display objects are not implemented for mock system states"), + } +} + +/// Get a system display object unique key. +/// * tag - is a tag of a type for which the display object is created. +pub fn system_display_object_key(tag: StructTag) -> String { + let with_prefix = false; + + tag.to_canonical_string(with_prefix) +} + #[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Default)] pub struct PoolTokenExchangeRate { iota_amount: u64, diff --git a/crates/iota-types/src/transaction.rs b/crates/iota-types/src/transaction.rs index f8ff33452b3..daf7e3bd43f 100644 --- a/crates/iota-types/src/transaction.rs +++ b/crates/iota-types/src/transaction.rs @@ -292,6 +292,14 @@ pub enum TransactionKind { // .. more transaction types go here } +/// SystemDisplayTransactionKind +#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize, IntoStaticStr)] +pub enum SystemDisplayTransactionKind { + StakedIotaV1, + TimelockedStakedIotaV1, + TimelockedIotaV1, +} + /// EndOfEpochTransactionKind #[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize, IntoStaticStr)] pub enum EndOfEpochTransactionKind { @@ -300,6 +308,7 @@ pub enum EndOfEpochTransactionKind { AuthenticatorStateExpire(AuthenticatorStateExpire), BridgeStateCreate(ChainIdentifier), BridgeCommitteeInit(SequenceNumber), + SystemDisplay(Vec), } impl EndOfEpochTransactionKind { @@ -347,6 +356,10 @@ impl EndOfEpochTransactionKind { Self::BridgeCommitteeInit(bridge_shared_version) } + pub fn system_display(txs: Vec) -> Self { + Self::SystemDisplay(txs) + } + fn input_objects(&self) -> Vec { match self { Self::ChangeEpoch(_) => { @@ -377,6 +390,13 @@ impl EndOfEpochTransactionKind { mutable: true, }, ], + Self::SystemDisplay(_) => { + vec![InputObjectKind::SharedMoveObject { + id: IOTA_SYSTEM_STATE_OBJECT_ID, + initial_shared_version: IOTA_SYSTEM_STATE_OBJECT_SHARED_VERSION, + mutable: true, + }] + } } } @@ -406,6 +426,9 @@ impl EndOfEpochTransactionKind { ] .into_iter(), ), + Self::SystemDisplay(_) => { + Either::Left(vec![SharedInputObject::IOTA_SYSTEM_OBJ].into_iter()) + } } } @@ -438,6 +461,33 @@ impl EndOfEpochTransactionKind { )); } } + Self::SystemDisplay(txs) => { + for tx in txs { + match tx { + SystemDisplayTransactionKind::StakedIotaV1 => { + if !config.enable_staked_iota_display_v1() { + return Err(UserInputError::Unsupported( + "`StakedIota` display is not enabled".to_string(), + )); + } + } + SystemDisplayTransactionKind::TimelockedStakedIotaV1 => { + if !config.enable_timelocked_staked_iota_display_v1() { + return Err(UserInputError::Unsupported( + "`TimelockedStakedIota` display is not enabled".to_string(), + )); + } + } + SystemDisplayTransactionKind::TimelockedIotaV1 => { + if !config.enable_timelocked_iota_display_v1() { + return Err(UserInputError::Unsupported( + "`TimeLock>` display is not enabled".to_string(), + )); + } + } + } + } + } } Ok(()) } diff --git a/iota-execution/latest/iota-adapter/src/execution_engine.rs b/iota-execution/latest/iota-adapter/src/execution_engine.rs index 26353e36d0a..0cdfb2650e3 100644 --- a/iota-execution/latest/iota-adapter/src/execution_engine.rs +++ b/iota-execution/latest/iota-adapter/src/execution_engine.rs @@ -16,7 +16,7 @@ mod checked { use iota_types::{ BRIDGE_ADDRESS, IOTA_AUTHENTICATOR_STATE_OBJECT_ID, IOTA_BRIDGE_OBJECT_ID, IOTA_FRAMEWORK_ADDRESS, IOTA_FRAMEWORK_PACKAGE_ID, IOTA_RANDOMNESS_STATE_OBJECT_ID, - IOTA_SYSTEM_PACKAGE_ID, + IOTA_SYSTEM_ADDRESS, IOTA_SYSTEM_PACKAGE_ID, authenticator_state::{ AUTHENTICATOR_STATE_CREATE_FUNCTION_NAME, AUTHENTICATOR_STATE_EXPIRE_JWKS_FUNCTION_NAME, AUTHENTICATOR_STATE_MODULE_NAME, @@ -46,7 +46,9 @@ mod checked { id::UID, inner_temporary_store::InnerTemporaryStore, iota_system_state::{ - ADVANCE_EPOCH_FUNCTION_NAME, AdvanceEpochParams, IOTA_SYSTEM_MODULE_NAME, + ADVANCE_EPOCH_FUNCTION_NAME, AdvanceEpochParams, CREATE_STAKED_IOTA_DISPLAY_V1, + CREATE_TIMELOCKED_IOTA_DISPLAY_V1, CREATE_TIMELOCKED_STAKED_IOTA_DISPLAY_V1, + IOTA_SYSTEM_DISPLAY_MODULE_NAME, IOTA_SYSTEM_MODULE_NAME, }, messages_checkpoint::CheckpointTimestamp, metrics::LimitsMetrics, @@ -57,7 +59,8 @@ mod checked { transaction::{ Argument, AuthenticatorStateExpire, AuthenticatorStateUpdateV1, CallArg, ChangeEpoch, CheckedInputObjects, Command, EndOfEpochTransactionKind, GenesisTransaction, ObjectArg, - ProgrammableTransaction, RandomnessStateUpdate, TransactionKind, + ProgrammableTransaction, RandomnessStateUpdate, SystemDisplayTransactionKind, + TransactionKind, }, }; use move_binary_format::CompiledModule; @@ -696,6 +699,9 @@ mod checked { assert!(protocol_config.should_try_to_finalize_bridge_committee()); builder = setup_bridge_committee_update(builder, bridge_shared_version) } + EndOfEpochTransactionKind::SystemDisplay(txs) => { + builder = setup_system_display_objects(builder, protocol_config, txs) + } } } unreachable!( @@ -1232,4 +1238,64 @@ mod checked { pt, ) } + + /// Configures a `ProgrammableTransactionBuilder` to update the system + /// display objects. + fn setup_system_display_objects( + mut builder: ProgrammableTransactionBuilder, + protocol_config: &ProtocolConfig, + txs: Vec, + ) -> ProgrammableTransactionBuilder { + for tx in txs { + match tx { + SystemDisplayTransactionKind::StakedIotaV1 => { + assert!(protocol_config.enable_staked_iota_display_v1()); + + let system_state = builder + .obj(ObjectArg::IOTA_SYSTEM_MUT) + .expect("Unable to create System State object arg!"); + + builder.programmable_move_call( + IOTA_SYSTEM_ADDRESS.into(), + IOTA_SYSTEM_DISPLAY_MODULE_NAME.to_owned(), + CREATE_STAKED_IOTA_DISPLAY_V1.to_owned(), + vec![], + vec![system_state], + ); + } + SystemDisplayTransactionKind::TimelockedStakedIotaV1 => { + assert!(protocol_config.enable_timelocked_staked_iota_display_v1()); + + let system_state = builder + .obj(ObjectArg::IOTA_SYSTEM_MUT) + .expect("Unable to create System State object arg!"); + + builder.programmable_move_call( + IOTA_SYSTEM_ADDRESS.into(), + IOTA_SYSTEM_DISPLAY_MODULE_NAME.to_owned(), + CREATE_TIMELOCKED_STAKED_IOTA_DISPLAY_V1.to_owned(), + vec![], + vec![system_state], + ); + } + SystemDisplayTransactionKind::TimelockedIotaV1 => { + assert!(protocol_config.enable_timelocked_iota_display_v1()); + + let system_state = builder + .obj(ObjectArg::IOTA_SYSTEM_MUT) + .expect("Unable to create System State object arg!"); + + builder.programmable_move_call( + IOTA_SYSTEM_ADDRESS.into(), + IOTA_SYSTEM_DISPLAY_MODULE_NAME.to_owned(), + CREATE_TIMELOCKED_IOTA_DISPLAY_V1.to_owned(), + vec![], + vec![system_state], + ); + } + } + } + + builder + } }