From 346ec7f20fca83538228f20c74b6e1742f48f3fd Mon Sep 17 00:00:00 2001 From: Bogdan Warinschi Date: Wed, 2 Apr 2025 17:11:23 +0200 Subject: [PATCH 01/10] initial draft --- ICRCs/ICRC-124/ICRC-124.md | 67 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 ICRCs/ICRC-124/ICRC-124.md diff --git a/ICRCs/ICRC-124/ICRC-124.md b/ICRCs/ICRC-124/ICRC-124.md new file mode 100644 index 00000000..0659daae --- /dev/null +++ b/ICRCs/ICRC-124/ICRC-124.md @@ -0,0 +1,67 @@ +## Motivation + +ICRC-124 provides essential administrative controls for token ledgers on the Internet Computer to: + +1. **Emergency Response**: Enable temporary suspension during security incidents or suspected fraud +2. **Regulatory Compliance**: Support mechanisms for meeting legal requirements +3. **Lifecycle Management**: Allow for transparent and standardized token retirement +4. **Auditability**: Create clear records of administrative actions and their authorization +5. **Operational Stability**: Provide standardized recovery paths from exceptional states + + +## Overview of Block Types + +- **Pause Ledger**: `124pause` +- **Unpause Ledger**: `124unpause` +- **Deactivate Ledger**: `124deactivate` + +## Common Structure + +Each block introduced by this standard MUST include a `tx` field containing a map that encodes the specific administrative action that was submitted to the ledger and which resulted in the block being created. These blocks follow the ICRC-3 structure and include: + +| Field | Type (ICRC-3 `Value`) | Required | Description | +|----------|------------------------|----------|-------------| +| `btype` | `Text` | Yes | One of: `"124pause"`, `"124unpause"`, or `"124deactivate"` | +| `ts` | `Nat` | Yes | Timestamp (in nanoseconds) of block creation | +| `phash` | `Blob` | Yes | Hash of the previous block | +| `tx` | `Map(Text, Value)` | Yes | Encodes the pause, unpause, or deactivate transaction | + +### `tx` Field Schema + +All three block types share the same schema: + +| Field | Type (ICRC-3 `Value`) | Required | Description | +|--------------|------------------------|----------|-------------| +| `authorizer` | `Blob` | Yes | Principal that authorized the action | +| `metadata` | `Map(Text, Value)` | Optional | Additional context (e.g., reason, governance proposal) | + +## Semantics +- When a `124pause` block is recorded, the ledger MUST reject all new transactions **except** a `124unpause` transaction. +- When a `124unpause` block is recorded, the ledger MUST resume accepting transactions (unless in terminal state). +- When a `124deactivate` block is recorded, the ledger MUST transition to a **terminal state** where: + - All new state-modifying transactions are permanently rejected + - Historical transaction data remains available for querying + - The token's transaction history is preserved as an immutable record + +Once a `124deactivate` block is recorded, the ledger's state becomes **immutable** for transfer operations while maintaining read access to historical data. + + +## Compliance Reporting + +Ledgers implementing this standard MUST return the following entries from `icrc3_supported_block_types`: + +```motoko +vec { + variant { Record = vec { + record { "btype"; variant { Text = "124pause" }}; + record { "url"; variant { Text = "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md" }}; + }}; + variant { Record = vec { + record { "btype"; variant { Text = "124unpause" }}; + record { "url"; variant { Text = "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md" }}; + }}; + variant { Record = vec { + record { "btype"; variant { Text = "124deactivate" }}; + record { "url"; variant { Text = "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md" }}; + }}; +} From 52d2660f1bf84e7083728169ef2431f6aea843e4 Mon Sep 17 00:00:00 2001 From: bogwar <51327868+bogwar@users.noreply.github.com> Date: Fri, 4 Apr 2025 16:00:13 +0200 Subject: [PATCH 02/10] example blocks --- ICRCs/ICRC-124/ICRC-124.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/ICRCs/ICRC-124/ICRC-124.md b/ICRCs/ICRC-124/ICRC-124.md index 0659daae..953ebc04 100644 --- a/ICRCs/ICRC-124/ICRC-124.md +++ b/ICRCs/ICRC-124/ICRC-124.md @@ -46,6 +46,35 @@ All three block types share the same schema: Once a `124deactivate` block is recorded, the ledger's state becomes **immutable** for transfer operations while maintaining read access to historical data. +## Example blocks + +``` +variant { Map = vec { + // Block type identifier + record { "btype"; variant { Text = "124pause" }}; + + // Timestamp when the block was appended (nanoseconds since epoch) + record { "ts"; variant { Nat = 1_741_312_737_184_874_392 : nat }}; + + // Hash of the previous block in the ledger chain + record { "phash"; variant { + Blob = blob "\de\ad\be\ef\00\11\22\33\44\55\66\77\88\99\aa\bb\cc\dd\ee\ff\10\20\30\40\50\60\70\80\90\a0\b0\c0" + }}; + + // Pause transaction payload + record { "tx"; variant { Map = vec { + // Principal that authorized the pause + record { "authorizer"; variant { Blob = blob "\ab\cd\01\23\45\67\89\ef\01\23\45\67\89\ab\cd\ef\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f" }}; + + // Optional metadata + record { "metadata"; variant { Map = vec { + record { "reason"; variant { Text = "DAO vote: pause due to upgrade prep" }} + }}} + }}}; +}}; +``` + + ## Compliance Reporting Ledgers implementing this standard MUST return the following entries from `icrc3_supported_block_types`: From 735d4def2efb36df3abcb8f59b199d0aad57750c Mon Sep 17 00:00:00 2001 From: bogwar <51327868+bogwar@users.noreply.github.com> Date: Fri, 4 Apr 2025 16:03:26 +0200 Subject: [PATCH 03/10] example names --- ICRCs/ICRC-124/ICRC-124.md | 40 +++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/ICRCs/ICRC-124/ICRC-124.md b/ICRCs/ICRC-124/ICRC-124.md index 953ebc04..f045be43 100644 --- a/ICRCs/ICRC-124/ICRC-124.md +++ b/ICRCs/ICRC-124/ICRC-124.md @@ -48,6 +48,8 @@ Once a `124deactivate` block is recorded, the ledger's state becomes **immutable ## Example blocks +### 124pause Example + ``` variant { Map = vec { // Block type identifier @@ -64,7 +66,7 @@ variant { Map = vec { // Pause transaction payload record { "tx"; variant { Map = vec { // Principal that authorized the pause - record { "authorizer"; variant { Blob = blob "\ab\cd\01\23\45\67\89\ef\01\23\45\67\89\ab\cd\ef\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f" }}; + record { "authorizer"; variant { Blob = blob "\ab\cd\01\23\45\67\89\ef\01\23\45\67\89\ab\cd\ef\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\01" }}; // Optional metadata record { "metadata"; variant { Map = vec { @@ -74,7 +76,43 @@ variant { Map = vec { }}; ``` +### 124unpause Example + +``` +variant { Map = vec { + record { "btype"; variant { Text = "124unpause" }}; + record { "ts"; variant { Nat = 1_741_312_737_200_000_000 : nat }}; + record { "phash"; variant { + Blob = blob "\be\ba\fe\ca\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\10\11\12\13\14\15\16\17\18\19\1a\1b" + }}; + record { "tx"; variant { Map = vec { + record { "authorizer"; variant { Blob = blob "\11\22\33\44\55\66\77\88\99\aa\bb\cc\dd\ee\ff\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\01" }}; + record { "metadata"; variant { Map = vec { + record { "note"; variant { Text = "Ledger resumes after maintenance window" }} + }}} + }}}; +}}; +``` + +### 124deactivate Example + +``` +variant { Map = vec { + record { "btype"; variant { Text = "124deactivate" }}; + record { "ts"; variant { Nat = 1_741_312_737_250_000_000 : nat }}; + record { "phash"; variant { + Blob = blob "\c0\ff\ee\00\10\20\30\40\50\60\70\80\90\a0\b0\c0\d0\e0\f0\00\11\22\33\44\55\66\77\88\99\aa\bb\cc" + }}; + record { "tx"; variant { Map = vec { + record { "authorizer"; variant { Blob = blob "\de\ad\be\ef\00\11\22\33\44\55\66\77\88\99\aa\bb\cc\dd\ee\ff\10\20\30\40\50\60\70\80\90\a0\b0\01" }}; + record { "metadata"; variant { Map = vec { + record { "finalized_by"; variant { Text = "SNS DAO proposal 314" }}, + record { "note"; variant { Text = "Ledger permanently frozen to preserve historical state" }} + }}} + }}}; +}}; +``` ## Compliance Reporting Ledgers implementing this standard MUST return the following entries from `icrc3_supported_block_types`: From baa31dbbd93dcaaf96442bb4befad6015e585b34 Mon Sep 17 00:00:00 2001 From: bogwar <51327868+bogwar@users.noreply.github.com> Date: Fri, 4 Apr 2025 16:11:54 +0200 Subject: [PATCH 04/10] appended -> recorded --- ICRCs/ICRC-124/ICRC-124.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ICRCs/ICRC-124/ICRC-124.md b/ICRCs/ICRC-124/ICRC-124.md index f045be43..e6ee7ab8 100644 --- a/ICRCs/ICRC-124/ICRC-124.md +++ b/ICRCs/ICRC-124/ICRC-124.md @@ -55,7 +55,7 @@ variant { Map = vec { // Block type identifier record { "btype"; variant { Text = "124pause" }}; - // Timestamp when the block was appended (nanoseconds since epoch) + // Timestamp when the block was recorded (nanoseconds since epoch) record { "ts"; variant { Nat = 1_741_312_737_184_874_392 : nat }}; // Hash of the previous block in the ledger chain From 4180d2bfaf0a68450b64e749bf94b7aa34c2e3d1 Mon Sep 17 00:00:00 2001 From: bogwar <51327868+bogwar@users.noreply.github.com> Date: Fri, 4 Apr 2025 18:01:31 +0200 Subject: [PATCH 05/10] consistent intro --- ICRCs/ICRC-124/ICRC-124.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/ICRCs/ICRC-124/ICRC-124.md b/ICRCs/ICRC-124/ICRC-124.md index e6ee7ab8..bc327162 100644 --- a/ICRCs/ICRC-124/ICRC-124.md +++ b/ICRCs/ICRC-124/ICRC-124.md @@ -1,12 +1,8 @@ -## Motivation +# ICRC-124: Ledger Pausing, Unpausing, and Deactivation + +ICRC-124 introduces new block types for recording administrative actions that control the operational state of an ICRC-compliant ledger. These blocks allow ledgers to be paused (temporarily halted), unpaused (resumed), or permanently deactivated (made immutable). This standard provides a consistent, auditable way to represent these state transitions within the ledger itself, ensuring transparency and enabling robust governance and recovery mechanisms. -ICRC-124 provides essential administrative controls for token ledgers on the Internet Computer to: -1. **Emergency Response**: Enable temporary suspension during security incidents or suspected fraud -2. **Regulatory Compliance**: Support mechanisms for meeting legal requirements -3. **Lifecycle Management**: Allow for transparent and standardized token retirement -4. **Auditability**: Create clear records of administrative actions and their authorization -5. **Operational Stability**: Provide standardized recovery paths from exceptional states ## Overview of Block Types From 161de4254c81b00460fa1a8cfca4e7d56b0c88f3 Mon Sep 17 00:00:00 2001 From: Bogdan Warinschi Date: Tue, 15 Apr 2025 10:42:08 +0200 Subject: [PATCH 06/10] memo -> reason --- ICRCs/ICRC-124/ICRC-124.md | 142 ++++++++++++++++++++----------------- 1 file changed, 77 insertions(+), 65 deletions(-) diff --git a/ICRCs/ICRC-124/ICRC-124.md b/ICRCs/ICRC-124/ICRC-124.md index bc327162..1c5ed2bb 100644 --- a/ICRCs/ICRC-124/ICRC-124.md +++ b/ICRCs/ICRC-124/ICRC-124.md @@ -1,130 +1,142 @@ # ICRC-124: Ledger Pausing, Unpausing, and Deactivation -ICRC-124 introduces new block types for recording administrative actions that control the operational state of an ICRC-compliant ledger. These blocks allow ledgers to be paused (temporarily halted), unpaused (resumed), or permanently deactivated (made immutable). This standard provides a consistent, auditable way to represent these state transitions within the ledger itself, ensuring transparency and enabling robust governance and recovery mechanisms. +## Status +Draft +## Introduction +This standard defines new block types for recording administrative actions that control the operational state of an ICRC-compliant ledger: pausing (`124pause`), unpausing (`124unpause`), and deactivating (`124deactivate`). These actions allow ledger operations to be temporarily halted (e.g., for maintenance), resumed, or permanently stopped (making the ledger immutable). This standard provides a consistent, auditable way to represent these ledger-wide state transitions within the ledger's block history, ensuring transparency and enabling robust governance mechanisms. -## Overview of Block Types +## Motivation -- **Pause Ledger**: `124pause` -- **Unpause Ledger**: `124unpause` -- **Deactivate Ledger**: `124deactivate` +Ledger lifecycle management may require administrative actions like pausing for upgrades, unpausing after checks, or deactivating at the end of a token's useful life. These significant events must be recorded transparently on-chain. This standard provides explicit block types for these actions, defining a minimal block structure sufficient for recording the action and basic context, while relying on the ledger implementation to provide access to the full invocation details (like the authorizing principal) for comprehensive auditability. -## Common Structure +## Common Elements +This standard follows the conventions set by ICRC-3, inheriting key structural components. +- **Principals** involved (like the authorizer, though not stored *in* the `tx` field) are represented using the ICRC-3 `Value` type as `variant { Blob = }`. +- Each block includes `phash`, a `Blob` representing the hash of the parent block, and `ts`, a `Nat` representing the timestamp of the block. -Each block introduced by this standard MUST include a `tx` field containing a map that encodes the specific administrative action that was submitted to the ledger and which resulted in the block being created. These blocks follow the ICRC-3 structure and include: +## Block Types & Schema + +Each block introduced by this standard MUST include a `tx` field containing a map that encodes minimal information about the administrative action, primarily an optional reason. + +**Important Note on Transaction Recoverability:** The `tx` field defined below is intentionally minimal, containing only an optional reason string. For full auditability and transparency, ledger implementations compliant with ICRC-124 **MUST** ensure that the complete details of the original transaction invocation that led to the pause, unpause, or deactivation can be recovered independently. This includes, but is not limited to, the principal that invoked the ledger operation (the authorizer/caller), the specific ledger method called (e.g., `pause_ledger`), and the full arguments passed to that method. Mechanisms for recovering this data (e.g., via archive queries or specific lookup methods) are implementation-dependent but necessary for compliance. The `tx` field itself is *not* designed to hold this exhaustive information. + +Each block defined by this standard consists of the following top-level fields: | Field | Type (ICRC-3 `Value`) | Required | Description | |----------|------------------------|----------|-------------| -| `btype` | `Text` | Yes | One of: `"124pause"`, `"124unpause"`, or `"124deactivate"` | -| `ts` | `Nat` | Yes | Timestamp (in nanoseconds) of block creation | -| `phash` | `Blob` | Yes | Hash of the previous block | -| `tx` | `Map(Text, Value)` | Yes | Encodes the pause, unpause, or deactivate transaction | +| `btype` | `Text` | Yes | MUST be one of: `"124pause"`, `"124unpause"`, or `"124deactivate"`. | +| `ts` | `Nat` | Yes | Timestamp in nanoseconds when the block was added to the ledger. | +| `phash` | `Blob` | Yes | Hash of the parent block. | +| `tx` | `Map(Text, Value)` | Yes | Encodes minimal information about the pause/unpause/deactivate operation. See schema below. | ### `tx` Field Schema -All three block types share the same schema: +The `tx` field schema is the same for `124pause`, `124unpause`, and `124deactivate`: | Field | Type (ICRC-3 `Value`) | Required | Description | |--------------|------------------------|----------|-------------| -| `authorizer` | `Blob` | Yes | Principal that authorized the action | -| `metadata` | `Map(Text, Value)` | Optional | Additional context (e.g., reason, governance proposal) | +| `reason` | `Text` | Optional | Human-readable reason for the administrative action. | ## Semantics -- When a `124pause` block is recorded, the ledger MUST reject all new transactions **except** a `124unpause` transaction. -- When a `124unpause` block is recorded, the ledger MUST resume accepting transactions (unless in terminal state). -- When a `124deactivate` block is recorded, the ledger MUST transition to a **terminal state** where: - - All new state-modifying transactions are permanently rejected - - Historical transaction data remains available for querying - - The token's transaction history is preserved as an immutable record -Once a `124deactivate` block is recorded, the ledger's state becomes **immutable** for transfer operations while maintaining read access to historical data. +The recording of these blocks MUST influence the behavior of the ledger according to the following semantics: +### Pause Ledger (`124pause`) +- When a `124pause` block is recorded, the ledger MUST enter a "paused" state. +- While paused, the ledger MUST reject all incoming requests that attempt to modify the ledger state (e.g., `icrc1_transfer`, `icrc2_approve`, `icrc122_mint`, `icrc123_freezeaccount`, etc.), **except** for requests that would result in recording a `124unpause` block. +- Query calls SHOULD generally remain operational. -## Example blocks +### Unpause Ledger (`124unpause`) +- When a `124unpause` block is recorded, the ledger MUST exit the "paused" state and resume normal operation, accepting transactions as defined by its implementation and other active states (unless it is in a terminal state). +- An `124unpause` block has no effect if the ledger is already unpaused or if it is in a terminal state due to deactivation. -### 124pause Example +### Deactivate Ledger (`124deactivate`) +- When a `124deactivate` block is recorded, the ledger MUST transition to a permanent "terminal" or "deactivated" state. +- In this terminal state: + - All incoming requests that attempt to modify the ledger state MUST be permanently rejected. This includes transfers, approvals, mints, burns, freezes, pauses, unpauses, and any other state-changing operations. + - Query calls retrieving historical data (e.g., transaction history, past balances via `icrc3_get_blocks`) MUST remain available. +- The deactivated state is irreversible. The ledger effectively becomes an immutable historical record. + +## Compliance Reporting + +Ledgers implementing this standard MUST return the following entries (including entries for other supported types like ICRC-1, ICRC-3, etc.) from `icrc3_supported_block_types`, with URLs pointing to the standards defining each block type: +```candid +vec { + // ... other supported types like ICRC-1, ICRC-3, ICRC-122, ICRC-123 ... + variant { Record = vec { + record { "btype"; variant { Text = "124pause" }}; + record { "url"; variant { Text = "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md" }}; // Placeholder URL + }}; + variant { Record = vec { + record { "btype"; variant { Text = "124unpause" }}; + record { "url"; variant { Text = "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md" }}; // Placeholder URL + }}; + variant { Record = vec { + record { "btype"; variant { Text = "124deactivate" }}; + record { "url"; variant { Text = "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md" }}; // Placeholder URL + }}; +} ``` + +## Example Blocks + +### 124pause Example + +```candid variant { Map = vec { // Block type identifier record { "btype"; variant { Text = "124pause" }}; // Timestamp when the block was recorded (nanoseconds since epoch) - record { "ts"; variant { Nat = 1_741_312_737_184_874_392 : nat }}; + record { "ts"; variant { Nat = 1_741_384_155_000_000_000 : nat }}; // Approx 2025-04-15T10:29:15Z // Hash of the previous block in the ledger chain record { "phash"; variant { Blob = blob "\de\ad\be\ef\00\11\22\33\44\55\66\77\88\99\aa\bb\cc\dd\ee\ff\10\20\30\40\50\60\70\80\90\a0\b0\c0" }}; - // Pause transaction payload + // Minimal pause transaction details record { "tx"; variant { Map = vec { - // Principal that authorized the pause - record { "authorizer"; variant { Blob = blob "\ab\cd\01\23\45\67\89\ef\01\23\45\67\89\ab\cd\ef\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\01" }}; - - // Optional metadata - record { "metadata"; variant { Map = vec { - record { "reason"; variant { Text = "DAO vote: pause due to upgrade prep" }} - }}} + // Optional reason + record { "reason"; variant { Text = "DAO vote: pause due to upgrade prep" }}; }}}; }}; ``` ### 124unpause Example -``` +```candid variant { Map = vec { record { "btype"; variant { Text = "124unpause" }}; - record { "ts"; variant { Nat = 1_741_312_737_200_000_000 : nat }}; + record { "ts"; variant { Nat = 1_741_384_155_000_000_000 : nat }}; // Approx 2025-04-15T10:29:15Z record { "phash"; variant { Blob = blob "\be\ba\fe\ca\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\10\11\12\13\14\15\16\17\18\19\1a\1b" }}; + // Minimal unpause transaction details record { "tx"; variant { Map = vec { - record { "authorizer"; variant { Blob = blob "\11\22\33\44\55\66\77\88\99\aa\bb\cc\dd\ee\ff\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\01" }}; - record { "metadata"; variant { Map = vec { - record { "note"; variant { Text = "Ledger resumes after maintenance window" }} - }}} + // Optional reason + record { "reason"; variant { Text = "Ledger resumes after maintenance window" }}; }}}; }}; ``` ### 124deactivate Example -``` +```candid variant { Map = vec { record { "btype"; variant { Text = "124deactivate" }}; - record { "ts"; variant { Nat = 1_741_312_737_250_000_000 : nat }}; + record { "ts"; variant { Nat = 1_741_384_155_000_000_000 : nat }}; // Approx 2025-04-15T10:29:15Z record { "phash"; variant { Blob = blob "\c0\ff\ee\00\10\20\30\40\50\60\70\80\90\a0\b0\c0\d0\e0\f0\00\11\22\33\44\55\66\77\88\99\aa\bb\cc" }}; + // Minimal deactivate transaction details record { "tx"; variant { Map = vec { - record { "authorizer"; variant { Blob = blob "\de\ad\be\ef\00\11\22\33\44\55\66\77\88\99\aa\bb\cc\dd\ee\ff\10\20\30\40\50\60\70\80\90\a0\b0\01" }}; - record { "metadata"; variant { Map = vec { - record { "finalized_by"; variant { Text = "SNS DAO proposal 314" }}, - record { "note"; variant { Text = "Ledger permanently frozen to preserve historical state" }} - }}} + // Optional reason + record { "reason"; variant { Text = "Finalized by SNS DAO proposal 314. Ledger permanently frozen to preserve historical state." }}; }}}; }}; - ``` -## Compliance Reporting - -Ledgers implementing this standard MUST return the following entries from `icrc3_supported_block_types`: - -```motoko -vec { - variant { Record = vec { - record { "btype"; variant { Text = "124pause" }}; - record { "url"; variant { Text = "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md" }}; - }}; - variant { Record = vec { - record { "btype"; variant { Text = "124unpause" }}; - record { "url"; variant { Text = "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md" }}; - }}; - variant { Record = vec { - record { "btype"; variant { Text = "124deactivate" }}; - record { "url"; variant { Text = "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md" }}; - }}; -} From 0ad037d3838e2b1002e0a2ed342733283e4d2855 Mon Sep 17 00:00:00 2001 From: Bogdan Warinschi Date: Tue, 15 Apr 2025 10:44:26 +0200 Subject: [PATCH 07/10] more relaxed semantics --- ICRCs/ICRC-124/ICRC-124.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ICRCs/ICRC-124/ICRC-124.md b/ICRCs/ICRC-124/ICRC-124.md index 1c5ed2bb..4c61d1b2 100644 --- a/ICRCs/ICRC-124/ICRC-124.md +++ b/ICRCs/ICRC-124/ICRC-124.md @@ -46,8 +46,9 @@ The recording of these blocks MUST influence the behavior of the ledger accordin ### Pause Ledger (`124pause`) - When a `124pause` block is recorded, the ledger MUST enter a "paused" state. -- While paused, the ledger MUST reject all incoming requests that attempt to modify the ledger state (e.g., `icrc1_transfer`, `icrc2_approve`, `icrc122_mint`, `icrc123_freezeaccount`, etc.), **except** for requests that would result in recording a `124unpause` block. -- Query calls SHOULD generally remain operational. +- While paused, the ledger MUST reject incoming requests for standard token operations such as `icrc1_transfer` and `icrc2_approve`, and potentially other non-administrative state changes like `icrc122_mint` or `icrc122_burn`. +- However, while paused, the ledger MUST continue to accept specific administrative or management operations necessary for governance or recovery. This includes operations defined in ICRC-123 (e.g., `123freezeaccount`, `123unfreezeaccount`, `123freezeprincipal`, `123unfreezeprincipal`) and, critically, requests that result in recording a `124unpause` block. The exact set of allowed administrative operations during a pause SHOULD be defined by the specific ledger implementation's policy. +- Query calls SHOULD generally remain operational while the ledger is paused. ### Unpause Ledger (`124unpause`) - When a `124unpause` block is recorded, the ledger MUST exit the "paused" state and resume normal operation, accepting transactions as defined by its implementation and other active states (unless it is in a terminal state). @@ -56,9 +57,9 @@ The recording of these blocks MUST influence the behavior of the ledger accordin ### Deactivate Ledger (`124deactivate`) - When a `124deactivate` block is recorded, the ledger MUST transition to a permanent "terminal" or "deactivated" state. - In this terminal state: - - All incoming requests that attempt to modify the ledger state MUST be permanently rejected. This includes transfers, approvals, mints, burns, freezes, pauses, unpauses, and any other state-changing operations. - - Query calls retrieving historical data (e.g., transaction history, past balances via `icrc3_get_blocks`) MUST remain available. -- The deactivated state is irreversible. The ledger effectively becomes an immutable historical record. + - All ingress calls attempting to modify the ledger state MUST be permanently rejected. This includes, but is not limited to, transfers, approvals, mints, burns, freezes, unfreezes, pauses, unpauses, and any other state-changing operations defined now or in the future. **No transactions that alter state are permitted.** + - Query calls retrieving historical data (e.g., transaction history, past balances via `icrc3_get_blocks`) MUST remain available indefinitely to preserve the immutable record. +- The deactivated state is irreversible. ## Compliance Reporting From 124a173940876ab702a0749d6a62fd20d1e2baad Mon Sep 17 00:00:00 2001 From: Bogdan Warinschi Date: Mon, 19 May 2025 15:40:54 +0200 Subject: [PATCH 08/10] added caller to the tx, adapted the examples, refined semantics for stopped ledgers --- ICRCs/ICRC-124/ICRC-124.md | 142 ++++++++++++++++++++----------------- 1 file changed, 76 insertions(+), 66 deletions(-) diff --git a/ICRCs/ICRC-124/ICRC-124.md b/ICRCs/ICRC-124/ICRC-124.md index 4c61d1b2..f0ba56b2 100644 --- a/ICRCs/ICRC-124/ICRC-124.md +++ b/ICRCs/ICRC-124/ICRC-124.md @@ -6,39 +6,40 @@ Draft ## Introduction -This standard defines new block types for recording administrative actions that control the operational state of an ICRC-compliant ledger: pausing (`124pause`), unpausing (`124unpause`), and deactivating (`124deactivate`). These actions allow ledger operations to be temporarily halted (e.g., for maintenance), resumed, or permanently stopped (making the ledger immutable). This standard provides a consistent, auditable way to represent these ledger-wide state transitions within the ledger's block history, ensuring transparency and enabling robust governance mechanisms. +This standard defines new block types for recording administrative actions that control the operational state of an ICRC-compliant ledger: pausing (`124pause`), unpausing (`124unpause`), and deactivating (`124deactivate`). These actions allow ledger operations to be temporarily halted (e.g., for maintenance), resumed, or permanently stopped (making the ledger immutable). This standard provides a consistent, auditable way to represent these ledger-wide state transitions within the ledger's block history, ensuring transparency and enabling robust governance mechanisms. The transaction details (`tx`) within each block explicitly include the `caller` principal that authorized the operation. ## Motivation -Ledger lifecycle management may require administrative actions like pausing for upgrades, unpausing after checks, or deactivating at the end of a token's useful life. These significant events must be recorded transparently on-chain. This standard provides explicit block types for these actions, defining a minimal block structure sufficient for recording the action and basic context, while relying on the ledger implementation to provide access to the full invocation details (like the authorizing principal) for comprehensive auditability. +Ledger lifecycle management may require administrative actions like pausing for upgrades, unpausing after checks, or deactivating at the end of a token's useful life. These significant events must be recorded transparently on-chain. This standard provides explicit block types for these actions, defining a block structure that includes the initiator (`caller`) and essential details for the operation, enhancing on-chain auditability. ## Common Elements This standard follows the conventions set by ICRC-3, inheriting key structural components. -- **Principals** involved (like the authorizer, though not stored *in* the `tx` field) are represented using the ICRC-3 `Value` type as `variant { Blob = }`. +- **Principals** (such as the `caller`) are represented using the ICRC-3 `Value` type as `variant { Blob = }`. - Each block includes `phash`, a `Blob` representing the hash of the parent block, and `ts`, a `Nat` representing the timestamp of the block. ## Block Types & Schema -Each block introduced by this standard MUST include a `tx` field containing a map that encodes minimal information about the administrative action, primarily an optional reason. +Each block introduced by this standard MUST include a `tx` field containing a map. This map encodes information about the administrative action, including the `caller` principal and an optional reason. -**Important Note on Transaction Recoverability:** The `tx` field defined below is intentionally minimal, containing only an optional reason string. For full auditability and transparency, ledger implementations compliant with ICRC-124 **MUST** ensure that the complete details of the original transaction invocation that led to the pause, unpause, or deactivation can be recovered independently. This includes, but is not limited to, the principal that invoked the ledger operation (the authorizer/caller), the specific ledger method called (e.g., `pause_ledger`), and the full arguments passed to that method. Mechanisms for recovering this data (e.g., via archive queries or specific lookup methods) are implementation-dependent but necessary for compliance. The `tx` field itself is *not* designed to hold this exhaustive information. +**Important Note on Transaction Recoverability:** The `tx` field defined below now includes the `caller` principal. However, for full auditability and transparency in complex scenarios, ledger implementations compliant with ICRC-124 **MUST** ensure that any other details of the original transaction invocation not captured in `tx` can be recovered independently. This could include, but is not limited to, the full arguments passed to the ledger method (if more complex than the data in `tx`), or any intermediary calls if the operation was part of a multi-step process. Mechanisms for recovering such extended data (e.g., via archive queries or specific lookup methods) remain implementation-dependent. The rules determining *who* is authorized to invoke these ledger state change operations are an implementation detail of the ledger's governance model. Each block defined by this standard consists of the following top-level fields: -| Field | Type (ICRC-3 `Value`) | Required | Description | +| Field    | Type (ICRC-3 `Value`) | Required | Description | |----------|------------------------|----------|-------------| -| `btype` | `Text` | Yes | MUST be one of: `"124pause"`, `"124unpause"`, or `"124deactivate"`. | -| `ts` | `Nat` | Yes | Timestamp in nanoseconds when the block was added to the ledger. | -| `phash` | `Blob` | Yes | Hash of the parent block. | -| `tx` | `Map(Text, Value)` | Yes | Encodes minimal information about the pause/unpause/deactivate operation. See schema below. | +| `btype`  | `Text`                 | Yes      | MUST be one of: `"124pause"`, `"124unpause"`, or `"124deactivate"`. | +| `ts`     | `Nat`                  | Yes      | Timestamp in nanoseconds when the block was added to the ledger. | +| `phash`  | `Blob`                 | Yes      | Hash of the parent block. | +| `tx`     | `Map(Text, Value)`     | Yes      | Encodes information about the pause/unpause/deactivate operation, including the caller. See schema below. | ### `tx` Field Schema The `tx` field schema is the same for `124pause`, `124unpause`, and `124deactivate`: -| Field | Type (ICRC-3 `Value`) | Required | Description | -|--------------|------------------------|----------|-------------| -| `reason` | `Text` | Optional | Human-readable reason for the administrative action. | +| Field        | Type (ICRC-3 `Value`)                                    | Required | Description | +|--------------|----------------------------------------------------------|----------|-------------| +| `caller` | `Value` (Must be `variant { Blob = }`) | Yes | The principal that invoked the ledger method causing this block. | +| `reason`     | `Text`                                                   | Optional | Human-readable reason for the administrative action. | ## Semantics @@ -46,8 +47,8 @@ The recording of these blocks MUST influence the behavior of the ledger accordin ### Pause Ledger (`124pause`) - When a `124pause` block is recorded, the ledger MUST enter a "paused" state. -- While paused, the ledger MUST reject incoming requests for standard token operations such as `icrc1_transfer` and `icrc2_approve`, and potentially other non-administrative state changes like `icrc122_mint` or `icrc122_burn`. -- However, while paused, the ledger MUST continue to accept specific administrative or management operations necessary for governance or recovery. This includes operations defined in ICRC-123 (e.g., `123freezeaccount`, `123unfreezeaccount`, `123freezeprincipal`, `123unfreezeprincipal`) and, critically, requests that result in recording a `124unpause` block. The exact set of allowed administrative operations during a pause SHOULD be defined by the specific ledger implementation's policy. +- While paused, the ledger MUST reject incoming requests for standard token operations such as `icrc1_transfer`, `icrc2_approve`, and other non-administrative state changes such as those defined in ICRC-122 (e.g., `122mint`, `122burn`). +- However, while paused, the ledger MUST continue to accept specific administrative or management operations necessary for governance or recovery. This includes operations defined in ICRC-123 (e.g., `123freezeaccount`, `123unfreezeaccount`, `123freezeprincipal`, `123unfreezeprincipal`) and, critically, requests that result in recording a `124unpause` block. Ledger implementations MAY also permit requests that result in recording a `124deactivate` block while the ledger is paused, according to their defined governance policies. The exact set of allowed administrative operations during a pause SHOULD be defined by the specific ledger implementation's policy. - Query calls SHOULD generally remain operational while the ledger is paused. ### Unpause Ledger (`124unpause`) @@ -57,8 +58,8 @@ The recording of these blocks MUST influence the behavior of the ledger accordin ### Deactivate Ledger (`124deactivate`) - When a `124deactivate` block is recorded, the ledger MUST transition to a permanent "terminal" or "deactivated" state. - In this terminal state: - - All ingress calls attempting to modify the ledger state MUST be permanently rejected. This includes, but is not limited to, transfers, approvals, mints, burns, freezes, unfreezes, pauses, unpauses, and any other state-changing operations defined now or in the future. **No transactions that alter state are permitted.** - - Query calls retrieving historical data (e.g., transaction history, past balances via `icrc3_get_blocks`) MUST remain available indefinitely to preserve the immutable record. +    - All ingress calls attempting to modify the ledger state MUST be permanently rejected. This includes, but is not limited to, transfers, approvals, mints, burns, freezes, unfreezes, pauses, unpauses, and any other state-changing operations defined now or in the future. **No transactions that alter state are permitted.** +    - Query calls retrieving historical data (e.g., transaction history, past balances via `icrc3_get_blocks`) MUST remain available indefinitely to preserve the immutable record. - The deactivated state is irreversible. ## Compliance Reporting @@ -67,20 +68,21 @@ Ledgers implementing this standard MUST return the following entries (including ```candid vec { - // ... other supported types like ICRC-1, ICRC-3, ICRC-122, ICRC-123 ... - variant { Record = vec { - record { "btype"; variant { Text = "124pause" }}; - record { "url"; variant { Text = "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md" }}; // Placeholder URL - }}; - variant { Record = vec { - record { "btype"; variant { Text = "124unpause" }}; - record { "url"; variant { Text = "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md" }}; // Placeholder URL - }}; - variant { Record = vec { - record { "btype"; variant { Text = "124deactivate" }}; - record { "url"; variant { Text = "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md" }}; // Placeholder URL - }}; +    // ... other supported types like ICRC-1, ICRC-3, ICRC-122, ICRC-123 ... +    variant { Record = vec { +        record { "btype"; variant { Text = "124pause" }}; +        record { "url"; variant { Text = "[https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md](https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md)" }}; // Placeholder URL +    }}; +    variant { Record = vec { +        record { "btype"; variant { Text = "124unpause" }}; +        record { "url"; variant { Text = "[https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md](https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md)" }}; // Placeholder URL +    }}; +    variant { Record = vec { +        record { "btype"; variant { Text = "124deactivate" }}; +        record { "url"; variant { Text = "[https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md](https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md)" }}; // Placeholder URL +    }}; } + ``` ## Example Blocks @@ -89,39 +91,44 @@ vec { ```candid variant { Map = vec { - // Block type identifier - record { "btype"; variant { Text = "124pause" }}; - - // Timestamp when the block was recorded (nanoseconds since epoch) - record { "ts"; variant { Nat = 1_741_384_155_000_000_000 : nat }}; // Approx 2025-04-15T10:29:15Z - - // Hash of the previous block in the ledger chain - record { "phash"; variant { - Blob = blob "\de\ad\be\ef\00\11\22\33\44\55\66\77\88\99\aa\bb\cc\dd\ee\ff\10\20\30\40\50\60\70\80\90\a0\b0\c0" - }}; - - // Minimal pause transaction details - record { "tx"; variant { Map = vec { - // Optional reason - record { "reason"; variant { Text = "DAO vote: pause due to upgrade prep" }}; - }}}; +    // Block type identifier +    record { "btype"; variant { Text = "124pause" }}; + +    // Timestamp when the block was recorded (nanoseconds since epoch) +    record { "ts"; variant { Nat = 1_747_774_560_000_000_000 : nat }}; // Example: 2025-05-19T12:56:00Z + +    // Hash of the previous block in the ledger chain +    record { "phash"; variant { +        Blob = blob "\de\ad\be\ef\00\11\22\33\44\55\66\77\88\99\aa\bb\cc\dd\ee\ff\10\20\30\40\50\60\70\80\90\a0\b0\c0" +    }}; + +    // Pause transaction details +    record { "tx"; variant { Map = vec { + // The principal that invoked the pause_ledger operation +        record { "caller"; variant { Blob = blob "\00\00\00\00\00\00\f0\0d\01\03" }}; // Example caller principal (e.g., a governance canister) +        // Optional reason +        record { "reason"; variant { Text = "DAO vote #78: pause for scheduled maintenance." }}; +    }}}; }}; + ``` ### 124unpause Example ```candid variant { Map = vec { - record { "btype"; variant { Text = "124unpause" }}; - record { "ts"; variant { Nat = 1_741_384_155_000_000_000 : nat }}; // Approx 2025-04-15T10:29:15Z - record { "phash"; variant { - Blob = blob "\be\ba\fe\ca\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\10\11\12\13\14\15\16\17\18\19\1a\1b" - }}; - // Minimal unpause transaction details - record { "tx"; variant { Map = vec { - // Optional reason - record { "reason"; variant { Text = "Ledger resumes after maintenance window" }}; - }}}; +    record { "btype"; variant { Text = "124unpause" }}; +    record { "ts"; variant { Nat = 1_747_778_160_000_000_000 : nat }}; // Example: 2025-05-19T13:56:00Z +    record { "phash"; variant { +        Blob = blob "\be\ba\fe\ca\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\10\11\12\13\14\15\16\17\18\19\1a\1b" +    }}; +    // Unpause transaction details +    record { "tx"; variant { Map = vec { + // The principal that invoked the unpause_ledger operation +        record { "caller"; variant { Blob = blob "\00\00\00\00\00\00\f0\0d\01\03" }}; // Example caller principal +        // Optional reason +        record { "reason"; variant { Text = "Ledger resumes after maintenance window (DAO vote #79)." }}; +    }}}; }}; ``` @@ -129,15 +136,18 @@ variant { Map = vec { ```candid variant { Map = vec { - record { "btype"; variant { Text = "124deactivate" }}; - record { "ts"; variant { Nat = 1_741_384_155_000_000_000 : nat }}; // Approx 2025-04-15T10:29:15Z - record { "phash"; variant { - Blob = blob "\c0\ff\ee\00\10\20\30\40\50\60\70\80\90\a0\b0\c0\d0\e0\f0\00\11\22\33\44\55\66\77\88\99\aa\bb\cc" - }}; - // Minimal deactivate transaction details - record { "tx"; variant { Map = vec { - // Optional reason - record { "reason"; variant { Text = "Finalized by SNS DAO proposal 314. Ledger permanently frozen to preserve historical state." }}; - }}}; +    record { "btype"; variant { Text = "124deactivate" }}; +    record { "ts"; variant { Nat = 1_747_864_560_000_000_000 : nat }}; // Example: 2025-05-20T12:56:00Z +    record { "phash"; variant { +        Blob = blob "\c0\ff\ee\00\10\20\30\40\50\60\70\80\90\a0\b0\c0\d0\e0\f0\00\11\22\33\44\55\66\77\88\99\aa\bb\cc" +    }}; +    // Deactivate transaction details +    record { "tx"; variant { Map = vec { + // The principal that invoked the deactivate_ledger operation +        record { "caller"; variant { Blob = blob "\00\00\00\00\00\00\f0\0d\01\04" }}; // Example caller (e.g., project multisig or final DAO vote) +        // Optional reason +        record { "reason"; variant { Text = "Token project sunset. Ledger permanently archived as per SNS DAO proposal #314." }}; +    }}}; }}; + ``` From a5e8887c164ee51dd66fd36f2b8950c2987a3611 Mon Sep 17 00:00:00 2001 From: Bogdan Warinschi Date: Fri, 12 Sep 2025 12:58:58 +0200 Subject: [PATCH 09/10] alignment with the new ICRC-3 version --- ICRCs/ICRC-124/ICRC-124.md | 137 ++++++++++++++++++++++++------------- 1 file changed, 91 insertions(+), 46 deletions(-) diff --git a/ICRCs/ICRC-124/ICRC-124.md b/ICRCs/ICRC-124/ICRC-124.md index f0ba56b2..19d169c4 100644 --- a/ICRCs/ICRC-124/ICRC-124.md +++ b/ICRCs/ICRC-124/ICRC-124.md @@ -6,83 +6,101 @@ Draft ## Introduction -This standard defines new block types for recording administrative actions that control the operational state of an ICRC-compliant ledger: pausing (`124pause`), unpausing (`124unpause`), and deactivating (`124deactivate`). These actions allow ledger operations to be temporarily halted (e.g., for maintenance), resumed, or permanently stopped (making the ledger immutable). This standard provides a consistent, auditable way to represent these ledger-wide state transitions within the ledger's block history, ensuring transparency and enabling robust governance mechanisms. The transaction details (`tx`) within each block explicitly include the `caller` principal that authorized the operation. +This standard defines new block types for recording administrative actions that control the operational state of an ICRC-compliant ledger: pausing (`124pause`), unpausing (`124unpause`), and deactivating (`124deactivate`). These actions allow ledger operations to be temporarily halted (e.g., for maintenance), resumed, or permanently stopped (making the ledger immutable). This standard provides a consistent, auditable way to represent these ledger-wide state transitions within the ledger's block history, ensuring transparency and enabling robust governance mechanisms. ## Motivation -Ledger lifecycle management may require administrative actions like pausing for upgrades, unpausing after checks, or deactivating at the end of a token's useful life. These significant events must be recorded transparently on-chain. This standard provides explicit block types for these actions, defining a block structure that includes the initiator (`caller`) and essential details for the operation, enhancing on-chain auditability. +Ledger lifecycle management may require administrative actions like pausing for upgrades, unpausing after checks, or deactivating at the end of a token's useful life. These significant events must be recorded transparently on-chain. This standard provides explicit block types for these actions, defining a minimal block structure sufficient for semantics, while allowing optional provenance for auditability. ## Common Elements -This standard follows the conventions set by ICRC-3, inheriting key structural components. -- **Principals** (such as the `caller`) are represented using the ICRC-3 `Value` type as `variant { Blob = }`. -- Each block includes `phash`, a `Blob` representing the hash of the parent block, and `ts`, a `Nat` representing the timestamp of the block. + +This standard follows the conventions set by ICRC-3, inheriting key structural components: + +- **Principals** are represented using the ICRC-3 `Value` type as `variant { Blob = }`. +- **Timestamps:** `ts` (and any optional `created_at_time`) are **nanoseconds since the Unix epoch**, encoded as `Nat` but **MUST fit into `nat64`**. +- **Parent hash:** `phash : Blob` **MUST** be present if the block has a parent (omit for the genesis block). ## Block Types & Schema -Each block introduced by this standard MUST include a `tx` field containing a map. This map encodes information about the administrative action, including the `caller` principal and an optional reason. +Each block introduced by this standard MUST include a `tx` field containing a map. This map encodes the **minimal information** about the ledger state change. Additional provenance MAY be included but is not required for semantics. -**Important Note on Transaction Recoverability:** The `tx` field defined below now includes the `caller` principal. However, for full auditability and transparency in complex scenarios, ledger implementations compliant with ICRC-124 **MUST** ensure that any other details of the original transaction invocation not captured in `tx` can be recovered independently. This could include, but is not limited to, the full arguments passed to the ledger method (if more complex than the data in `tx`), or any intermediary calls if the operation was part of a multi-step process. Mechanisms for recovering such extended data (e.g., via archive queries or specific lookup methods) remain implementation-dependent. The rules determining *who* is authorized to invoke these ledger state change operations are an implementation detail of the ledger's governance model. +Each block consists of the following top-level fields: -Each block defined by this standard consists of the following top-level fields: +| Field | Type (ICRC-3 `Value`) | Required | Description | +|-------|------------------------|----------|-------------| +| `btype` | `Text` | Yes | MUST be one of: `"124pause"`, `"124unpause"`, or `"124deactivate"`. | +| `ts` | `Nat` | Yes | Timestamp (ns since Unix epoch) when the block was added to the ledger. MUST fit in `nat64`. | +| `phash` | `Blob` | Yes/No | Hash of the parent block; omitted only for the genesis block. | +| `tx` | `Map(Text, Value)` | Yes | Minimal operation details (see below). | -| Field    | Type (ICRC-3 `Value`) | Required | Description | -|----------|------------------------|----------|-------------| -| `btype`  | `Text`                 | Yes      | MUST be one of: `"124pause"`, `"124unpause"`, or `"124deactivate"`. | -| `ts`     | `Nat`                  | Yes      | Timestamp in nanoseconds when the block was added to the ledger. | -| `phash`  | `Blob`                 | Yes      | Hash of the parent block. | -| `tx`     | `Map(Text, Value)`     | Yes      | Encodes information about the pause/unpause/deactivate operation, including the caller. See schema below. | +### `tx` Field Schema (minimal) -### `tx` Field Schema +For all `124pause`, `124unpause`, and `124deactivate` blocks: -The `tx` field schema is the same for `124pause`, `124unpause`, and `124deactivate`: +- No required fields are needed for semantics. +- The presence of the block type alone (`btype`) determines the state transition. -| Field        | Type (ICRC-3 `Value`)                                    | Required | Description | -|--------------|----------------------------------------------------------|----------|-------------| -| `caller` | `Value` (Must be `variant { Blob = }`) | Yes | The principal that invoked the ledger method causing this block. | -| `reason`     | `Text`                                                   | Optional | Human-readable reason for the administrative action. | +### Optional Provenance (non-semantic) -## Semantics +Producers MAY include fields such as: + +- `caller : Blob` — principal that invoked the operation. +- `reason : Text` — human-readable context. +- `created_at_time : Nat` — caller-supplied timestamp (ns; MUST fit nat64). +- `policy_ref : Text` — identifier for proposal/vote/policy. +- `op : Text` — namespaced operation identifier, e.g. `148pause_ledger`. -The recording of these blocks MUST influence the behavior of the ledger according to the following semantics: +These fields MUST NOT affect semantics or verification. Verifiers MUST ignore them. + +> **Informative note (recoverability):** Implementations **SHOULD** provide mechanisms (e.g., archives or lookups) to retrieve extended invocation context not present in `tx` when useful for audits. The authorization model that permits these actions is implementation-defined. + +--- + +## Semantics ### Pause Ledger (`124pause`) - When a `124pause` block is recorded, the ledger MUST enter a "paused" state. -- While paused, the ledger MUST reject incoming requests for standard token operations such as `icrc1_transfer`, `icrc2_approve`, and other non-administrative state changes such as those defined in ICRC-122 (e.g., `122mint`, `122burn`). -- However, while paused, the ledger MUST continue to accept specific administrative or management operations necessary for governance or recovery. This includes operations defined in ICRC-123 (e.g., `123freezeaccount`, `123unfreezeaccount`, `123freezeprincipal`, `123unfreezeprincipal`) and, critically, requests that result in recording a `124unpause` block. Ledger implementations MAY also permit requests that result in recording a `124deactivate` block while the ledger is paused, according to their defined governance policies. The exact set of allowed administrative operations during a pause SHOULD be defined by the specific ledger implementation's policy. -- Query calls SHOULD generally remain operational while the ledger is paused. +- While paused, the ledger MUST reject all state-changing operations except those required for governance or recovery (e.g., `124unpause`, optionally `124deactivate`, and operations like freeze/unfreeze if permitted by governance policy). +- Query calls SHOULD remain operational. ### Unpause Ledger (`124unpause`) -- When a `124unpause` block is recorded, the ledger MUST exit the "paused" state and resume normal operation, accepting transactions as defined by its implementation and other active states (unless it is in a terminal state). -- An `124unpause` block has no effect if the ledger is already unpaused or if it is in a terminal state due to deactivation. +- When a `124unpause` block is recorded, the ledger MUST exit the "paused" state and resume normal operation, unless it is already in the terminal state due to deactivation. +- An `124unpause` block has no effect if the ledger is already unpaused or deactivated. ### Deactivate Ledger (`124deactivate`) -- When a `124deactivate` block is recorded, the ledger MUST transition to a permanent "terminal" or "deactivated" state. -- In this terminal state: -    - All ingress calls attempting to modify the ledger state MUST be permanently rejected. This includes, but is not limited to, transfers, approvals, mints, burns, freezes, unfreezes, pauses, unpauses, and any other state-changing operations defined now or in the future. **No transactions that alter state are permitted.** -    - Query calls retrieving historical data (e.g., transaction history, past balances via `icrc3_get_blocks`) MUST remain available indefinitely to preserve the immutable record. +- When a `124deactivate` block is recorded, the ledger MUST transition to a permanent "terminal" state. +- In this state: + - All ingress calls that modify state MUST be rejected (transfers, approvals, mints, burns, freezes, pauses, unpauses, etc.). + - Query calls retrieving historical data MUST remain available. - The deactivated state is irreversible. +--- + +## Guidance for Standards That Define Methods + +A standard that defines ledger methods which produce ICRC-124 blocks (e.g., “pause ledger” or “deactivate ledger”) SHOULD: + +1. **Include `tx.op`** in the resulting block’s `tx` map. + - Use a namespaced value per ICRC-3: `` (e.g., `148pause_ledger`). + - This makes the call uniquely identifiable and prevents collisions across standards. + +2. **Define a canonical mapping** from the method’s call parameters to the block’s minimal `tx` fields. + - Since 124 blocks have no required fields, only provenance may be mapped. + +3. **Document deduplication inputs** (if any). If the method uses a caller-supplied timestamp, put it in `tx.created_at_time`. + +--- + ## Compliance Reporting -Ledgers implementing this standard MUST return the following entries (including entries for other supported types like ICRC-1, ICRC-3, etc.) from `icrc3_supported_block_types`, with URLs pointing to the standards defining each block type: +Ledgers implementing this standard MUST return the following entries (along with entries for other supported block types) from `icrc3_supported_block_types`: ```candid vec { -    // ... other supported types like ICRC-1, ICRC-3, ICRC-122, ICRC-123 ... -    variant { Record = vec { -        record { "btype"; variant { Text = "124pause" }}; -        record { "url"; variant { Text = "[https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md](https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md)" }}; // Placeholder URL -    }}; -    variant { Record = vec { -        record { "btype"; variant { Text = "124unpause" }}; -        record { "url"; variant { Text = "[https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md](https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md)" }}; // Placeholder URL -    }}; -    variant { Record = vec { -        record { "btype"; variant { Text = "124deactivate" }}; -        record { "url"; variant { Text = "[https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md](https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md)" }}; // Placeholder URL -    }}; + record { block_type = "124pause"; url = "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md" }; + record { block_type = "124unpause"; url = "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md" }; + record { block_type = "124deactivate"; url = "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-124.md" }; } - ``` ## Example Blocks @@ -151,3 +169,30 @@ variant { Map = vec { }}; ``` + +### Informative Example: Integration with a Standardized Method +ICRC-124 defines only block types and their semantics. It does not define any ledger methods. +However, future standards may specify methods that map directly to these block types. + +For illustration, suppose a future standard (e.g., ICRC-148) introduces the method: +``` +icrc148_pause_ledger : (opt text) -> result nat +``` + +Invoking this method with an optional reason could produce a `124pause` block: +``` +variant { Map = vec { + record { "btype"; variant { Text = "124pause" }}; + record { "ts"; variant { Nat = 1_747_900_000_000_000_000 : nat }}; + record { "phash"; variant { + Blob = blob "\aa\bb\cc\dd\ee\ff\00\11\22\33\44\55\66\77\88\99" + }}; + record { "tx"; variant { Map = vec { + record { "op"; variant { Text = "148pause_ledger" }}; + record { "caller"; variant { Blob = blob "\00\00\00\00\00\00\f0\0d\01\03" }}; + record { "reason"; variant { Text = "DAO vote #101: emergency pause" }}; + }}}; +}}; +``` + +This example is non-normative and illustrates how a standardized method can map into the ICRC-124 block structure while using a namespaced `tx.op` for unambiguous identification. The authoritative semantics remain defined by the ICRC-124 block types. \ No newline at end of file From 47a8c6255b5d8c8414469f4de9b67190f30966a8 Mon Sep 17 00:00:00 2001 From: Bogdan Warinschi Date: Fri, 26 Sep 2025 10:15:33 +0200 Subject: [PATCH 10/10] clarify it's blocks that are standardised --- ICRCs/ICRC-124/ICRC-124.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ICRCs/ICRC-124/ICRC-124.md b/ICRCs/ICRC-124/ICRC-124.md index 19d169c4..90b00654 100644 --- a/ICRCs/ICRC-124/ICRC-124.md +++ b/ICRCs/ICRC-124/ICRC-124.md @@ -1,4 +1,4 @@ -# ICRC-124: Ledger Pausing, Unpausing, and Deactivation +# ICRC-124: Pause, Unpause & Deactivate Blocks ## Status