From 52355007d9afc174700b5d0962c29a63095b520e Mon Sep 17 00:00:00 2001 From: Valerii Reutov Date: Fri, 8 Nov 2024 14:25:39 +0200 Subject: [PATCH] feat: improved system displays implementation --- .../authority/authority_per_epoch_store.rs | 21 +++- .../authority/epoch_start_configuration.rs | 24 +++- .../iota-framework/sources/display.move | 5 + .../sources/system_admin_cap.move | 3 +- .../iota-system/sources/iota_system.move | 74 +++++++------ .../sources/iota_system_state_inner.move | 104 +++++++++++++----- .../iota-system/sources/system_display.move | 82 -------------- .../packages_compiled/iota-framework | Bin 70167 -> 70208 bytes .../packages_compiled/iota-system | Bin 43987 -> 43700 bytes crates/iota-framework/published_api.txt | 55 +++++---- crates/iota-json-rpc/src/coin_api.rs | 3 + crates/iota-types/src/display.rs | 4 +- .../iota_system_state_inner_v1.rs | 2 + .../iota-types/src/iota_system_state/mod.rs | 44 +++++++- 14 files changed, 241 insertions(+), 180 deletions(-) delete mode 100644 crates/iota-framework/packages/iota-system/sources/system_display.move 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..f5468bf9032 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::{ + display_object_key, + epoch_start_iota_system_state::{EpochStartSystemState, EpochStartSystemStateTrait}, }, 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 system_display_object_created(&self, ty: StructTag, version: u16) -> bool { + let key = display_object_key(ty); + + 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-framework/packages/iota-framework/sources/display.move b/crates/iota-framework/packages/iota-framework/sources/display.move index 8acd7442ae8..037889fcacf 100644 --- a/crates/iota-framework/packages/iota-framework/sources/display.move +++ b/crates/iota-framework/packages/iota-framework/sources/display.move @@ -164,6 +164,11 @@ module iota::display { 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 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 e8bb079eccc..8c7103a94b6 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}; + 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,41 +507,51 @@ module iota_system::iota_system { self.load_system_state().iota_system_admin_cap() } - /// Add an object with the specified key to the extra fields collection. - public(package) fun add_extra_field( + /// Create an empty `Display` object with `IotaSystemAdminCap`. + public(package) fun new_system_display( wrapper: &mut IotaSystemState, - key: K, - value: V, - ) { - let self = load_system_state_mut(wrapper); - self.add_extra_field(key, value); + ctx: &mut TxContext, + ): Display { + let self = wrapper.load_system_state(); + self.new_system_display(ctx) } - /// Immutable borrows the value associated with the key in the extra fields. - public(package) fun borrow_extra_field( + /// Create a new `Display` object with a set of fields using `IotaSystemAdminCap`. + public(package) fun new_system_display_with_fields( wrapper: &mut IotaSystemState, - key: K, - ): &V { - let self = load_system_state(wrapper); - self.borrow_extra_field(key) + fields: vector, + values: vector, + ctx: &mut TxContext, + ): Display { + let self = wrapper.load_system_state(); + self.new_system_display_with_fields(fields, values, ctx) } - /// Mutable borrows the value associated with the key in the extra fields. - public(package) fun borrow_extra_field_mut( + /// Insert a display object. + public(package) fun insert_display_object( wrapper: &mut IotaSystemState, - key: K, - ): &mut V { - let self = load_system_state_mut(wrapper); - self.borrow_extra_field_mut(key) + display: Display, + ) { + let self = wrapper.load_system_state_mut(); + self.insert_display_object(display); } - /// Returns true if there is an extra field associated with the key. - public(package) fun contains_extra_field( - wrapper: &mut IotaSystemState, - key: K, - ): bool { - let self = load_system_state_mut(wrapper); - self.contains_extra_field(key) + /// Borrow an immutable display object. + public(package) fun borrow_display_object(wrapper: &mut IotaSystemState): &Display { + let self = wrapper.load_system_state(); + self.borrow_display_object() + } + + /// Borrow a mutable display object. + public(package) fun borrow_display_object_mut(wrapper: &mut IotaSystemState): &mut Display { + let self = wrapper.load_system_state_mut(); + self.borrow_display_object_mut() + } + + /// Returns true if the related display object exists. + public(package) fun contains_display_object(wrapper: &mut IotaSystemState): bool { + let self = wrapper.load_system_state(); + self.contains_display_object() } #[allow(unused_function)] 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 49315a79e60..f092e1ba699 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,10 @@ module iota_system::iota_system_state_inner { /// 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, } @@ -171,6 +178,7 @@ module iota_system::iota_system_state_inner { safe_mode_storage_rebates: 0, safe_mode_non_refundable_storage_fee: 0, epoch_start_timestamp_ms, + system_display_objects: vec_map::empty(), extra_fields: bag::new(ctx), }; system_state @@ -442,37 +450,75 @@ module iota_system::iota_system_state_inner { } } - /// Add an object with the specified key to the extra fields collection. - public(package) fun add_extra_field( - self: &mut IotaSystemStateV1, - key: K, - value: V, - ) { - self.extra_fields.add(key, value); + /// Create an empty `Display` object with `IotaSystemAdminCap`. + public(package) fun new_system_display( + self: &IotaSystemStateV1, + ctx: &mut TxContext, + ): Display { + display::system_new(&self.iota_system_admin_cap, ctx) } - /// Immutable borrows the value associated with the key in the extra fields. - public(package) fun borrow_extra_field( + /// Create a new `Display` object with a set of fields using `IotaSystemAdminCap`. + public(package) fun new_system_display_with_fields( self: &IotaSystemStateV1, - key: K, - ): &V { - self.extra_fields.borrow(key) + fields: vector, + values: vector, + ctx: &mut TxContext, + ): Display { + display::system_new_with_fields(&self.iota_system_admin_cap, fields, values, ctx) } - /// Mutable borrows the value associated with the key in the extra fields. - public(package) fun borrow_extra_field_mut( + /// Insert a display object. + public(package) fun insert_display_object( self: &mut IotaSystemStateV1, - key: K, - ): &mut V { - self.extra_fields.borrow_mut(key) + display: Display, + ) { + // Get a display object unique key. + let key = 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); } - /// Returns true if there is an extra field associated with the key. - public(package) fun contains_extra_field( - self: &IotaSystemStateV1, - key: K, - ): bool { - self.extra_fields.contains(key) + /// Borrow an immutable display object. + public(package) fun borrow_display_object(self: &IotaSystemStateV1): &Display { + // Get a display object unique key. + let key = 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 display object. + public(package) fun borrow_display_object_mut(self: &mut IotaSystemStateV1): &mut Display { + // Get a display object unique key. + let key = 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 display object exists. + public(package) fun contains_display_object(self: &IotaSystemStateV1): bool { + // Get a display object unique key. + let key = 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 display_object_key(): String { + string::from_ascii(std::type_name::get_with_original_ids().into_string()) } // ==== validator metadata management functions ==== diff --git a/crates/iota-framework/packages/iota-system/sources/system_display.move b/crates/iota-framework/packages/iota-system/sources/system_display.move deleted file mode 100644 index 92c7c2ada6a..00000000000 --- a/crates/iota-framework/packages/iota-system/sources/system_display.move +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -module iota_system::system_display { - - use std::string::{Self, String}; - - use iota::display::{Self, Display}; - - use iota_system::iota_system::IotaSystemState; - - /// Create an empty `Display` object with `IotaSystemAdminCap`. - public(package) fun new( - iota_system: &mut IotaSystemState, - ctx: &mut TxContext - ): Display { - // Load the `IotaSystemAdminCap` instance. - let sys_admin_cap = iota_system.load_iota_system_admin_cap(); - - // Create a `Display` object. - display::system_new(sys_admin_cap, ctx) - } - - /// Create a new `Display` object with a set of fields using `IotaSystemAdminCap`. - public(package) fun new_with_fields( - iota_system: &mut IotaSystemState, - fields: vector, - values: vector, - ctx: &mut TxContext - ): Display { - // Load the `IotaSystemAdminCap` instance. - let sys_admin_cap = iota_system.load_iota_system_admin_cap(); - - // Create a `Display` object with fields. - display::system_new_with_fields(sys_admin_cap, fields, values, ctx) - } - - /// Add a display object to the system state store. - public(package) fun add_display_object( - iota_system: &mut IotaSystemState, - display: Display - ) { - // Get a display object unique key. - let key = display_object_key(); - - // Store the display object. - iota_system.add_extra_field(key, display); - } - - /// Borrow an immutable display object from the system state store. - public(package) fun borrow_display_object(iota_system: &mut IotaSystemState): &Display { - // Get a display object unique key. - let key = display_object_key(); - - // Borrow the display object. - iota_system.borrow_extra_field(key) - } - - /// Borrow a mutable display object from the system state store. - public(package) fun borrow_display_object_mut(iota_system: &mut IotaSystemState): &mut Display { - // Get a display object unique key. - let key = display_object_key(); - - // Borrow the display object. - iota_system.borrow_extra_field_mut(key) - } - - /// Returns true if the related display object exists. - public(package) fun contains_display_object(iota_system: &mut IotaSystemState): bool { - // Get a display object unique key. - let key = display_object_key(); - - // Check if the related display object exists. - iota_system.contains_extra_field(key) - } - - /// Return a fully qualified type name with the original package IDs - /// that is used as a display object key. - fun display_object_key(): String { - string::from_ascii(std::type_name::get_with_original_ids().into_string()) - } -} diff --git a/crates/iota-framework/packages_compiled/iota-framework b/crates/iota-framework/packages_compiled/iota-framework index 2c66d13a041446362f9a6551ad09fffc2f0bd559..e6ebfffe882ed98e816da31bf7c6224239e4e278 100644 GIT binary patch delta 433 zcmWlVzfK!L5XNU_Z~ypqZ|%K1pY5|TA>pr6M2alsoGKuMkkUj#NIU^Azylx}(nL|D zEdmKf0?{HN`~XRlE-9kWqV&+Eb48Zs_sx9LjAp*i7t!~N=<59F-EV!?yVn8$5`>h} zmu&qjMt`y7Q@la>i(NDIAl`^?GLQerMLm_mJjnMfIn=^_2!nOVpbI^igLznh760#O z3zz-I@w5HHB&c9uY+!EcfwqBxT5?qA97jf-MjvRgNPw1#7O-Zl5%^5b(TLeJ1DWzC zgdkgU{89S7nIN&V4xDu4n%HR9U8kG7#%!zG?vhYkDv27f2LASVhY7_d!!LK}KV`~y zPCoVr2@)2H5wXBQl50h(rfTFcEcHK5c56k&iDLv!KO8@Oo@vxHf=ZAG9_Jb!jY^UX zZD+yaYH6Z4vb0+IgYmp7b4xK>EB)no`!%_g3dvoo{anVp?ouWi<`9rDJaO9AUt1VsqCNKt+Q@B_%7phMb%B#I;D zC8dm%f)3FlQBb5qDUd6KL_tZF3C(wO&(+a=d^wLko<~=w``ef1WboT404bs1VqI)~ zpy-DB@(+C{{aIXyc&47IGhHU1^s2el%FgsZPHz+CW{EHrvz1$GIWH6V!@T@T4@jH)_o~ln+)MZB{l)BFCFmGo3ESRp~ep&#UI^ zboUiXwggCF@RT?WUmRM4+*@*#=M$>KX|;I?OqgBhN@ehb{tvJWM#v&8#{PQm_}jZX DiC{UJ diff --git a/crates/iota-framework/packages_compiled/iota-system b/crates/iota-framework/packages_compiled/iota-system index c8bcab19473e4052d13337b4ce630ccacc8c70aa..9441eaaaf92c1a30285eb1b25104b5416bc220e7 100644 GIT binary patch delta 7045 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, diff --git a/crates/iota-types/src/iota_system_state/iota_system_state_inner_v1.rs b/crates/iota-types/src/iota_system_state/iota_system_state_inner_v1.rs index f4797f3f4e2..5191be6c45e 100644 --- a/crates/iota-types/src/iota_system_state/iota_system_state_inner_v1.rs +++ b/crates/iota-types/src/iota_system_state/iota_system_state_inner_v1.rs @@ -454,6 +454,7 @@ pub struct IotaSystemStateV1 { 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. } @@ -631,6 +632,7 @@ impl IotaSystemStateTrait for IotaSystemStateV1 { safe_mode_storage_rebates, safe_mode_non_refundable_storage_fee, epoch_start_timestamp_ms, + system_display_objects: _, extra_fields: _, } = self; IotaSystemStateSummary { diff --git a/crates/iota-types/src/iota_system_state/mod.rs b/crates/iota-types/src/iota_system_state/mod.rs index 5e5634a53d5..89b0ac84888 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; @@ -18,6 +18,7 @@ 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, @@ -392,6 +393,47 @@ 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(inner) => inner + .system_display_objects + .contents + .into_iter() + .map(|entry| { + let display_object_id = entry.value.bytes; + + 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. +/// * ty - is a type for which a display object is created. +pub fn display_object_key(ty: StructTag) -> String { + let with_prefix = false; + + ty.to_canonical_string(with_prefix) +} + #[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Default)] pub struct PoolTokenExchangeRate { iota_amount: u64,