-
Notifications
You must be signed in to change notification settings - Fork 759
feat(gas-keys): charge compute for gas key nonce removal #15068
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,15 +1,16 @@ | ||||||||||||||||||||||||||||||||||
| use std::mem::size_of; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| use near_crypto::PublicKey; | ||||||||||||||||||||||||||||||||||
| use near_parameters::RuntimeFeesConfig; | ||||||||||||||||||||||||||||||||||
| use near_parameters::{RuntimeConfig, RuntimeFeesConfig}; | ||||||||||||||||||||||||||||||||||
| use near_primitives::account::{AccessKey, Account, GasKeyInfo}; | ||||||||||||||||||||||||||||||||||
| use near_primitives::action::{TransferToGasKeyAction, WithdrawFromGasKeyAction}; | ||||||||||||||||||||||||||||||||||
| use near_primitives::errors::{ActionErrorKind, IntegerOverflowError, RuntimeError}; | ||||||||||||||||||||||||||||||||||
| use near_primitives::transaction::{AddKeyAction, DeleteKeyAction}; | ||||||||||||||||||||||||||||||||||
| use near_primitives::types::{AccountId, BlockHeight, Compute, Nonce, NonceIndex, StorageUsage}; | ||||||||||||||||||||||||||||||||||
| use near_primitives::types::{AccountId, BlockHeight, Nonce, NonceIndex, StorageUsage}; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| use crate::config::safe_add_compute; | ||||||||||||||||||||||||||||||||||
| use crate::config::{safe_add_compute, storage_removes_compute}; | ||||||||||||||||||||||||||||||||||
| use crate::{ActionResult, ApplyState}; | ||||||||||||||||||||||||||||||||||
| use near_primitives::trie_key::gas_key_nonce_key_len; | ||||||||||||||||||||||||||||||||||
| use near_store::{ | ||||||||||||||||||||||||||||||||||
| StorageError, TrieUpdate, get_access_key, remove_access_key, remove_gas_key_nonce, | ||||||||||||||||||||||||||||||||||
| set_access_key, set_gas_key_nonce, | ||||||||||||||||||||||||||||||||||
|
|
@@ -42,20 +43,14 @@ fn gas_key_storage_cost( | |||||||||||||||||||||||||||||||||
| + access_key_storage_usage(fee_config, public_key, access_key) | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| /// Returns the compute cost for deleting a single gas key nonce. | ||||||||||||||||||||||||||||||||||
| fn gas_key_nonce_delete_compute_cost() -> Compute { | ||||||||||||||||||||||||||||||||||
| // TODO(gas-keys): properly handle GasKey fees | ||||||||||||||||||||||||||||||||||
| near_primitives::gas::Gas::ZERO.as_gas() | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| pub(crate) fn initial_nonce_value(block_height: BlockHeight) -> Nonce { | ||||||||||||||||||||||||||||||||||
| // Set default nonce for newly created access key to avoid transaction hash collision. | ||||||||||||||||||||||||||||||||||
| // See <https://github.com/near/nearcore/issues/3779>. | ||||||||||||||||||||||||||||||||||
| (block_height - 1) * near_primitives::account::AccessKey::ACCESS_KEY_NONCE_RANGE_MULTIPLIER | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| pub(crate) fn action_delete_key( | ||||||||||||||||||||||||||||||||||
| fee_config: &RuntimeFeesConfig, | ||||||||||||||||||||||||||||||||||
| config: &RuntimeConfig, | ||||||||||||||||||||||||||||||||||
| state_update: &mut TrieUpdate, | ||||||||||||||||||||||||||||||||||
| account: &mut Account, | ||||||||||||||||||||||||||||||||||
| result: &mut ActionResult, | ||||||||||||||||||||||||||||||||||
|
|
@@ -66,7 +61,7 @@ pub(crate) fn action_delete_key( | |||||||||||||||||||||||||||||||||
| if let Some(access_key) = access_key { | ||||||||||||||||||||||||||||||||||
| if let Some(gas_key_info) = access_key.gas_key_info() { | ||||||||||||||||||||||||||||||||||
| delete_gas_key( | ||||||||||||||||||||||||||||||||||
| fee_config, | ||||||||||||||||||||||||||||||||||
| config, | ||||||||||||||||||||||||||||||||||
| state_update, | ||||||||||||||||||||||||||||||||||
| account, | ||||||||||||||||||||||||||||||||||
| result, | ||||||||||||||||||||||||||||||||||
|
|
@@ -77,7 +72,7 @@ pub(crate) fn action_delete_key( | |||||||||||||||||||||||||||||||||
| )?; | ||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||
| delete_regular_key( | ||||||||||||||||||||||||||||||||||
| fee_config, | ||||||||||||||||||||||||||||||||||
| &config.fees, | ||||||||||||||||||||||||||||||||||
| state_update, | ||||||||||||||||||||||||||||||||||
| account, | ||||||||||||||||||||||||||||||||||
| account_id, | ||||||||||||||||||||||||||||||||||
|
|
@@ -96,7 +91,7 @@ pub(crate) fn action_delete_key( | |||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| fn delete_gas_key( | ||||||||||||||||||||||||||||||||||
| fee_config: &RuntimeFeesConfig, | ||||||||||||||||||||||||||||||||||
| config: &RuntimeConfig, | ||||||||||||||||||||||||||||||||||
| state_update: &mut TrieUpdate, | ||||||||||||||||||||||||||||||||||
| account: &mut Account, | ||||||||||||||||||||||||||||||||||
| result: &mut ActionResult, | ||||||||||||||||||||||||||||||||||
|
|
@@ -116,15 +111,21 @@ fn delete_gas_key( | |||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| result.tokens_burnt = | ||||||||||||||||||||||||||||||||||
| result.tokens_burnt.checked_add(gas_key_info.balance).ok_or(IntegerOverflowError)?; | ||||||||||||||||||||||||||||||||||
| let num_nonces = gas_key_info.num_nonces as usize; | ||||||||||||||||||||||||||||||||||
| for i in 0..gas_key_info.num_nonces { | ||||||||||||||||||||||||||||||||||
| remove_gas_key_nonce(state_update, account_id.clone(), public_key.clone(), i); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| let nonce_delete_compute_cost = | ||||||||||||||||||||||||||||||||||
| gas_key_nonce_delete_compute_cost() * gas_key_info.num_nonces as u64; | ||||||||||||||||||||||||||||||||||
| result.compute_usage = safe_add_compute(result.compute_usage, nonce_delete_compute_cost)?; | ||||||||||||||||||||||||||||||||||
| let nonce_key_len = gas_key_nonce_key_len(account_id, public_key); | ||||||||||||||||||||||||||||||||||
| let nonce_remove_compute = storage_removes_compute( | ||||||||||||||||||||||||||||||||||
| &config.wasm_config.ext_costs, | ||||||||||||||||||||||||||||||||||
| num_nonces, | ||||||||||||||||||||||||||||||||||
| nonce_key_len * num_nonces, | ||||||||||||||||||||||||||||||||||
| AccessKey::NONCE_VALUE_LEN * num_nonces, | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+119
to
+123
|
||||||||||||||||||||||||||||||||||
| let nonce_remove_compute = storage_removes_compute( | |
| &config.wasm_config.ext_costs, | |
| num_nonces, | |
| nonce_key_len * num_nonces, | |
| AccessKey::NONCE_VALUE_LEN * num_nonces, | |
| let total_nonce_key_len = | |
| nonce_key_len.checked_mul(num_nonces).ok_or(IntegerOverflowError)?; | |
| let total_nonce_value_len = | |
| AccessKey::NONCE_VALUE_LEN | |
| .checked_mul(num_nonces) | |
| .ok_or(IntegerOverflowError)?; | |
| let nonce_remove_compute = storage_removes_compute( | |
| &config.wasm_config.ext_costs, | |
| num_nonces, | |
| total_nonce_key_len, | |
| total_nonce_value_len, |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,6 +1,7 @@ | ||||||||||||||||||||||||||||||||||||
| use crate::access_keys::initial_nonce_value; | ||||||||||||||||||||||||||||||||||||
| use crate::config::{ | ||||||||||||||||||||||||||||||||||||
| safe_add_compute, total_prepaid_exec_fees, total_prepaid_gas, total_prepaid_send_fees, | ||||||||||||||||||||||||||||||||||||
| safe_add_compute, storage_removes_compute, total_prepaid_exec_fees, total_prepaid_gas, | ||||||||||||||||||||||||||||||||||||
| total_prepaid_send_fees, | ||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||
| use crate::deterministic_account_id::create_deterministic_account; | ||||||||||||||||||||||||||||||||||||
| use crate::{ActionResult, ApplyState}; | ||||||||||||||||||||||||||||||||||||
|
|
@@ -337,6 +338,7 @@ pub(crate) fn action_delete_account( | |||||||||||||||||||||||||||||||||||
| result: &mut ActionResult, | ||||||||||||||||||||||||||||||||||||
| account_id: &AccountId, | ||||||||||||||||||||||||||||||||||||
| delete_account: &DeleteAccountAction, | ||||||||||||||||||||||||||||||||||||
| config: &RuntimeConfig, | ||||||||||||||||||||||||||||||||||||
| current_protocol_version: ProtocolVersion, | ||||||||||||||||||||||||||||||||||||
| ) -> Result<(), StorageError> { | ||||||||||||||||||||||||||||||||||||
| let account_ref = account.as_ref().unwrap(); | ||||||||||||||||||||||||||||||||||||
|
|
@@ -377,11 +379,22 @@ pub(crate) fn action_delete_account( | |||||||||||||||||||||||||||||||||||
| .new_receipts | ||||||||||||||||||||||||||||||||||||
| .push(Receipt::new_balance_refund(&delete_account.beneficiary_id, account_balance)); | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| remove_account(state_update, account_id)?; | ||||||||||||||||||||||||||||||||||||
| let remove_result = remove_account(state_update, account_id)?; | ||||||||||||||||||||||||||||||||||||
| result.tokens_burnt = | ||||||||||||||||||||||||||||||||||||
| result.tokens_burnt.checked_add(gas_key_balance_to_burn).ok_or_else(|| { | ||||||||||||||||||||||||||||||||||||
| StorageError::StorageInconsistentState("tokens_burnt overflow".to_string()) | ||||||||||||||||||||||||||||||||||||
| })?; | ||||||||||||||||||||||||||||||||||||
| if remove_result.gas_key_nonce_count > 0 { | ||||||||||||||||||||||||||||||||||||
| let compute = storage_removes_compute( | ||||||||||||||||||||||||||||||||||||
| &config.wasm_config.ext_costs, | ||||||||||||||||||||||||||||||||||||
| remove_result.gas_key_nonce_count, | ||||||||||||||||||||||||||||||||||||
| remove_result.gas_key_nonce_total_key_bytes, | ||||||||||||||||||||||||||||||||||||
| AccessKey::NONCE_VALUE_LEN * remove_result.gas_key_nonce_count, | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+388
to
+392
|
||||||||||||||||||||||||||||||||||||
| let compute = storage_removes_compute( | |
| &config.wasm_config.ext_costs, | |
| remove_result.gas_key_nonce_count, | |
| remove_result.gas_key_nonce_total_key_bytes, | |
| AccessKey::NONCE_VALUE_LEN * remove_result.gas_key_nonce_count, | |
| let nonce_value_bytes = AccessKey::NONCE_VALUE_LEN | |
| .checked_mul(remove_result.gas_key_nonce_count) | |
| .ok_or_else(|| { | |
| StorageError::StorageInconsistentState( | |
| "gas_key_nonce_count overflow when computing nonce bytes".to_string(), | |
| ) | |
| })?; | |
| let compute = storage_removes_compute( | |
| &config.wasm_config.ext_costs, | |
| remove_result.gas_key_nonce_count, | |
| remove_result.gas_key_nonce_total_key_bytes, | |
| nonce_value_bytes, |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -6,7 +6,8 @@ use near_primitives::action::DeployGlobalContractAction; | |||||||||||||||||||||||||||||||||||||
| use near_primitives::errors::IntegerOverflowError; | ||||||||||||||||||||||||||||||||||||||
| // Just re-exporting RuntimeConfig for backwards compatibility. | ||||||||||||||||||||||||||||||||||||||
| use near_parameters::{ | ||||||||||||||||||||||||||||||||||||||
| ActionCosts, RuntimeConfig, RuntimeFeesConfig, transfer_exec_fee, transfer_send_fee, | ||||||||||||||||||||||||||||||||||||||
| ActionCosts, ExtCosts, ExtCostsConfig, RuntimeConfig, RuntimeFeesConfig, transfer_exec_fee, | ||||||||||||||||||||||||||||||||||||||
| transfer_send_fee, | ||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||
| pub use near_primitives::num_rational::Rational32; | ||||||||||||||||||||||||||||||||||||||
| use near_primitives::transaction::{Action, DeployContractAction, Transaction}; | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -68,6 +69,22 @@ fn gas_key_transfer_exec_fee( | |||||||||||||||||||||||||||||||||||||
| .unwrap() | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| /// Compute cost for `count` storage_remove operations with `total_key_bytes` total | ||||||||||||||||||||||||||||||||||||||
| /// key bytes and `total_value_bytes` total value bytes across all removals. | ||||||||||||||||||||||||||||||||||||||
| pub(crate) fn storage_removes_compute( | ||||||||||||||||||||||||||||||||||||||
| ext: &ExtCostsConfig, | ||||||||||||||||||||||||||||||||||||||
| count: usize, | ||||||||||||||||||||||||||||||||||||||
| total_key_bytes: usize, | ||||||||||||||||||||||||||||||||||||||
| total_value_bytes: usize, | ||||||||||||||||||||||||||||||||||||||
| ) -> Compute { | ||||||||||||||||||||||||||||||||||||||
| let count = count as u64; | ||||||||||||||||||||||||||||||||||||||
| let total_key_bytes = total_key_bytes as u64; | ||||||||||||||||||||||||||||||||||||||
| let total_value_bytes = total_value_bytes as u64; | ||||||||||||||||||||||||||||||||||||||
| ext.compute_cost(ExtCosts::storage_remove_base) * count | ||||||||||||||||||||||||||||||||||||||
| + ext.compute_cost(ExtCosts::storage_remove_key_byte) * total_key_bytes | ||||||||||||||||||||||||||||||||||||||
| + ext.compute_cost(ExtCosts::storage_remove_ret_value_byte) * total_value_bytes | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+83
to
+85
|
||||||||||||||||||||||||||||||||||||||
| ext.compute_cost(ExtCosts::storage_remove_base) * count | |
| + ext.compute_cost(ExtCosts::storage_remove_key_byte) * total_key_bytes | |
| + ext.compute_cost(ExtCosts::storage_remove_ret_value_byte) * total_value_bytes | |
| ext.compute_cost(ExtCosts::storage_remove_base) | |
| .checked_mul(count) | |
| .unwrap() | |
| .checked_add( | |
| ext.compute_cost(ExtCosts::storage_remove_key_byte) | |
| .checked_mul(total_key_bytes) | |
| .unwrap(), | |
| ) | |
| .unwrap() | |
| .checked_add( | |
| ext.compute_cost(ExtCosts::storage_remove_ret_value_byte) | |
| .checked_mul(total_value_bytes) | |
| .unwrap(), | |
| ) | |
| .unwrap() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The multiplication
nonce_key_len * num_noncescould potentially overflow. For consistency with similar code patterns in the codebase, consider using checked arithmetic (e.g.,checked_mul().unwrap()or returning a Result on overflow).