Skip to content
Open
Changes from 1 commit
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
d8bbe07
account examples, no btype for legacy blocks
bogwar Jul 29, 2025
6e85916
Update standards/ICRC-3/README.md
bogwar Aug 6, 2025
ce7be73
Update standards/ICRC-3/README.md
bogwar Aug 6, 2025
c0201b0
added principles of recording transactions in blocks and extended Int…
bogwar Aug 15, 2025
d4d5856
introduced a section on kinds of blocks
bogwar Aug 15, 2025
825f3f1
added guideliness for defining blocks/cannonical mappings
bogwar Aug 15, 2025
1091df4
Merge branch 'bw/icrc-3update' of github.com:dfinity/ICRC-1 into bw/i…
bogwar Aug 15, 2025
9f7a603
core state transition, bypte vs tx
bogwar Aug 27, 2025
79018dc
typos
bogwar Sep 1, 2025
4e88917
minor changes
bogwar Sep 1, 2025
164f310
fixed some corner cases
bogwar Sep 3, 2025
ec99a9d
Update standards/ICRC-3/README.md
bogwar Sep 5, 2025
570e13c
timestampe is nanoseconds
bogwar Sep 5, 2025
797aa1d
Merge branch 'bw/icrc-3update' of github.com:dfinity/ICRC-1 into bw/i…
bogwar Sep 5, 2025
231779c
removed the consolidation section
bogwar Sep 5, 2025
d2e6f3e
clarified tx.op includes standard number
bogwar Sep 15, 2025
df78e30
promoted effective fee to a first class citizen; minor typos and rewr…
bogwar Sep 18, 2025
f4fd592
minor changes
bogwar Sep 18, 2025
35f2c3f
q-int's comment & fix transfer from based mints semantic
bogwar Sep 18, 2025
45a4b8e
make the standard about an event log
bogwar Oct 7, 2025
5d9c8d8
spelled out the generic aspect
bogwar Oct 7, 2025
6251107
language ledger agnonstic
bogwar Oct 8, 2025
f4a5211
relaxed core state transition
bogwar Oct 9, 2025
06ae958
relaxed the btype/tx recommmendations
bogwar Oct 9, 2025
1f12fa2
explicit demand that tx captures the user's call
bogwar Oct 9, 2025
85bf500
use producer canister throughout
bogwar Oct 9, 2025
dbbfcb4
added back
bogwar Oct 13, 2025
460bb51
semantics for top level ts
bogwar Oct 13, 2025
a96fbca
added one more example, removed a spurious line
bogwar Oct 16, 2025
f987387
Nat64 --> Nat
bogwar Oct 16, 2025
a495e4f
non-normative section with encodings of bools and optionals
bogwar Oct 16, 2025
71bda9d
draft methods section
bogwar Nov 19, 2025
abacc47
semantics for the remaining methods, small fixes
bogwar Nov 20, 2025
ef6013d
clearer gudiance on user calls, clearer language on icrc3_get_blocks …
bogwar Nov 21, 2025
a974a97
further clarifications on tx, tx.op etc
bogwar Nov 21, 2025
7fe04c6
refined Semantics of Blocks section
bogwar Nov 21, 2025
2476490
refined Namespacing for Operations
bogwar Nov 21, 2025
bb53670
removed duplicate sections
bogwar Nov 21, 2025
cd0374c
minor rewording
bogwar Nov 21, 2025
6194432
Candid spec
bogwar Nov 21, 2025
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
32 changes: 20 additions & 12 deletions standards/ICRC-3/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ Although many deployments are token ledgers, the same verifiable log applies to
## Block Log

- The parent of block `i` is block `i-1` for `i > 0`, and `null` for the genesis block (`i = 0`).
+ The parent of block `i` is block `i-1` for `i > 0`.
+ The genesis block (`i = 0`) has no parent and therefore MUST NOT include a `"phash"` field.
- The parent of block `i` is block `i-1` for `i > 0`.
- The genesis block (`i = 0`) has no parent and therefore MUST NOT include a `"phash"` field.



Expand Down Expand Up @@ -98,7 +98,7 @@ and the rules for defining new block types under ICRC-3.
The [candid](https://github.com/dfinity/candid) format supports sharing information even when the client and the server involved do not have the same schema (see the [Upgrading and subtyping](https://github.com/dfinity/candid/blob/master/spec/Candid.md#upgrading-and-subtyping) section of the candid spec). While this mechanism allows to evolve services and clients
independently without breaking them, it also means that a client may not receive all the information that the server is sending, e.g. in case the client schema lacks some fields that the server schema has.

This loss of information is not an option for `ICRC-3`. The client must receive the same exact data the server sent in order to verify it. Verification is done by hashing the data and checking that the result is consistent with what has been certified by the server.
Lossy decoding is unacceptable for verification. The client must receive the same exact data the server sent in order to verify it. Verification is done by hashing the data and checking that the result is consistent with what has been certified by the server.

For this reason, `ICRC-3` introduces the `Value` type which never changes:

Expand Down Expand Up @@ -133,10 +133,12 @@ Pseudocode for representation-independent hashing of `Value`, together with test

## Blocks Verification

The producer canister MUST certify the last block (tip) recorded. The producer canister MUST allow to download the certificate via the `icrc3_get_tip_certificate` endpoint. The certificate follows the [IC Specification for Certificates](https://internetcomputer.org/docs/current/references/ic-interface-spec#certification). The certificate is comprised of a tree containing the certified data and the signature. The tree MUST contain two labeled values (leaves):
The producer canister MUST certify the last block (tip) recorded. The producer canister MUST expose the certificate via the `icrc3_get_tip_certificate` endpoint. The certificate follows the [IC Specification for Certificates](https://internetcomputer.org/docs/current/references/ic-interface-spec#certification). The certificate is comprised of a tree containing the certified data and the signature. The tree MUST contain two labeled values (leaves):
1. `last_block_index`: the index of the last block in the chain. The value MUST be expressed as [`leb128`](https://en.wikipedia.org/wiki/LEB128#Unsigned_LEB128)
2. `last_block_hash`: the hash of the last block in the chain

These labels are direct children at the tree root (no extra path segments).

Clients SHOULD download the tip certificate first and then download the blocks backward starting from `last_block_index` and validate the blocks in the process.

Validation of block `i` is done by checking the block hash against
Expand All @@ -145,18 +147,19 @@ Validation of block `i` is done by checking the block hash against

## Generic Block Schema

An ICRC-3 compliant Block
An ICRC-3 compliant block:

1. MUST be a `Value` of variant `Map`
2. MUST contain a field `phash: Blob` which is the hash of its parent if it has a parent block
3. SHOULD contain a field `btype: Text` which uniquely describes the type of the Block. If this field is not set then the block type falls back to ICRC-1 and ICRC-2 for backward compatibility purposes
1. MUST be a `Value` of variant `Map`.
2. MUST contain `"phash" : Blob` — the hash of its parent block (absent only for the genesis block).
3. MUST contain `"ts" : Nat` — the producer-assigned timestamp in nanoseconds since Unix epoch.
4. SHOULD contain `"btype" : Text` — a unique identifier for the block type. If absent, the block is interpreted using the legacy ICRC-1/2 rules (see below).


### Kinds of Blocks

An ICRC-3 block can record different kinds of information. Some blocks record the result of a transaction submitted by a user. These typically contain a `tx` field describing the user’s intent and any parameters they provided.

Other blocks may be created by the producer canister itself, for example during an upgrade, migration, or system operation, to record changes in the canistesr state that did not come from a user call.
Other blocks may be created by the producer canister itself, for example during an upgrade, migration, or system operation, to record changes in the canister's state that did not come from a user call.

The `tx` field, when present, encodes the **intent** or **state change payload** associated with the block:
- In user-initiated blocks, `tx` reflects the call parameters, subject to the canonical mapping defined for that block type.
Expand Down Expand Up @@ -209,9 +212,10 @@ The following principles guide the evolution and interpretation of ICRC-3 and an

### 5. Future-Proofing and Extensibility
- Additional non-semantic fields (e.g., metadata, hashes, references) MAY be added to `tx` without introducing a new `btype`, provided:
- They do not affect the block’s **core state transition**.
- They do not affect the block’s interpreted effects.
- They are ignored by block verification and interpretation logic that only relies on the minimal `tx` structure defined by the `btype`.
- Any change to the minimal semantic structure of a block REQUIRES introducing a new `btype`.
- Any change to the minimal semantic structure of a block REQUIRES introducing a new `btype`. If additions change how a block’s effect is determined from `tx`, a new btype SHOULD be introduced.


### Note on Ledger-Specific Fields
- Blocks may include additional fields specific to a given standard or ledger (e.g., `fee`, metadata, references).
Expand Down Expand Up @@ -446,7 +450,11 @@ Although legacy ICRC-1 and ICRC-2 blocks do not include the `btype` field, ledge

### Account Type
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i still think it would be valuable to have a Principal variant in the Value. this way there is no ambiguity on how to interpret arrays


ICRC-1 Account is represented as an `Array` containing the `owner` bytes and optionally the subaccount bytes. Two examples of accounts, one with subaccount and the second without are below.
ICRC-1 Account is represented as an `Array` containing the `owner` bytes and optionally the subaccount bytes.

* `owner` is the raw principal bytes.
* `subaccount` is a 32-byte blob when present.
* The account value is Array of 1 or 2 Blob items in order: `[owner, subaccount?]`.

Example of account representation as an array with two blobs, one for the owner principal and the second for the subaccount:
```
Expand Down