Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions bindings/wasm/notarization_wasm/src/wasm_notarization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,10 +447,8 @@ impl WasmUpdateMetadata {
/// @remarks
/// The notarization must currently be destroy-allowed (see
/// {@link NotarizationClientReadOnly.isDestroyAllowed}); otherwise the
/// on-chain transaction aborts. All component {@link TimeLock}s of the
/// on-chain transaction aborts. All package-local {@link TimeLock}s of the
/// attached {@link LockMetadata} are destroyed in the process.
/// A {@link TimeLockType.Infinite} lock is not
/// destructible and therefore always blocks destruction.
///
/// Emits a `NotarizationDestroyed` event on success.
#[wasm_bindgen(js_name = DestroyNotarization, inspectable)]
Expand Down
11 changes: 6 additions & 5 deletions bindings/wasm/notarization_wasm/src/wasm_notarization_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,10 @@ impl WasmNotarizationClient {
.collect()
}

/// The TF-Components package ID for the current network, when available;
/// `undefined` otherwise.
/// The TF-Components package ID for product_common compatibility.
///
/// Notarization uses the package-local `timelock` module, so this is
/// always `undefined`.
#[wasm_bindgen(js_name = tfComponentsPackageId)]
pub fn tf_components_package_id(&self) -> Option<String> {
None
Expand Down Expand Up @@ -211,12 +213,11 @@ impl WasmNotarizationClient {
/// releases its object ID.
///
/// @remarks
/// All component {@link TimeLock}s of the attached {@link LockMetadata}
/// All package-local {@link TimeLock}s of the attached {@link LockMetadata}
/// are destroyed in the process. The notarization must currently be
/// destroy-allowed (see
/// {@link NotarizationClientReadOnly.isDestroyAllowed}); otherwise the
/// on-chain transaction aborts. A {@link TimeLockType.Infinite} lock is
/// not destructible and therefore always blocks destruction.
/// on-chain transaction aborts.
///
/// @param notarizationId - The notarization object's ID.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,10 @@ impl WasmNotarizationClientReadOnly {
.collect()
}

/// The TF-Components package ID for the current network, when available;
/// `undefined` otherwise.
/// The TF-Components package ID for product_common compatibility.
///
/// Notarization uses the package-local `timelock` module, so this is
/// always `undefined`.
#[wasm_bindgen(js_name = tfComponentsPackageId)]
pub fn tf_components_package_id(&self) -> Option<String> {
None
Expand Down
33 changes: 3 additions & 30 deletions bindings/wasm/notarization_wasm/src/wasm_time_lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,16 @@ pub enum WasmTimeLockType {
None = "None",
/// Unlocks at a specific timestamp expressed in seconds since the Unix epoch.
UnlockAt = "UnlockAt",
/// Unlocks at a specific timestamp expressed in milliseconds since the Unix epoch.
UnlockAtMs = "UnlockAtMs",
/// Stays locked until the notarization is destroyed.
/// Cannot be used for the `deleteLock` field of {@link LockMetadata}.
UntilDestroyed = "UntilDestroyed",
/// Permanently locked — never unlocks.
Infinite = "Infinite",
}

/// A time-based lock applied to one of the lock fields of a notarization.
///
/// @remarks
/// Construct one with the static factory methods ({@link TimeLock.withUnlockAt},
/// {@link TimeLock.withUnlockAtMs}, {@link TimeLock.withUntilDestroyed},
/// {@link TimeLock.withInfinite}, {@link TimeLock.withNone}) and inspect it via
/// {@link TimeLock.withUntilDestroyed}, {@link TimeLock.withNone}) and inspect it via
/// the {@link TimeLock.type} and {@link TimeLock.args} getters.
#[wasm_bindgen(js_name = TimeLock, inspectable)]
#[derive(Debug, Clone, Serialize, Deserialize)]
Expand All @@ -49,16 +44,6 @@ impl WasmTimeLock {
Self(TimeLock::UnlockAt(time_sec))
}

/// Creates a lock that releases at a specific timestamp in milliseconds.
///
/// @param timeMs - Unlock time, in milliseconds since the Unix epoch.
///
/// @returns A {@link TimeLock} of type {@link TimeLockType.UnlockAtMs}.
#[wasm_bindgen(js_name = withUnlockAtMs)]
pub fn with_unlock_at_ms(time_ms: u64) -> Self {
Self(TimeLock::UnlockAtMs(time_ms))
}

/// Creates a lock that stays engaged until the notarization is destroyed.
///
/// @remarks
Expand All @@ -72,14 +57,6 @@ impl WasmTimeLock {
Self(TimeLock::UntilDestroyed)
}

/// Creates a permanent lock that never releases.
///
/// @returns A {@link TimeLock} of type {@link TimeLockType.Infinite}.
#[wasm_bindgen(js_name = withInfinite)]
pub fn with_infinite() -> Self {
Self(TimeLock::Infinite)
}

/// Creates an absent lock — semantically "no restriction".
///
/// @returns A {@link TimeLock} of type {@link TimeLockType.None}.
Expand All @@ -93,23 +70,19 @@ impl WasmTimeLock {
pub fn lock_type(&self) -> WasmTimeLockType {
match &self.0 {
TimeLock::UnlockAt(_) => WasmTimeLockType::UnlockAt,
TimeLock::UnlockAtMs(_) => WasmTimeLockType::UnlockAtMs,
TimeLock::UntilDestroyed => WasmTimeLockType::UntilDestroyed,
TimeLock::Infinite => WasmTimeLockType::Infinite,
TimeLock::None => WasmTimeLockType::None,
}
}

/// The argument carried by the lock variant, if any.
///
/// @returns The unlock timestamp (`number`) for `UnlockAt` (seconds) and
/// `UnlockAtMs` (milliseconds); `undefined` for `None`, `UntilDestroyed`,
/// and `Infinite`.
/// @returns The unlock timestamp (`number`) for `UnlockAt` (seconds);
/// `undefined` for `None` and `UntilDestroyed`.
#[wasm_bindgen(js_name = "args", getter)]
pub fn args(&self) -> JsValue {
match &self.0 {
TimeLock::UnlockAt(u) => JsValue::from(*u),
TimeLock::UnlockAtMs(u) => JsValue::from(*u),
_ => JsValue::UNDEFINED,
}
}
Expand Down
10 changes: 5 additions & 5 deletions notarization-move/Move.history.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
{
"aliases": {
"devnet": "daf90477",
"testnet": "2304aa97",
"mainnet": "6364aad5"
"mainnet": "6364aad5",
"testnet": "2304aa97"
},
"envs": {
"daf90477": [
"0x72c8433b88e6bdee0eb02a257fdebd0ec2b6c990043f35b155cb4c5cf727fdca"
],
"2304aa97": [
"0x00412bd469b7f980227c6c574090348239852e43aa07818b315854fdd8a2d25f"
],
"daf90477": [
"0x72c8433b88e6bdee0eb02a257fdebd0ec2b6c990043f35b155cb4c5cf727fdca"
],
"6364aad5": [
"0x909ce9dcd9a5e97b7b8884fac8e018fad9dece348bf73837379b8694ff684cf3"
]
Expand Down
37 changes: 2 additions & 35 deletions notarization-move/Move.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,10 @@

[move]
version = 3
manifest_digest = "E8F9EAB938F4F4898CB27E88DD059EEA0544D15A08AC9AFC6A0E81D4F3030DAC"
deps_digest = "397E6A9F7A624706DBDFEE056CE88391A15876868FD18A88504DA74EB458D697"
manifest_digest = "F6A54EEF62E080B67E4ACC8AFED64941661C020EFF00A8D68A404001EC85DD35"
deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082"
dependencies = [
{ id = "Iota", name = "Iota" },
{ id = "IotaSystem", name = "IotaSystem" },
{ id = "MoveStdlib", name = "MoveStdlib" },
{ id = "Stardust", name = "Stardust" },
{ id = "TfComponents", name = "TfComponents" },
]

[[move.package]]
Expand All @@ -20,39 +16,10 @@ dependencies = [
{ id = "MoveStdlib", name = "MoveStdlib" },
]

[[move.package]]
id = "IotaSystem"
source = { git = "https://github.com/iotaledger/iota.git", rev = "e694e2ee8f2f9f0b9b03b843a24ff0f7bcff2930", subdir = "crates/iota-framework/packages/iota-system" }

dependencies = [
{ id = "Iota", name = "Iota" },
{ id = "MoveStdlib", name = "MoveStdlib" },
]

[[move.package]]
id = "MoveStdlib"
source = { git = "https://github.com/iotaledger/iota.git", rev = "e694e2ee8f2f9f0b9b03b843a24ff0f7bcff2930", subdir = "crates/iota-framework/packages/move-stdlib" }

[[move.package]]
id = "Stardust"
source = { git = "https://github.com/iotaledger/iota.git", rev = "e694e2ee8f2f9f0b9b03b843a24ff0f7bcff2930", subdir = "crates/iota-framework/packages/stardust" }

dependencies = [
{ id = "Iota", name = "Iota" },
{ id = "MoveStdlib", name = "MoveStdlib" },
]

[[move.package]]
id = "TfComponents"
source = { git = "https://github.com/iotaledger/product-core.git", rev = "main", subdir = "components_move" }

dependencies = [
{ id = "Iota", name = "Iota" },
{ id = "IotaSystem", name = "IotaSystem" },
{ id = "MoveStdlib", name = "MoveStdlib" },
{ id = "Stardust", name = "Stardust" },
]

[move.toolchain-version]
compiler-version = "1.16.2-rc"
edition = "2024.beta"
Expand Down
2 changes: 1 addition & 1 deletion notarization-move/Move.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ name = "IotaNotarization"
edition = "2024.beta"

[dependencies]
TfComponents = { git = "https://github.com/iotaledger/product-core.git", subdir = "components_move", rev = "main" }
Iota = { git = "https://github.com/iotaledger/iota.git", subdir = "crates/iota-framework/packages/iota-framework", rev = "e694e2ee8f2f9f0b9b03b843a24ff0f7bcff2930" }

[addresses]
iota_notarization = "0x0"
Expand Down
4 changes: 2 additions & 2 deletions notarization-move/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ It defines the core `Notarization` object and the supporting modules for:
- state updates, transfer rules, and destruction checks
- emitted events for notarization lifecycle changes

The package depends on `TfComponents` for shared timelock primitives.

## Modules

- `iota_notarization::notarization`
Core object, state model, metadata, lock metadata, updates, and destruction logic.
- `iota_notarization::timelock`
Package-local timelock primitives used by notarization lock metadata.
- `iota_notarization::dynamic_notarization`
Dynamic notarization creation and transfer flows.
- `iota_notarization::locked_notarization`
Expand Down
3 changes: 0 additions & 3 deletions notarization-move/api_mapping.toml
Original file line number Diff line number Diff line change
Expand Up @@ -124,15 +124,12 @@ rust = [
"LockMetadata",
"TimeLock",
"TimeLock::new_with_ts",
"TimeLock::new_with_ts_ms",
]
wasm = [
"WasmLockMetadata",
"WasmTimeLock",
"WasmTimeLock::with_unlock_at",
"WasmTimeLock::with_unlock_at_ms",
"WasmTimeLock::with_until_destroyed",
"WasmTimeLock::with_infinite",
"WasmTimeLock::with_none",
"WasmTimeLockType",
]
Expand Down
3 changes: 1 addition & 2 deletions notarization-move/sources/dynamic_notarization.move
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
module iota_notarization::dynamic_notarization;

use iota::{clock::Clock, event};
use iota_notarization::notarization;
use iota_notarization::{notarization, timelock::TimeLock};
use std::string::String;
use tf_components::timelock::TimeLock;

// ===== Constants =====
/// Raised when `transfer` is called on a notarization whose `transfer_lock`
Expand Down
3 changes: 1 addition & 2 deletions notarization-move/sources/locked_notarization.move
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
module iota_notarization::locked_notarization;

use iota::{clock::Clock, event};
use iota_notarization::notarization;
use iota_notarization::{notarization, timelock::TimeLock};
use std::string::String;
use tf_components::timelock::TimeLock;

/// Emitted by `create` after a Locked-Notarization is created and
/// transferred to the sender.
Expand Down
38 changes: 16 additions & 22 deletions notarization-move/sources/notarization.move
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
module iota_notarization::notarization;

use iota::{clock::{Self, Clock}, event};
use iota_notarization::method::{NotarizationMethod, new_dynamic, new_locked};
use iota_notarization::{
method::{NotarizationMethod, new_dynamic, new_locked},
timelock::{Self, TimeLock}
};
use std::string::String;
use tf_components::timelock::{Self, TimeLock};

// ===== Constants =====
/// Raised when `state` or `updatable_metadata` is updated while the update lock is active.
Expand Down Expand Up @@ -150,13 +152,12 @@ public fun new_state_from_generic<D: store + drop + copy>(
State { data, metadata }
}

/// Constructs a `LockMetadata` from the three component `TimeLock`s.
/// Constructs a `LockMetadata` from the three package-local `TimeLock`s.
///
/// Rejects combinations that would let the object be destroyed before its
/// update or transfer locks expire. When `delete_lock` is a `TimeLock::UnlockAt`
/// (or `UnlockAtMs`), its unlock time must be greater than or equal to the
/// unlock time of any `UnlockAt` (or `UnlockAtMs`) `update_lock` or
/// `transfer_lock`.
/// update or transfer locks expire. When `delete_lock` is a `TimeLock::UnlockAt`,
/// its unlock time must be greater than or equal to the unlock time of any
/// `UnlockAt` `update_lock` or `transfer_lock`.
///
/// In the current implementation the legal combinations are further narrowed
/// by the method-specific invariants enforced in `new_dynamic_notarization`
Expand All @@ -166,9 +167,8 @@ public fun new_state_from_generic<D: store + drop + copy>(
///
/// Aborts with:
/// * `EUntilDestroyedLockNotAllowed` when `delete_lock` is `TimeLock::UntilDestroyed`.
/// * `ELockTimeNotSatisfied` when `delete_lock` is `UnlockAt`/`UnlockAtMs` and
/// its unlock time is earlier than the unlock time of `update_lock` or
/// `transfer_lock`.
/// * `ELockTimeNotSatisfied` when `delete_lock` is `UnlockAt` and its unlock
/// time is earlier than the unlock time of `update_lock` or `transfer_lock`.
///
/// Returns the constructed `LockMetadata`.
public fun new_lock_metadata(
Expand Down Expand Up @@ -375,15 +375,14 @@ public fun update_state<D: store + drop + copy>(

/// Destroys `self` and releases the underlying object id.
///
/// All component `TimeLock`s of the optional `LockMetadata` are destroyed in
/// All package-local `TimeLock`s of the optional `LockMetadata` are destroyed in
/// the process; the gating check `is_destroy_allowed` ensures that no
/// `UnlockAt`/`UnlockAtMs` lock is still active. `TimeLock::Infinite` is not
/// destructible and therefore always blocks destruction.
/// `UnlockAt` lock is still active.
///
/// Aborts with:
/// * `EDestroyWhileLocked` when `is_destroy_allowed` is `false`.
/// * `tf_components::timelock::ETimelockNotExpired` when any component
/// `TimeLock` is `TimeLock::Infinite`.
/// * `iota_notarization::timelock::ETimelockNotExpired` when any `UnlockAt`
/// lock is destroyed before it expires.
///
/// Emits a `NotarizationDestroyed` event on success.
public fun destroy<D: drop + store + copy>(self: Notarization<D>, clock: &Clock) {
Expand Down Expand Up @@ -563,15 +562,10 @@ public fun is_transfer_locked<D: store + drop + copy>(self: &Notarization<D>, cl
/// Checks whether `self` is currently eligible for destruction.
///
/// The result depends on the Notarization Method:
/// * `Dynamic`: returns `false` when an `UnlockAt`/`UnlockAtMs`
/// * `Dynamic`: returns `false` when an `UnlockAt`
/// `transfer_lock` has not yet expired, and `true` otherwise.
/// * `Locked`: returns `true` only when none of `update_lock`, `delete_lock`,
/// or `transfer_lock` is currently an unexpired `UnlockAt`/`UnlockAtMs`
/// lock.
///
/// `TimeLock::Infinite` is treated as not currently `UnlockAt` for this
/// check but will still abort `destroy`, because such locks are not
/// destructible.
/// or `transfer_lock` is currently an unexpired `UnlockAt` lock.
public fun is_destroy_allowed<D: store + drop + copy>(self: &Notarization<D>, clock: &Clock): bool {
if (self.method.is_dynamic()) {
!option::is_some_and!(
Expand Down
Loading
Loading