From f6cec7bb30c901299e8fd8e78cb3b97809fdafa1 Mon Sep 17 00:00:00 2001 From: "Dieter M. Sommer" Date: Sun, 18 Aug 2024 20:22:39 +0200 Subject: [PATCH 01/13] ICRC-22 draft --- ICRCs/ICRC-22/ICRC-22.md | 133 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 ICRCs/ICRC-22/ICRC-22.md diff --git a/ICRCs/ICRC-22/ICRC-22.md b/ICRCs/ICRC-22/ICRC-22.md new file mode 100644 index 0000000..ab2bb82 --- /dev/null +++ b/ICRCs/ICRC-22/ICRC-22.md @@ -0,0 +1,133 @@ +# ICRC-22 — URI Format for Payment Requests + +|ICRC|Title|Author|Discussions|Status|Type|Category|Created| +|:----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:| +|22|URI Format for Payment Requests|Dieter Sommer (@dietersommer), Thomas (@sea-snake), Austin Fatheree (@skilesare), David Dal Busco (@peterpeterparker)|[Issue 10](https://github.com/dfinity/ICRC/issues/22)|Draft|Standards Track||2024-08-18| + +## Introduction + +ICRC-22 defines a standard way of representing payment requests on ICP as URIs. URIs can be embedded in QR codes, hyperlinks on Web pages, emails, or chat communication and serve the purpose of robust signalling between loosely-coupled applications. Such pre-canned or on-the-fly generated payment requests can be immediately used by the user's wallet application, where relevant parameters are provided by the URI and some other parameters may be filled in by the wallet application. This makes such URI encoding an indispensible tool in a larger blockchain ecosystem to allow for convenient communication of payment-related information. + +Relevant prior work in other blockchain ecosystems comprises the standards on payment URLs for Bitcoin \[Bit1, Bit2\] as well as Ethereum's [ERC-681 \[Nag17\]](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-681.md) for expressing payment requests and, more generally, transactions, for the Ethereum blockchain. The specification put forth in ICRC-22 is an adaptation of the ideas in the above listed references to establish a standard way of sharing URIs that represent payment requests on the Internet Computer. + +## Specification + +The below specification defines the syntax and (non-formal) semantics for an ICRC-22 payment request. The specification takes the approaches of [Bit1, Bit2, Nag17, WLGH19] into consideration. Particularly, an authority-less URI format has been chosen following this prior art in the domain. + +The following shows the structure of a URI with the concrete parameters represented through `<>`-placeholders. Note that the URI does not contain an authority, but encodes the `network` as part of the URI path. +``` +icp::/exec/?from_subaccount=&to=&amount=4.042E8&fee=&memo= +``` + +// FIX syntax details +ABNF syntax: +``` +request = network_identifier ":" contract_address "/" "exec" transaction [ "?" parameters ] +network_identifier = protocol ":" network // network id +protocol = "icp" // always "icp" referring to the current version of the Internet Computer Protocol +network = [0..9a..fA..F]* // specifies the network through a prefix of its public key hash +contract_address = ... FIX: canister principal ABNF // canister address to which to make the call +transaction = ...// method on the canister to call +parameters = parameter [ "&" parameter ] +parameter = key "=" value +key = ... +value = ... +``` + +The grammar productions not further specified are equal to those in the syntax of URIs and can be looked up in RFC 3986 [BFM05]. Note that the production `transaction` above is part of the path and `paramters` part of the query string and the according constraints of RFC 3986 apply. + +The `network_identifier` uniquely identifies the network to make the transaction on. Following the ideas of the Chain Agnostic Standards Alliance [Cha24] of having a standardized way of referring to any blockchain network, ICP uses the following mechanism for referring to ICP mainnet or any other ICP-based network that may be available in the future, such as testnets or private networks based on the ICP protocol stack. +The network identifier for an ICP-based network is comprised of the constant `icp` referring to the Internet Computer Protocol, followed by `:`, followed by `` where `pub_key_hash_prefix` is a ??-character prefix in ?? encoding of the SHA256 hash of the binary representation of the public key of the network. The prefix length and encoding scheme used ensures that the probability of collision is negligible for all practical purposes. For ICP mainnet the public key of the network is the NNS public key. +// FIX using base-64 encoding for the network allows for using a shorter prefix, which is crucial for usability and human readibility; prefix length t.b.d. + +The `contract_address` is the canister smart contract principal identifier of the contract the transaction is to be performed on. This is represented in the standardized format for principals. The address, together with the network identifier, unambiguously determines the token that is to be transacted. + +The constant `exec` means that the forthcoming part in the path component specifies which transaction (smart contract method) should be invoked with the information in the URI. In the future, other ICRC standards may emerge that can have a different string with different semantics in the place of this. // FIX: do we want to call this `tx`? + +The `transaction` parameter specifies the canister method to be called on the canister indicated through `contract_address`. This is the string-based name as it appears in the canister's Candid specification. This standard requires support of all of ICP ledger's `transfer`, ICRC-1's `transfer` and ICRC-2's `approve` methods. + +The `parameters` are the parameters of the method to be called. They SHOULD be given in the order in which they appear in the Candid specification of the method to be called. A subset of the parameters defind in the Candid specification of the method can be present, the remaining non-optional parameters MUST be filled in by the party executing the transaction. + +// FIX: Details need to be worked out to make it possible to call different methods we want to cover in the base standard (at least ICP and ICRC-1 transfer and ICRC-2 approve). The result may not be so far away from a generic standard covering the call of any method of canisters. Specifically: Should types be decomposed into their constituents or the compound values be provided using a specific or their Candid encoding? + +Next, we exhaustively define the parameters required for realizing the supported transactions of the supported ledger standards: +* `from_subaccount` (ICRC-1, ICRC-2): 32-byte subaccount in Base64 representation +* `to` (ICRC-1, ICRC-2): // FIX t.b.d.: The human readable [textual representation](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md) of an ICRC-1 account or a shortened version thereof, e.g., with removed checksum or removed dashes between character groups, or using more concise encoding for parts. +* `spender` (ICRC-2): +* `spender_subaccount` (ICRC-2): +* `from` (ICRC-2): +* `expected_allowance` (ICRC-2): +* `expires_at` (ICRC-2): +* `amount` (ICP, ICRC-1, ICRC-2): The transaction amount, specified in scientific representation, e.g., 4.042E8 means 804200000 base units of the addressed ledger. +* `fee` (ICP, ICRC-1, ICRC-2): Fee expressed in base units of the addressed ledger. +* `memo` (ICP, ICRC-1, ICRC-2): blob +* `created_at_time`: (ICP, ICRC-1, ICRC-2) +* ... +Accounts are always represented through the size-reduced textual encoding as specified in [the section](## Size-reduced-ICRC-1-textual-account-representation) below. +// FIX complete the list, define the respective encoding + +The `amount` should be provided as a nonnegative integer number. The amount represents the amount of tokens in the base unit used by the ledger, i.e., 4 ICP tokens would amount to 4 * 10^8 = 400000000 base units as managed by the ICP token ledger. It is strongly recommended to use scientific notation for the amount. Decimal representation can be combined with scientific representation, e.g., 4.042E8 ICP means a count of 404200000 base units as managed by the ICP ledger. As only integer numbers are allowed as amount, the exponent MUST be greater than or equal the decimal places of the number in scientific representation. + +// FIX How exactly can the mapping from the paramters to the Candid method signature be done? Is it sufficient to enumerate all named parameters, with the type inferable by the recipient using the canister's Candid specification which can be obtained from the canister? + +// FIX How to handle optional fields in the Candid specification of the method? As long as the input can be constructed unambiguously, they can be left out, otherwise be included as `key=null`. + +## Size-reduced ICRC-1 textual account representation + +// FIX maybe call "compressed" + +The Chain Agnostic Standards Alliance [Cha24] has specified account identifiers to be of a maximum length of 128 characters [Gom22]. There seems to be no strong reason behind this, but it has been considered sufficient for the foreseeable future by the CAIP working group. This limitation cannot be changed at the current time. + +// FIX use maximum-length textual account representation + +ICRC-1 account identifiers on ICP may exceed this limitation by a few bytes when using the human-readable representation of ICRC-1 accounts, i.e., textual encoding of ICRC-1 accounts [Dfi22]. For this reason, we define a size-reduced textual ICRC-1 account representation as part of this standard in order to fit the CAIP limits of 128 characters. The size-reduced representation is easily computed by removing all the dashes ("-") between the character groups of the representation, except for the rightmost one (the one preceding the CRC32 checksum) for non-default accounts (non-zero subaccount). For default accounts (all-zero subaccount), all dashes are removed. It is easy to reconstruct the standard textual encoding from a size-reduced textual encoding by adding dash separators from the left of the representation for every 5-character group. + +It is guaranteed that any ICRC-1 account in size-reduced representation fits into the 128-byte limit. According to the The Internet Computer Interface Specification [Dfi], the maximum lenght of a textual representation of a principal is 63 bytes, including 10 dashes. The additional CRC-32 checksum in Base-32 encoding takes another 7 characters, the dash separator one. This makes the maximum length of the size-reduced representation 126 characters: 63 - 10 separators + 1 separator + 7 CRC32 checksum + 1 .-separator + 64 subaccount in HEX. + +The following is an example of an almost maximum-length long textual representation that exceeds the size limits imposed by CAIP with its 1135 characters. +``` +k2t6j-2nvnp-4zjm3-25dtz-6xhaa-c7boj-5gayf-oj3xs-i43lp-teztq-6ae-dfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 +``` +The following is the above example in size-reduced form and fits within the 128-character limit with its 124 characters. +``` +k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6aedfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 +``` + +## Examples + +### ICRC-1 token transfer + +// FIX replace 1234abcd90 with a prefix of the SHA256 hash of the mainnet NNS public key in binary + +// FIX fill in subaccounts etc. with accounts in the proper format + +The following is a payment request for 4.042 ckBTC on the ckBTC ledger. The wallet reading and executing this request would insert the `created_at_time` field based on the current time. +``` +icp:1234abcd90:mxzaz-hqaaa-aaaar-qaada-cai/exec/icrc1_transfer?from_subaccount=&to=&amount=4.042E8&fee=&memo= +``` + +### ICP token transfer + +``` +icp:mainnet:/exec/transfer?from_subaccount=&to=&amount=4.042E8&fee=&memo=&created_at_time= +``` + +### ICRC-2 approval + +An ICRC-2 approval can be made on any ICRC-2-compliant ledger, e.g., the ICP ledger or any ICRC-1-compliant token ledger. + +``` +icp:mainnet:/exec/icrc2_approve?from_subaccount=&spender=&amount=&expected_allowance=&... +``` + +## References + +[Nag17] Daniel A. Nagy, URL Format for Transaction Requests. Ethereum EIP-681, https://github.com/ethereum/EIPs/blob/master/EIPS/eip-681.md, 2017 +[Bit1] Unified payment requests. https://bitcoin.design/guide/how-it-works/payment-request-formats/#unified-payment-requests +[Bit2] Unified QRs for Bitcoin. https://bitcoinqr.dev/ +[Dfi22] DFINITY, ICRC-1 Token Standard -- Textual encoding of ICRC-1 accounts. 2024, https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md, 2022 +[WLGH19] Simon Warta, ligi , Pedro Gomes, Antoine Herzog, Blockchain ID Specification, https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md, 2019 +[Cha24] Chain Agnostic Standards Alliance. https://github.com/ChainAgnostic +[Gom22] Pedro Gomes, Account ID Specification. CAIP-10, https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md, 2022 +[Dfi] DFINITY Foundation, The Internet Computer Interface Specification: Principals. https://internetcomputer.org/docs/current/references/ic-interface-spec#principal +[BFM05] T. Berners-Lee, R. Fielding, L. Masinter: Uniform Resource Identifier (URI): Generic Syntax. 2005, https://datatracker.ietf.org/doc/html/rfc3986 From 7b7da761f800bc36d63f23f572ab53fff4dc0111 Mon Sep 17 00:00:00 2001 From: "Dieter M. Sommer" Date: Mon, 19 Aug 2024 11:03:19 +0200 Subject: [PATCH 02/13] Update --- ICRCs/ICRC-22/ICRC-22.md | 47 +++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/ICRCs/ICRC-22/ICRC-22.md b/ICRCs/ICRC-22/ICRC-22.md index ab2bb82..aa60808 100644 --- a/ICRCs/ICRC-22/ICRC-22.md +++ b/ICRCs/ICRC-22/ICRC-22.md @@ -2,39 +2,43 @@ |ICRC|Title|Author|Discussions|Status|Type|Category|Created| |:----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:| -|22|URI Format for Payment Requests|Dieter Sommer (@dietersommer), Thomas (@sea-snake), Austin Fatheree (@skilesare), David Dal Busco (@peterpeterparker)|[Issue 10](https://github.com/dfinity/ICRC/issues/22)|Draft|Standards Track||2024-08-18| +|22|URI Format for Payment Requests|Dieter Sommer (@dietersommer), David Dal Busco (@peterpeterparker), Thomas (@sea-snake), Austin Fatheree (@skilesare)|[Issue 10](https://github.com/dfinity/ICRC/issues/22)|Draft|Standards Track||2024-08-18| ## Introduction -ICRC-22 defines a standard way of representing payment requests on ICP as URIs. URIs can be embedded in QR codes, hyperlinks on Web pages, emails, or chat communication and serve the purpose of robust signalling between loosely-coupled applications. Such pre-canned or on-the-fly generated payment requests can be immediately used by the user's wallet application, where relevant parameters are provided by the URI and some other parameters may be filled in by the wallet application. This makes such URI encoding an indispensible tool in a larger blockchain ecosystem to allow for convenient communication of payment-related information. +ICRC-22 defines a standard way of representing payment requests on ICP as URIs. URIs can be embedded in QR codes, hyperlinks on Web pages, emails, or chat communication and serve the purpose of robust signalling between loosely-coupled applications. Such pre-canned or on-the-fly generated payment requests can be immediately used by the user's wallet application, where relevant parameters are provided by the URI and some other parameters may be filled in by the wallet application. This makes such URI encoding an indispensible tool in a larger blockchain ecosystem to allow for convenient communication of payment-related information over many different communication channels. -Relevant prior work in other blockchain ecosystems comprises the standards on payment URLs for Bitcoin \[Bit1, Bit2\] as well as Ethereum's [ERC-681 \[Nag17\]](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-681.md) for expressing payment requests and, more generally, transactions, for the Ethereum blockchain. The specification put forth in ICRC-22 is an adaptation of the ideas in the above listed references to establish a standard way of sharing URIs that represent payment requests on the Internet Computer. +Relevant prior work in other blockchain ecosystems comprises the standards on payment URLs for Bitcoin \[Bit1, Bit2\] as well as Ethereum's [ERC-681 \[Nag17\]](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-681.md) for expressing payment requests and, more generally, transactions using EVM ABI encoding, for the Ethereum blockchain. The specification put forth in ICRC-22 is an adaptation of the ideas in the abovelisted references to establish a standard way of sharing URIs that represent payment requests on the Internet Computer. ## Specification The below specification defines the syntax and (non-formal) semantics for an ICRC-22 payment request. The specification takes the approaches of [Bit1, Bit2, Nag17, WLGH19] into consideration. Particularly, an authority-less URI format has been chosen following this prior art in the domain. -The following shows the structure of a URI with the concrete parameters represented through `<>`-placeholders. Note that the URI does not contain an authority, but encodes the `network` as part of the URI path. +The following shows the structure of a URI for an example with the concrete parameters represented through `<>`-placeholders. Note that the URI does not contain an authority, but encodes the `network` as part of the URI path, directly following the URI scheme. ``` -icp::/exec/?from_subaccount=&to=&amount=4.042E8&fee=&memo= +icp::/exec/?from_subaccount=&to=&amount=4.042E8&fee=&memo= ``` // FIX syntax details ABNF syntax: ``` -request = network_identifier ":" contract_address "/" "exec" transaction [ "?" parameters ] -network_identifier = protocol ":" network // network id -protocol = "icp" // always "icp" referring to the current version of the Internet Computer Protocol -network = [0..9a..fA..F]* // specifies the network through a prefix of its public key hash -contract_address = ... FIX: canister principal ABNF // canister address to which to make the call -transaction = ...// method on the canister to call +request = protocol ":" network ":" contract_address "/" "exec" transaction [ "?" parameters ] +protocol = "icp" ; always "icp" referring to the current version of the Internet Computer Protocol +network = (1..12)[0..9a..fA..F] / ; specifies the network through a prefix of its public key hash +contract_address = principal FIX: canister principal ABNF ; canister address to which to make the call +transaction = transfer / icrc1_transfer / icrc2_approve ; method on the canister to call parameters = parameter [ "&" parameter ] parameter = key "=" value key = ... value = ... ``` -The grammar productions not further specified are equal to those in the syntax of URIs and can be looked up in RFC 3986 [BFM05]. Note that the production `transaction` above is part of the path and `paramters` part of the query string and the according constraints of RFC 3986 apply. +// FIX: Do we default the network to ICP's mainnet current value when omitted? +// Would result in `icp::/exec/?` + +// FIX: Should we keep it open to other methods and supported ICRCs as long as their API can be canonically expressed using a sequential list of parameters encoded as query parameters + +The grammar productions not further specified can be looked up in the syntax specification for URIs in RFC 3986 [BFM05]. Note that the production `transaction` above is part of the path and `parameters` part of the query string and the according constraints of RFC 3986 apply. The `network_identifier` uniquely identifies the network to make the transaction on. Following the ideas of the Chain Agnostic Standards Alliance [Cha24] of having a standardized way of referring to any blockchain network, ICP uses the following mechanism for referring to ICP mainnet or any other ICP-based network that may be available in the future, such as testnets or private networks based on the ICP protocol stack. The network identifier for an ICP-based network is comprised of the constant `icp` referring to the Internet Computer Protocol, followed by `:`, followed by `` where `pub_key_hash_prefix` is a ??-character prefix in ?? encoding of the SHA256 hash of the binary representation of the public key of the network. The prefix length and encoding scheme used ensures that the probability of collision is negligible for all practical purposes. For ICP mainnet the public key of the network is the NNS public key. @@ -64,7 +68,7 @@ Next, we exhaustively define the parameters required for realizing the supported * `created_at_time`: (ICP, ICRC-1, ICRC-2) * ... Accounts are always represented through the size-reduced textual encoding as specified in [the section](## Size-reduced-ICRC-1-textual-account-representation) below. -// FIX complete the list, define the respective encoding +// FIX complete the list, define the respective encoding, maybe restructure per method The `amount` should be provided as a nonnegative integer number. The amount represents the amount of tokens in the base unit used by the ledger, i.e., 4 ICP tokens would amount to 4 * 10^8 = 400000000 base units as managed by the ICP token ledger. It is strongly recommended to use scientific notation for the amount. Decimal representation can be combined with scientific representation, e.g., 4.042E8 ICP means a count of 404200000 base units as managed by the ICP ledger. As only integer numbers are allowed as amount, the exponent MUST be greater than or equal the decimal places of the number in scientific representation. @@ -78,13 +82,11 @@ The `amount` should be provided as a nonnegative integer number. The amount repr The Chain Agnostic Standards Alliance [Cha24] has specified account identifiers to be of a maximum length of 128 characters [Gom22]. There seems to be no strong reason behind this, but it has been considered sufficient for the foreseeable future by the CAIP working group. This limitation cannot be changed at the current time. -// FIX use maximum-length textual account representation - ICRC-1 account identifiers on ICP may exceed this limitation by a few bytes when using the human-readable representation of ICRC-1 accounts, i.e., textual encoding of ICRC-1 accounts [Dfi22]. For this reason, we define a size-reduced textual ICRC-1 account representation as part of this standard in order to fit the CAIP limits of 128 characters. The size-reduced representation is easily computed by removing all the dashes ("-") between the character groups of the representation, except for the rightmost one (the one preceding the CRC32 checksum) for non-default accounts (non-zero subaccount). For default accounts (all-zero subaccount), all dashes are removed. It is easy to reconstruct the standard textual encoding from a size-reduced textual encoding by adding dash separators from the left of the representation for every 5-character group. -It is guaranteed that any ICRC-1 account in size-reduced representation fits into the 128-byte limit. According to the The Internet Computer Interface Specification [Dfi], the maximum lenght of a textual representation of a principal is 63 bytes, including 10 dashes. The additional CRC-32 checksum in Base-32 encoding takes another 7 characters, the dash separator one. This makes the maximum length of the size-reduced representation 126 characters: 63 - 10 separators + 1 separator + 7 CRC32 checksum + 1 .-separator + 64 subaccount in HEX. +It is guaranteed that any ICRC-1 account in size-reduced representation fits into the 128-byte limit. The Internet Computer Interface Specification [Dfi] specifies the maximum lenght of a textual representation of a principal to be 63 bytes, which includes 10 dashes. The additional CRC-32 checksum in Base-32 encoding takes another 7 characters, its dash separator one. This makes the maximum length of the size-reduced representation 126 characters: 63 for the maximum-length principal in textual encoding - 10 for separators + 1 for the "-"-separator + 7 for the CRC32 checksum + 1 for the "."-separator + 64 for the subaccount in hexadecimal representation. -The following is an example of an almost maximum-length long textual representation that exceeds the size limits imposed by CAIP with its 1135 characters. +The following is an example of an almost maximum-length textual representation that exceeds the size limits imposed by CAIP with its 135 characters. ``` k2t6j-2nvnp-4zjm3-25dtz-6xhaa-c7boj-5gayf-oj3xs-i43lp-teztq-6ae-dfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 ``` @@ -93,8 +95,12 @@ The following is the above example in size-reduced form and fits within the 128- k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6aedfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 ``` +// FIX use maximum-length textual account representation as example; the current one is close + ## Examples +The following examples show the application of ICRC-22 for ICP transfer, ICRC-1 transfer, and ICRC-2 approval use cases. + ### ICRC-1 token transfer // FIX replace 1234abcd90 with a prefix of the SHA256 hash of the mainnet NNS public key in binary @@ -103,13 +109,14 @@ k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6aedfxgiyy.102030405060708090a The following is a payment request for 4.042 ckBTC on the ckBTC ledger. The wallet reading and executing this request would insert the `created_at_time` field based on the current time. ``` -icp:1234abcd90:mxzaz-hqaaa-aaaar-qaada-cai/exec/icrc1_transfer?from_subaccount=&to=&amount=4.042E8&fee=&memo= +icp:1234abcd90:mxzaz-hqaaa-aaaar-qaada-cai/exec/icrc1_transfer?from_subaccount=10&to=k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6aedfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20&amount=4.042E8&memo=receipt%2012345678 ``` ### ICP token transfer +// FIX ``` -icp:mainnet:/exec/transfer?from_subaccount=&to=&amount=4.042E8&fee=&memo=&created_at_time= +icp:1234abcd90:/exec/transfer?from_subaccount=&to=&amount=4.042E8&fee=&memo=&created_at_time= ``` ### ICRC-2 approval @@ -117,7 +124,7 @@ icp:mainnet:/exec/transfer?from_subaccount=&to An ICRC-2 approval can be made on any ICRC-2-compliant ledger, e.g., the ICP ledger or any ICRC-1-compliant token ledger. ``` -icp:mainnet:/exec/icrc2_approve?from_subaccount=&spender=&amount=&expected_allowance=&... +icp:1234abcd90:/exec/icrc2_approve?from_subaccount=&spender=&amount=&expected_allowance=&... ``` ## References From c04e1ebc4548ffdb0e47b027ed8b4859f48e6294 Mon Sep 17 00:00:00 2001 From: "Dieter M. Sommer" Date: Mon, 19 Aug 2024 13:36:19 +0200 Subject: [PATCH 03/13] Update --- ICRCs/ICRC-22/ICRC-22.md | 71 ++++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/ICRCs/ICRC-22/ICRC-22.md b/ICRCs/ICRC-22/ICRC-22.md index aa60808..c6d1db9 100644 --- a/ICRCs/ICRC-22/ICRC-22.md +++ b/ICRCs/ICRC-22/ICRC-22.md @@ -12,7 +12,7 @@ Relevant prior work in other blockchain ecosystems comprises the standards on pa ## Specification -The below specification defines the syntax and (non-formal) semantics for an ICRC-22 payment request. The specification takes the approaches of [Bit1, Bit2, Nag17, WLGH19] into consideration. Particularly, an authority-less URI format has been chosen following this prior art in the domain. +The below specification defines the syntax and (non-formal) semantics for an ICRC-22 payment request. The specification takes the approaches of \[Bit1, Bit2, Nag17, WLGH19\] into consideration. Particularly, an authority-less URI format has been chosen following this prior art in the domain. The following shows the structure of a URI for an example with the concrete parameters represented through `<>`-placeholders. Note that the URI does not contain an authority, but encodes the `network` as part of the URI path, directly following the URI scheme. ``` @@ -26,71 +26,78 @@ request = protocol ":" network ":" contract_address "/" "exec" transaction [ "?" protocol = "icp" ; always "icp" referring to the current version of the Internet Computer Protocol network = (1..12)[0..9a..fA..F] / ; specifies the network through a prefix of its public key hash contract_address = principal FIX: canister principal ABNF ; canister address to which to make the call -transaction = transfer / icrc1_transfer / icrc2_approve ; method on the canister to call +transaction = ... ; canister method to call parameters = parameter [ "&" parameter ] parameter = key "=" value key = ... value = ... ``` -// FIX: Do we default the network to ICP's mainnet current value when omitted? -// Would result in `icp::/exec/?` +// FIX: We should default the network to ICP's mainnet current value when omitted +// Would result in `icp::/exec/?` for current mainnet; the interpretation of what "current mainnet" is would be left to the client // FIX: Should we keep it open to other methods and supported ICRCs as long as their API can be canonically expressed using a sequential list of parameters encoded as query parameters -The grammar productions not further specified can be looked up in the syntax specification for URIs in RFC 3986 [BFM05]. Note that the production `transaction` above is part of the path and `parameters` part of the query string and the according constraints of RFC 3986 apply. +// maybe add an encoding specifier in the beginning of query to keep it open for future work; this could look like `exec/enc_plain` for ICRC-22 and `exec/enc_candid` for the extensions in the future work; it could default to the further -The `network_identifier` uniquely identifies the network to make the transaction on. Following the ideas of the Chain Agnostic Standards Alliance [Cha24] of having a standardized way of referring to any blockchain network, ICP uses the following mechanism for referring to ICP mainnet or any other ICP-based network that may be available in the future, such as testnets or private networks based on the ICP protocol stack. +The grammar productions not further specified can be looked up in the syntax specification for URIs in RFC 3986 \[BFM05\]. Note that the production `transaction` above is part of the path and `parameters` part of the query string and the according constraints of RFC 3986 apply. + +The `network_identifier` uniquely identifies the network to make the transaction on. Following the ideas of the Chain Agnostic Standards Alliance \[Cha24\] of having a standardized way of referring to any blockchain network, ICP uses the following mechanism for referring to ICP mainnet or any other ICP-based network that may be available in the future, such as testnets or private networks based on the ICP protocol stack. The network identifier for an ICP-based network is comprised of the constant `icp` referring to the Internet Computer Protocol, followed by `:`, followed by `` where `pub_key_hash_prefix` is a ??-character prefix in ?? encoding of the SHA256 hash of the binary representation of the public key of the network. The prefix length and encoding scheme used ensures that the probability of collision is negligible for all practical purposes. For ICP mainnet the public key of the network is the NNS public key. -// FIX using base-64 encoding for the network allows for using a shorter prefix, which is crucial for usability and human readibility; prefix length t.b.d. +// FIX using Base64 encoding for the network allows for using a shorter prefix, which is crucial for usability and human readibility; prefix length t.b.d. The `contract_address` is the canister smart contract principal identifier of the contract the transaction is to be performed on. This is represented in the standardized format for principals. The address, together with the network identifier, unambiguously determines the token that is to be transacted. The constant `exec` means that the forthcoming part in the path component specifies which transaction (smart contract method) should be invoked with the information in the URI. In the future, other ICRC standards may emerge that can have a different string with different semantics in the place of this. // FIX: do we want to call this `tx`? -The `transaction` parameter specifies the canister method to be called on the canister indicated through `contract_address`. This is the string-based name as it appears in the canister's Candid specification. This standard requires support of all of ICP ledger's `transfer`, ICRC-1's `transfer` and ICRC-2's `approve` methods. +The `transaction` parameter specifies the canister method to be called on the canister indicated through `contract_address`. This is the string-based name as it appears in the canister's Candid specification. This standard requires support of all of ICP ledger's `transfer`, ICRC-1's `transfer` and ICRC-2's `approve` methods. The method names to handle payment-related use cases currently envisioned are `transfer`, `icrc1_transfer`, and `icrc2_approve`. The `parameters` are the parameters of the method to be called. They SHOULD be given in the order in which they appear in the Candid specification of the method to be called. A subset of the parameters defind in the Candid specification of the method can be present, the remaining non-optional parameters MUST be filled in by the party executing the transaction. // FIX: Details need to be worked out to make it possible to call different methods we want to cover in the base standard (at least ICP and ICRC-1 transfer and ICRC-2 approve). The result may not be so far away from a generic standard covering the call of any method of canisters. Specifically: Should types be decomposed into their constituents or the compound values be provided using a specific or their Candid encoding? -Next, we exhaustively define the parameters required for realizing the supported transactions of the supported ledger standards: +Next, we define the parameters required for realizing the supported transactions of the supported ledger standards: * `from_subaccount` (ICRC-1, ICRC-2): 32-byte subaccount in Base64 representation -* `to` (ICRC-1, ICRC-2): // FIX t.b.d.: The human readable [textual representation](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md) of an ICRC-1 account or a shortened version thereof, e.g., with removed checksum or removed dashes between character groups, or using more concise encoding for parts. -* `spender` (ICRC-2): +* `to` (ICRC-1, ICRC-2): The size-reduced human readable [textual representation](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md) of an ICRC-1 account as specified in this document. +* `spender` (ICRC-2): The size-reduced human readable [textual representation](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md) of an ICRC-1 account as specified in this document. * `spender_subaccount` (ICRC-2): -* `from` (ICRC-2): -* `expected_allowance` (ICRC-2): -* `expires_at` (ICRC-2): +* `from` (ICRC-2): The size-reduced human readable [textual representation](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md) of an ICRC-1 account as specified in this document. * `amount` (ICP, ICRC-1, ICRC-2): The transaction amount, specified in scientific representation, e.g., 4.042E8 means 804200000 base units of the addressed ledger. -* `fee` (ICP, ICRC-1, ICRC-2): Fee expressed in base units of the addressed ledger. -* `memo` (ICP, ICRC-1, ICRC-2): blob -* `created_at_time`: (ICP, ICRC-1, ICRC-2) +* `expected_allowance` (ICRC-2): The amount to be approved, specified in scientific representation, e.g., 4.042E8 means 804200000 base units of the addressed ledger. +* `expires_at` (ICRC-2): The expiration date of the approval. +* `fee` (ICP, ICRC-1, ICRC-2): Fee expressed in base units of the addressed ledger, using scientific notation if appropriate. +* `memo` (ICP, ICRC-1, ICRC-2): A hexadecimal string representing the memo. +* `created_at_time` (ICP, ICRC-1, ICRC-2): The creation time of the transaction. * ... -Accounts are always represented through the size-reduced textual encoding as specified in [the section](## Size-reduced-ICRC-1-textual-account-representation) below. +Accounts are always represented through the size-reduced textual encoding as specified in [the section below](## Size-reduced-ICRC-1-textual-account-representation). // FIX complete the list, define the respective encoding, maybe restructure per method The `amount` should be provided as a nonnegative integer number. The amount represents the amount of tokens in the base unit used by the ledger, i.e., 4 ICP tokens would amount to 4 * 10^8 = 400000000 base units as managed by the ICP token ledger. It is strongly recommended to use scientific notation for the amount. Decimal representation can be combined with scientific representation, e.g., 4.042E8 ICP means a count of 404200000 base units as managed by the ICP ledger. As only integer numbers are allowed as amount, the exponent MUST be greater than or equal the decimal places of the number in scientific representation. -// FIX How exactly can the mapping from the paramters to the Candid method signature be done? Is it sufficient to enumerate all named parameters, with the type inferable by the recipient using the canister's Candid specification which can be obtained from the canister? +// FIX How exactly can the mapping from the parameters to the Candid method signature be done? Is it sufficient to enumerate all named parameters, with the type inferable by the recipient using the canister's Candid specification which can be obtained from the canister? // FIX How to handle optional fields in the Candid specification of the method? As long as the input can be constructed unambiguously, they can be left out, otherwise be included as `key=null`. -## Size-reduced ICRC-1 textual account representation +## Generalization Towards Handling a Larger Class of Method Calls + +ICRC-22 does not handle generic calls of smart contract methods on ICP, but does allow for handling further requests that are sufficiently similar to the ones captured explicitly. This comprises requests that have parameters that can be represented as query parameters in a URI in a straightforward way and a canonical encoding exists for the parameters. Canonical encoding means that `text` parameters are represented as a strings, `number` paramters as the string of the number representation, binary `blob` parameters are hexadecimal encoded, records are "inlined", i.e., their fields are encoded sequentially in the query string while encoding the beginning of the record with the record name as key and the string `record` as value, and arrays are "inlined" as well so that every of its entries receives the array's name and the array starts with the array name as key and `array` as value. A large class of method interfaces can be handled with this method of canonical flattening of any nested Candid structure, however, this simple Candid-to-URI mapping may have its limits when parameters get nested in a too complex manner, contain the same names on different levels, or otherwise make it hard to re-assemble the Candid request in unambiguous form given the Candid specification of the method and the query string. Those cases may need a more elaborate approach of handling as outlined in the [Future Work](##Future-Work) section. +// FIX too vague, work out and explain in more detail + +## Size-Reduced ICRC-1 Textual Account Representation -// FIX maybe call "compressed" +// FIX maybe call "compressed" instead of "size-reduced" -The Chain Agnostic Standards Alliance [Cha24] has specified account identifiers to be of a maximum length of 128 characters [Gom22]. There seems to be no strong reason behind this, but it has been considered sufficient for the foreseeable future by the CAIP working group. This limitation cannot be changed at the current time. +The Chain Agnostic Standards Alliance \[Cha24\] has specified account identifiers to be of a maximum length of 128 characters \[Gom22\]. There seems to be no strong reason behind this, but it has been considered sufficient for the foreseeable future by the CAIP working group. This limitation cannot be changed at the current time. -ICRC-1 account identifiers on ICP may exceed this limitation by a few bytes when using the human-readable representation of ICRC-1 accounts, i.e., textual encoding of ICRC-1 accounts [Dfi22]. For this reason, we define a size-reduced textual ICRC-1 account representation as part of this standard in order to fit the CAIP limits of 128 characters. The size-reduced representation is easily computed by removing all the dashes ("-") between the character groups of the representation, except for the rightmost one (the one preceding the CRC32 checksum) for non-default accounts (non-zero subaccount). For default accounts (all-zero subaccount), all dashes are removed. It is easy to reconstruct the standard textual encoding from a size-reduced textual encoding by adding dash separators from the left of the representation for every 5-character group. +ICRC-1 account identifiers on ICP may exceed this limitation by a few bytes when using the human-readable representation of ICRC-1 accounts, i.e., textual encoding of ICRC-1 accounts \[Dfi22\]. For this reason, we define a size-reduced textual ICRC-1 account representation as part of this standard in order to fit the CAIP limits of 128 characters. The size-reduced representation is easily computed by removing all the dashes ("-") between the character groups of the representation, except for the rightmost one (the one preceding the CRC32 checksum) for non-default accounts (non-zero subaccount). For default accounts (all-zero subaccount), all dashes are removed. It is easy to reconstruct the standard textual encoding from a size-reduced textual encoding by adding dash separators from the left of the representation for every 5-character group. -It is guaranteed that any ICRC-1 account in size-reduced representation fits into the 128-byte limit. The Internet Computer Interface Specification [Dfi] specifies the maximum lenght of a textual representation of a principal to be 63 bytes, which includes 10 dashes. The additional CRC-32 checksum in Base-32 encoding takes another 7 characters, its dash separator one. This makes the maximum length of the size-reduced representation 126 characters: 63 for the maximum-length principal in textual encoding - 10 for separators + 1 for the "-"-separator + 7 for the CRC32 checksum + 1 for the "."-separator + 64 for the subaccount in hexadecimal representation. +It is guaranteed that any ICRC-1 account in size-reduced representation fits into the 128-character limit. The Internet Computer Interface Specification \[Dfi\] specifies the maximum lenght of a textual representation of a principal to be 63 bytes, which includes 10 dashes. The additional CRC32 checksum in Base32 encoding takes another 7 characters, its preceding dash separator one. This makes the maximum length of the size-reduced representation 126 characters: 63 for the maximum-length principal in textual encoding - 10 for separators + 1 for the checksum "-"-separator + 7 for the CRC32 checksum + 1 for the subaccount "."-separator + 64 for the subaccount in hexadecimal representation. -The following is an example of an almost maximum-length textual representation that exceeds the size limits imposed by CAIP with its 135 characters. +The following is an example of an almost maximum-length textual representation that exceeds the size limits imposed by CAIP with its length of 135 characters. ``` k2t6j-2nvnp-4zjm3-25dtz-6xhaa-c7boj-5gayf-oj3xs-i43lp-teztq-6ae-dfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 ``` -The following is the above example in size-reduced form and fits within the 128-character limit with its 124 characters. +The following is the above example in size-reduced form and fits within the 128-character limit with its length of 124 characters. ``` k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6aedfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 ``` @@ -101,7 +108,7 @@ k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6aedfxgiyy.102030405060708090a The following examples show the application of ICRC-22 for ICP transfer, ICRC-1 transfer, and ICRC-2 approval use cases. -### ICRC-1 token transfer +### ICRC-1 Token Transfer // FIX replace 1234abcd90 with a prefix of the SHA256 hash of the mainnet NNS public key in binary @@ -112,14 +119,14 @@ The following is a payment request for 4.042 ckBTC on the ckBTC ledger. The wall icp:1234abcd90:mxzaz-hqaaa-aaaar-qaada-cai/exec/icrc1_transfer?from_subaccount=10&to=k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6aedfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20&amount=4.042E8&memo=receipt%2012345678 ``` -### ICP token transfer +### ICP Token Transfer // FIX ``` icp:1234abcd90:/exec/transfer?from_subaccount=&to=&amount=4.042E8&fee=&memo=&created_at_time= ``` -### ICRC-2 approval +### ICRC-2 Approval An ICRC-2 approval can be made on any ICRC-2-compliant ledger, e.g., the ICP ledger or any ICRC-1-compliant token ledger. @@ -127,6 +134,12 @@ An ICRC-2 approval can be made on any ICRC-2-compliant ledger, e.g., the ICP led icp:1234abcd90:/exec/icrc2_approve?from_subaccount=&spender=&amount=&expected_allowance=&... ``` +## Future Work + +The current specification is focussed on expressing payment-related requests, concretely payments and approvals related to ICP, ICRC-1, and ICRC-2 standards. The idea can be generalized, like in ERC-681 \[Nag17\] to expressing any smart contract invocation. ERC-681 is handling this generalization with embedded EVM ABI encoded parameters in the URI. + +For the Internet Computer, embedding Candid-encoded parameters are the natural way to accomplish this. The remaining issue is that mandatory parameters such as timestamps may need to be filled in by the client, but must be encoded already in the Candid structure to result in valid Candid. This can be handled by encoding a default value, e.g., 0 for a number type, in such cases and providing additional metadata that such element must be replaced by the client. Due to those complexities that still need to be worked out, we do not handle this extension in ICRC-22, but defer it to future work when to be done when use cases demand such functionality. + ## References [Nag17] Daniel A. Nagy, URL Format for Transaction Requests. Ethereum EIP-681, https://github.com/ethereum/EIPs/blob/master/EIPS/eip-681.md, 2017 From 599419cf559c662061bb3cef5acc5e4077d937ba Mon Sep 17 00:00:00 2001 From: "Dieter M. Sommer" Date: Mon, 19 Aug 2024 13:46:47 +0200 Subject: [PATCH 04/13] ICRC-22 update --- ICRCs/ICRC-22/ICRC-22.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/ICRCs/ICRC-22/ICRC-22.md b/ICRCs/ICRC-22/ICRC-22.md index c6d1db9..9db76a7 100644 --- a/ICRCs/ICRC-22/ICRC-22.md +++ b/ICRCs/ICRC-22/ICRC-22.md @@ -14,27 +14,27 @@ Relevant prior work in other blockchain ecosystems comprises the standards on pa The below specification defines the syntax and (non-formal) semantics for an ICRC-22 payment request. The specification takes the approaches of \[Bit1, Bit2, Nag17, WLGH19\] into consideration. Particularly, an authority-less URI format has been chosen following this prior art in the domain. -The following shows the structure of a URI for an example with the concrete parameters represented through `<>`-placeholders. Note that the URI does not contain an authority, but encodes the `network` as part of the URI path, directly following the URI scheme. +The following shows the structure of a URI for an example with the concrete parameters represented through `<>`-placeholders. Note that the URI does not contain an authority, but encodes the `network` and `contract_address` as part of the URI path, directly following the URI scheme. ``` icp::/exec/?from_subaccount=&to=&amount=4.042E8&fee=&memo= ``` // FIX syntax details -ABNF syntax: +Next, we present the ABNF syntax for ICRC-22 URIs. ``` request = protocol ":" network ":" contract_address "/" "exec" transaction [ "?" parameters ] protocol = "icp" ; always "icp" referring to the current version of the Internet Computer Protocol -network = (1..12)[0..9a..fA..F] / ; specifies the network through a prefix of its public key hash -contract_address = principal FIX: canister principal ABNF ; canister address to which to make the call -transaction = ... ; canister method to call +network = (1..10)[0..9a..fA..F] / ; specifies the network through a prefix of its public key hash +contract_address = ICP principal FIX: canister principal ABNF ; canister address to which to make the call +transaction = ... ; canister method to call FIX: Candid method syntax parameters = parameter [ "&" parameter ] parameter = key "=" value -key = ... -value = ... +key = ... ; FIX: Candid parameter name syntax +value = ... ; FIX Candid encoded value syntax ``` // FIX: We should default the network to ICP's mainnet current value when omitted -// Would result in `icp::/exec/?` for current mainnet; the interpretation of what "current mainnet" is would be left to the client +// Would result in `icp::/exec/?` for current mainnet; the interpretation of what "current mainnet" is would be left to the client (the currently active key for mainnet, which can only change in the event of an NNS recovery after a large desaster event that destroys the NNS private threshold key) // FIX: Should we keep it open to other methods and supported ICRCs as long as their API can be canonically expressed using a sequential list of parameters encoded as query parameters @@ -43,8 +43,9 @@ value = ... The grammar productions not further specified can be looked up in the syntax specification for URIs in RFC 3986 \[BFM05\]. Note that the production `transaction` above is part of the path and `parameters` part of the query string and the according constraints of RFC 3986 apply. The `network_identifier` uniquely identifies the network to make the transaction on. Following the ideas of the Chain Agnostic Standards Alliance \[Cha24\] of having a standardized way of referring to any blockchain network, ICP uses the following mechanism for referring to ICP mainnet or any other ICP-based network that may be available in the future, such as testnets or private networks based on the ICP protocol stack. -The network identifier for an ICP-based network is comprised of the constant `icp` referring to the Internet Computer Protocol, followed by `:`, followed by `` where `pub_key_hash_prefix` is a ??-character prefix in ?? encoding of the SHA256 hash of the binary representation of the public key of the network. The prefix length and encoding scheme used ensures that the probability of collision is negligible for all practical purposes. For ICP mainnet the public key of the network is the NNS public key. +Base16 encoding of the SHA256 hash of the binary representation of the DER-encoded public key of the network. The prefix length used ensures that the probability of collision is negligible for all practical purposes. For ICP mainnet the public key of the network is the NNS public key. // FIX using Base64 encoding for the network allows for using a shorter prefix, which is crucial for usability and human readibility; prefix length t.b.d. +// FIX Is it a security risk to use a prefix of the hash? The `contract_address` is the canister smart contract principal identifier of the contract the transaction is to be performed on. This is represented in the standardized format for principals. The address, together with the network identifier, unambiguously determines the token that is to be transacted. From d4e848218feab3c3ebe94acbe3f311a4f96c6067 Mon Sep 17 00:00:00 2001 From: "Dieter M. Sommer" Date: Mon, 19 Aug 2024 14:12:06 +0200 Subject: [PATCH 05/13] Network identifier --- ICRCs/ICRC-22/ICRC-22.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ICRCs/ICRC-22/ICRC-22.md b/ICRCs/ICRC-22/ICRC-22.md index 9db76a7..4070ec6 100644 --- a/ICRCs/ICRC-22/ICRC-22.md +++ b/ICRCs/ICRC-22/ICRC-22.md @@ -43,7 +43,7 @@ value = ... ; FIX Candid encoded value syntax The grammar productions not further specified can be looked up in the syntax specification for URIs in RFC 3986 \[BFM05\]. Note that the production `transaction` above is part of the path and `parameters` part of the query string and the according constraints of RFC 3986 apply. The `network_identifier` uniquely identifies the network to make the transaction on. Following the ideas of the Chain Agnostic Standards Alliance \[Cha24\] of having a standardized way of referring to any blockchain network, ICP uses the following mechanism for referring to ICP mainnet or any other ICP-based network that may be available in the future, such as testnets or private networks based on the ICP protocol stack. -Base16 encoding of the SHA256 hash of the binary representation of the DER-encoded public key of the network. The prefix length used ensures that the probability of collision is negligible for all practical purposes. For ICP mainnet the public key of the network is the NNS public key. +The network is identified by the Base16 encoding of the SHA256 hash of the binary representation of the DER-encoded public key of the network. In case of a well-known public network, an 8-character prefix of the key hash is used as network identifier. Currently, only ICP mainnet qualifies as a well-known network, in the future public testnets may be added to this. For ICP mainnet the public key of the network is the NNS public key. In case of a private ICP deployement, the full key hash in Base64 representation is used as network identifier. // FIX or a 32-character prefix, align this with the CAIP discussion // FIX using Base64 encoding for the network allows for using a shorter prefix, which is crucial for usability and human readibility; prefix length t.b.d. // FIX Is it a security risk to use a prefix of the hash? From ebd958dd3f81936ea5dacb1e71481373f7511790 Mon Sep 17 00:00:00 2001 From: "Dieter M. Sommer" Date: Mon, 19 Aug 2024 14:17:29 +0200 Subject: [PATCH 06/13] Update FIX comments --- ICRCs/ICRC-22/ICRC-22.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/ICRCs/ICRC-22/ICRC-22.md b/ICRCs/ICRC-22/ICRC-22.md index 4070ec6..a1ce1d5 100644 --- a/ICRCs/ICRC-22/ICRC-22.md +++ b/ICRCs/ICRC-22/ICRC-22.md @@ -55,8 +55,6 @@ The `transaction` parameter specifies the canister method to be called on the ca The `parameters` are the parameters of the method to be called. They SHOULD be given in the order in which they appear in the Candid specification of the method to be called. A subset of the parameters defind in the Candid specification of the method can be present, the remaining non-optional parameters MUST be filled in by the party executing the transaction. -// FIX: Details need to be worked out to make it possible to call different methods we want to cover in the base standard (at least ICP and ICRC-1 transfer and ICRC-2 approve). The result may not be so far away from a generic standard covering the call of any method of canisters. Specifically: Should types be decomposed into their constituents or the compound values be provided using a specific or their Candid encoding? - Next, we define the parameters required for realizing the supported transactions of the supported ledger standards: * `from_subaccount` (ICRC-1, ICRC-2): 32-byte subaccount in Base64 representation * `to` (ICRC-1, ICRC-2): The size-reduced human readable [textual representation](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md) of an ICRC-1 account as specified in this document. @@ -75,14 +73,17 @@ Accounts are always represented through the size-reduced textual encoding as spe The `amount` should be provided as a nonnegative integer number. The amount represents the amount of tokens in the base unit used by the ledger, i.e., 4 ICP tokens would amount to 4 * 10^8 = 400000000 base units as managed by the ICP token ledger. It is strongly recommended to use scientific notation for the amount. Decimal representation can be combined with scientific representation, e.g., 4.042E8 ICP means a count of 404200000 base units as managed by the ICP ledger. As only integer numbers are allowed as amount, the exponent MUST be greater than or equal the decimal places of the number in scientific representation. -// FIX How exactly can the mapping from the parameters to the Candid method signature be done? Is it sufficient to enumerate all named parameters, with the type inferable by the recipient using the canister's Candid specification which can be obtained from the canister? - -// FIX How to handle optional fields in the Candid specification of the method? As long as the input can be constructed unambiguously, they can be left out, otherwise be included as `key=null`. - ## Generalization Towards Handling a Larger Class of Method Calls ICRC-22 does not handle generic calls of smart contract methods on ICP, but does allow for handling further requests that are sufficiently similar to the ones captured explicitly. This comprises requests that have parameters that can be represented as query parameters in a URI in a straightforward way and a canonical encoding exists for the parameters. Canonical encoding means that `text` parameters are represented as a strings, `number` paramters as the string of the number representation, binary `blob` parameters are hexadecimal encoded, records are "inlined", i.e., their fields are encoded sequentially in the query string while encoding the beginning of the record with the record name as key and the string `record` as value, and arrays are "inlined" as well so that every of its entries receives the array's name and the array starts with the array name as key and `array` as value. A large class of method interfaces can be handled with this method of canonical flattening of any nested Candid structure, however, this simple Candid-to-URI mapping may have its limits when parameters get nested in a too complex manner, contain the same names on different levels, or otherwise make it hard to re-assemble the Candid request in unambiguous form given the Candid specification of the method and the query string. Those cases may need a more elaborate approach of handling as outlined in the [Future Work](##Future-Work) section. -// FIX too vague, work out and explain in more detail + +// FIX too vague, work out and explain in more detail; or decide to keep this out of the standard + +// FIX How exactly can the mapping from the parameters back to the Candid method signature be done? Is it sufficient to enumerate all named parameters, with the type inferable by the recipient using the canister's Candid specification which can be obtained from the canister? + +// FIX How to handle optional fields in the Candid specification of the method? As long as the input can be constructed unambiguously, they can be left out, otherwise be included as `key=null`. + +// FIX: Details need to be worked out to make it possible to call different methods we want to cover in the base standard (at least ICP and ICRC-1 transfer and ICRC-2 approve). The result may not be so far away from a generic standard covering the call of any method of canisters. Specifically: Should types be decomposed into their constituents or the compound values be provided using a specific or their Candid encoding? ## Size-Reduced ICRC-1 Textual Account Representation From e0d896f19f472ae91667a6c930cc49634d549c08 Mon Sep 17 00:00:00 2001 From: "Dieter M. Sommer" Date: Tue, 15 Oct 2024 11:15:58 +0200 Subject: [PATCH 07/13] Update, generalized --- ICRCs/ICRC-22/ICRC-22.md | 142 ++++++++++++++++++++++++--------------- 1 file changed, 87 insertions(+), 55 deletions(-) diff --git a/ICRCs/ICRC-22/ICRC-22.md b/ICRCs/ICRC-22/ICRC-22.md index a1ce1d5..42a1af3 100644 --- a/ICRCs/ICRC-22/ICRC-22.md +++ b/ICRCs/ICRC-22/ICRC-22.md @@ -6,17 +6,17 @@ ## Introduction -ICRC-22 defines a standard way of representing payment requests on ICP as URIs. URIs can be embedded in QR codes, hyperlinks on Web pages, emails, or chat communication and serve the purpose of robust signalling between loosely-coupled applications. Such pre-canned or on-the-fly generated payment requests can be immediately used by the user's wallet application, where relevant parameters are provided by the URI and some other parameters may be filled in by the wallet application. This makes such URI encoding an indispensible tool in a larger blockchain ecosystem to allow for convenient communication of payment-related information over many different communication channels. +ICRC-22 defines a standard way of representing transaction requests, e.g., for payments or approvals of token transactions, on ICP as URIs. A variety of transport mechanisms can be used to communicate URIs to their recipients, e.g., they can be embedded in QR codes, hyperlinks on Web pages, emails, or chat communication, to obtain robust signalling between loosely-coupled applications. Such pre-defined or on-the-fly generated payment requests can be immediately used by the user's wallet application, where relevant parameters are provided through the URI and further parameters may be filled in by the wallet application or the user themselves. This makes such URI encoding an indispensible tool in a larger blockchain ecosystem to allow for convenient communication of payment-related information over many different communication channels. ICRC-22 clearly focusses on payment-related transactions, but supports a wider range of transactions to be expressed as URIs. -Relevant prior work in other blockchain ecosystems comprises the standards on payment URLs for Bitcoin \[Bit1, Bit2\] as well as Ethereum's [ERC-681 \[Nag17\]](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-681.md) for expressing payment requests and, more generally, transactions using EVM ABI encoding, for the Ethereum blockchain. The specification put forth in ICRC-22 is an adaptation of the ideas in the abovelisted references to establish a standard way of sharing URIs that represent payment requests on the Internet Computer. +Relevant prior work in other blockchain ecosystems comprises the standards on payment URLs for Bitcoin \[Bit1, Bit2\] as well as Ethereum's [ERC-681 \[Nag17\]](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-681.md) for expressing payment requests and, more generally, transactions using EVM ABI encoding, for the Ethereum blockchain. The specification put forth in ICRC-22 is an adaptation of the ideas in the above listed references to establish a standard way of sharing URIs that represent payment and other requests on the Internet Computer. -## Specification +## Specification for Payments -The below specification defines the syntax and (non-formal) semantics for an ICRC-22 payment request. The specification takes the approaches of \[Bit1, Bit2, Nag17, WLGH19\] into consideration. Particularly, an authority-less URI format has been chosen following this prior art in the domain. +The below specification defines the syntax and (non-formal) semantics for an ICRC-22 payment request and extension to further requests. The specification takes the approaches of \[Bit1, Bit2, Nag17, WLGH19\] into consideration. Particularly, an authority-less URI format has been chosen following this prior art in the domain. -The following shows the structure of a URI for an example with the concrete parameters represented through `<>`-placeholders. Note that the URI does not contain an authority, but encodes the `network` and `contract_address` as part of the URI path, directly following the URI scheme. +Next, we show the structure of a request URI with the concrete parameters represented through `<>`-placeholders. Note that the URI does not contain an authority, but encodes the `network` and `contract_address` as part of the URI path, directly following the URI scheme. ``` -icp::/exec/?from_subaccount=&to=&amount=4.042E8&fee=&memo= +icp:737ba355e855bd4b61279056603e0550:/exec/icrc1_transfer?enc=plain&from_subaccount=&to=&amount=&memo= ``` // FIX syntax details @@ -34,64 +34,83 @@ value = ... ; FIX Candid encoded value syntax ``` // FIX: We should default the network to ICP's mainnet current value when omitted -// Would result in `icp::/exec/?` for current mainnet; the interpretation of what "current mainnet" is would be left to the client (the currently active key for mainnet, which can only change in the event of an NNS recovery after a large desaster event that destroys the NNS private threshold key) +The `network` defaults to the identifier `737ba355e855bd4b61279056603e0550` for ICP mainnet. When the network identifier is left out, the prefix of a URI would thus be `icp::/exec/?` for the current ICP mainnet. The interpretation of what "current mainnet" is is left to the client. It should refer to the currently active key for mainnet, which can only change in the event of an NNS recovery after a large desaster event that destroys the NNS private threshold key, and thus is considered very stable. // FIX: Should we keep it open to other methods and supported ICRCs as long as their API can be canonically expressed using a sequential list of parameters encoded as query parameters -// maybe add an encoding specifier in the beginning of query to keep it open for future work; this could look like `exec/enc_plain` for ICRC-22 and `exec/enc_candid` for the extensions in the future work; it could default to the further +An encoding specifier in the beginning of query string defines the kind of encoding used for the parameters. ICRC-22 defines only the encoding `plain`. We envision a future ICRC that uses Candid for encoding any list of parameters and uses the `candid` constant. If omitted, the encoding defaults to the `plain` encoding. -The grammar productions not further specified can be looked up in the syntax specification for URIs in RFC 3986 \[BFM05\]. Note that the production `transaction` above is part of the path and `parameters` part of the query string and the according constraints of RFC 3986 apply. +The grammar productions not further specified above can be looked up in the syntax specification for URIs in RFC 3986 \[BFM05\]. Note that the production `transaction` above is part of the path and `parameters` part of the query string and the according constraints of RFC 3986 apply. // FIX -The `network_identifier` uniquely identifies the network to make the transaction on. Following the ideas of the Chain Agnostic Standards Alliance \[Cha24\] of having a standardized way of referring to any blockchain network, ICP uses the following mechanism for referring to ICP mainnet or any other ICP-based network that may be available in the future, such as testnets or private networks based on the ICP protocol stack. -The network is identified by the Base16 encoding of the SHA256 hash of the binary representation of the DER-encoded public key of the network. In case of a well-known public network, an 8-character prefix of the key hash is used as network identifier. Currently, only ICP mainnet qualifies as a well-known network, in the future public testnets may be added to this. For ICP mainnet the public key of the network is the NNS public key. In case of a private ICP deployement, the full key hash in Base64 representation is used as network identifier. // FIX or a 32-character prefix, align this with the CAIP discussion -// FIX using Base64 encoding for the network allows for using a shorter prefix, which is crucial for usability and human readibility; prefix length t.b.d. -// FIX Is it a security risk to use a prefix of the hash? +The `network_identifier` uniquely identifies the ICP network to make the transaction on. Following the ideas of the Chain Agnostic Standards Alliance \[Cha24\] of having a standardized way of referring to any blockchain network, ICP uses the following mechanism for referring to ICP mainnet or any other ICP-based network that may be available in the future, such as testnets or private networks based on the ICP protocol stack ("UTOPIA" private networks). +The network is identified by a prefix of the the Base16 (HEX) encoding of the SHA256 hash of the binary representation of the DER-encoded public key of the network. In case of a *well-known public network*, an 8-character prefix of the key hash can be used as network identifier, for private networks, a 32-character prefix is used to represent the network. Currently, only ICP mainnet qualifies as a well-known public network, in the future public testnets might be eligible also to be well-known public networks. For ICP mainnet, the public key of the network is the NNS public key: +``` +308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100814c0e6ec71fab583b08bd81373c255c3c371b2e84863c98a4f1e08b74235d14fb5d9c0cd546d9685f913a0c0b2cc5341583bf4b4392e467db96d65b9bb4cb717112f8472e0d5a4d14505ffd7484b01291091c5f87b98883463f98091a0baaae +``` +Its 32-character prefix of the HEX-encoded SHA256 hash is +`737ba355e855bd4b61279056603e0550`. +In case of a private ICP deployment, the 32-character prefix of the SHA256 hash of the network's DER-encoded public key is used as network identifier. +The approach of expressing network identifiers through the 32-character prefix of the SHA256 hash of their public key is based on the approach proposed by the CAIP initiative, the shorter prefix for well-known networks or the default is a simplification for the most used network(s). The `contract_address` is the canister smart contract principal identifier of the contract the transaction is to be performed on. This is represented in the standardized format for principals. The address, together with the network identifier, unambiguously determines the token that is to be transacted. -The constant `exec` means that the forthcoming part in the path component specifies which transaction (smart contract method) should be invoked with the information in the URI. In the future, other ICRC standards may emerge that can have a different string with different semantics in the place of this. // FIX: do we want to call this `tx`? +The constant `exec` means that the forthcoming part in the path component specifies which transaction (smart contract method) should be invoked with the information in the URI. In the future, other ICRC standards may emerge that can have a different string with different semantics in the place of this. The `transaction` parameter specifies the canister method to be called on the canister indicated through `contract_address`. This is the string-based name as it appears in the canister's Candid specification. This standard requires support of all of ICP ledger's `transfer`, ICRC-1's `transfer` and ICRC-2's `approve` methods. The method names to handle payment-related use cases currently envisioned are `transfer`, `icrc1_transfer`, and `icrc2_approve`. The `parameters` are the parameters of the method to be called. They SHOULD be given in the order in which they appear in the Candid specification of the method to be called. A subset of the parameters defind in the Candid specification of the method can be present, the remaining non-optional parameters MUST be filled in by the party executing the transaction. -Next, we define the parameters required for realizing the supported transactions of the supported ledger standards: -* `from_subaccount` (ICRC-1, ICRC-2): 32-byte subaccount in Base64 representation +Next, we define the parameters required for realizing the supported transactions of the supported ledger standards and their encoding. For each parameter we indicate the standards for which they are required: +* `from_subaccount` (ICRC-1, ICRC-2): 32-byte subaccount in Base64 representation. * `to` (ICRC-1, ICRC-2): The size-reduced human readable [textual representation](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md) of an ICRC-1 account as specified in this document. * `spender` (ICRC-2): The size-reduced human readable [textual representation](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md) of an ICRC-1 account as specified in this document. -* `spender_subaccount` (ICRC-2): +* `spender_subaccount` (ICRC-2): 32-byte subaccount in Base64 representation. * `from` (ICRC-2): The size-reduced human readable [textual representation](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md) of an ICRC-1 account as specified in this document. -* `amount` (ICP, ICRC-1, ICRC-2): The transaction amount, specified in scientific representation, e.g., 4.042E8 means 804200000 base units of the addressed ledger. -* `expected_allowance` (ICRC-2): The amount to be approved, specified in scientific representation, e.g., 4.042E8 means 804200000 base units of the addressed ledger. -* `expires_at` (ICRC-2): The expiration date of the approval. +* `amount` (ICP, ICRC-1, ICRC-2): The transaction amount, specified as integer or in scientific representation, e.g., 4.042E8 or 804200000. The number refers to the base units of the ledger the request is targeted at. +* `expected_allowance` (ICRC-2): The amount to be approved, , specified as integer or in scientific representation, e.g., 4.042E8 or 804200000. The number refers to the base units of the ledger the request is targeted at. +* `expires_at` (ICRC-2): The expiration date of the approval expressed as integer timestamp. * `fee` (ICP, ICRC-1, ICRC-2): Fee expressed in base units of the addressed ledger, using scientific notation if appropriate. -* `memo` (ICP, ICRC-1, ICRC-2): A hexadecimal string representing the memo. -* `created_at_time` (ICP, ICRC-1, ICRC-2): The creation time of the transaction. +* `memo` (ICP, ICRC-1, ICRC-2): An integer (for ICP transactions) or byte array expressed as hexadecimal string (for ICRC-1 transactions) representing the memo. +* `created_at_time` (ICP, ICRC-1, ICRC-2): The creation time of the transaction expressed as integer timestamp. * ... -Accounts are always represented through the size-reduced textual encoding as specified in [the section below](## Size-reduced-ICRC-1-textual-account-representation). +Accounts are always represented through the size-reduced textual encoding as specified in [Size-Reduced ICRC-1 Textual Account Representationbelow](## Size-reduced-ICRC-1-textual-account-representation) because of the built-in checksum over both the principal and subaccount components of the account and the human readability. // FIX complete the list, define the respective encoding, maybe restructure per method -The `amount` should be provided as a nonnegative integer number. The amount represents the amount of tokens in the base unit used by the ledger, i.e., 4 ICP tokens would amount to 4 * 10^8 = 400000000 base units as managed by the ICP token ledger. It is strongly recommended to use scientific notation for the amount. Decimal representation can be combined with scientific representation, e.g., 4.042E8 ICP means a count of 404200000 base units as managed by the ICP ledger. As only integer numbers are allowed as amount, the exponent MUST be greater than or equal the decimal places of the number in scientific representation. +Subaccounts are 32-byte byte arrays and encoded in hexadecimal representation for ICRC-22. Leading zeroes on the left of a subaccount SHOULD be omitted in the encoding. + +The `amount` should be provided as a nonnegative integer number. The amount represents the amount of tokens in the base unit used by the ledger, i.e., 4 ICP tokens would amount to 4 * 10^8 = 400000000 base units as managed by the ICP token ledger. It is strongly recommended to use scientific notation for the amount. Decimal representation can be combined with scientific representation, e.g., 4.042E8 ICP means a count of 404200000 base units as managed by the ICP ledger. As only integer numbers are allowed as amount, the exponent MUST be greater than or equal to the decimal places of the number in scientific representation. ## Generalization Towards Handling a Larger Class of Method Calls -ICRC-22 does not handle generic calls of smart contract methods on ICP, but does allow for handling further requests that are sufficiently similar to the ones captured explicitly. This comprises requests that have parameters that can be represented as query parameters in a URI in a straightforward way and a canonical encoding exists for the parameters. Canonical encoding means that `text` parameters are represented as a strings, `number` paramters as the string of the number representation, binary `blob` parameters are hexadecimal encoded, records are "inlined", i.e., their fields are encoded sequentially in the query string while encoding the beginning of the record with the record name as key and the string `record` as value, and arrays are "inlined" as well so that every of its entries receives the array's name and the array starts with the array name as key and `array` as value. A large class of method interfaces can be handled with this method of canonical flattening of any nested Candid structure, however, this simple Candid-to-URI mapping may have its limits when parameters get nested in a too complex manner, contain the same names on different levels, or otherwise make it hard to re-assemble the Candid request in unambiguous form given the Candid specification of the method and the query string. Those cases may need a more elaborate approach of handling as outlined in the [Future Work](##Future-Work) section. +ICRC-22 does not handle generic calls of smart contract methods on ICP, but does allow for handling further requests that are sufficiently similar to the ones captured explicitly. This comprises requests that have parameters that can be represented as query parameters in a URI in a straightforward way and a canonical encoding exists for the parameters. -// FIX too vague, work out and explain in more detail; or decide to keep this out of the standard +The generic representation of call parameters is done as follows through a canonical encoding of the method parameters as URI query parameters: +* a `bool` parameter is represented as either `true` or `false` +* a `text` parameter is represented as a string representing the text +* a `number` parameter is encoded as the string representation of the decimal number +* a binary `blob` parameter is hexadecimal encoded +* a record is inlined, i.e., its fields are encoded sequentially in the query string according to the encoding rules; the beginning of the record is encoded with the query parameter `*record=fieldName`, where `fieldName` is the name of the field containing the record; the end of the record is encoded as `-record=fieldName` +* an array is inlined so that every of its entries receives the array field's name (e.g., `fieldName=8` for a field with value `8`); the array's start is indicated with `*array=fieldName` and its termination with `-array=fieldName` +* an enumeration ... -// FIX How exactly can the mapping from the parameters back to the Candid method signature be done? Is it sufficient to enumerate all named parameters, with the type inferable by the recipient using the canister's Candid specification which can be obtained from the canister? +Fields that are mandatory according to the Candid specification may be left out from the encoding in case that the canister needs to fill in those missing values. Note that those values MUST be provided by the canister in order to obtain a valid Candid value to use for the method invocation. -// FIX How to handle optional fields in the Candid specification of the method? As long as the input can be constructed unambiguously, they can be left out, otherwise be included as `key=null`. +All method interfaces can be handled with this method of canonical flattening of nested data types expressible in Candid. However, for complex data structures an approach of mapping the parameters to Candid and encoding the Candid value in the URI may be preferable and part of a future ICRC as outlined in the [Future Work](##Future-Work) section. +this simple Candid-to-URI mapping may have its limits when parameters get nested in a too complex manner, contain the -// FIX: Details need to be worked out to make it possible to call different methods we want to cover in the base standard (at least ICP and ICRC-1 transfer and ICRC-2 approve). The result may not be so far away from a generic standard covering the call of any method of canisters. Specifically: Should types be decomposed into their constituents or the compound values be provided using a specific or their Candid encoding? +The specification of payment-related method calls as defined for ICP and ICRC-1 payments and ICRC-2 approvals are a special case of the generalized encoding introduced in this section, with the following differences: +* the parameters are provided as a flat list, with the enclosing `TransferArgs` record +* ICRC-1 accounts are encoded using the (size-reduced) representation of the textual representation of ICRC-1 accounts ([Dfi22]) as defined in this document + +The generalization introduced in this section is optional for an implementation of ICRC-22 to keep the minimum requirements for an implementation simple and help widespread use of ICRC-22 for payments-related use cases. ## Size-Reduced ICRC-1 Textual Account Representation -// FIX maybe call "compressed" instead of "size-reduced" +The Chain Agnostic Standards Alliance \[Cha24\] has specified account identifiers to be of a maximum length of 128 characters \[Gom22\]. There seems to be no strong reason behind this, but it had been considered sufficient for the foreseeable future by the CAIP working group and is thus a limitation for representing accounts. This limitation cannot be changed at the current time. -The Chain Agnostic Standards Alliance \[Cha24\] has specified account identifiers to be of a maximum length of 128 characters \[Gom22\]. There seems to be no strong reason behind this, but it has been considered sufficient for the foreseeable future by the CAIP working group. This limitation cannot be changed at the current time. +ICRC-1 account identifiers on ICP may exceed this limitation of 128 bytes by a few bytes when using the human-readable representation of ICRC-1 accounts, i.e., the textual encoding of ICRC-1 accounts \[Dfi22\]. For this reason, we define a size-reduced textual ICRC-1 account representation as part of this standard in order to fit the CAIP limits of 128 characters. -ICRC-1 account identifiers on ICP may exceed this limitation by a few bytes when using the human-readable representation of ICRC-1 accounts, i.e., textual encoding of ICRC-1 accounts \[Dfi22\]. For this reason, we define a size-reduced textual ICRC-1 account representation as part of this standard in order to fit the CAIP limits of 128 characters. The size-reduced representation is easily computed by removing all the dashes ("-") between the character groups of the representation, except for the rightmost one (the one preceding the CRC32 checksum) for non-default accounts (non-zero subaccount). For default accounts (all-zero subaccount), all dashes are removed. It is easy to reconstruct the standard textual encoding from a size-reduced textual encoding by adding dash separators from the left of the representation for every 5-character group. +The size-reduced representation is easily computed by removing all the dashes ("-") between the character groups of the representation of the principal and checksum, except for the rightmost dash (the one preceding the CRC32 checksum) for non-default accounts (i.e., accounts with a non-zero subaccount). For default accounts (i.e., accounts with the all-zero subaccount), all dashes are removed. It is easy to reconstruct the standard textual encoding from a size-reduced textual encoding by adding dash separators, starting from the left of the representation, for every 5-character group. It is guaranteed that any ICRC-1 account in size-reduced representation fits into the 128-character limit. The Internet Computer Interface Specification \[Dfi\] specifies the maximum lenght of a textual representation of a principal to be 63 bytes, which includes 10 dashes. The additional CRC32 checksum in Base32 encoding takes another 7 characters, its preceding dash separator one. This makes the maximum length of the size-reduced representation 126 characters: 63 for the maximum-length principal in textual encoding - 10 for separators + 1 for the checksum "-"-separator + 7 for the CRC32 checksum + 1 for the subaccount "."-separator + 64 for the subaccount in hexadecimal representation. @@ -99,41 +118,54 @@ The following is an example of an almost maximum-length textual representation t ``` k2t6j-2nvnp-4zjm3-25dtz-6xhaa-c7boj-5gayf-oj3xs-i43lp-teztq-6ae-dfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 ``` -The following is the above example in size-reduced form and fits within the 128-character limit with its length of 124 characters. +The following is the above example in size-reduced form and fits within the 128-character limit with its length of 125 characters. Note that the final dash in the first part (the part left of the `.`) is retained as it separates the principal from the checksum of the account representation. +``` +k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6ae-dfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 +``` +This size-reduced representation can easily be transformed back to the original textual representation as defined in \[Dfi22\] by adding dashes every group of 5 characters from the left. Note that the rightmost character group left of the checksum can have less than 5 characters. ``` -k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6aedfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 +k2t6j-2nvnp-4zjm3-25dtz-6xhaa-c7boj-5gayf-oj3xs-i43lp-teztq-6ae-dfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 ``` -// FIX use maximum-length textual account representation as example; the current one is close +## Data Compression + +Depending on the transport mechanism used, data compression of the URI resulting from the encoding MAY be used to reduce the size of the message to be sent over the transport. This is particularly important for QR codes used as transport mechanism as they have limited bandwidth and larger QR codes are harder to scan. + +Compression of URIs for transfer in QR codes, if used, MUST be performed using the gzip algorithm. This algorithm is reasonably simple and native implementations are available in many languages and have a small code size, thus it is easy to implement this feature in both tools and canister smart contracts without too much bloat. Future standards may add additional compression algorithms with better compression ratios such as zstd or Brotli. ## Examples The following examples show the application of ICRC-22 for ICP transfer, ICRC-1 transfer, and ICRC-2 approval use cases. -### ICRC-1 Token Transfer - -// FIX replace 1234abcd90 with a prefix of the SHA256 hash of the mainnet NNS public key in binary +### ICP Token Transfer -// FIX fill in subaccounts etc. with accounts in the proper format +``` +icp::ryjl3-tyaaa-aaaaa-aaaba-cai/exec/transfer?from_subaccount=&to=&amount=4.042E8&memo= +``` -The following is a payment request for 4.042 ckBTC on the ckBTC ledger. The wallet reading and executing this request would insert the `created_at_time` field based on the current time. ``` -icp:1234abcd90:mxzaz-hqaaa-aaaar-qaada-cai/exec/icrc1_transfer?from_subaccount=10&to=k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6aedfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20&amount=4.042E8&memo=receipt%2012345678 +icp:737ba355e855bd4b61279056603e0550:ryjl3-tyaaa-aaaaa-aaaba-cai/exec/transfer?from_subaccount=0&to=61342bfbd397f0c36c5da1f9661b802db60a20e973012c99903fc8637b5bf32b&amount=4.042E8&memo= ``` -### ICP Token Transfer +Note that `ryjl3-tyaaa-aaaaa-aaaba-cai` is the principal of the ICP ledger. + +### ICRC-1 Token Transfer + +// FIX replace 1234abcd90 with a prefix of the SHA256 hash of the mainnet NNS public key in binary + +// FIX fill in subaccounts etc. with accounts in the proper format -// FIX +The following is a payment request for `0.04042` ckBTC on the ckBTC ledger from subaccount `ef` of the caller to the account `k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6aedfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20` with memo `1b69b4ba630f34e15fd40af`. The wallet reading and executing this request must insert the `created_at_time` field based on the current time to create a valid ledger transaction. For the representation of the amount, note that 1 ckBTC equals `1E8` (100 million) base units of the ckBTC ledger. ``` -icp:1234abcd90:/exec/transfer?from_subaccount=&to=&amount=4.042E8&fee=&memo=&created_at_time= +icp:737ba355e855bd4b61279056603e0550:mxzaz-hqaaa-aaaar-qaada-cai/exec/icrc1_transfer?from_subaccount=ef&to=k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6aedfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20&amount=4.042E6&memo=1b69b4ba630f34e15fd40af ``` ### ICRC-2 Approval -An ICRC-2 approval can be made on any ICRC-2-compliant ledger, e.g., the ICP ledger or any ICRC-1-compliant token ledger. +An ICRC-2 approval can be made on any ICRC-2-compliant ledger, e.g., the ICP ledger or any ICRC-1-compliant token ledger like the ckBTC legder. The following example shows an ICRC-2 approval of `0.04042` ckBTC to account `h2oto-yhzgh-fdd7o-ucdym-dnwul-ihnjb-67dlq-ed3x2-mxzf2-des4t-xqe`. The `fee` and `created_at_time` parameters need to be provided by the wallet. ``` -icp:1234abcd90:/exec/icrc2_approve?from_subaccount=&spender=&amount=&expected_allowance=&... +icp:737ba355e855bd4b61279056603e0550:mxzaz-hqaaa-aaaar-qaada-cai/exec/icrc2_approve?from_subaccount=3&spender=h2otoyhzghfdd7oucdymdnwulihnjb67dlqed3x2mxzf2des4txqe&amount=4.042E6&expected_allowance=0&... ``` ## Future Work @@ -144,12 +176,12 @@ For the Internet Computer, embedding Candid-encoded parameters are the natural w ## References -[Nag17] Daniel A. Nagy, URL Format for Transaction Requests. Ethereum EIP-681, https://github.com/ethereum/EIPs/blob/master/EIPS/eip-681.md, 2017 -[Bit1] Unified payment requests. https://bitcoin.design/guide/how-it-works/payment-request-formats/#unified-payment-requests -[Bit2] Unified QRs for Bitcoin. https://bitcoinqr.dev/ -[Dfi22] DFINITY, ICRC-1 Token Standard -- Textual encoding of ICRC-1 accounts. 2024, https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md, 2022 -[WLGH19] Simon Warta, ligi , Pedro Gomes, Antoine Herzog, Blockchain ID Specification, https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md, 2019 -[Cha24] Chain Agnostic Standards Alliance. https://github.com/ChainAgnostic -[Gom22] Pedro Gomes, Account ID Specification. CAIP-10, https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md, 2022 -[Dfi] DFINITY Foundation, The Internet Computer Interface Specification: Principals. https://internetcomputer.org/docs/current/references/ic-interface-spec#principal -[BFM05] T. Berners-Lee, R. Fielding, L. Masinter: Uniform Resource Identifier (URI): Generic Syntax. 2005, https://datatracker.ietf.org/doc/html/rfc3986 +* [Nag17] Daniel A. Nagy, URL Format for Transaction Requests. Ethereum EIP-681, https://github.com/ethereum/EIPs/blob/master/EIPS/eip-681.md, 2017 +* [Bit1] Unified payment requests. https://bitcoin.design/guide/how-it-works/payment-request-formats/#unified-payment-requests +* [Bit2] Unified QRs for Bitcoin. https://bitcoinqr.dev/ +* [Dfi22] DFINITY, ICRC-1 Token Standard -- Textual encoding of ICRC-1 accounts. 2024, https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md, 2022 +* [WLGH19] Simon Warta, ligi , Pedro Gomes, Antoine Herzog, Blockchain ID Specification, https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md, 2019 +* [Cha24] Chain Agnostic Standards Alliance. https://github.com/ChainAgnostic +* [Gom22] Pedro Gomes, Account ID Specification. CAIP-10, https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md, 2022 +* [Dfi] DFINITY Foundation, The Internet Computer Interface Specification: Principals. https://internetcomputer.org/docs/current/references/ic-interface-spec#principal +* [BFM05] T. Berners-Lee, R. Fielding, L. Masinter: Uniform Resource Identifier (URI): Generic Syntax. 2005, https://datatracker.ietf.org/doc/html/rfc3986 From 704af536cb5dea6814ba719e4a15810cff011c27 Mon Sep 17 00:00:00 2001 From: "Dieter M. Sommer" Date: Tue, 15 Oct 2024 17:37:39 +0200 Subject: [PATCH 08/13] Update --- ICRCs/ICRC-22/ICRC-22.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/ICRCs/ICRC-22/ICRC-22.md b/ICRCs/ICRC-22/ICRC-22.md index 42a1af3..41b86b2 100644 --- a/ICRCs/ICRC-22/ICRC-22.md +++ b/ICRCs/ICRC-22/ICRC-22.md @@ -36,9 +36,8 @@ value = ... ; FIX Candid encoded value syntax // FIX: We should default the network to ICP's mainnet current value when omitted The `network` defaults to the identifier `737ba355e855bd4b61279056603e0550` for ICP mainnet. When the network identifier is left out, the prefix of a URI would thus be `icp::/exec/?` for the current ICP mainnet. The interpretation of what "current mainnet" is is left to the client. It should refer to the currently active key for mainnet, which can only change in the event of an NNS recovery after a large desaster event that destroys the NNS private threshold key, and thus is considered very stable. -// FIX: Should we keep it open to other methods and supported ICRCs as long as their API can be canonically expressed using a sequential list of parameters encoded as query parameters - -An encoding specifier in the beginning of query string defines the kind of encoding used for the parameters. ICRC-22 defines only the encoding `plain`. We envision a future ICRC that uses Candid for encoding any list of parameters and uses the `candid` constant. If omitted, the encoding defaults to the `plain` encoding. +An encoding specifier as initial element of query string defines the kind of encoding used for the parameters. ICRC-22 defines only the encoding `plain`. We envision a future ICRC that uses Candid for encoding any list of parameters, indicated through the `candid` constant. If omitted, the encoding defaults to the `plain` encoding. +// Do we need to distinguish between payment and generic method defined here? The grammar productions not further specified above can be looked up in the syntax specification for URIs in RFC 3986 \[BFM05\]. Note that the production `transaction` above is part of the path and `parameters` part of the query string and the according constraints of RFC 3986 apply. // FIX @@ -89,20 +88,20 @@ The generic representation of call parameters is done as follows through a canon * a `text` parameter is represented as a string representing the text * a `number` parameter is encoded as the string representation of the decimal number * a binary `blob` parameter is hexadecimal encoded -* a record is inlined, i.e., its fields are encoded sequentially in the query string according to the encoding rules; the beginning of the record is encoded with the query parameter `*record=fieldName`, where `fieldName` is the name of the field containing the record; the end of the record is encoded as `-record=fieldName` -* an array is inlined so that every of its entries receives the array field's name (e.g., `fieldName=8` for a field with value `8`); the array's start is indicated with `*array=fieldName` and its termination with `-array=fieldName` -* an enumeration ... +* a tuple is encoded by having an opening element `*tuple`, followed by the tuple values, followed by a closing element `-tuple` +* a record is encoding is started with the query parameter `*record=fieldName`, where `fieldName` is the name of the field containing the record; this is followed by a sequence of encodings of its fields according to the encoding rules; the termination of the record is encoded with `-record=fieldName` +* an array is started with `*array=fieldName`, followed by an encoding of its entries the names of which are their index using 0-based indexing (e.g., `0=8` for the 0-th field with value `8`), followed by a termination `-array=fieldName` +* an enumeration is encoded by a start element `*enum=fieldName` and a variant element encoding the variant of the enumeration; for variants that have an associated value, the value is encoded after the variant using the encoding rules Fields that are mandatory according to the Candid specification may be left out from the encoding in case that the canister needs to fill in those missing values. Note that those values MUST be provided by the canister in order to obtain a valid Candid value to use for the method invocation. -All method interfaces can be handled with this method of canonical flattening of nested data types expressible in Candid. However, for complex data structures an approach of mapping the parameters to Candid and encoding the Candid value in the URI may be preferable and part of a future ICRC as outlined in the [Future Work](##Future-Work) section. -this simple Candid-to-URI mapping may have its limits when parameters get nested in a too complex manner, contain the +A large class of method interfaces — every method the encoding of which can be uniquely decoded back to Candid — can be handled with this method of canonical flattening of nested data types expressible in Candid. However, for complex data structures an approach of mapping the parameters to Candid and encoding the Candid value in the URI may be preferable and part of a future ICRC as outlined in the [Future Work](##Future-Work) section. -The specification of payment-related method calls as defined for ICP and ICRC-1 payments and ICRC-2 approvals are a special case of the generalized encoding introduced in this section, with the following differences: -* the parameters are provided as a flat list, with the enclosing `TransferArgs` record -* ICRC-1 accounts are encoded using the (size-reduced) representation of the textual representation of ICRC-1 accounts ([Dfi22]) as defined in this document +The specification of payment-related transaction requests as defined for ICP and ICRC-1 payments and ICRC-2 approvals is a special case of the generalized encoding introduced in this section, with the following differences: +* the parameters are provided as a flat list, with the enclosing `TransferArgs` record being made explicit; the rationale behind this is that payment-related use cases are the primary target of this specification; +* ICRC-1 accounts are encoded using the size-reduced textual representation of ICRC-1 accounts ([Dfi22]) as defined in this document. -The generalization introduced in this section is optional for an implementation of ICRC-22 to keep the minimum requirements for an implementation simple and help widespread use of ICRC-22 for payments-related use cases. +The generalization introduced in this section is optional for an implementation of ICRC-22 to keep the minimum requirements for an implementation simple and help widespread adoption of ICRC-22 for payment-related use cases. ## Size-Reduced ICRC-1 Textual Account Representation From f600b3565e843466263623d1fd4fcb99a7764f46 Mon Sep 17 00:00:00 2001 From: "Dieter M. Sommer" Date: Wed, 16 Oct 2024 08:31:49 +0200 Subject: [PATCH 09/13] Update --- ICRCs/ICRC-22/ICRC-22.md | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/ICRCs/ICRC-22/ICRC-22.md b/ICRCs/ICRC-22/ICRC-22.md index 41b86b2..e5d920d 100644 --- a/ICRCs/ICRC-22/ICRC-22.md +++ b/ICRCs/ICRC-22/ICRC-22.md @@ -6,17 +6,17 @@ ## Introduction -ICRC-22 defines a standard way of representing transaction requests, e.g., for payments or approvals of token transactions, on ICP as URIs. A variety of transport mechanisms can be used to communicate URIs to their recipients, e.g., they can be embedded in QR codes, hyperlinks on Web pages, emails, or chat communication, to obtain robust signalling between loosely-coupled applications. Such pre-defined or on-the-fly generated payment requests can be immediately used by the user's wallet application, where relevant parameters are provided through the URI and further parameters may be filled in by the wallet application or the user themselves. This makes such URI encoding an indispensible tool in a larger blockchain ecosystem to allow for convenient communication of payment-related information over many different communication channels. ICRC-22 clearly focusses on payment-related transactions, but supports a wider range of transactions to be expressed as URIs. +ICRC-22 defines a standard way of representing transaction requests for payments or approvals of token transactions on ICP as URIs. A variety of transport mechanisms can be used to communicate URIs to their recipients, e.g., they can be embedded in QR codes, hyperlinks on Web pages, emails, or chat communication to obtain robust signalling between loosely-coupled applications. Such either pre-defined or on-the-fly generated payment requests can be immediately used by the user's wallet application, where relevant parameters are provided through the URI and further parameters may be filled in by the wallet application or the user themselves. This makes such URI encoding an indispensible tool in a larger blockchain ecosystem to allow for convenient communication of payment- or approval-related information over a variety of different communication channels. Generic smart contract method calls are left to a future ICRC standard. Relevant prior work in other blockchain ecosystems comprises the standards on payment URLs for Bitcoin \[Bit1, Bit2\] as well as Ethereum's [ERC-681 \[Nag17\]](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-681.md) for expressing payment requests and, more generally, transactions using EVM ABI encoding, for the Ethereum blockchain. The specification put forth in ICRC-22 is an adaptation of the ideas in the above listed references to establish a standard way of sharing URIs that represent payment and other requests on the Internet Computer. -## Specification for Payments +## Specification -The below specification defines the syntax and (non-formal) semantics for an ICRC-22 payment request and extension to further requests. The specification takes the approaches of \[Bit1, Bit2, Nag17, WLGH19\] into consideration. Particularly, an authority-less URI format has been chosen following this prior art in the domain. +The below specification defines the syntax and (non-formal) semantics for ICRC-22 token transfer and approval requests. The specification takes the approaches of \[Bit1, Bit2, Nag17, WLGH19\] into consideration. Particularly, an authority-less URI format has been chosen following this prior art in the domain. Next, we show the structure of a request URI with the concrete parameters represented through `<>`-placeholders. Note that the URI does not contain an authority, but encodes the `network` and `contract_address` as part of the URI path, directly following the URI scheme. ``` -icp:737ba355e855bd4b61279056603e0550:/exec/icrc1_transfer?enc=plain&from_subaccount=&to=&amount=&memo= +icp:737ba355e855bd4b61279056603e0550:icrc22:/icrc1_transfer?to=&amount=&memo= ``` // FIX syntax details @@ -33,15 +33,11 @@ key = ... ; FIX: Candid parameter name syntax value = ... ; FIX Candid encoded value syntax ``` -// FIX: We should default the network to ICP's mainnet current value when omitted -The `network` defaults to the identifier `737ba355e855bd4b61279056603e0550` for ICP mainnet. When the network identifier is left out, the prefix of a URI would thus be `icp::/exec/?` for the current ICP mainnet. The interpretation of what "current mainnet" is is left to the client. It should refer to the currently active key for mainnet, which can only change in the event of an NNS recovery after a large desaster event that destroys the NNS private threshold key, and thus is considered very stable. - -An encoding specifier as initial element of query string defines the kind of encoding used for the parameters. ICRC-22 defines only the encoding `plain`. We envision a future ICRC that uses Candid for encoding any list of parameters, indicated through the `candid` constant. If omitted, the encoding defaults to the `plain` encoding. -// Do we need to distinguish between payment and generic method defined here? - The grammar productions not further specified above can be looked up in the syntax specification for URIs in RFC 3986 \[BFM05\]. Note that the production `transaction` above is part of the path and `parameters` part of the query string and the according constraints of RFC 3986 apply. // FIX -The `network_identifier` uniquely identifies the ICP network to make the transaction on. Following the ideas of the Chain Agnostic Standards Alliance \[Cha24\] of having a standardized way of referring to any blockchain network, ICP uses the following mechanism for referring to ICP mainnet or any other ICP-based network that may be available in the future, such as testnets or private networks based on the ICP protocol stack ("UTOPIA" private networks). +The `network` defaults to the identifier `737ba355e855bd4b61279056603e0550` for ICP mainnet following the approach defined by CAIP for specifying blockchain networks. When the network identifier is left out, the network defaults to the current ICP mainnet. In this default case, the prefix of a URI would thus be `icp::icrc22:?`. The interpretation of what "current mainnet" is is left to the client. Semantically, it should refer to the currently active public key for mainnet,. This key can only change in the event of an NNS recovery after a large desaster event that destroys the NNS private threshold key, and thus the key is considered very stable and unlikely to ever change. + +The `network` uniquely identifies the ICP network to make the transaction on. Following the ideas of the Chain Agnostic Standards Alliance \[Cha24\] of having a standardized way of referring to any blockchain network, ICP uses the following mechanism for referring to ICP mainnet or any other ICP-based network that may be available in the future, such as testnets or private networks based on the ICP protocol stack ("UTOPIA" private networks). The network is identified by a prefix of the the Base16 (HEX) encoding of the SHA256 hash of the binary representation of the DER-encoded public key of the network. In case of a *well-known public network*, an 8-character prefix of the key hash can be used as network identifier, for private networks, a 32-character prefix is used to represent the network. Currently, only ICP mainnet qualifies as a well-known public network, in the future public testnets might be eligible also to be well-known public networks. For ICP mainnet, the public key of the network is the NNS public key: ``` 308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100814c0e6ec71fab583b08bd81373c255c3c371b2e84863c98a4f1e08b74235d14fb5d9c0cd546d9685f913a0c0b2cc5341583bf4b4392e467db96d65b9bb4cb717112f8472e0d5a4d14505ffd7484b01291091c5f87b98883463f98091a0baaae From 1714b97b98029425286a86a95ef482f8324bca10 Mon Sep 17 00:00:00 2001 From: "Dieter M. Sommer" Date: Wed, 16 Oct 2024 09:45:31 +0200 Subject: [PATCH 10/13] Major revision --- ICRCs/ICRC-22/ICRC-22.md | 76 ++++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 26 deletions(-) diff --git a/ICRCs/ICRC-22/ICRC-22.md b/ICRCs/ICRC-22/ICRC-22.md index e5d920d..c858025 100644 --- a/ICRCs/ICRC-22/ICRC-22.md +++ b/ICRCs/ICRC-22/ICRC-22.md @@ -6,7 +6,7 @@ ## Introduction -ICRC-22 defines a standard way of representing transaction requests for payments or approvals of token transactions on ICP as URIs. A variety of transport mechanisms can be used to communicate URIs to their recipients, e.g., they can be embedded in QR codes, hyperlinks on Web pages, emails, or chat communication to obtain robust signalling between loosely-coupled applications. Such either pre-defined or on-the-fly generated payment requests can be immediately used by the user's wallet application, where relevant parameters are provided through the URI and further parameters may be filled in by the wallet application or the user themselves. This makes such URI encoding an indispensible tool in a larger blockchain ecosystem to allow for convenient communication of payment- or approval-related information over a variety of different communication channels. Generic smart contract method calls are left to a future ICRC standard. +ICRC-22 defines a standard way of representing transaction requests for payments or approvals of token transactions on ICP as URIs. A variety of transport mechanisms can be used to communicate URIs to their recipients, e.g., they can be embedded in QR codes, hyperlinks on Web pages, emails, or chat communication to obtain robust signalling between loosely-coupled applications. Such either pre-defined or on-the-fly generated payment requests can be immediately used by the user's wallet application, where relevant arguments are provided through the URI and further arguments may be filled in by the wallet application or the user themselves. This makes such URI encoding an indispensible tool in a larger blockchain ecosystem to allow for convenient communication of payment- or approval-related information over a variety of different communication channels. Generic smart contract method calls are left to a future ICRC standard. Relevant prior work in other blockchain ecosystems comprises the standards on payment URLs for Bitcoin \[Bit1, Bit2\] as well as Ethereum's [ERC-681 \[Nag17\]](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-681.md) for expressing payment requests and, more generally, transactions using EVM ABI encoding, for the Ethereum blockchain. The specification put forth in ICRC-22 is an adaptation of the ideas in the above listed references to establish a standard way of sharing URIs that represent payment and other requests on the Internet Computer. @@ -14,7 +14,7 @@ Relevant prior work in other blockchain ecosystems comprises the standards on pa The below specification defines the syntax and (non-formal) semantics for ICRC-22 token transfer and approval requests. The specification takes the approaches of \[Bit1, Bit2, Nag17, WLGH19\] into consideration. Particularly, an authority-less URI format has been chosen following this prior art in the domain. -Next, we show the structure of a request URI with the concrete parameters represented through `<>`-placeholders. Note that the URI does not contain an authority, but encodes the `network` and `contract_address` as part of the URI path, directly following the URI scheme. +Next, we show the structure of an ICRC1 transfer request URI with the concrete arguments represented through `<>`-placeholders. Note that the URI does not contain an authority, but encodes the `network`, the `icrc22` standard specifier, and `canister_principal` as part of the URI path, directly following the URI scheme. ``` icp:737ba355e855bd4b61279056603e0550:icrc22:/icrc1_transfer?to=&amount=&memo= ``` @@ -25,7 +25,7 @@ Next, we present the ABNF syntax for ICRC-22 URIs. request = protocol ":" network ":" contract_address "/" "exec" transaction [ "?" parameters ] protocol = "icp" ; always "icp" referring to the current version of the Internet Computer Protocol network = (1..10)[0..9a..fA..F] / ; specifies the network through a prefix of its public key hash -contract_address = ICP principal FIX: canister principal ABNF ; canister address to which to make the call +canister_principal = ICP principal FIX: canister principal ABNF ; canister address to which to make the call transaction = ... ; canister method to call FIX: Candid method syntax parameters = parameter [ "&" parameter ] parameter = key "=" value @@ -55,31 +55,61 @@ The `transaction` parameter specifies the canister method to be called on the ca The `parameters` are the parameters of the method to be called. They SHOULD be given in the order in which they appear in the Candid specification of the method to be called. A subset of the parameters defind in the Candid specification of the method can be present, the remaining non-optional parameters MUST be filled in by the party executing the transaction. -Next, we define the parameters required for realizing the supported transactions of the supported ledger standards and their encoding. For each parameter we indicate the standards for which they are required: -* `from_subaccount` (ICRC-1, ICRC-2): 32-byte subaccount in Base64 representation. -* `to` (ICRC-1, ICRC-2): The size-reduced human readable [textual representation](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md) of an ICRC-1 account as specified in this document. -* `spender` (ICRC-2): The size-reduced human readable [textual representation](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md) of an ICRC-1 account as specified in this document. -* `spender_subaccount` (ICRC-2): 32-byte subaccount in Base64 representation. +### Supported Method Invocations + +Next, we define the parameters allowed in the various smart contract methods this standard supports. A subset of the parameters can be specified in the URI, meaning that the remaining paramters need to be filled in by the client (e.g., wallet) in case they are mandatory and can be filled in in case they are optional in the method's specification. Note also that the initiator of the transaction may be specified through the `from` or just the `from_subaccount`. If omitted, they need to be provided by the client application. We give the following example use case scenarios: +* A payment use case where a shop provides a payment link with `to`, `amount`, and `memo` and the wallet provides the source account through the caller principal and filling in the `from_subaccount` according to user's preferences and sets the `fee` and `created_at_time`. A simple shop use case can also comprise a similar set up with the `amount` being provided by the user and being communicated to the user by the salesperson. This may be a proper setup for a market where the URI is provided as a printed QR code. +* A token transfer use case triggered by a dapp where the dapp knows the principal and subaccount of the transferring user. In this case, all of `from`, `to`, `amount`,`fee`, and `memo` may be provided in the request and the client application only needs to fill in `created_at_time`. The client application extracts the `from_subaccount` from `from` and the caller principal of the method invocation must match the `principal` of the `from` parameter. + +The arguments `from` and `from_subaccount` are always mutually exclusive and both optional. + +ICRC-22 focuses on the transmission of the information and does not standardize any application-level flows. And discussions of such are meant as illustrating examples and are not normative. + +// FIX text for arguments + +#### ICP's transfer + +* `from`: The initiator of the transfer, i.e., the spender. Encoded using the [size-reduced human readable textual representation](## Size-reduced-ICRC-1-textual-account-representation) of an ICRC-1 account as specified in this document. Used when the spender is specified by the URI creator already. Must match the recipient of the URI. +* `from_subaccount` The spender subaccount expressed as 32-byte subaccount in base64 representation. Subaccounts are 32-byte byte arrays and encoded in hexadecimal representation for ICRC-22. Leading zeroes on the left of a subaccount SHOULD be omitted in the encoding. Used when the subaccount from which the funds should be transferred is known by the creator of the URI. Must match the subaccount intended by the recipient. +* `to`: The [size-reduced human readable textual representation](## Size-reduced-ICRC-1-textual-account-representation) of an ICRC-1 account as specified in this document. Specifies the recipient of the token transfer. +* `amount` The transaction amount, specified as decimal integer or in scientific representation, e.g., 4.042E8 and 804200000 express the same integer. The number refers to the number of tokens in the base units of the ledger the request is targeted at. +* `fee`: The fee expressed in base units of the addressed ledger, using scientific notation if appropriate. +* `memo`: An integer representing the memo. +* `created_at_time`: The creation time of the transaction expressed as integer timestamp. + +#### ICRC1 icrc1_transfer + +* `from` (ICRC-2): The size-reduced human readable [textual representation](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md) of an ICRC-1 account as specified in this document. +* `from_subaccount` (ICP, ICRC-1, ICRC-2): 32-byte subaccount in Base64 representation. +* `to` (ICP, ICRC-1, ICRC-2): The size-reduced human readable [textual representation](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md) of an ICRC-1 account as specified in this document. +* `amount` (ICP, ICRC-1, ICRC-2): The transaction amount, specified as integer or in scientific representation, e.g., 4.042E8 or 804200000. The number refers to the base units of the ledger the request is targeted at. +* `fee` (ICP, ICRC-1, ICRC-2): Fee expressed in base units of the addressed ledger, using scientific notation if appropriate. +* `memo` A byte array expressed as hexadecimal string representing the memo. +* `created_at_time` (ICP, ICRC-1, ICRC-2): The creation time of the transaction expressed as integer timestamp. + +#### ICRC2 icrc2_approve + * `from` (ICRC-2): The size-reduced human readable [textual representation](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md) of an ICRC-1 account as specified in this document. +* `from_subaccount` (ICP, ICRC-1, ICRC-2): 32-byte subaccount in Base64 representation. +* `spender` (ICRC-2): The size-reduced human readable [textual representation](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md) of an ICRC-1 account as specified in this document. * `amount` (ICP, ICRC-1, ICRC-2): The transaction amount, specified as integer or in scientific representation, e.g., 4.042E8 or 804200000. The number refers to the base units of the ledger the request is targeted at. * `expected_allowance` (ICRC-2): The amount to be approved, , specified as integer or in scientific representation, e.g., 4.042E8 or 804200000. The number refers to the base units of the ledger the request is targeted at. * `expires_at` (ICRC-2): The expiration date of the approval expressed as integer timestamp. * `fee` (ICP, ICRC-1, ICRC-2): Fee expressed in base units of the addressed ledger, using scientific notation if appropriate. -* `memo` (ICP, ICRC-1, ICRC-2): An integer (for ICP transactions) or byte array expressed as hexadecimal string (for ICRC-1 transactions) representing the memo. +* `memo` A byte array expressed as hexadecimal string representing the memo. * `created_at_time` (ICP, ICRC-1, ICRC-2): The creation time of the transaction expressed as integer timestamp. -* ... -Accounts are always represented through the size-reduced textual encoding as specified in [Size-Reduced ICRC-1 Textual Account Representationbelow](## Size-reduced-ICRC-1-textual-account-representation) because of the built-in checksum over both the principal and subaccount components of the account and the human readability. -// FIX complete the list, define the respective encoding, maybe restructure per method -Subaccounts are 32-byte byte arrays and encoded in hexadecimal representation for ICRC-22. Leading zeroes on the left of a subaccount SHOULD be omitted in the encoding. +Accounts are always represented through the size-reduced textual encoding as specified in [Size-Reduced ICRC-1 Textual Account Representationbelow](## Size-reduced-ICRC-1-textual-account-representation) because of the human readability and the built-in checksum over both the principal and subaccount components of the account. The `amount` should be provided as a nonnegative integer number. The amount represents the amount of tokens in the base unit used by the ledger, i.e., 4 ICP tokens would amount to 4 * 10^8 = 400000000 base units as managed by the ICP token ledger. It is strongly recommended to use scientific notation for the amount. Decimal representation can be combined with scientific representation, e.g., 4.042E8 ICP means a count of 404200000 base units as managed by the ICP ledger. As only integer numbers are allowed as amount, the exponent MUST be greater than or equal to the decimal places of the number in scientific representation. ## Generalization Towards Handling a Larger Class of Method Calls -ICRC-22 does not handle generic calls of smart contract methods on ICP, but does allow for handling further requests that are sufficiently similar to the ones captured explicitly. This comprises requests that have parameters that can be represented as query parameters in a URI in a straightforward way and a canonical encoding exists for the parameters. +// FIX remove + +ICRC-22 does not handle generic calls of smart contract methods on ICP, but does allow for handling further requests that are sufficiently similar to the ones captured explicitly. This comprises requests that have arguments that can be represented as query parameters in a URI in a straightforward way and a canonical encoding exists for the argument. -The generic representation of call parameters is done as follows through a canonical encoding of the method parameters as URI query parameters: +The generic representation of call arguments is done as follows through a canonical encoding of the method parameters as URI query parameters: * a `bool` parameter is represented as either `true` or `false` * a `text` parameter is represented as a string representing the text * a `number` parameter is encoded as the string representation of the decimal number @@ -146,28 +176,22 @@ Note that `ryjl3-tyaaa-aaaaa-aaaba-cai` is the principal of the ICP ledger. ### ICRC-1 Token Transfer -// FIX replace 1234abcd90 with a prefix of the SHA256 hash of the mainnet NNS public key in binary - -// FIX fill in subaccounts etc. with accounts in the proper format - -The following is a payment request for `0.04042` ckBTC on the ckBTC ledger from subaccount `ef` of the caller to the account `k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6aedfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20` with memo `1b69b4ba630f34e15fd40af`. The wallet reading and executing this request must insert the `created_at_time` field based on the current time to create a valid ledger transaction. For the representation of the amount, note that 1 ckBTC equals `1E8` (100 million) base units of the ckBTC ledger. +The following is a payment request for `0.04042` ckBTC on the ckBTC ledger of the caller to the account `k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6aedfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20` with memo `1b69b4ba630f34e15fd40af`. The wallet reading and executing this request must insert the `created_at_time` field based on the current time to create a valid ledger transaction. For the representation of the amount, note that 1 ckBTC equals `1E8` (100 million) base units of the ckBTC ledger. ``` -icp:737ba355e855bd4b61279056603e0550:mxzaz-hqaaa-aaaar-qaada-cai/exec/icrc1_transfer?from_subaccount=ef&to=k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6aedfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20&amount=4.042E6&memo=1b69b4ba630f34e15fd40af +icp:737ba355e855bd4b61279056603e0550:icrc22:mxzaz-hqaaa-aaaar-qaada-cai/icrc1_transfer?to=k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6ae-dfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20&amount=4.042E6&memo=1b69b4ba630f34e15fd40af ``` ### ICRC-2 Approval -An ICRC-2 approval can be made on any ICRC-2-compliant ledger, e.g., the ICP ledger or any ICRC-1-compliant token ledger like the ckBTC legder. The following example shows an ICRC-2 approval of `0.04042` ckBTC to account `h2oto-yhzgh-fdd7o-ucdym-dnwul-ihnjb-67dlq-ed3x2-mxzf2-des4t-xqe`. The `fee` and `created_at_time` parameters need to be provided by the wallet. +An ICRC-2 approval can be made on any ICRC-2-compliant ledger, e.g., the ICP ledger or any ICRC-1-compliant token ledger like the ckBTC legder. The following example shows an ICRC-2 approval of `0.04042` ckBTC to account `h2oto-yhzgh-fdd7o-ucdym-dnwul-ihnjb-67dlq-ed3x2-mxzf2-des4t-xqe`. The `fee` and `created_at_time` arguments need to be provided by the wallet. ``` -icp:737ba355e855bd4b61279056603e0550:mxzaz-hqaaa-aaaar-qaada-cai/exec/icrc2_approve?from_subaccount=3&spender=h2otoyhzghfdd7oucdymdnwulihnjb67dlqed3x2mxzf2des4txqe&amount=4.042E6&expected_allowance=0&... +icp:737ba355e855bd4b61279056603e0550:icrc22:mxzaz-hqaaa-aaaar-qaada-cai/exec/icrc2_approve?spender=h2otoyhzghfdd7oucdymdnwulihnjb67dlqed3x2mxzf2des4txqe&amount=4.042E6&memo=1b69b4ba630f34e15fd40ab ``` ## Future Work -The current specification is focussed on expressing payment-related requests, concretely payments and approvals related to ICP, ICRC-1, and ICRC-2 standards. The idea can be generalized, like in ERC-681 \[Nag17\] to expressing any smart contract invocation. ERC-681 is handling this generalization with embedded EVM ABI encoded parameters in the URI. - -For the Internet Computer, embedding Candid-encoded parameters are the natural way to accomplish this. The remaining issue is that mandatory parameters such as timestamps may need to be filled in by the client, but must be encoded already in the Candid structure to result in valid Candid. This can be handled by encoding a default value, e.g., 0 for a number type, in such cases and providing additional metadata that such element must be replaced by the client. Due to those complexities that still need to be worked out, we do not handle this extension in ICRC-22, but defer it to future work when to be done when use cases demand such functionality. +The current specification is focussed on expressing token transfer and approval requests for the ICP, ICRC-1, and ICRC-2 token standards. The idea can be generalized, similar to ERC-681 \[Nag17\], to express any canister smart contract method invocation. ERC-681 is handling this generalization with embedded EVM ABI encoded arguments in the URI. For the Internet Computer, embedding Candid- or otherwise encoded arguments into the request is the natural way to accomplish this. The remaining issue is that mandatory parameters such as timestamps may need to be filled in by the client, but must be encoded already in the Candid structure to result in valid Candid. This can be handled by encoding a default value, e.g., 0 for a number type, in such cases and providing additional metadata that such element must be replaced by the client. Due to those complexities that still need to be worked out, we do not handle this extension in ICRC-22, but defer it to future work when to be done when use cases demand such functionality. ## References From 2dda8b02ba2b994c757eb6af90f9a7656d4306ef Mon Sep 17 00:00:00 2001 From: "Dieter M. Sommer" Date: Wed, 16 Oct 2024 10:15:25 +0200 Subject: [PATCH 11/13] Update --- ICRCs/ICRC-22/ICRC-22.md | 42 +++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/ICRCs/ICRC-22/ICRC-22.md b/ICRCs/ICRC-22/ICRC-22.md index c858025..2dedc45 100644 --- a/ICRCs/ICRC-22/ICRC-22.md +++ b/ICRCs/ICRC-22/ICRC-22.md @@ -69,40 +69,42 @@ ICRC-22 focuses on the transmission of the information and does not standardize #### ICP's transfer -* `from`: The initiator of the transfer, i.e., the spender. Encoded using the [size-reduced human readable textual representation](## Size-reduced-ICRC-1-textual-account-representation) of an ICRC-1 account as specified in this document. Used when the spender is specified by the URI creator already. Must match the recipient of the URI. -* `from_subaccount` The spender subaccount expressed as 32-byte subaccount in base64 representation. Subaccounts are 32-byte byte arrays and encoded in hexadecimal representation for ICRC-22. Leading zeroes on the left of a subaccount SHOULD be omitted in the encoding. Used when the subaccount from which the funds should be transferred is known by the creator of the URI. Must match the subaccount intended by the recipient. -* `to`: The [size-reduced human readable textual representation](## Size-reduced-ICRC-1-textual-account-representation) of an ICRC-1 account as specified in this document. Specifies the recipient of the token transfer. -* `amount` The transaction amount, specified as decimal integer or in scientific representation, e.g., 4.042E8 and 804200000 express the same integer. The number refers to the number of tokens in the base units of the ledger the request is targeted at. -* `fee`: The fee expressed in base units of the addressed ledger, using scientific notation if appropriate. -* `memo`: An integer representing the memo. +* `from`: The initiator of the transfer, i.e., the spender. Encoded using the [size-reduced human readable textual representation](## Size-reduced-ICRC-1-textual-account-representation) of an ICRC-1 account as specified in this document. Used when the spender is specified by the URI creator already. Must match the initiator of the transfer and the inteded subaccount to transfer the funds from. +* `from_subaccount` The spender subaccount expressed as 32-byte subaccount in base64 representation. Subaccounts are 32-byte byte arrays and encoded in hexadecimal representation for use in ICRC-22. Leading zeroes on the left of a subaccount SHOULD be omitted in the encoding. Used when the subaccount from which the funds should be transferred is known by the creator of the URI. Must match the subaccount intended by the initiator of the transfer. +* `to`: The recipient of the token transfer. Encoded as an ICP account identifier. +* `amount` The amount of tokens to be transferred. The number refers to the number of tokens in the base units of the ledger the request is targeted at. Specified as decimal integer or in scientific representation, e.g., 4.042E8 and 804200000 express the same integer. +* `fee`: The fee for the transfer. The number refers to the number of tokens in the base units of the ledger the request is targeted at. Specified as decimal integer or in scientific representation. +* `memo`: A decimal non-negative integer representing the memo. * `created_at_time`: The creation time of the transaction expressed as integer timestamp. #### ICRC1 icrc1_transfer -* `from` (ICRC-2): The size-reduced human readable [textual representation](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md) of an ICRC-1 account as specified in this document. -* `from_subaccount` (ICP, ICRC-1, ICRC-2): 32-byte subaccount in Base64 representation. -* `to` (ICP, ICRC-1, ICRC-2): The size-reduced human readable [textual representation](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md) of an ICRC-1 account as specified in this document. -* `amount` (ICP, ICRC-1, ICRC-2): The transaction amount, specified as integer or in scientific representation, e.g., 4.042E8 or 804200000. The number refers to the base units of the ledger the request is targeted at. -* `fee` (ICP, ICRC-1, ICRC-2): Fee expressed in base units of the addressed ledger, using scientific notation if appropriate. +* `from` The initiator of the transfer, i.e., the spender. Encoded using the [size-reduced human readable textual representation](## Size-reduced-ICRC-1-textual-account-representation) of an ICRC-1 account as specified in this document. Used when the spender is specified by the URI creator already. Must match the initiator of the transfer and the inteded subaccount to transfer the funds from. +* `from_subaccount` The spender subaccount expressed as 32-byte subaccount in base64 representation. Subaccounts are 32-byte byte arrays and encoded in hexadecimal representation for use in ICRC-22. Leading zeroes on the left of a subaccount SHOULD be omitted in the encoding. Used when the subaccount from which the funds should be transferred is known by the creator of the URI. Must match the subaccount intended by the initiator of the transfer. +* `to` The recipient of the token transfer. Encoded using the [size-reduced human readable textual representation](## Size-reduced-ICRC-1-textual-account-representation) of an ICRC-1 account as specified in this document. +* `amount` The amount of tokens to be transferred. The number refers to the number of tokens in the base units of the ledger the request is targeted at. Specified as decimal integer or in scientific representation, e.g., 4.042E8 and 804200000 express the same integer. +* `fee` The fee for the transfer. The number refers to the number of tokens in the base units of the ledger the request is targeted at. Specified as decimal integer or in scientific representation. * `memo` A byte array expressed as hexadecimal string representing the memo. -* `created_at_time` (ICP, ICRC-1, ICRC-2): The creation time of the transaction expressed as integer timestamp. +* `created_at_time` The creation time of the transaction expressed as integer timestamp. #### ICRC2 icrc2_approve -* `from` (ICRC-2): The size-reduced human readable [textual representation](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md) of an ICRC-1 account as specified in this document. -* `from_subaccount` (ICP, ICRC-1, ICRC-2): 32-byte subaccount in Base64 representation. -* `spender` (ICRC-2): The size-reduced human readable [textual representation](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/TextualEncoding.md) of an ICRC-1 account as specified in this document. -* `amount` (ICP, ICRC-1, ICRC-2): The transaction amount, specified as integer or in scientific representation, e.g., 4.042E8 or 804200000. The number refers to the base units of the ledger the request is targeted at. +* `from` The initiator of the approval. Encoded using the [size-reduced human readable textual representation](## Size-reduced-ICRC-1-textual-account-representation) of an ICRC-1 account as specified in this document. Used when the spender is specified by the URI creator already. Must match the initiator of the transfer and the inteded subaccount to transfer the funds from. +* `from_subaccount` The source subaccount expressed as 32-byte subaccount in base64 representation. Subaccounts are 32-byte byte arrays and encoded in hexadecimal representation for use in ICRC-22. Leading zeroes on the left of a subaccount SHOULD be omitted in the encoding. Used when the subaccount from which the funds should be transferred is known by the creator of the URI. Must match the subaccount intended by the initiator of the transfer. +* `spender` (ICRC-2): The spender of the approved funds. Encoded using the [size-reduced human readable textual representation](## Size-reduced-ICRC-1-textual-account-representation) of an ICRC-1 account as specified in this document. +* `amount` The amount of tokens to be transferred. The number refers to the number of tokens in the base units of the ledger the request is targeted at. Specified as decimal integer or in scientific representation, e.g., 4.042E8 and 804200000 express the same integer. * `expected_allowance` (ICRC-2): The amount to be approved, , specified as integer or in scientific representation, e.g., 4.042E8 or 804200000. The number refers to the base units of the ledger the request is targeted at. * `expires_at` (ICRC-2): The expiration date of the approval expressed as integer timestamp. -* `fee` (ICP, ICRC-1, ICRC-2): Fee expressed in base units of the addressed ledger, using scientific notation if appropriate. +* `fee` The fee for the transfer. The number refers to the number of tokens in the base units of the ledger the request is targeted at. Specified as decimal integer or in scientific representation. * `memo` A byte array expressed as hexadecimal string representing the memo. -* `created_at_time` (ICP, ICRC-1, ICRC-2): The creation time of the transaction expressed as integer timestamp. +* `created_at_time` The creation time of the transaction expressed as integer timestamp. Accounts are always represented through the size-reduced textual encoding as specified in [Size-Reduced ICRC-1 Textual Account Representationbelow](## Size-reduced-ICRC-1-textual-account-representation) because of the human readability and the built-in checksum over both the principal and subaccount components of the account. The `amount` should be provided as a nonnegative integer number. The amount represents the amount of tokens in the base unit used by the ledger, i.e., 4 ICP tokens would amount to 4 * 10^8 = 400000000 base units as managed by the ICP token ledger. It is strongly recommended to use scientific notation for the amount. Decimal representation can be combined with scientific representation, e.g., 4.042E8 ICP means a count of 404200000 base units as managed by the ICP ledger. As only integer numbers are allowed as amount, the exponent MUST be greater than or equal to the decimal places of the number in scientific representation. +The arguments `expires_at`, `fee`, and `created_at_time` will in most use cases likely be set by the client application and not be contained in the URI. + ## Generalization Towards Handling a Larger Class of Method Calls // FIX remove @@ -154,9 +156,9 @@ k2t6j-2nvnp-4zjm3-25dtz-6xhaa-c7boj-5gayf-oj3xs-i43lp-teztq-6ae-dfxgiyy.10203040 ## Data Compression -Depending on the transport mechanism used, data compression of the URI resulting from the encoding MAY be used to reduce the size of the message to be sent over the transport. This is particularly important for QR codes used as transport mechanism as they have limited bandwidth and larger QR codes are harder to scan. +Depending on the transport mechanism intended to be used, data compression of the URI resulting from the encoding MAY be used to reduce the size of the message to be sent over the transport. This is particularly important for QR codes used as transport mechanism as they have limited bandwidth and larger QR codes are harder to scan. -Compression of URIs for transfer in QR codes, if used, MUST be performed using the gzip algorithm. This algorithm is reasonably simple and native implementations are available in many languages and have a small code size, thus it is easy to implement this feature in both tools and canister smart contracts without too much bloat. Future standards may add additional compression algorithms with better compression ratios such as zstd or Brotli. +Compression of URIs for transfer in QR codes, if used, MUST be performed using the gzip algorithm. This algorithm is reasonably simple and native implementations are available in many languages and have a small code size, thus it is easy to implement this feature in both tools and canister smart contracts without too much bloat. Future standards may add additional compression algorithms with better compression ratios such as zstd or Brotli, with the drawbacks of much larger code size and not as widespread open source implementations being available. ## Examples From 1982ba2b577b9141a368057c815c0dcead3eec52 Mon Sep 17 00:00:00 2001 From: "Dieter M. Sommer" Date: Wed, 16 Oct 2024 11:25:58 +0200 Subject: [PATCH 12/13] Major revision ongoing --- ICRCs/ICRC-22/ICRC-22.md | 91 +++++++++++++++------------------------- 1 file changed, 33 insertions(+), 58 deletions(-) diff --git a/ICRCs/ICRC-22/ICRC-22.md b/ICRCs/ICRC-22/ICRC-22.md index 2dedc45..9e1fe58 100644 --- a/ICRCs/ICRC-22/ICRC-22.md +++ b/ICRCs/ICRC-22/ICRC-22.md @@ -12,50 +12,46 @@ Relevant prior work in other blockchain ecosystems comprises the standards on pa ## Specification -The below specification defines the syntax and (non-formal) semantics for ICRC-22 token transfer and approval requests. The specification takes the approaches of \[Bit1, Bit2, Nag17, WLGH19\] into consideration. Particularly, an authority-less URI format has been chosen following this prior art in the domain. +The below specification defines the syntax and informal semantics for ICRC-22 token transfer and approval requests. The specification takes the approaches of \[Bit1, Bit2, Nag17, WLGH19\] into consideration. Particularly, an authority-less URI format has been chosen following this prior art in the domain. -Next, we show the structure of an ICRC1 transfer request URI with the concrete arguments represented through `<>`-placeholders. Note that the URI does not contain an authority, but encodes the `network`, the `icrc22` standard specifier, and `canister_principal` as part of the URI path, directly following the URI scheme. +Next, we show the structure of an ICRC1 transfer request URI with some of the concrete arguments represented through `<>`-placeholders. `737ba355e855bd4b61279056603e0550` is the network id for ICP mainnet. Note that the URI does not contain an authority, but encodes the `network`, the `icrc22` standard specifier, and `canister_principal` as part of the URI path, directly following the URI scheme. ``` icp:737ba355e855bd4b61279056603e0550:icrc22:/icrc1_transfer?to=&amount=&memo= ``` -// FIX syntax details -Next, we present the ABNF syntax for ICRC-22 URIs. +Next, we present the ABNF syntax for the prefix of ICRC-22 URIs. The details of the full ICRC-22 URI, i.e., encoding of the method name to call and the query string follow from the Candid method name and parameter syntax defined already in the respective specification and thus are not repeated here. Note that certain characters may require URI encoding, e.g., UTF8 characters outside of the character set allowed in URIs that are used in method names need to be encoded with URI encoding. ``` -request = protocol ":" network ":" contract_address "/" "exec" transaction [ "?" parameters ] -protocol = "icp" ; always "icp" referring to the current version of the Internet Computer Protocol -network = (1..10)[0..9a..fA..F] / ; specifies the network through a prefix of its public key hash -canister_principal = ICP principal FIX: canister principal ABNF ; canister address to which to make the call -transaction = ... ; canister method to call FIX: Candid method syntax -parameters = parameter [ "&" parameter ] -parameter = key "=" value -key = ... ; FIX: Candid parameter name syntax -value = ... ; FIX Candid encoded value syntax +request = protocol ":" network ":" "icrc22" ":" canister_principal "/" method_name [ "?" parameters ] +protocol = "icp" ; always "icp", referring to the current version of the Internet Computer Protocol +network = (1..32)[0..9a..fA..F] ; specifies the network through a prefix of its public key hash ``` -The grammar productions not further specified above can be looked up in the syntax specification for URIs in RFC 3986 \[BFM05\]. Note that the production `transaction` above is part of the path and `parameters` part of the query string and the according constraints of RFC 3986 apply. // FIX +The grammar productions not further specified above can be easily derived from the Candid method name and parameter syntax. Note that `method_name` is part of the path and `parameters` part of the query string and the according constraints of RFC 3986 apply. -The `network` defaults to the identifier `737ba355e855bd4b61279056603e0550` for ICP mainnet following the approach defined by CAIP for specifying blockchain networks. When the network identifier is left out, the network defaults to the current ICP mainnet. In this default case, the prefix of a URI would thus be `icp::icrc22:?`. The interpretation of what "current mainnet" is is left to the client. Semantically, it should refer to the currently active public key for mainnet,. This key can only change in the event of an NNS recovery after a large desaster event that destroys the NNS private threshold key, and thus the key is considered very stable and unlikely to ever change. +The `protocol` is always the string `icp` and refers to the namespace for the Internet Computer Protocol. -The `network` uniquely identifies the ICP network to make the transaction on. Following the ideas of the Chain Agnostic Standards Alliance \[Cha24\] of having a standardized way of referring to any blockchain network, ICP uses the following mechanism for referring to ICP mainnet or any other ICP-based network that may be available in the future, such as testnets or private networks based on the ICP protocol stack ("UTOPIA" private networks). -The network is identified by a prefix of the the Base16 (HEX) encoding of the SHA256 hash of the binary representation of the DER-encoded public key of the network. In case of a *well-known public network*, an 8-character prefix of the key hash can be used as network identifier, for private networks, a 32-character prefix is used to represent the network. Currently, only ICP mainnet qualifies as a well-known public network, in the future public testnets might be eligible also to be well-known public networks. For ICP mainnet, the public key of the network is the NNS public key: +The `network` uniquely identifies the ICP network to make the transaction on. Following the approach of the Chain Agnostic Standards Alliance \[Cha24\] of having a standardized way of referring to any blockchain network, ICP uses the following mechanism for referring to ICP mainnet or any other ICP-based network that may be available in the future, such as testnets or private networks based on the ICP protocol stack ("UTOPIA" private networks): +The network is identified by a prefix of the the base16 (i.e., hexadecimal) encoding of the SHA256 hash of the binary representation of the current DER-encoded public key of the network. +// In case of a *well-known public network*, an 8-character prefix of the key hash can be used as network identifier, for private networks, a 32-character prefix is used to represent the network. Currently, only ICP mainnet qualifies as a well-known public network, in the future public testnets might be eligible also to be well-known public networks. +For ICP mainnet, the public key of the network is the NNS public key: ``` 308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100814c0e6ec71fab583b08bd81373c255c3c371b2e84863c98a4f1e08b74235d14fb5d9c0cd546d9685f913a0c0b2cc5341583bf4b4392e467db96d65b9bb4cb717112f8472e0d5a4d14505ffd7484b01291091c5f87b98883463f98091a0baaae ``` -Its 32-character prefix of the HEX-encoded SHA256 hash is -`737ba355e855bd4b61279056603e0550`. +Its 32-character prefix of the HEX-encoded SHA256 hash is `737ba355e855bd4b61279056603e0550`. In case of a private ICP deployment, the 32-character prefix of the SHA256 hash of the network's DER-encoded public key is used as network identifier. -The approach of expressing network identifiers through the 32-character prefix of the SHA256 hash of their public key is based on the approach proposed by the CAIP initiative, the shorter prefix for well-known networks or the default is a simplification for the most used network(s). +// The approach of expressing network identifiers through the 32-character prefix of the SHA256 hash of their public key is based on the approach proposed by the CAIP initiative, the shorter prefix for well-known networks or the default is a simplification for the most used network(s). -The `contract_address` is the canister smart contract principal identifier of the contract the transaction is to be performed on. This is represented in the standardized format for principals. The address, together with the network identifier, unambiguously determines the token that is to be transacted. +The `network` argument defaults to the identifier `737ba355e855bd4b61279056603e0550` for ICP mainnet if left out. In this default case, the prefix of an ICRC-22 URI thus is `icp::icrc22:/`. The interpretation of what "current mainnet" is is left to the client. Semantically, it refers to the currently active public key for mainnet. This public key can only change in the event of an NNS recovery after a large desaster event that destroys the NNS private threshold key, and thus the key is considered very stable and very unlikely to change. -The constant `exec` means that the forthcoming part in the path component specifies which transaction (smart contract method) should be invoked with the information in the URI. In the future, other ICRC standards may emerge that can have a different string with different semantics in the place of this. +The `icrc22` constant provides a sub-namespace for ICRC-22. The URI namespace following this specifier is controlled by ICRC-22. -The `transaction` parameter specifies the canister method to be called on the canister indicated through `contract_address`. This is the string-based name as it appears in the canister's Candid specification. This standard requires support of all of ICP ledger's `transfer`, ICRC-1's `transfer` and ICRC-2's `approve` methods. The method names to handle payment-related use cases currently envisioned are `transfer`, `icrc1_transfer`, and `icrc2_approve`. +The `canister_principal` is the canister smart contract principal identifier of the canister smart contract the transaction is to be performed on. This is represented in the standardized format for expressing principals in textual representation. The address, together with the network identifier, unambiguously determines the token that is to be operated on. -The `parameters` are the parameters of the method to be called. They SHOULD be given in the order in which they appear in the Candid specification of the method to be called. A subset of the parameters defind in the Candid specification of the method can be present, the remaining non-optional parameters MUST be filled in by the party executing the transaction. +The `method_name` parameter specifies the canister method to be called on the canister indicated through `canister_principal`. This is the string-based name as it appears in the canister's Candid specification. This standard requires support of all of ICP ledger's `transfer`, ICRC-1's `icrc1_transfer` and ICRC-2's `icrc2_approve` methods. -### Supported Method Invocations +The `parameters` are the parameters of the method to be called. They can be encoded in the URI in any order. A subset of the parameters defind in the Candid specification of the method can be present, the remaining non-optional parameters MUST be filled in by the party executing the method call in order to obtain the valid method call paramters. + +### Supported Methods Next, we define the parameters allowed in the various smart contract methods this standard supports. A subset of the parameters can be specified in the URI, meaning that the remaining paramters need to be filled in by the client (e.g., wallet) in case they are mandatory and can be filled in in case they are optional in the method's specification. Note also that the initiator of the transaction may be specified through the `from` or just the `from_subaccount`. If omitted, they need to be provided by the client application. We give the following example use case scenarios: * A payment use case where a shop provides a payment link with `to`, `amount`, and `memo` and the wallet provides the source account through the caller principal and filling in the `from_subaccount` according to user's preferences and sets the `fee` and `created_at_time`. A simple shop use case can also comprise a similar set up with the `amount` being provided by the user and being communicated to the user by the salesperson. This may be a proper setup for a market where the URI is provided as a printed QR code. @@ -105,31 +101,7 @@ The `amount` should be provided as a nonnegative integer number. The amount repr The arguments `expires_at`, `fee`, and `created_at_time` will in most use cases likely be set by the client application and not be contained in the URI. -## Generalization Towards Handling a Larger Class of Method Calls - -// FIX remove - -ICRC-22 does not handle generic calls of smart contract methods on ICP, but does allow for handling further requests that are sufficiently similar to the ones captured explicitly. This comprises requests that have arguments that can be represented as query parameters in a URI in a straightforward way and a canonical encoding exists for the argument. - -The generic representation of call arguments is done as follows through a canonical encoding of the method parameters as URI query parameters: -* a `bool` parameter is represented as either `true` or `false` -* a `text` parameter is represented as a string representing the text -* a `number` parameter is encoded as the string representation of the decimal number -* a binary `blob` parameter is hexadecimal encoded -* a tuple is encoded by having an opening element `*tuple`, followed by the tuple values, followed by a closing element `-tuple` -* a record is encoding is started with the query parameter `*record=fieldName`, where `fieldName` is the name of the field containing the record; this is followed by a sequence of encodings of its fields according to the encoding rules; the termination of the record is encoded with `-record=fieldName` -* an array is started with `*array=fieldName`, followed by an encoding of its entries the names of which are their index using 0-based indexing (e.g., `0=8` for the 0-th field with value `8`), followed by a termination `-array=fieldName` -* an enumeration is encoded by a start element `*enum=fieldName` and a variant element encoding the variant of the enumeration; for variants that have an associated value, the value is encoded after the variant using the encoding rules - -Fields that are mandatory according to the Candid specification may be left out from the encoding in case that the canister needs to fill in those missing values. Note that those values MUST be provided by the canister in order to obtain a valid Candid value to use for the method invocation. - -A large class of method interfaces — every method the encoding of which can be uniquely decoded back to Candid — can be handled with this method of canonical flattening of nested data types expressible in Candid. However, for complex data structures an approach of mapping the parameters to Candid and encoding the Candid value in the URI may be preferable and part of a future ICRC as outlined in the [Future Work](##Future-Work) section. - -The specification of payment-related transaction requests as defined for ICP and ICRC-1 payments and ICRC-2 approvals is a special case of the generalized encoding introduced in this section, with the following differences: -* the parameters are provided as a flat list, with the enclosing `TransferArgs` record being made explicit; the rationale behind this is that payment-related use cases are the primary target of this specification; -* ICRC-1 accounts are encoded using the size-reduced textual representation of ICRC-1 accounts ([Dfi22]) as defined in this document. - -The generalization introduced in this section is optional for an implementation of ICRC-22 to keep the minimum requirements for an implementation simple and help widespread adoption of ICRC-22 for payment-related use cases. +Implementors of ICRC-22 should take note of the different encoding of the `memo` for the ICP token standard on the one hand and ICRC-1 and ICRC-2 on the other hand. ## Size-Reduced ICRC-1 Textual Account Representation @@ -156,9 +128,9 @@ k2t6j-2nvnp-4zjm3-25dtz-6xhaa-c7boj-5gayf-oj3xs-i43lp-teztq-6ae-dfxgiyy.10203040 ## Data Compression -Depending on the transport mechanism intended to be used, data compression of the URI resulting from the encoding MAY be used to reduce the size of the message to be sent over the transport. This is particularly important for QR codes used as transport mechanism as they have limited bandwidth and larger QR codes are harder to scan. +Depending on the transport mechanism intended to be used, data compression of the URI resulting from the ICRC-22 encoding MAY be used to reduce the size of the message to be sent over the transport. This is particularly important and recommended for QR codes used as transport mechanism as they have limited bandwidth and larger QR codes are harder to scan. -Compression of URIs for transfer in QR codes, if used, MUST be performed using the gzip algorithm. This algorithm is reasonably simple and native implementations are available in many languages and have a small code size, thus it is easy to implement this feature in both tools and canister smart contracts without too much bloat. Future standards may add additional compression algorithms with better compression ratios such as zstd or Brotli, with the drawbacks of much larger code size and not as widespread open source implementations being available. +When compression of URIs for transfer in QR codes is used, it MUST be performed using the gzip algorithm. This algorithm is reasonably simple and native implementations are available in many languages and have a small code size, thus it is easy to implement this feature in both tools and canister smart contracts without too much bloat. Future standards may add additional compression algorithms with better compression ratios such as zstd or Brotli, with the drawbacks of much larger code size and not as widespread open source implementations being available. ## Examples @@ -170,25 +142,28 @@ The following examples show the application of ICRC-22 for ICP transfer, ICRC-1 icp::ryjl3-tyaaa-aaaaa-aaaba-cai/exec/transfer?from_subaccount=&to=&amount=4.042E8&memo= ``` +The following shows an example of a transfer request of `4.042` ICP using on the ICP token ledger to `61342bfbd397f0c36c5da1f9661b802db60a20e973012c99903fc8637b5bf32b` with `memo` being the natural number `9812345670123456`, where `to` (the recipient account id), `amount`, and `memo` are specified, while the `from_subaccount`, `fee`, and `created_at_time` are provided by the client application (e.g., a wallet). ``` -icp:737ba355e855bd4b61279056603e0550:ryjl3-tyaaa-aaaaa-aaaba-cai/exec/transfer?from_subaccount=0&to=61342bfbd397f0c36c5da1f9661b802db60a20e973012c99903fc8637b5bf32b&amount=4.042E8&memo= +icp:737ba355e855bd4b61279056603e0550:icrc22:ryjl3-tyaaa-aaaaa-aaaba-cai/transfer?to=61342bfbd397f0c36c5da1f9661b802db60a20e973012c99903fc8637b5bf32b&amount=4.042E8&memo=9812345670123456 ``` +The string `ryjl3-tyaaa-aaaaa-aaaba-cai` is the principal of the ICP ledger. -Note that `ryjl3-tyaaa-aaaaa-aaaba-cai` is the principal of the ICP ledger. +This is a typical example of requesting a payment in ICP tokens from an off-chain service. ### ICRC-1 Token Transfer -The following is a payment request for `0.04042` ckBTC on the ckBTC ledger of the caller to the account `k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6aedfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20` with memo `1b69b4ba630f34e15fd40af`. The wallet reading and executing this request must insert the `created_at_time` field based on the current time to create a valid ledger transaction. For the representation of the amount, note that 1 ckBTC equals `1E8` (100 million) base units of the ckBTC ledger. +The following is a payment request for `0.04042` ckBTC on the ckBTC ledger of the caller to the account `k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6aedfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20` with `memo` being the hex-encoded byte array `1b69b4ba630f34e15fd40af1`. The wallet reading and executing this request must insert the `from_subaccount`, `fee`, and `created_at_time` accordingly. For the representation of the amount, note that `1` ckBTC equals `1E8` (100 million) base units of the ckBTC ledger. ``` -icp:737ba355e855bd4b61279056603e0550:icrc22:mxzaz-hqaaa-aaaar-qaada-cai/icrc1_transfer?to=k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6ae-dfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20&amount=4.042E6&memo=1b69b4ba630f34e15fd40af +icp:737ba355e855bd4b61279056603e0550:icrc22:mxzaz-hqaaa-aaaar-qaada-cai/icrc1_transfer?to=k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6ae-dfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20&amount=4.042E6&memo=1b69b4ba630f34e15fd40af1 ``` +The string `mxzaz-hqaaa-aaaar-qaada-cai` is the principal of the ckBTC ledger. ### ICRC-2 Approval -An ICRC-2 approval can be made on any ICRC-2-compliant ledger, e.g., the ICP ledger or any ICRC-1-compliant token ledger like the ckBTC legder. The following example shows an ICRC-2 approval of `0.04042` ckBTC to account `h2oto-yhzgh-fdd7o-ucdym-dnwul-ihnjb-67dlq-ed3x2-mxzf2-des4t-xqe`. The `fee` and `created_at_time` arguments need to be provided by the wallet. +An ICRC-2 approval can be made on any ICRC-2-compliant ledger, e.g., the ICP ledger or any ICRC-1-compliant token ledger like the ckBTC legder. The following example shows an ICRC-2 approval of `0.04042` ckBTC to account `h2oto-yhzgh-fdd7o-ucdym-dnwul-ihnjb-67dlq-ed3x2-mxzf2-des4t-xqe`. The `fee` and `created_at_time` arguments need to be provided by the wallet. The arguments `from_subaccount`, `expected_allowance` (optional), `fee`, and `created_at_time` need to be provided by the client application accordingly. ``` -icp:737ba355e855bd4b61279056603e0550:icrc22:mxzaz-hqaaa-aaaar-qaada-cai/exec/icrc2_approve?spender=h2otoyhzghfdd7oucdymdnwulihnjb67dlqed3x2mxzf2des4txqe&amount=4.042E6&memo=1b69b4ba630f34e15fd40ab +icp:737ba355e855bd4b61279056603e0550:icrc22:mxzaz-hqaaa-aaaar-qaada-cai/icrc2_approve?spender=h2otoyhzghfdd7oucdymdnwulihnjb67dlqed3x2mxzf2des4txqe&amount=4.042E6&memo=1b69b4ba630f34e15fd40ab8 ``` ## Future Work From b2e5d32b1c39b36b19b006b48587ad7c8a701a71 Mon Sep 17 00:00:00 2001 From: "Dieter M. Sommer" Date: Wed, 16 Oct 2024 13:15:42 +0200 Subject: [PATCH 13/13] Update --- ICRCs/ICRC-22/ICRC-22.md | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/ICRCs/ICRC-22/ICRC-22.md b/ICRCs/ICRC-22/ICRC-22.md index 9e1fe58..d62a4de 100644 --- a/ICRCs/ICRC-22/ICRC-22.md +++ b/ICRCs/ICRC-22/ICRC-22.md @@ -32,14 +32,12 @@ The `protocol` is always the string `icp` and refers to the namespace for the In The `network` uniquely identifies the ICP network to make the transaction on. Following the approach of the Chain Agnostic Standards Alliance \[Cha24\] of having a standardized way of referring to any blockchain network, ICP uses the following mechanism for referring to ICP mainnet or any other ICP-based network that may be available in the future, such as testnets or private networks based on the ICP protocol stack ("UTOPIA" private networks): The network is identified by a prefix of the the base16 (i.e., hexadecimal) encoding of the SHA256 hash of the binary representation of the current DER-encoded public key of the network. -// In case of a *well-known public network*, an 8-character prefix of the key hash can be used as network identifier, for private networks, a 32-character prefix is used to represent the network. Currently, only ICP mainnet qualifies as a well-known public network, in the future public testnets might be eligible also to be well-known public networks. For ICP mainnet, the public key of the network is the NNS public key: ``` 308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100814c0e6ec71fab583b08bd81373c255c3c371b2e84863c98a4f1e08b74235d14fb5d9c0cd546d9685f913a0c0b2cc5341583bf4b4392e467db96d65b9bb4cb717112f8472e0d5a4d14505ffd7484b01291091c5f87b98883463f98091a0baaae ``` Its 32-character prefix of the HEX-encoded SHA256 hash is `737ba355e855bd4b61279056603e0550`. In case of a private ICP deployment, the 32-character prefix of the SHA256 hash of the network's DER-encoded public key is used as network identifier. -// The approach of expressing network identifiers through the 32-character prefix of the SHA256 hash of their public key is based on the approach proposed by the CAIP initiative, the shorter prefix for well-known networks or the default is a simplification for the most used network(s). The `network` argument defaults to the identifier `737ba355e855bd4b61279056603e0550` for ICP mainnet if left out. In this default case, the prefix of an ICRC-22 URI thus is `icp::icrc22:/`. The interpretation of what "current mainnet" is is left to the client. Semantically, it refers to the currently active public key for mainnet. This public key can only change in the event of an NNS recovery after a large desaster event that destroys the NNS private threshold key, and thus the key is considered very stable and very unlikely to change. @@ -63,7 +61,7 @@ ICRC-22 focuses on the transmission of the information and does not standardize // FIX text for arguments -#### ICP's transfer +#### ICP transfer * `from`: The initiator of the transfer, i.e., the spender. Encoded using the [size-reduced human readable textual representation](## Size-reduced-ICRC-1-textual-account-representation) of an ICRC-1 account as specified in this document. Used when the spender is specified by the URI creator already. Must match the initiator of the transfer and the inteded subaccount to transfer the funds from. * `from_subaccount` The spender subaccount expressed as 32-byte subaccount in base64 representation. Subaccounts are 32-byte byte arrays and encoded in hexadecimal representation for use in ICRC-22. Leading zeroes on the left of a subaccount SHOULD be omitted in the encoding. Used when the subaccount from which the funds should be transferred is known by the creator of the URI. Must match the subaccount intended by the initiator of the transfer. @@ -105,27 +103,43 @@ Implementors of ICRC-22 should take note of the different encoding of the `memo` ## Size-Reduced ICRC-1 Textual Account Representation -The Chain Agnostic Standards Alliance \[Cha24\] has specified account identifiers to be of a maximum length of 128 characters \[Gom22\]. There seems to be no strong reason behind this, but it had been considered sufficient for the foreseeable future by the CAIP working group and is thus a limitation for representing accounts. This limitation cannot be changed at the current time. +// FIX move into separate ICRC and reference this one from here -ICRC-1 account identifiers on ICP may exceed this limitation of 128 bytes by a few bytes when using the human-readable representation of ICRC-1 accounts, i.e., the textual encoding of ICRC-1 accounts \[Dfi22\]. For this reason, we define a size-reduced textual ICRC-1 account representation as part of this standard in order to fit the CAIP limits of 128 characters. +// FIX maybe present this in a more formal way + +The Chain Agnostic Standards Alliance \[Cha24\] has specified account identifiers to be of a maximum length of 128 characters \[Gom22\]. There seems to be no strong reason behind this, but it had been considered sufficient for the foreseeable future by the CAIP working group and is thus a hard limitation for representing accounts in a CAIP-compliant manner. This limitation cannot be changed at the current time. + +ICRC-1 account identifiers on ICP may exceed this limitation of 128 bytes by a few bytes when using the human-readable representation of ICRC-1 accounts, i.e., the textual encoding of ICRC-1 accounts \[Dfi22\]. For this reason, we define a *size-reduced textual ICRC-1 account representation* based on \[Dfi22\] as part of this standard in order to fit the CAIP limits of 128 characters. + +### Computing the Size-Reduced Textual Account Representation The size-reduced representation is easily computed by removing all the dashes ("-") between the character groups of the representation of the principal and checksum, except for the rightmost dash (the one preceding the CRC32 checksum) for non-default accounts (i.e., accounts with a non-zero subaccount). For default accounts (i.e., accounts with the all-zero subaccount), all dashes are removed. It is easy to reconstruct the standard textual encoding from a size-reduced textual encoding by adding dash separators, starting from the left of the representation, for every 5-character group. It is guaranteed that any ICRC-1 account in size-reduced representation fits into the 128-character limit. The Internet Computer Interface Specification \[Dfi\] specifies the maximum lenght of a textual representation of a principal to be 63 bytes, which includes 10 dashes. The additional CRC32 checksum in Base32 encoding takes another 7 characters, its preceding dash separator one. This makes the maximum length of the size-reduced representation 126 characters: 63 for the maximum-length principal in textual encoding - 10 for separators + 1 for the checksum "-"-separator + 7 for the CRC32 checksum + 1 for the subaccount "."-separator + 64 for the subaccount in hexadecimal representation. +### Computing the Textual Account Representation + +The transformation from a size-reduced textual account representation back to a regular ICRC-1 textual account representation is done by adding dashes (`-`-characters) after every group of 5 characters in the part left of the `.` character, starting from the left side until a final group of at most 5 characters before the `.` or before the `-` preceding the checksum of the textual account representation is reached. + +### Example + The following is an example of an almost maximum-length textual representation that exceeds the size limits imposed by CAIP with its length of 135 characters. ``` k2t6j-2nvnp-4zjm3-25dtz-6xhaa-c7boj-5gayf-oj3xs-i43lp-teztq-6ae-dfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 ``` -The following is the above example in size-reduced form and fits within the 128-character limit with its length of 125 characters. Note that the final dash in the first part (the part left of the `.`) is retained as it separates the principal from the checksum of the account representation. +The following is the above example in size-reduced form and fits within the 128-character limit with its length of 125 characters. Note that the final dash in the first part (the part left of the `.`) is retained as it separates the principal from the checksum of the account representation and makes the inverse mapping simpler. ``` k2t6j2nvnp4zjm325dtz6xhaac7boj5gayfoj3xsi43lpteztq6ae-dfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 ``` -This size-reduced representation can easily be transformed back to the original textual representation as defined in \[Dfi22\] by adding dashes every group of 5 characters from the left. Note that the rightmost character group left of the checksum can have less than 5 characters. +This size-reduced representation can easily be transformed back to the original textual representation as defined in \[Dfi22\] by adding dashes every group of 5 characters from the left in the part left of the `.` until either an existing `-` or the `.`-separator is reached (i.e., less than or equal to 5 characters are remaining). Note that the rightmost character group left of the checksum or `.` can have less than 5 characters in the general case. ``` k2t6j-2nvnp-4zjm3-25dtz-6xhaa-c7boj-5gayf-oj3xs-i43lp-teztq-6ae-dfxgiyy.102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 ``` +### Notes + +The approach of computing the size-reduced representation has been specified to build upon a textual account representation as starting point. It is easy to derive an algorithm to compute the size-reduced account representation from its basic constituents, a principal byte array and a subaccount byte array, if implementors so prefer. + ## Data Compression Depending on the transport mechanism intended to be used, data compression of the URI resulting from the ICRC-22 encoding MAY be used to reduce the size of the message to be sent over the transport. This is particularly important and recommended for QR codes used as transport mechanism as they have limited bandwidth and larger QR codes are harder to scan. @@ -138,10 +152,6 @@ The following examples show the application of ICRC-22 for ICP transfer, ICRC-1 ### ICP Token Transfer -``` -icp::ryjl3-tyaaa-aaaaa-aaaba-cai/exec/transfer?from_subaccount=&to=&amount=4.042E8&memo= -``` - The following shows an example of a transfer request of `4.042` ICP using on the ICP token ledger to `61342bfbd397f0c36c5da1f9661b802db60a20e973012c99903fc8637b5bf32b` with `memo` being the natural number `9812345670123456`, where `to` (the recipient account id), `amount`, and `memo` are specified, while the `from_subaccount`, `fee`, and `created_at_time` are provided by the client application (e.g., a wallet). ``` icp:737ba355e855bd4b61279056603e0550:icrc22:ryjl3-tyaaa-aaaaa-aaaba-cai/transfer?to=61342bfbd397f0c36c5da1f9661b802db60a20e973012c99903fc8637b5bf32b&amount=4.042E8&memo=9812345670123456