From 1387a2c8f4a9bd7102966f5df207bafb91113339 Mon Sep 17 00:00:00 2001 From: BenKurrek Date: Wed, 13 Jul 2022 15:52:36 -0400 Subject: [PATCH 1/8] initial impl of new NEP for access keys --- neps/nep-9999.md | 95 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 neps/nep-9999.md diff --git a/neps/nep-9999.md b/neps/nep-9999.md new file mode 100644 index 000000000..ab7577fe6 --- /dev/null +++ b/neps/nep-9999.md @@ -0,0 +1,95 @@ +--- +NEP: 9999 +Title: Runtime Access Key Info +Author: Ben Kurrek +DiscussionsTo: https://github.com/nearprotocol/neps/pull/0000 +Status: Draft +Type: Standards Track +Category: Contract +Created: 13-Jul-2022 +--- + +## Summary + +There is currently no way to query for information about access keys stored on your contract at runtime. + +## Motivation + +As contracts start to use access keys in more creative ways, developers will want to know information such as the access key's allowance, nonce, receiver and more. Since contracts are often built for scalability, Gas and storage costs are often delegated to the end user. If you charge the user for an access key and its allowance, when the key is deleted or used up, that allowance should be refunded to the purchaser. Currently, there is no way to query for the leftover allowance before a key is deleted. This information can tell you how much Gas was spent, and allows for a slew of different scenarios to arise. + +## Rationale and alternatives + +Without creating a promise, we can only query for information stored on the same shard. This is why in this proposal, the access key information at runtime will only come from keys stored on the current contract. We had also investigated the possibility of introducing pagination for all keys stored on the contract but this is infeasible at the moment due to the significant redesign requirement of the VM logic. + +## Specification + +In the runtime, key information will be queryable by passing in the desired public key. The key information will be of the following form. + +```js +enum KeyPermission { + FullAccess, + FunctionCall(FunctionCall), +} + +type KeyInformation = { + public_key: string, + access_key: { + nonce: number, + permission: KeyPermission + } +} + +type FunctionCall = { + receiver_id: string, + allowance: string, + method_names: Array, +} +``` + +The key information will expose the public key and access key data. If the key is a full access key, the permission will simply be a string `"FullAccess"`. If the key is a function call access key, the permission will be of type `FunctionCall`. + +This information should be queryable via a new function called `key_info_by_public_key_for_current_account` which takes a public key as a parameter. + +```ts +function key_info_by_public_key_for_current_account( + public_key: &PublicKey, +): KeyInformation | null +``` + +This function should be exposed in the environment and callable using `env::key_info_by_public_key_for_current_account();`. An example of this can be seen below. + +```rs +pub fn check_key_exists(&self, pk: PublicKey) { + let key_info: KeyInformation = env::key_info_by_public_key_for_current_account(&pk); + + if let Some(info) = key_info { + near_sdk::log!("key info found"); + } else { + near_sdk::log!("No public key found"); + } +} +``` + +An example of returning the allowance of the key can be seen below. + +```rs +pub fn check_key_allowance(&self, pk: PublicKey) { + let key_info: KeyInformation = env::key_info_by_public_key_for_current_account(&pk).unwrap(); + + if let KeyPermission::FunctionCall(fc) = key_info.access_key.permission { + let allowance = fc.allowance; + near_sdk::log!("key allowance: {}", allowance); + } else { + near_sdk::log!("key has no allowance as it's a full access key"); + } +} +``` + +## Future possibilities + +Some of the future possibilities for the standard could be to return a vector of `KeyInformation` by paginating through the keys on the contract. In addition, we could add a `key_total_supply` function that returns the number of access keys stored on the contract. One could also expand and introduce the ability to query for access key info from other contracts by using a promise. + +## Copyright +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From c99a32d4837dca366cae4a54c42ef3682f710367 Mon Sep 17 00:00:00 2001 From: BenKurrek Date: Wed, 13 Jul 2022 15:54:25 -0400 Subject: [PATCH 2/8] renamed NEP version to match PR --- neps/{nep-9999.md => nep-0371.md} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename neps/{nep-9999.md => nep-0371.md} (97%) diff --git a/neps/nep-9999.md b/neps/nep-0371.md similarity index 97% rename from neps/nep-9999.md rename to neps/nep-0371.md index ab7577fe6..d3f5f7ea7 100644 --- a/neps/nep-9999.md +++ b/neps/nep-0371.md @@ -1,8 +1,8 @@ --- -NEP: 9999 +NEP: 371 Title: Runtime Access Key Info Author: Ben Kurrek -DiscussionsTo: https://github.com/nearprotocol/neps/pull/0000 +DiscussionsTo: https://gov.near.org/t/expose-gas-price-and-contract-access-key-info-within-runtime/24788 Status: Draft Type: Standards Track Category: Contract From 3aadb58bc45e46d389c46a45852bffe8290104f3 Mon Sep 17 00:00:00 2001 From: BenKurrek Date: Thu, 14 Jul 2022 10:12:04 -0400 Subject: [PATCH 3/8] Changed NEP to only focus on function call access keys --- neps/nep-0371.md | 54 +++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 33 deletions(-) diff --git a/neps/nep-0371.md b/neps/nep-0371.md index d3f5f7ea7..56e671f32 100644 --- a/neps/nep-0371.md +++ b/neps/nep-0371.md @@ -1,6 +1,6 @@ --- NEP: 371 -Title: Runtime Access Key Info +Title: Runtime Function Call Access Key Info Author: Ben Kurrek DiscussionsTo: https://gov.near.org/t/expose-gas-price-and-contract-access-key-info-within-runtime/24788 Status: Draft @@ -11,56 +11,43 @@ Created: 13-Jul-2022 ## Summary -There is currently no way to query for information about access keys stored on your contract at runtime. +There is currently no way to query for information about function call access keys stored on your contract at runtime. ## Motivation -As contracts start to use access keys in more creative ways, developers will want to know information such as the access key's allowance, nonce, receiver and more. Since contracts are often built for scalability, Gas and storage costs are often delegated to the end user. If you charge the user for an access key and its allowance, when the key is deleted or used up, that allowance should be refunded to the purchaser. Currently, there is no way to query for the leftover allowance before a key is deleted. This information can tell you how much Gas was spent, and allows for a slew of different scenarios to arise. +As contracts start to use access keys in more creative ways, developers will want to know information such as the access key's allowance, receiver and more. Since contracts are often built for scalability, Gas and storage costs are often delegated to the end user. If you charge the user for an access key and its allowance, when the key is deleted or used up, that allowance should be refunded to the purchaser. Currently, there is no way to query for the leftover allowance before a key is deleted. This information can tell you how much Gas was spent, and allows for a slew of different scenarios to arise. ## Rationale and alternatives -Without creating a promise, we can only query for information stored on the same shard. This is why in this proposal, the access key information at runtime will only come from keys stored on the current contract. We had also investigated the possibility of introducing pagination for all keys stored on the contract but this is infeasible at the moment due to the significant redesign requirement of the VM logic. +Without creating a promise, we can only query for information stored on the same shard. This is why in this proposal, the access key information at runtime will only come from keys stored on the current contract. We had also investigated the possibility of introducing pagination for all keys stored on the contract but this is infeasible at the moment due to the significant redesign requirement of the VM logic. In addition, we have thought about introducing a way to query for full access key information but this didn't seem useful and we can always add it in another NEP. ## Specification -In the runtime, key information will be queryable by passing in the desired public key. The key information will be of the following form. +In the runtime, function call access key information will be queryable via a function by passing in the desired public key. The key information will be of the following form. ```js -enum KeyPermission { - FullAccess, - FunctionCall(FunctionCall), -} - -type KeyInformation = { +type FunctionCallKeyInfo = { public_key: string, - access_key: { - nonce: number, - permission: KeyPermission - } -} - -type FunctionCall = { + nonce: number, receiver_id: string, allowance: string, method_names: Array, } ``` -The key information will expose the public key and access key data. If the key is a full access key, the permission will simply be a string `"FullAccess"`. If the key is a function call access key, the permission will be of type `FunctionCall`. - -This information should be queryable via a new function called `key_info_by_public_key_for_current_account` which takes a public key as a parameter. +This information should be queryable via a new function called `function_call_key_info_for_current_contract` which takes a public key as a parameter. ```ts -function key_info_by_public_key_for_current_account( +function function_call_key_info_for_current_contract( public_key: &PublicKey, -): KeyInformation | null +): FunctionCallKeyInfo | null ``` -This function should be exposed in the environment and callable using `env::key_info_by_public_key_for_current_account();`. An example of this can be seen below. +This function should be exposed in the environment and callable using `env::function_call_key_info_for_current_contract();`. An example of this can be seen below. ```rs pub fn check_key_exists(&self, pk: PublicKey) { - let key_info: KeyInformation = env::key_info_by_public_key_for_current_account(&pk); + let key_info: FunctionCallKeyInfo = env::function_call_key_info_for_current_contract(&pk); if let Some(info) = key_info { near_sdk::log!("key info found"); @@ -74,20 +61,21 @@ An example of returning the allowance of the key can be seen below. ```rs pub fn check_key_allowance(&self, pk: PublicKey) { - let key_info: KeyInformation = env::key_info_by_public_key_for_current_account(&pk).unwrap(); + let key_info: FunctionCallKeyInfo = env::function_call_key_info_for_current_contract(&pk).unwrap(); - if let KeyPermission::FunctionCall(fc) = key_info.access_key.permission { - let allowance = fc.allowance; - near_sdk::log!("key allowance: {}", allowance); - } else { - near_sdk::log!("key has no allowance as it's a full access key"); - } + let allowance = fc.allowance; + near_sdk::log!("key allowance: {}", allowance); } ``` ## Future possibilities -Some of the future possibilities for the standard could be to return a vector of `KeyInformation` by paginating through the keys on the contract. In addition, we could add a `key_total_supply` function that returns the number of access keys stored on the contract. One could also expand and introduce the ability to query for access key info from other contracts by using a promise. +There were several future possibilities we had discussed and decided it would be best to start small and expand in the future if there was public interest. One of which was the ability to query for full access key information as well. In addition, adding the ability to check the type of key as either full access or function call access would allow for an interesting slew of use-cases. + +We had also discussed the idea of paginating through keys on the contract and returning a vector of `FunctionCallKeyInfo`, or full access key info. In addition, we could add a `key_total_supply` function that returns the number of access keys stored on the contract. We had also thought of allowing + + +One could also expand and introduce the ability to query for access key info from other contracts by using a promise. ## Copyright [copyright]: #copyright From 047873d52b724f74a555f4e274ca7ada93e15646 Mon Sep 17 00:00:00 2001 From: Jakob Meier Date: Fri, 15 Jul 2022 10:00:20 +0200 Subject: [PATCH 4/8] Add runtime specification --- neps/nep-0371.md | 90 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 72 insertions(+), 18 deletions(-) diff --git a/neps/nep-0371.md b/neps/nep-0371.md index 56e671f32..201352b9e 100644 --- a/neps/nep-0371.md +++ b/neps/nep-0371.md @@ -11,7 +11,7 @@ Created: 13-Jul-2022 ## Summary -There is currently no way to query for information about function call access keys stored on your contract at runtime. +There is currently no way to query for information about access keys stored on a contract at runtime. Adding the host function `access_key_info` to the runtime specification will allow to query this for the current account an easy way. This fully covers the most important use cases that are currently known for querying access keys at runtime. ## Motivation @@ -19,35 +19,94 @@ As contracts start to use access keys in more creative ways, developers will wan ## Rationale and alternatives -Without creating a promise, we can only query for information stored on the same shard. This is why in this proposal, the access key information at runtime will only come from keys stored on the current contract. We had also investigated the possibility of introducing pagination for all keys stored on the contract but this is infeasible at the moment due to the significant redesign requirement of the VM logic. In addition, we have thought about introducing a way to query for full access key information but this didn't seem useful and we can always add it in another NEP. +Without creating a promise, we can only query for information stored on the same shard. This is why in this proposal, the access key information at runtime will only come from keys stored on the current contract. We had also investigated the possibility of introducing pagination for all keys stored on the contract but this is infeasible at the moment due to the significant redesign requirement of the VM logic. -## Specification +## Runtime specification -In the runtime, function call access key information will be queryable via a function by passing in the desired public key. The key information will be of the following form. +The contract runtime provides one host function called `access_key_info` which is callable in regular calls and views. + +```rust +fn access_key_info ( + public_key_len: u64, // in: number of bytes of the public key to query + public_key_ptr: u64, // in: pointer to the public key to query + nonce_ptr: u64 // out: pointer to where a u64 can be written by the host + allowance_ptr: u64, // out: pointer to where a u128 can be written by the host + account_id_register_id: u64, // out: register to write the access key holder account id + method_names_register_id: u64, // out: register to write the method names as a comma separated list +) +-> u64; +``` + +### Return values + +- Returns 0 if the given public key is not registered as access key to the current account. In this case, the memory locations behind `nonce_ptr` and `allowance_ptr` are not changed by the host. The register content of `account_id_register_id` and `method_names_register_id` are not changed, either. +- Returns 1 if the given public key is a full access key to the current account. The memory location at `nonce_ptr` contains the current nonce value of the access key. The memory location at `allowance_ptr` is not changed by the host. The register content of `account_id_register_id` and `method_names_register_id` are not changed, either. +- Returns 2 if the given public key is a function call access key to the current account. The memory location at `nonce_ptr` contains the current nonce value of the access key. The memory location at `allowance_ptr` contains a `u128` value that is the remaining allowance in yoctoNEAR. The register `account_id_register_id` contains the account name of the access key holder. The register `method_names_register_id` contains a comma separated list of all method names that the access key is valid for. + +### Panics + +- `InvalidPublicKey`: Calling `access_key_info` with an invalid public key. +- `MemoryAccessViolation`: Any of the following ranges are not fully inside the guest memory. + - [public_key_ptr, public_key_ptr + public_key_len) + - [nonce_ptr, nonce_ptr + 8) + - [allowance_ptr, allowance_ptr + 16) +- `InvalidRegisterId`: `account_id_register_id` and `method_names_register_id` are equal + +### Gas cost + +No new gas cost parameter needs to be created. The workload out upon the runtime is almost exactly the same as `storage_read`. The only difference is that two register are written to instead of only one. + +The gas cost for accessing is the base host-function cost (currently 264_768_111 gas) plus storage read costs (base 56_356_845_750 + 5_611_005 per byte + 30_952_533 per key_byte + *delayed* 16_101_955_926 for every touched trie node) + costs to write results into guest memory (2 x write_memory_base: 2_803_794_861 + write_memory_byte: 2_723_772 * num_bytes). + + +### Rationale behind runtime specification choices + +The parameter values are mostly analog to `promise_batch_action_add_key_with_function_call` but only the public key is an input parameter. All other parameters are used to define output locations. + +The output for nonce and allowance is of a small and fixed size, so a pointer to guest memory works well. + +The Receiver ID can be between 2 and 64 bytes, based on the limits of account id length. It is also thinkable that this range changes in the future. Using a register to return the location is the most flexible solution to make the host-function signature agnostic to this dynamic size. + +The method names list can be between 0 and 2000 bytes, based on `max_number_bytes_method_names` runtime parameter. Again, it is thinkable that this range changes in the future. The register is again the right choice here. + +## User perspective + +In the runtime, access key information will be queryable via a function by passing in the desired public key. The key information will be of the following form. ```js -type FunctionCallKeyInfo = { +enum KeyPermission { + FullAccess, + FunctionCall(FunctionCall), +} + +type KeyInformation = { public_key: string, - nonce: number, + access_key: { + nonce: number, + permission: KeyPermission + } +} + +type FunctionCall = { receiver_id: string, allowance: string, method_names: Array, } ``` -This information should be queryable via a new function called `function_call_key_info_for_current_contract` which takes a public key as a parameter. +This information should be queryable via a new function called `access_key_info_for_current_contract` which takes a public key as a parameter. ```ts -function function_call_key_info_for_current_contract( +function access_key_info_for_current_contract( public_key: &PublicKey, -): FunctionCallKeyInfo | null +): KeyInformation | null ``` -This function should be exposed in the environment and callable using `env::function_call_key_info_for_current_contract();`. An example of this can be seen below. +This function should be exposed in the environment and callable using `env::access_key_info_for_current_contract();`. An example of this can be seen below. ```rs pub fn check_key_exists(&self, pk: PublicKey) { - let key_info: FunctionCallKeyInfo = env::function_call_key_info_for_current_contract(&pk); + let key_info: FunctionCallKeyInfo = env::access_key_info_for_current_contract(&pk); if let Some(info) = key_info { near_sdk::log!("key info found"); @@ -61,7 +120,7 @@ An example of returning the allowance of the key can be seen below. ```rs pub fn check_key_allowance(&self, pk: PublicKey) { - let key_info: FunctionCallKeyInfo = env::function_call_key_info_for_current_contract(&pk).unwrap(); + let key_info: FunctionCallKeyInfo = env::access_key_info_for_current_contract(&pk).unwrap(); let allowance = fc.allowance; near_sdk::log!("key allowance: {}", allowance); @@ -70,12 +129,7 @@ pub fn check_key_allowance(&self, pk: PublicKey) { ## Future possibilities -There were several future possibilities we had discussed and decided it would be best to start small and expand in the future if there was public interest. One of which was the ability to query for full access key information as well. In addition, adding the ability to check the type of key as either full access or function call access would allow for an interesting slew of use-cases. - -We had also discussed the idea of paginating through keys on the contract and returning a vector of `FunctionCallKeyInfo`, or full access key info. In addition, we could add a `key_total_supply` function that returns the number of access keys stored on the contract. We had also thought of allowing - - -One could also expand and introduce the ability to query for access key info from other contracts by using a promise. +Some of the future possibilities for the standard could be to return a vector of KeyInformation by paginating through the keys on the contract. In addition, we could add a `key_total_supply` function that returns the number of access keys stored on the contract. One could also expand and introduce the ability to query for access key info from other contracts by using a promise. ## Copyright [copyright]: #copyright From 7e52d6cadd05e6c5b4af04991c48a1fc06f06556 Mon Sep 17 00:00:00 2001 From: Jakob Meier Date: Fri, 15 Jul 2022 12:07:03 +0200 Subject: [PATCH 5/8] Exact gas cost specification --- neps/nep-0371.md | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/neps/nep-0371.md b/neps/nep-0371.md index 201352b9e..4e1b60c47 100644 --- a/neps/nep-0371.md +++ b/neps/nep-0371.md @@ -54,10 +54,22 @@ fn access_key_info ( ### Gas cost -No new gas cost parameter needs to be created. The workload out upon the runtime is almost exactly the same as `storage_read`. The only difference is that two register are written to instead of only one. - -The gas cost for accessing is the base host-function cost (currently 264_768_111 gas) plus storage read costs (base 56_356_845_750 + 5_611_005 per byte + 30_952_533 per key_byte + *delayed* 16_101_955_926 for every touched trie node) + costs to write results into guest memory (2 x write_memory_base: 2_803_794_861 + write_memory_byte: 2_723_772 * num_bytes). - +No new gas cost parameter needs to be created. The workload put upon the runtime is almost exactly the same as `storage_read`, with slight changes to how the key is constructed and how values are returned + +The gas cost for accessing is the base host-function cost, storage read costs including trie node costs, and writing to guest memory cost. The exact list is given here. + +- `wasm_base` *-- host-function call base cost* +- `wasm_storage_read_base` +- `wasm_storage_read_key_byte` * `(2 + public_key_len + number of bytes in current account id)` +- `wasm_storage_read_value_byte` * `(number of bytes in method_names + number of bytes in returned account id)` +- `wasm_touching_trie_node` * `(number of accessed trie nodes that were no in chunk cache)` +- `wasm_read_cached_trie_node` * `(number of accessed trie nodes that were in chunk cache)` +- `wasm_write_memory_base` *-- for writing nonce to guest memory* +- 8 * `wasm_write_memory_byte` *-- for writing nonce to guest memory* + +Additional costs that only occur if the result is a function access key: +- `wasm_write_memory_base` *-- for writing allowance* +- 16 * `wasm_write_memory_byte` *-- for writing allowance* ### Rationale behind runtime specification choices From 186f0241d9901b5ce4a3afc0ef435d9e7b9c4808 Mon Sep 17 00:00:00 2001 From: BenKurrek Date: Fri, 15 Jul 2022 16:37:10 -0400 Subject: [PATCH 6/8] Changed NEP to review and added jakob's info --- neps/nep-0371.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neps/nep-0371.md b/neps/nep-0371.md index 4e1b60c47..8c496be18 100644 --- a/neps/nep-0371.md +++ b/neps/nep-0371.md @@ -1,11 +1,11 @@ --- NEP: 371 Title: Runtime Function Call Access Key Info -Author: Ben Kurrek +Author: Ben Kurrek , Jakob Meier DiscussionsTo: https://gov.near.org/t/expose-gas-price-and-contract-access-key-info-within-runtime/24788 Status: Draft Type: Standards Track -Category: Contract +Category: Review Created: 13-Jul-2022 --- From aecf5ad851a48303a8cbfb111a14b022c9c922c8 Mon Sep 17 00:00:00 2001 From: Jakob Meier Date: Mon, 18 Jul 2022 13:18:45 +0200 Subject: [PATCH 7/8] Add gas costs to write to registers --- neps/nep-0371.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/neps/nep-0371.md b/neps/nep-0371.md index 8c496be18..bdc7c29c6 100644 --- a/neps/nep-0371.md +++ b/neps/nep-0371.md @@ -70,6 +70,9 @@ The gas cost for accessing is the base host-function cost, storage read costs in Additional costs that only occur if the result is a function access key: - `wasm_write_memory_base` *-- for writing allowance* - 16 * `wasm_write_memory_byte` *-- for writing allowance* +- 2 * `write_register_base` +- `wasm_write_register_byte` * `(length of returned account id)` +- `wasm_write_register_byte` * `(length of returned method names list)` ### Rationale behind runtime specification choices From 74f2447e869e9506c6f11e746bafa7b18fffedf6 Mon Sep 17 00:00:00 2001 From: Jakob Meier Date: Mon, 18 Jul 2022 14:08:15 +0200 Subject: [PATCH 8/8] Be more specific about input public key --- neps/nep-0371.md | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/neps/nep-0371.md b/neps/nep-0371.md index bdc7c29c6..a1e52ab3b 100644 --- a/neps/nep-0371.md +++ b/neps/nep-0371.md @@ -27,16 +27,25 @@ The contract runtime provides one host function called `access_key_info` which i ```rust fn access_key_info ( - public_key_len: u64, // in: number of bytes of the public key to query - public_key_ptr: u64, // in: pointer to the public key to query - nonce_ptr: u64 // out: pointer to where a u64 can be written by the host - allowance_ptr: u64, // out: pointer to where a u128 can be written by the host - account_id_register_id: u64, // out: register to write the access key holder account id - method_names_register_id: u64, // out: register to write the method names as a comma separated list + /// in: number of bytes of the public key to query OR u64::MAX + public_key_len: u64, + /// in: pointer OR register ID to the public key to query + public_key_ptr: u64, + /// out: pointer to where a u64 can be written by the host + nonce_ptr: u64 + /// out: pointer to where a u128 can be written by the host + allowance_ptr: u64, + /// out: register to write the access key holder account id + account_id_register_id: u64, + /// out: register to write the method names as a comma separated list + method_names_register_id: u64, ) -> u64; ``` +Just like other host functions, such as `storage_read`, if `public_key_len` is set to `u64::MAX` it will treat the input as a register input instead of memory input. +That is, `public_key_ptr` will be used as a register id. + ### Return values - Returns 0 if the given public key is not registered as access key to the current account. In this case, the memory locations behind `nonce_ptr` and `allowance_ptr` are not changed by the host. The register content of `account_id_register_id` and `method_names_register_id` are not changed, either. @@ -50,6 +59,7 @@ fn access_key_info ( - [public_key_ptr, public_key_ptr + public_key_len) - [nonce_ptr, nonce_ptr + 8) - [allowance_ptr, allowance_ptr + 16) +- `MemoryAccessViolation`: If writing to the registers increases the total register memory beyond `registers_memory_limit`. - `InvalidRegisterId`: `account_id_register_id` and `method_names_register_id` are equal ### Gas cost @@ -60,13 +70,21 @@ The gas cost for accessing is the base host-function cost, storage read costs in - `wasm_base` *-- host-function call base cost* - `wasm_storage_read_base` -- `wasm_storage_read_key_byte` * `(2 + public_key_len + number of bytes in current account id)` +- `wasm_storage_read_key_byte` * `(2 + public key length + number of bytes in current account id)` - `wasm_storage_read_value_byte` * `(number of bytes in method_names + number of bytes in returned account id)` - `wasm_touching_trie_node` * `(number of accessed trie nodes that were no in chunk cache)` - `wasm_read_cached_trie_node` * `(number of accessed trie nodes that were in chunk cache)` - `wasm_write_memory_base` *-- for writing nonce to guest memory* - 8 * `wasm_write_memory_byte` *-- for writing nonce to guest memory* +If input public key is read from memory: +- `wasm_read_memory_base` +- `public_key_len` * `wasm_read_memory_byte` + +If input public key is read from register (`public_key_len` == `u64::MAX`): +- `wasm_read_register_base` +- (public key length) * `wasm_read_register_byte` + Additional costs that only occur if the result is a function access key: - `wasm_write_memory_base` *-- for writing allowance* - 16 * `wasm_write_memory_byte` *-- for writing allowance*