Toward a Cleaner ICRC-3: One Format for ICRC-1/2, Clear Rules for the Future

As the ICRC-3 standard matures, it’s worth reconsidering some core design decisions — particularly how transaction blocks are structured. Two key issues have emerged that point to a lack of principled foundations in the current design and suggest that a revision is warranted.

Issue: Dual Formats for ICRC-1 and ICRC-2 Blocks

ICRC-3 currently allows two different formats for ICRC-1 and ICRC-2 transactions:

  • The legacy ICRC-1 format, where the transaction type is inferred from block content.

  • The ICRC-3 format, which wraps transaction details in a tx field and introduces an explicit btype.

This duality creates ambiguity. When a user submits a simple transfer, there’s no guarantee how it will be recorded on-chain. It could appear as a legacy-style block with no btype, or as a typed ICRC-3-style block. This inconsistency makes it harder to reason about transactions, compare behavior across ledgers, and build reliable tooling like explorers or indexers.

Some early ICRC-3 implementations have already diverged in how they log ICRC-1 transactions — creating incompatibilities between ledgers that all claim ICRC-3 support.

Issue: User Intent Is Not Isolated

In the current ICRC-3 design, the block format encodes user intent (e.g., “approve”, “transfer_from”) in the btype field, while spreading the rest of the transaction across other parts of the block.

This poses challenges for any tooling that tries to work directly with user intent:

  • A frontend cannot easily hash the user’s transaction to generate a transaction ID for later lookup.

  • A block explorer must reverse-engineer intent from multiple scattered fields.

  • Ledger implementers must guess which parts of a user’s request should be preserved and which are optional metadata.

These issues, too, stem from a lack of a principled and consistent mapping from user input to recorded transaction. Without a canonical definition — or at the very least, clear guidelines — for what gets logged in a block, we lack a foundation for interoperability, auditability, and reliable tooling.

Principles Behind the Proposed Revision

The revision to ICRC-3 is grounded in a small set of design principles meant to bring clarity, predictability, and interoperability to how ledgers record transactions.

Canonical Representation of User Intent

Each method that causes a ledger to record a block must specify how to construct a canonical tx object that captures the user’s request. Optional fields not supplied by the user are omitted. This tx becomes the definitive record of intent and the basis for deriving the transaction ID.

Deterministic Transaction Hashing

Transaction IDs are derived from hash(tx) using only the canonical tx field — not the full block. This enables clients and tools to compute transaction IDs independently and reliably.

Typed Blocks for New Semantics Only

The btype field is reserved for new kinds of transactions introduced in future standards. Each btype defines the minimum tx structure required to determine the ledger state effect. Existing ICRC-1 and ICRC-2 methods continue to use the legacy untyped format.

Separation of Semantics and Intent

The structure and semantics of a block (btype) are decoupled from the specific method call that generated it. This separation allows multiple methods or interfaces to share the same btype while still producing unique tx values based on user input.

Standardized Method-to-tx Mappings Going Forward

Standards that define methods which add blocks must specify how to construct the canonical tx from the call’s input. This mapping ensures predictability, avoids guesswork, and enables consistent tooling across the ecosystem.

Reusability via Shared Libraries

Because tx mappings are canonical and deterministic, shared libraries can be developed to construct tx objects uniformly across:

  • Clients, which need to precompute transaction hashes or prepare signed requests,

  • Ledgers, which must log the canonical tx in blocks.

This reduces duplication, improves correctness, and fosters interoperability throughout the stack.

Relationship Between btype and tx: Meaning vs. Intent

To support clarity and extensibility, the revised ICRC-3 architecture establishes a principled separation between the meaning of a block and the intent that produced it.

btype Defines the Block’s Meaning

When present, the btype field identifies the semantic category of the block. Each btype:

  • Is introduced by a standard,

  • Defines the minimum tx structure required to interpret the block and determine its effect on ledger state,

  • Omits user-specific metadata or optional fields not required to define the core semantics.

This minimal structure acts as the target shape that must be populated by any method that emits that btype.

Method-to-tx Mapping Captures User Intent

The standard defining a method (e.g., icrc147_freeze_account) is responsible for specifying:

  • Which btype the method produces (if any),

  • How to populate the required tx fields defined by the btype,

  • Any additional fields in the tx that reflect the original call (e.g., optional parameters, memo, or timestamp).

The resulting tx must unambiguously reflect the user’s request, enabling deterministic hashing and full auditability.

Canonical tx Must Include the User Call

To avoid collisions and ensure transparency, the tx must include the structure of the user call that triggered it — particularly when the call is standardized. This ensures that:

  • The transaction hash is unique per call,

  • The tx captures exactly what the user asked the ledger to do,

  • Different methods producing the same btype do not collide, thanks to namespacing via standard numbers or method identifiers.

This design reinforces the separation of concerns: btype defines what the block means; the tx records how and why it was created.

Proposed Changes

Based on the principles outlined above, we propose a set of changes to the ICRC-3 standard. The changes fall into three categories: clarifications to ICRC-1/2 block formatting, specification of canonical tx mappings, and new editorial rules for future standards that record ledger transactions.

ICRC-1 and ICRC-2 Blocks: Legacy Format with No btype

The revised ICRC-3 will clarify that all blocks resulting from ICRC-1 and ICRC-2 method calls must use the legacy format and must not include a btype field.

  • This removes ambiguity introduced by the coexistence of two block formats.

  • It ensures compatibility with existing tooling and simplifies parsing.

  • It creates a clear boundary between legacy operations and new typed block types introduced by future standards.

Canonical tx Definitions for ICRC-1 and ICRC-2 Methods

The revised ICRC-3 will spell out the precise canonical tx values to be recorded for each supported ICRC-1 and ICRC-2 method:

  • icrc1_transfer

  • icrc1_approve

  • icrc2_transfer_from

Each mapping will define:

  • Which fields appear in the tx (based only on user-supplied input),

  • How optional fields like memo and created_at_time are handled when present or omitted,

  • Examples for various valid input combinations.

This ensures deterministic transaction ID computation and unambiguous indexing of ledger history.

Transaction ID Based on hash(tx)

The revised ICRC-3 will define the canonical transaction ID for a block as the hash of the tx portion of the block. This definition applies to ICRC-1 and ICRC-2 blocks, and provides a stable, portable way to reference transactions.

Canonical Examples

The revised specification will include concrete examples of canonical tx values for each ICRC-1 and ICRC-2 method, covering:

  • Required-only tx cases,

  • Various combinations of optional fields,

  • Edge cases and minimal viable calls.

These examples will support implementers and indexers by clarifying expected behavior and reducing ambiguity.

Guidance for Future Standards

A new section will be added to ICRC-3 to establish best practices (and, in some cases, requirements) for future standards that define either:

  • New btype values, or

  • Methods that produce ledger blocks.

This section will formalize the expectations for consistency, auditability, and compatibility across the ICRC ecosystem.

btype Ownership and Definition

Standards that introduce a new btype must:

  • Assign a unique btype value,

  • Define the minimum required tx structure needed to interpret the block and compute its effect on ledger state,

  • Avoid including fields not essential to the semantics of the block.

This ensures that any block with a given btype is unambiguous in its meaning and function.

Method-to-Block Mapping

Standards that define methods which produce blocks must:

  • Specify which btype the method produces,

  • Define how to populate the tx in a canonical way from the method call,

  • Ensure that the tx includes all fields required by the corresponding btype,

  • Optionally include additional fields reflecting metadata such as timestamp, caller, or memo.

This enables consistent interpretation of blocks and supports correct indexing, verification, and auditing.

Inclusion of the Call in the tx

Rule: Canonical tx Must Include the User Call
To avoid transaction ID collisions and ensure transparency, the tx must include a canonical representation of the user call that triggered the transaction — particularly when the call is standardized.

This ensures that:

  • The tx captures exactly what the user asked the ledger to do,

  • Transactions from different methods producing the same btype do not collide,

  • The inclusion of the standard number or method name in the tx serves as a namespace to guarantee uniqueness.

By establishing this rule, we preserve determinism and clarity in transaction logging, even as the ICRC ledger ecosystem grows in complexity.

Coordination Across Standards

This proposal formalizes a principled division of responsibilities between standards in the ICRC ecosystem:

  • Standards that introduce a btype define what blocks mean. They must:

    • Assign a unique btype number,

    • Define the minimal tx structure required to interpret the block and determine its effect on ledger state,

    • Exclude optional or user-specific metadata not essential to the semantics.

  • This tx structure acts as a target shape — the minimal schema that must be populated for the block to be meaningful and valid.

  • Standards that define methods specify how blocks are created. They must:

    • Specify which btype the method produces,

    • Define a canonical way to construct the tx from the method’s input,

    • Ensure the tx includes all required fields from the btype definition,

    • Optionally include additional metadata such as caller, timestamp, or memo.

This coordination model enables reuse of block types across different interfaces while ensuring that each recorded tx is both semantically valid and uniquely identifies the user’s original request. It avoids collisions, promotes clarity, and supports consistent tooling across the ICRC ledger ecosystem.

Why This Matters

By clarifying how ledger blocks record transactions — and aligning that structure with user intent — this revision lays a stronger foundation for the ICRC ledger ecosystem:

  • Consistent transaction IDs across ledgers and tools.

  • Simplified parsing of blocks by indexers, explorers, and auditors.

  • Stronger guarantees about what a ledger actually recorded.

  • Cleaner extensibility for future features like fee handling (ICRC-107), RWA controls, or metadata standards.

This revision makes ICRC-3 a more predictable, more interoperable, and ultimately more trustworthy standard for ledger design on the Internet Computer.

Disruption

This proposal suggests replacing the current version of ICRC-3 with a revised version that incorporates the changes described above. As a result, some disruption for early adopters is expected:

  • Block logs may differ from earlier expectations.

  • Transaction hashes may not match prior definitions.

  • Some tooling and indexers may need to adapt to the clarified format.

However, we believe the cost of not fixing this now is greater. Letting ambiguity persist at the foundation of ICRC-3 will make long-term interoperability and reliability far harder to achieve.

Ask

Would you support moving forward with this revision? We welcome feedback on the proposed direction, especially from ledger implementers, dapp developers, and tooling providers.

7 Likes

@bogwar Thanks for all the work on this. Seeing it in print now, a couple of things occurred to me as possible.

implicit schema vs explicit schema - the idea that each schema should predefined what will be in a tx block gives me pause as it is very hard to predict all inevitability. Something along the lines of saying that field names with a particular prefix or pattern must be in the hash may be a bit more pliable ling term and still accomplish the same thing.

For example, “7_key_to” and “7_key_from”. If later someone comes along and thinks it is important for there to be a field like “7_key_seed” that is used in an nft random modification then that can make sure it is included in a hash by adding the “_key_”. Any items without a number_key can be safely ignored.

Call data- I really like the distinction and insistence that this is included. Might it warrant its own section with call parameters? I had taken atab at capturing a call and even associated important metadata in ICRC-133 Generic Input Capture and State Change - Extends ICRC3 . It may have some overlap. There may be some issues down the road as well since some things like icrc7’s mint block may have megabytes of data included, which isn’t great for a log(in that case 133 offers to hash the args.)

I’m not wild about ledgers being abandoned to the wolves and icrc-1 ledgers with the current block types that are actually not compliant icrc-3 get a pass, but certainly nice to get everyone on the same page going forward.

2 Likes

Thanks for the thoughtful feedback @skilesare — especially on the extensibility angle.

On “implicit vs explicit schema” (prefix pattern like 7_key_*):
I don’t see a safe way this outperforms the current approach.

  • If a new field changes ledger semantics, old clients cannot stay correct by merely hashing a name-patterned field. They’d still misinterpret state because they don’t know the new rule. In the proposed model, that’s the clear signal to introduce a new btype with a minimal schema that encodes the new effect. This is what protects older clients and tools from silent divergence.

  • If a new field does not change semantics (it’s extra context/metadata), the current proposal already allows it: you can add additional, non-semantic fields to tx (and to the call capture) without a new btype. Old clients can ignore unknown fields for semantics, while hash(tx) remains deterministic because the canonical mapping defines which parts of the call are captured.

Concretely: the prefix rule pushes complexity into name conventions and hashing rules, but it can’t solve the compatibility problem when semantics actually change; and when semantics don’t change, the proposal already supports additive fields.

Why I prefer explicit over prefix patterns:

  • It prevents backdoor semantic changes via “just another keyed field.”

  • It keeps determinism auditably explicit (no heuristics about which names are hashed).

  • It aligns with the meaning vs intent split: btype = minimal semantic shape; method→tx mapping = how we fill it (plus call capture).

On call data inclusion & large payloads:
I agree this deserves its own subsection. For oversized args (e.g., NFT mints), a pragmatic pattern could be:

  • include a canonical hash of the call args in tx (and possibly a stable content address / reference),

  • optionally include truncated or summarized metadata for UX,

  • keep the full payload off-chain or in a separate object, referenced by hash.
    That preserves auditability and hash(tx) determinism without ballooning the block log. Happy to cross-reference ICRC-133 here and harmonize terms.

On existing ICRC-1 ledgers:
I share the desire not to leave anyone behind, but I think we agree that the current status-quo with two distinct formats for the same transaction lends itself to troubles. The intent is to stop the drift now (one legacy format for ICRC-1/2; canonical tx spelled out) and give a crisp path forward. If there’s interest, perhaps we can add a non-normative migration note (e.g., “if you currently emit typed blocks for ICRC-1/2, switch to legacy blocks and publish a mapping for indexers”, or something along this lines?).

1 Like

Follow-up: Fee Calculation and Fee Payer Principles for ICRC-3

In addition to the previous suggestions, I’d like to propose that the ICRC-3 revision explicitly define principles for how fees are recorded and how fee payers are determined. These rules would apply to existing block types (ICRC-1/2) as well as any new types introduced in future standards.

Fee calculation
The effective fee for a block should be determined in the following order:

  1. If a top-level fee field is present, that is the fee charged.

  2. Otherwise, if tx.fee is present, that is the fee charged.

  3. Otherwise, the fee is 0.

The meaning of each field is distinct:

  • tx.fee records the amount the user offered to pay.

  • The top-level fee records the fee the ledger actually charged under its policy.

If the two values are identical, the top-level fee can be omitted for efficiency. This keeps the format compact while still allowing for dynamic or policy-driven fees — e.g. variable fees, special rates, or rebates — without creating ambiguity in the block log.

Fee payer
The account paying the fee should be determinable from the block type alone, without needing an explicit payer field in the block. Each block type would define its own rule. For example:

  • In an ICRC-1 transfer block, the sender pays.

  • In a burn block, the burning account pays.

  • In an ICRC-123 freeze_account block initiated by governance, either the governance account pays or no fee is charged.

This makes it straightforward for explorers, auditors, and other tools to identify the fee payer without digging into method-specific details.

Proposal
These rules should be added to the list of principles in the ICRC-3 revision, so that:

  • The method for calculating the effective fee is fixed and predictable.

  • The payer rule is tied to the block type and must be defined when a new type is introduced.

This would make fee handling consistent, while still giving ledgers the freedom to implement their own fee policies.

Thanks for the insights!

I think creating an SDK that integrates cognitive packets into the ICRC-3 standard would be a fantastic way to ensure clarity and efficiency. For example, we could classify transactions by type—such as payments, token transfers, smart contract interactions, and governance actions—and include metadata like priority, size, timestamp, and the required compute resources (e.g., GPU, TPU, ASIC, or photonic chips). By defining canonical transaction objects and deterministic IDs, developers and tooling can reliably parse, verify, and index transactions across different ledgers. This approach would enhance interoperability, reduce ambiguity, and facilitate the creation of robust explorers, indexers, and client libraries

3 Likes

Can we do something entirely different.

We know that different Candid encoding implementation result in different hashes, however tx blocks can include encoded Candid Blob instead of decoded one. Then the Blob can be hashed easily and will work everywhere. Clients will then decode the Blob and get their object. So there will be no need for generic values at all. Decoding will always work on all platforms no matter how it was encoded. Everything will be way simpler. Example transaction


{
type: Text;
payload: Blob;
phash: Blob;
}

The issue with this in the past is there was a understanding that they could not commit to a deterministic and backwards compatible form at for to_candid, to the extent that I was told not to rely that I’d be able to from_candid my to_candid in the future. This may have resolved itself, but we would need an update from DFINITY.

we should be calling that Candid2 if it’s not backwards compatible.

The binary blocks allow you to encode different types of transactions with different encoders.

Hi all,

Thanks for the insightful discussion so far! I wanted to propose a way to combine the strengths of both Infu’s and Bogwar’s approaches while future-proofing ICRC-3 for AI-driven ecosystems.

1. Canonical Blob Base Layer (Infu’s Idea):

Store transactions as encoded Candid blobs:

{ type: Text; payload: Blob; phash: Blob }

Ensures deterministic hashing across platforms.

Guarantees that clients can decode transactions consistently, no matter the encoding implementation.

2. Optional Cognitive Packet Layer (My Proposal):

Add structured metadata for advanced tooling and AI integration:

Transaction type (payments, token transfers, governance, smart contracts, etc.)

Priority, timestamp, size

Compute requirements (GPU, TPU, ASIC, photonic chips)

Deterministic IDs for reliable indexing and parsing

Benefits: improves interoperability, enables compute-aware transaction handling, and facilitates robust explorers and client libraries.

3. Fee Handling (Bogwar’s Proposal):

Keep standardized fee calculation and fee payer rules tied to block type.

Ensures that explorers, auditors, and automated agents can reason about fees deterministically.

Synthesis:

Base layer = deterministic, simple, interoperable (blob).

Optional metadata layer = rich, AI/compute-aware, semantic.

Fees remain consistent and predictable.

This approach gives ledgers and developers flexibility: simple ledgers can stick with blobs, while advanced ledgers can leverage cognitive packets for richer analysis and tooling. It also aligns well with an AI-driven future where agents may need to classify, prioritize, and compute over transactions autonomously.

Happy to discuss further or provide examples of what a canonical cognitive packet might look like in practice.

—Kurt

1 Like

I think it’s useful to separate what Candid is good for, and what it is not so good for in this context.

Candid is excellent as an IDL for method calls: it allows services and clients to evolve independently, and it gives us a human-readable, type-rich way of describing arguments. But those same strengths become weaknesses when we try to use Candid blobs as the authoritative encoding of ledger transactions.

  • Candid allows multiple valid binary encodings of the same value.

  • By design, Candid decoders may silently skip fields they don’t know. That’s great for service evolution, but completely wrong for a ledger, where every field must be preserved

  • If we were to store the raw Candid blob in tx, the ledger and client would need to agree on a single canonical Candid encoding and enforce “fail on unknown fields.” But this effectively fights Candid’s design — Candid was meant to allow flexibility in encoding and to permit forward/backward compatibility.

This is why ICRC-3 introduced the Value type and representation-independent hashing. With Value:

  • The transaction ID is simply hash(tx).

  • Ledgers and clients only need to agree on Value and its hashing rules, not on how to encode Candid.

  • If a ledger still wants to preserve the raw Candid blob for debugging or audits, it can do so via an auxiliary field, e.g. raw_call : Blob, stored outside tx. That blob is purely informational and is not part of hashing or verification.

This way, we get the best of both worlds:

  • Value ensures deterministic hashing and strict preservation of fields.

  • Candid remains the convenient wire format for calls.

  • Debuggers can still look at the raw Candid bytes, but clients and ledgers never need to agree on canonical Candid encoding.

So in short: using Candid blobs directly in tx would force us to bolt determinism onto something that was designed for flexibility. That’s why we introduced Value, and the proposal here is to also extend it in a way that allows for canonical representation of transactions and transaction IDs.

I’d like to understand better the meaning of cognitive packets. What level of the stack do they target? Do they need to be introduced in ICRC-3 or it’s one layer above? (or below? :slight_smile: ).

To figure out Kurt’s idea it may be useful that I spell out the mental model that I have used to guide my work on the ICRC standards. It is ledger-specific, since most of the standards deal with token ledgers, but it is important to note that ICRC-3 itself is more general. One can also imagine using ICRC-3 to store other kinds of information: for example, recording calls and their downstream calls and responses, or tracking compute requirements, or logging resources consumed. In this work:

1. ICRC-3: Transport layer

  • Defines how blocks are stored, fetched, paginated, and certified.

  • Provides guarantees: append-only sequence, block indices, hashes, and certificates.

  • Does not define the content of blocks.

ICRC-3 is a transport/proof standard. It ensures everyone sees the same block chain but is independent of what the blocks contain.

2. Transaction semantics: ICRC-1, ICRC-2, ICRC-103, ICRC-122/123/124

  • Define how user calls are recorded in blocks.

  • Each standard specifies a canonical tx schema for a given call.

  • They also specify how to derive the ledger semantics (balances, approvals, freezes, etc.) from that tx.

Key definitions:

  • tx = canonical record of the user’s call (user intent).

  • effects = resulting state changes on the ledger (balances, approvals, freezes, etc.), computed deterministically from the block content.

Not every state mutation is in tx. The requirement is that the block contains enough information to allow afn external verifier to recompute the relevant part of ledger state from the block history alone.

3. Cross-cutting extensions: ICRC-107 and others

  • Add additional fields and invariants that affect semantics.

  • Example: ICRC-107 extends transfer/approval txs with fee, payer, fee_collector.

  • These fields allow recomputing balances including fees purely from block history.

  • Old blocks without fees remain valid; new blocks include the extra fields if the ledger supports the extension.

Summary

  • ICRC-3 = transport/proof, agnostic to content.

  • ICRC-1/2/103/122/123/124 = transaction semantics, define canonical tx and how to compute effects.

  • ICRC-107 and similar = cross-cutting extensions, extending tx schemas with additional semantics.

This separation ensures that:

  • The transport remains reusable and generic.

  • Ledger semantics are deterministic and auditable.

  • Extensions can be composed without breaking existing blocks.

1 Like

Sorry I go on sometimes like everyone knows what I know without a full explanation and understands, it’s a problem I haven’t solved just yet …Let me clarify what Cognitive Packets (CPs) are and where they fit in the stack.

CPs are essentially structured metadata units that sit on top of the canonical ICRC-3 transaction (like an encoded Candid blob). They don’t replace the transaction—they augment it with machine-readable context to make it easier for explorers, indexers, and AI agents to parse and reason about transactions.

Typical CP fields might include:

transaction_type (payment, governance, smart contract, etc.)

priority and timestamp

size

compute type and amount

Deterministic IDs or hashes for cross-platform consistency

You can think of CPs as mini knowledge packets that describe the semantic and operational aspects of a transaction. When multiple AI agents or tools use them, they can reference a Shared Knowledge Core (SKC)—a shared memory or repository where CPs and other structured knowledge live. The SKC allows agents to reason about transactions, priorities, and compute requirements efficiently and consistently.

So, in the stack:

The base transaction (blob) ensures deterministic integrity and compatibility across ledgers.

The Cognitive Packet layer is optional but standardized metadata for semantic richness.

CPs can be integrated into ICRC-3 as an optional layer, so ledgers can include them for advanced tooling without breaking compatibility.

In short: the base transaction guarantees reliability, and CPs + SKC give a smart, machine-readable layer for advanced explorers, AI agents, and compute-aware handling.

—Kurt

I feel like I must be overlooking a use case that’s important to you. From my experience writing ledgers, ledger clients, and ICRC-3 implementations, I haven’t yet encountered a practical scenario where protection against transaction malleability provides a clear benefit on the IC - aside from this one:

If off-chain clients, using self-authenticating principals, were to construct transaction blocks themselves, sign them, and include the corresponding delegation chain and signature, then the ledger would have cryptographic proof that each transaction was genuinely authorized by its owner rather than injected by developers. Clients replaying or following the log could independently verify these signed transactions, thereby reducing the degree of trust placed in ledger canisters. In effect, this would make the system operate more like Bitcoin or Ethereum. Is this the model that ICRC-3 is aiming to support?

You’re right that transaction malleability mostly matters if we want self-verifiable, client-signed transactions like Bitcoin or Ethereum. My Cognitive Packets (CPs) sit above the base transaction and are meant for AI agents, not humans. In 2 years, with potentially billions of AI agents interacting with the web and ledgers, CPs make transactions machine-readable, semantically rich, and compute-aware. Malleability protection just makes their reasoning and cross-ledger trust more reliable.

I realized after I wrote this and speaking with @sea-snake that letting people just inject their own _key items would lose the determinism before submitting a transaction.

With that said, is it maybe a good idea from a usability standpoint to put in the standard that any item in the deterministic key also have the X_key_ in the name so that someone reading the log sees that it is in the key? And/Or perhaps we should have a separate key section in the tx section. I’m just leaning toward more explicit.

Totally agree — the base ICRC-3 tx has to stay deterministic and any _key fields should be explicit so there’s no ambiguity. That’s why I see Cognitive Packets as a sidecar layer: they reference the tx hash but don’t touch the canonical fields. The blob stays clean + deterministic, while CPs give explorers/AI agents the richer context they’ll need when we’ve got billions of them running around the web in a couple years.

I know this might sound a bit “out there,” but I’m really thinking ahead to the world we’re about to step into. Within a couple of years, we’re going to have billions of AI agents transacting and reasoning across the web. For them, the deterministic base transaction will be the anchor of trust, but they’ll also need a semantic layer — richer context they can parse, index, and act on without ambiguity. That’s why I’m pushing this Cognitive Packet idea: not to replace the ledger, but to make it legible and usable for the next generation of machine participants. Humans may not need it, but the AIs will.

There is a practical workflow where deterministic transaction hashing matters already: centralized exchange (CEX) integrations which indeed has influenced some of the decisions in the proposal outlined above.

  • On a CEX, transactions are typically constructed off-chain (e.g. an approval or transfer initiated in the exchange backend). These are signed using cold key storage and submitted to the chain.

  • The exchange then needs to later detect this transaction on-chain and be able to point users to a block explorer entry for it (for reconciliation, audits, or user support).

  • For this to work reliably, the exchange needs either:

    • full knowledge of the ledger’s block encoding to scan blocks directly, or

    • a canonical transaction hash that lets it quickly detect and reference the exact block containing the transaction.

Deterministic transaction hashing (no malleability) provides the latter. It enables a robust workflow:

  1. Construct the transaction off-chain.

  2. Compute its canonical hash.

  3. Submit it to the ledger.

  4. Later, search the block log by transaction hash (directly, or on some indexer) and retrieve the block index.

  5. Link to a block explorer that shows the transaction with that hash.

Without this, a CEX has to implement ledger-specific block parsing and can’t use transaction hashes as stable identifiers across tooling.

I don’t see any impediment to introducing Cognitive Packets as an additional semantic overlay, provided they have no bearing on the core semantics of transactions (the canonical tx stays untouched).

The only potential inconvenience I see is practical: if CPs are introduced later, parsers and indexers need a clean, standardized way to “know” where to look for them. But that feels like a solvable integration detail, not a blocker to the concept.

1 Like

Happy to be as explicit as possible about the structure of tx; the more explicit, the less room for interpretation there is.

For icrc-1/2 I can’t think of good examples where this would be applicable (to drive what we put in the standard). Perhaps a good example is in icrc-107 where there’s a key icrc107_fee_collector?