dfinity / ICRC-1

A fungible token standard developed by the Ledger & Tokenization working group for the IC.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ICRC1: "Transaction deduplication" is very unreliable when used.

iclighthouse opened this issue · comments

Consider the following scenario:

An agent sends a transaction to an ICRC-1 ledger hosted on the IC.
The ledger accepts the transaction.
The agent loses the network connection for several minutes and cannot learn about the outcome of the transaction.
An ICRC-1 ledger SHOULD implement transfer deduplication to simplify the error recovery for agents. The deduplication covers all transactions submitted within a pre-configured time window TX_WINDOW (for example, last 24 hours). The ledger MAY extend the deduplication window into the future by the PERMITTED_DRIFT parameter (for example, 2 minutes) to account for the time drift between the client and the Internet Computer.

The client can control the deduplication algorithm using the created_at_time and memo fields of the [transfer](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/README.md#transfer_method) call argument:

The created_at_time field sets the transaction construction time as the number of nanoseconds from the UNIX epoch in the UTC timezone.
The memo field does not have any meaning to the ledger, except that the ledger will not deduplicate transfers with different values of the memo field.
The ledger SHOULD use the following algorithm for transaction deduplication if the client set the created_at_time field:

If created_at_time is set and is before time() - TX_WINDOW - PERMITTED_DRIFT as observed by the ledger, the ledger should return variant { TooOld } error.
If created_at_time is set and is after time() + PERMITTED_DRIFT as observed by the ledger, the ledger should return variant { CreatedInFuture = record { ledger_time = ... } } error.
If the ledger observed a structurally equal transfer payload (i.e., all the transfer argument fields and the caller have the same values) at transaction with index i, it should return variant { Duplicate = record { duplicate_of = i } }.
Otherwise, the transfer is a new transaction.
If the client did not set the created_at_time field, the ledger SHOULD NOT deduplicate the transaction.

When implementing a Token, the developer may specify a different TX_WINDOW and PERMITTED_DRIFT, which is not controllable.
If I am a Dex developer and I want to use this feature to implement idempotent calls, it becomes very unreliable. Because I can't know the TX_WINDOW and PERMITTED_DRIFT of a Token and can't query it. Even if I could query it, the variance settings of different Tokens would be enough to make me give up using the feature.
So, this broad feature will become meaningless when placed in the standard.

Recommendation.
(1) Remove this rule or make it optional, keeping the 'created_at_time' parameter in the interface unchanged for forward compatibility.
or.
(2) Strengthen this rule by specifying what the minimum values of TX_WINDOW and PERMITTED_DRIFT should be.

If (1) is not possible because it is necessary, could (2) be implemented as a default minimum value?

Yes. The minimum values of TX_WINDOW and PERMITTED_DRIFT should be explicitly regulated in the standard.