Protocol
This release introduces protocol version 26
#11443: Add iota::protocol_config::is_feature_enabled() to allow Move code to query protocol feature flags at runtime.
Nodes (Validators and Full nodes)
#11331: Debug format of ObjectId was changed from 0x... to ObjectId("0x...")
#11450: Added periodic checkpoint progress status message and reduced log spam
#11463: Removed the epoch-db-pruning-period-secs node config parameter. Pruning is now automatically triggered during every epoch transition. This fixes a potential memory leak and ensures consistent pruning behavior during node synchronization.
#11451: Hardened state sync peer tracking:
- added a handshake protocol to eliminate race conditions during peer registration
- fixed stale peer handling
- added periodic cleanup to prevent memory growth during long syncs
Indexer
#11312: JSON-RPC supports fetching objects before a requested version from the fallback KV storage when the indexer database does not contain the requested version due to pruning.
⚠️ The next release v1.24 will mark the removal of the old IOTA Indexer CLI which was deprecated in v1.3.1. Last call to refactor dependent scripts accordingly.
JSON-RPC
#10508: Remove all schemars / JsonSchema dependencies from iota-types (the core domain crate) and re-implement JSON schema generation exclusively within iota-json-rpc-types
#11326: Sequence numbers are now displayed in decimal format in error messages
#11331: Debug format of ObjectId was changed from 0x... to ObjectId("0x...")
#11395: IotaExecutionStatus::Failure error strings are produced
from the SDK's ExecutionError variants. Wording is the same for existing
cases, but field names quoted in the message have changed in line with the
variant/field renames listed above (e.g. arg_idx → argument).
#11397: Fixed "Could not find the referenced object" errors in balance/object changes for concurrent shared-object transactions.
GraphQL
#11439: Optimize Mutation.executeTransactionBlock.
CLI
#11390: Owner is now displayed using the SDK's Display impl
(Address(<addr>), Object(<id>), Shared(<v>), Immutable) instead of
the previous Account Address ( <addr> ) / Object ID: ( <id> ) /
Shared( <v> ) formatting.
#11393: The Argument::GasCoin PTB argument now displays as Gas instead
of GasCoin in CLI output and PTB snapshots.
Rust SDK
#11326: Some methods have been removed from SequenceNumber due to
crate externalization (iota-sdk-types::Version is replacing
iota-types::SequenceNumber). Constructors and arithmetic helpers
(next, increment, decrement, lamport_increment,
new_congested_with_suggested_gas_price) are now fallible on the SDK type.
#11330: Some methods have been removed from IotaAddress due to
crate externalization (iota-sdk-types::Address is replacing
iota-types::IotaAddress). Notably, random_for_testing_only is renamed
to random, to_inner / tuple-field access is replaced by into_bytes,
try_from(&[u8]) / try_from(Vec<u8>) are replaced by
from_bytes(&[u8]), the blanket From<&IotaPublicKey> impl is replaced
by the address_from_iota_pub_key free function, and Default is no
longer derived (use IotaAddress::ZERO).
#11331: Some methods have been removed from ObjectID due to crate externalization (iota-rust-sdk::ObjectId is replacing iota-types::ObjectID).
#11338: The Digest type and the per-domain digest wrappers
(TransactionDigest, CheckpointDigest, ObjectDigest, etc.) are now
re-exports/aliases of iota_sdk_types::Digest rather than locally defined
newtypes. Surface changes: genesis_marker() is replaced by the
GENESIS_MARKER associated constant; base58_encode() is replaced by
to_base58(); try_from(Vec<u8>) / try_from(&[u8]) are replaced by
from_bytes(...); next_lexicographical(&self) -> Self now wraps at
all-FF (use next_lexicographical_opt for the previous
Option-returning behavior); the ObjectDigest tombstone constants are
renamed (OBJECT_DIGEST_DELETED → OBJECT_DELETED,
OBJECT_DIGEST_WRAPPED → OBJECT_WRAPPED,
OBJECT_DIGEST_CANCELLED → OBJECT_CANCELLED); the matching predicates
are renamed (is_deleted → is_object_deleted,
is_wrapped → is_object_wrapped); the Debug representation is
unified as Digest("<base58>").
#11337: iota-types::gas::GasCostSummary is now a re-export of iota_sdk_types::gas::GasCostSummary. The new_from_txn_effects associated function has been removed; its single caller now uses a free function colocated in iota-core::checkpoints. GasCostSummary::sender_rebate was not ported over to the external SDK.
#11355: Identifier, StructTag and TypeTag exported from iota-types are now re-exports of iota_sdk_types::{Identifier, StructTag, TypeTag}. Their public API differs from the previous move-core-types types: struct fields are private and accessed via methods (address(), module(), name(), type_params()), constructors like StructTag::new_coin(...) / StructTag::new_balance(...) / StructTag::new_gas() replace the manual StructTag { … } literals and the per-type T::type_() helpers, and MoveObjectType::address() now returns IotaAddress while module() / name() return owned Identifier.
#11376: iota-types::event::Event is now a re-export of
iota_sdk_types::Event. The transaction_module field has been renamed
to module; the Event::new constructor and
Event::move_event_to_move_value associated function have been removed.
DisplayVersionUpdatedEvent::inner_type / try_from_event and the unused
DisplayCreatedEvent have been removed from iota-types::display.
#11380: ObjectRef (previously a tuple alias
(ObjectID, SequenceNumber, ObjectDigest) in iota-types) is now a
re-export of iota_sdk_types::ObjectReference. Code that destructured it
positionally or built it with tuple syntax must switch to the struct's
named fields (object_id, version, digest) and
ObjectReference::new(...) / ObjectReference::into_parts().
#11388: RandomnessStateUpdate and RandomnessRound are now defined
in iota-sdk-types and re-exported from iota-types. RandomnessRound is
no longer a tuple struct — use RandomnessRound::new(n) to construct and
round.value() to access the inner u64 instead of RandomnessRound(n) /
round.0.
#11390: iota_types::object::Owner is now a re-export of
iota_sdk_types::Owner. Variant names and shapes changed
(AddressOwner/ObjectOwner/Shared { .. } →
Address/Object/Shared(..)), helper methods were renamed
(is_address_owned → is_address, is_child_object → is_object,
get_owner_address → address_or_object), and the enum is now
#[non_exhaustive].
#11393: iota_types::transaction::Argument is now a re-export of
iota_sdk_types::Argument. The GasCoin variant has been renamed to Gas
to match the SDK definition.
#11395: iota_types::execution_status::{ExecutionStatus, ExecutionFailureStatus, MoveLocation, CommandArgumentError, PackageUpgradeError, TypeArgumentError} are now re-exports of their
iota-sdk-types counterparts. Most call sites are unaffected, but
consumers relying on the previous tuple-variant layouts (MoveAbort(_, _),
MovePrimitiveRuntimeError(MoveLocationOpt)), the CongestedObjects
newtype, the is_ok/is_err helpers, or the previous field names on
these enums will need to update accordingly. CommandIndex is now u64
instead of usize.
#11408: MovePackage, TypeOrigin and UpgradeInfo are now defined
in iota-sdk-types and re-exported from iota-types. Direct field access
on MovePackage (module_map, type_origin_table, linkage_table) is
replaced by the SDK shape (modules keyed by Identifier, identifier
fields on TypeOrigin). Constructors and helpers that depend on
CompiledModule / ProtocolConfig (new_initial, new_upgraded,
new_system, from_module_iter_with_type_origin_table,
original_package_id, deserialize_module, normalize) now live on the
MovePackageExt trait in iota-types.
#11409: Input gains constants (IOTA_SYSTEM_MUTABLE,
CLOCK_IMMUTABLE, CLOCK_MUTABLE, AUTHENTICATOR_STATE_MUTABLE),
a pure() constructor and *_opt accessors. Input::Shared now wraps
the new SharedObjectReference struct, and Input::Pure is a tuple
variant.
#11410: EndOfEpochTransactionKind gains new_change_epoch*
constructors, a shared_input_objects() iterator, is_*/as_*/into_*
accessors for all variants, and a Hash impl on the variant and its
ChangeEpoch* payloads.
#11411: iota_types::transaction::TransactionExpiration is now a
re-export of iota_sdk_types::TransactionExpiration. The variants
(None, Epoch) are unchanged and the BCS encoding is preserved, but
because the SDK type may grow new variants in the future, exhaustive
match expressions over TransactionExpiration should add a
catch-all arm.
#11423: the GasData field payment has been renamed to objects to match the SDK type (re-exported from iota-sdk-types::GasPayment).
#11425: ConsensusCommitPrologueV1, ConsensusDeterminedVersionAssignments,
CancelledTransaction, VersionAssignment, and TimestampMs are now
re-exported from iota_types::messages_consensus and originate in
iota-sdk-types. Downstream consumers can depend on the SDK directly
instead of iota-types.
#11426: iota-types::base_types::MoveObjectType is now a re-export
of iota_sdk_types::MoveObjectType. MoveObject's public API now takes
and returns StructTag instead of MoveObjectType (in
new_from_execution, new_from_execution_with_limit, into_type,
into_inner); a new MoveObject::type_tag() helper is added.
coin_type_maybe has been renamed to coin_type_opt and now returns
Option<&TypeTag>. Wire formats (BCS and JSON) are unchanged.
#11430: Command, ProgrammableMoveCall and the per-variant payload
structs (Publish, Upgrade, TransferObjects, SplitCoins,
MergeCoins, MakeMoveVector) are now re-exported from iota-sdk-types
via iota-types. The MakeMoveVec variant is renamed to MakeMoveVector,
variants now carry named-field structs instead of tuples, and constructor
helpers are renamed from Command::move_call to Command::new_move_call
(with matching new_* constructors for the other variants).
#11433: iota-types::transaction::ProgrammableTransaction is now a
re-export of iota_sdk_types::ProgrammableTransaction. Methods that
previously lived on the inherent impl (input_objects,
receiving_objects, validity_check, shared_input_objects,
move_calls, non_system_packages_to_be_published) have moved to a new
ProgrammableTransactionExt trait in iota-types::transaction; the
Display impl is replaced by ProgrammableTransactionExt::fmt_display.
Call sites need to import ProgrammableTransactionExt to use these
methods.
#11454: iota-types::object::Data is now a re-export of
iota_sdk_types::ObjectData. The Move variant is renamed
Data::Move(MoveObject) → Data::Struct(MoveObject), and a few helpers
move from the inherent impl to the SDK type: try_as_move →
as_struct_opt, type_ → object_type. Call sites that pattern-match on
the variant or use these helpers need to be updated; the BCS wire format
is unchanged.
#11456: GenesisObject is now re-exported from iota-sdk-types and is a struct rather than a single-variant enum. Construction sites must use GenesisObject::new(data, owner) (or struct literal) instead of GenesisObject::RawObject { data, owner }, and pattern matches/field access are updated accordingly.
#11467: UnchangedSharedKind is now sourced from iota-sdk-types
(re-exported from iota-types). Variants are struct-style
(ReadOnlyRoot { version, digest }, MutateDeleted { version },
ReadDeleted { version }, Cancelled { version }) instead of
tuple/newtype. BCS encoding is unchanged.
#11468: TransactionKind (and its variant payload types) is now
re-exported from iota_types::transaction and originates in
iota-sdk-types. Downstream consumers can depend on the SDK directly
instead of iota-types. Methods that require iota-types-specific types
are exposed via a new TransactionKindExt extension trait. Several
inherent methods are renamed to match the SDK
(is_system_tx → is_system, is_programmable_transaction →
is_programmable, tx_count → num_transactions).
#11470: iota-types::transaction::TransactionData is now a
re-export of iota_sdk_types::Transaction (and TransactionDataV1 of
TransactionV1). The TransactionDataV1::gas_data field is renamed to
gas_payment; the gas_data() / gas_data_mut() trait accessors keep
their names. All inherent constructors (new, new_move_call,
new_programmable, …) and the message_version / execution_parts
helpers have moved onto TransactionDataAPI; calls that used to go
through the inherent impl need the trait in scope. The unused
contains_shared_object, uses_randomness, and inherent digest
methods have been removed; transaction digest computation now goes
through the SDK's Transaction::digest(), which uses the salt
"TransactionData::" to preserve hash stability across the rename.
#11471: MoveStruct (re-exported as iota-types::object::MoveObject)
now has private fields. Construction must go through
MoveStruct::new(object_type, version, contents) and content updates
through set_contents(...); both are fallible and reject contents
shorter than ObjectId::LENGTH (32 bytes), since every Move object
must carry its ObjectId as the leading bytes. The associated helper
MoveObject::id_opt(&bytes) has been removed — call
ObjectID::from_bytes(&bytes[..ObjectID::LENGTH]) directly. Direct
field access (.object_type, .version, .contents) is replaced by
the equivalent getter methods. Wire formats (BCS and JSON) are
unchanged.