From f00ac62d64bda9cd36d1af92bdda4486e7089a16 Mon Sep 17 00:00:00 2001 From: Alexey Date: Fri, 17 Jan 2020 18:30:47 +0300 Subject: [PATCH 1/7] add an actual_amount to AccountView. Move rent calculation into account.rs --- chain/chain/src/test_utils.rs | 30 +++++++------ core/primitives/src/account.rs | 45 ++++++++++++++++++- core/primitives/src/types.rs | 2 +- core/primitives/src/utils.rs | 2 +- core/primitives/src/views.rs | 39 +++++++++++++--- .../genesis-csv-to-json/src/csv_parser.rs | 5 ++- genesis-tools/genesis-populate/src/lib.rs | 5 +-- near/src/config.rs | 5 +-- near/src/runtime.rs | 41 ++++++++++++----- runtime/runtime/src/actions.rs | 43 +++++++----------- runtime/runtime/src/store.rs | 5 ++- .../runtime/tests/runtime_group_tools/mod.rs | 5 +-- runtime/runtime/tests/test_regression.rs | 5 +-- test-utils/testlib/src/user/runtime_user.rs | 9 +++- 14 files changed, 163 insertions(+), 78 deletions(-) diff --git a/chain/chain/src/test_utils.rs b/chain/chain/src/test_utils.rs index e908d81f21c..3f1a3e91ad8 100644 --- a/chain/chain/src/test_utils.rs +++ b/chain/chain/src/test_utils.rs @@ -33,7 +33,8 @@ use near_primitives::types::{ StateRootNode, ValidatorStake, }; use near_primitives::views::{ - AccessKeyInfoView, AccessKeyList, EpochValidatorInfo, QueryResponse, QueryResponseKind, + AccessKeyInfoView, AccessKeyList, AccountView, EpochValidatorInfo, QueryResponse, + QueryResponseKind, }; use near_store::test_utils::create_test_store; use near_store::{ @@ -670,20 +671,21 @@ impl RuntimeAdapter for KeyValueRuntime { "account" => { let account_id = path[1].to_string(); let account_id2 = account_id.clone(); + let amount = self + .state + .read() + .unwrap() + .get(&state_root) + .map_or_else(|| 0, |state| *state.amounts.get(&account_id2).unwrap_or(&0)); Ok(QueryResponse { - kind: QueryResponseKind::ViewAccount( - Account { - amount: self.state.read().unwrap().get(&state_root).map_or_else( - || 0, - |state| *state.amounts.get(&account_id2).unwrap_or(&0), - ), - locked: 0, - code_hash: CryptoHash::default(), - storage_usage: 0, - storage_paid_at: 0, - } - .into(), - ), + kind: QueryResponseKind::ViewAccount(AccountView { + amount, + actual_amount: amount, + locked: 0, + code_hash: CryptoHash::default(), + storage_usage: 0, + storage_paid_at: 0, + }), block_height, }) } diff --git a/core/primitives/src/account.rs b/core/primitives/src/account.rs index b56653e9452..adfc7f89199 100644 --- a/core/primitives/src/account.rs +++ b/core/primitives/src/account.rs @@ -1,18 +1,22 @@ use borsh::{BorshDeserialize, BorshSerialize}; +use crate::serialize::u128_dec_format; + use crate::hash::CryptoHash; use crate::types::{AccountId, Balance, BlockHeight, Nonce, StorageUsage}; /// Per account information stored in the state. -#[derive(BorshSerialize, BorshDeserialize, Serialize, PartialEq, Eq, Debug, Clone)] +#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq, Debug, Clone)] pub struct Account { /// The total not locked tokens. + #[serde(with = "u128_dec_format")] pub amount: Balance, /// The amount locked due to staking + #[serde(with = "u128_dec_format")] pub locked: Balance, /// Hash of the code stored in the storage for this account. pub code_hash: CryptoHash, - /// Storage used by the given account. + /// Storage used by the given account (in bytes). pub storage_usage: StorageUsage, /// Last height at which the storage was paid for. pub storage_paid_at: BlockHeight, @@ -24,6 +28,43 @@ impl Account { } } +/// Calculates the storage rent for the given account +pub fn calculate_rent( + account_id: &AccountId, + account: &Account, + // TODO #1903 block_height: BlockHeight, + block_index: BlockHeight, + account_length_baseline_cost_per_block: Balance, + storage_cost_byte_per_block: Balance, +) -> Balance { + let charge = u128::from(block_index - account.storage_paid_at) + * cost_per_block( + account_id, + account, + account_length_baseline_cost_per_block, + storage_cost_byte_per_block, + ); + let actual_charge = std::cmp::min(account.amount, charge); + actual_charge +} + +pub fn cost_per_block( + account_id: &AccountId, + account: &Account, + account_length_baseline_cost_per_block: Balance, + storage_cost_byte_per_block: Balance, +) -> Balance { + let account_length_cost_per_block = if account_id.len() > 10 { + 0 + } else { + account_length_baseline_cost_per_block / 3_u128.pow(account_id.len() as u32 - 2) + }; + + let storage_cost_per_block = u128::from(account.storage_usage) * storage_cost_byte_per_block; + + account_length_cost_per_block + storage_cost_per_block +} + /// Access key provides limited access to an account. Each access key belongs to some account and /// is identified by a unique (within the account) public key. One account may have large number of /// access keys. Access keys allow to act on behalf of the account by restricting transactions diff --git a/core/primitives/src/types.rs b/core/primitives/src/types.rs index ce1119d6baa..e9b7298f778 100644 --- a/core/primitives/src/types.rs +++ b/core/primitives/src/types.rs @@ -12,7 +12,7 @@ pub type MerkleHash = CryptoHash; pub type ValidatorId = u64; /// Mask which validators participated in multi sign. pub type ValidatorMask = Vec; -/// StorageUsage is used to count the amount of storage used by a contract. +/// StorageUsage is used to count the amount of storage used by a contract (in bytes). pub type StorageUsage = u64; /// StorageUsageChange is used to count the storage usage within a single contract call. pub type StorageUsageChange = i64; diff --git a/core/primitives/src/utils.rs b/core/primitives/src/utils.rs index d36227e2250..a6307730dc6 100644 --- a/core/primitives/src/utils.rs +++ b/core/primitives/src/utils.rs @@ -297,7 +297,7 @@ where /// objects using tracing. /// /// ``` -/// tracing::debug!(target: "diagnostic", value=%ser(&object)); +/// // tracing::debug!(target: "diagnostic", value=%ser(&object)); /// ``` pub fn ser<'a, T>(object: &'a T) -> Serializable<'a, T> where diff --git a/core/primitives/src/views.rs b/core/primitives/src/views.rs index 15f4843711f..401522dc982 100644 --- a/core/primitives/src/views.rs +++ b/core/primitives/src/views.rs @@ -7,7 +7,9 @@ use chrono::{DateTime, Utc}; use borsh::{BorshDeserialize, BorshSerialize}; use near_crypto::{PublicKey, Signature}; -use crate::account::{AccessKey, AccessKeyPermission, Account, FunctionCallPermission}; +use crate::account::{ + calculate_rent, AccessKey, AccessKeyPermission, Account, FunctionCallPermission, +}; use crate::block::{Approval, Block, BlockHeader, BlockHeaderInnerLite, BlockHeaderInnerRest}; use crate::challenge::{Challenge, ChallengesResult}; use crate::errors::{ActionError, ExecutionError, InvalidAccessKeyError, InvalidTxError}; @@ -32,23 +34,48 @@ use crate::types::{ /// A view of the account #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct AccountView { + /// A spendable balance (before state rent charge) #[serde(with = "u128_dec_format")] pub amount: Balance, + /// An actual balance in storage + #[serde(with = "u128_dec_format")] + pub actual_amount: Balance, + /// The amount locked due to staking #[serde(with = "u128_dec_format")] pub locked: Balance, + /// Hash of the code stored in the storage for this account. pub code_hash: CryptoHash, + /// Storage used by the given account (in bytes). pub storage_usage: StorageUsage, + /// Last height at which the storage was paid for. pub storage_paid_at: BlockHeight, } -impl From for AccountView { - fn from(account: Account) -> Self { +impl AccountView { + /// Calculates spendable amount and transforms into the AccountView + pub fn from_account( + account_id: &AccountId, + account: &Account, + block_height: BlockHeight, + account_length_baseline_cost_per_block: Balance, + storage_cost_byte_per_block: Balance, + ) -> AccountView { + let actual_amount = account.amount; + let amount = actual_amount + - calculate_rent( + account_id, + account, + block_height, + account_length_baseline_cost_per_block, + storage_cost_byte_per_block, + ); AccountView { - amount: account.amount, - locked: account.locked, + amount, + actual_amount, code_hash: account.code_hash, storage_usage: account.storage_usage, storage_paid_at: account.storage_paid_at, + locked: account.locked, } } } @@ -56,7 +83,7 @@ impl From for AccountView { impl From for Account { fn from(view: AccountView) -> Self { Self { - amount: view.amount, + amount: view.actual_amount, locked: view.locked, code_hash: view.code_hash, storage_usage: view.storage_usage, diff --git a/genesis-tools/genesis-csv-to-json/src/csv_parser.rs b/genesis-tools/genesis-csv-to-json/src/csv_parser.rs index 3b8eb4c44d3..c526ba572a8 100644 --- a/genesis-tools/genesis-csv-to-json/src/csv_parser.rs +++ b/genesis-tools/genesis-csv-to-json/src/csv_parser.rs @@ -4,13 +4,14 @@ use csv::ReaderBuilder; use near::config::AccountInfo; use near_crypto::{KeyType, PublicKey}; use near_network::PeerInfo; +use near_primitives::account::Account; use near_primitives::hash::{hash, CryptoHash}; use near_primitives::receipt::{ActionReceipt, Receipt, ReceiptEnum}; use near_primitives::serialize::to_base64; use near_primitives::transaction::{Action, FunctionCallAction}; use near_primitives::types::{AccountId, Balance, Gas}; use near_primitives::utils::{create_nonce_with_nonce, is_valid_account_id}; -use near_primitives::views::{AccessKeyPermissionView, AccessKeyView, AccountView}; +use near_primitives::views::{AccessKeyPermissionView, AccessKeyView}; use node_runtime::StateRecord; use serde::{Deserialize, Serialize}; use std::fs::File; @@ -196,7 +197,7 @@ fn account_records(row: &Row, gas_price: Balance) -> Vec { let mut res = vec![StateRecord::Account { account_id: row.account_id.clone(), - account: AccountView { + account: Account { amount: row.amount, locked: row.validator_stake, code_hash: smart_contract_hash.into(), diff --git a/genesis-tools/genesis-populate/src/lib.rs b/genesis-tools/genesis-populate/src/lib.rs index f2d3a1ccc3a..6102add0fac 100644 --- a/genesis-tools/genesis-populate/src/lib.rs +++ b/genesis-tools/genesis-populate/src/lib.rs @@ -13,13 +13,12 @@ use tempdir::TempDir; use near::{get_store_path, GenesisConfig, NightshadeRuntime}; use near_chain::{Block, Chain, ChainStore, RuntimeAdapter, Tip}; use near_crypto::{InMemorySigner, KeyType}; -use near_primitives::account::AccessKey; +use near_primitives::account::{AccessKey, Account}; use near_primitives::block::genesis_chunks; use near_primitives::contract::ContractCode; use near_primitives::hash::{hash, CryptoHash}; use near_primitives::serialize::to_base64; use near_primitives::types::{AccountId, Balance, ChunkExtra, EpochId, ShardId, StateRoot}; -use near_primitives::views::AccountView; use near_store::{ create_store, get_account, set_access_key, set_account, set_code, ColState, Store, TrieUpdate, }; @@ -252,7 +251,7 @@ impl GenesisBuilder { self.state_updates.remove(&shard_id).expect("State update should have been added"); let signer = InMemorySigner::from_seed(&account_id, KeyType::ED25519, &account_id); - let account = AccountView { + let account = Account { amount: testing_init_balance, locked: testing_init_stake, code_hash: self.additional_accounts_code_hash.clone(), diff --git a/near/src/config.rs b/near/src/config.rs index 906b0d497b6..55ac032dc6d 100644 --- a/near/src/config.rs +++ b/near/src/config.rs @@ -21,14 +21,13 @@ use near_network::test_utils::open_port; use near_network::types::{PROTOCOL_VERSION, ROUTED_MESSAGE_TTL}; use near_network::utils::blacklist_from_vec; use near_network::NetworkConfig; -use near_primitives::account::AccessKey; +use near_primitives::account::{AccessKey, Account}; use near_primitives::hash::{hash, CryptoHash}; use near_primitives::serialize::{to_base64, u128_dec_format}; use near_primitives::types::{ AccountId, Balance, BlockHeightDelta, Gas, NumBlocks, NumSeats, NumShards, ShardId, }; use near_primitives::utils::{generate_random_string, get_num_seats_per_shard}; -use near_primitives::views::AccountView; use near_telemetry::TelemetryConfig; use node_runtime::config::RuntimeConfig; use node_runtime::StateRecord; @@ -652,7 +651,7 @@ fn state_records_account_with_key( vec![ StateRecord::Account { account_id: account_id.to_string(), - account: AccountView { + account: Account { amount, locked: staked, code_hash, diff --git a/near/src/runtime.rs b/near/src/runtime.rs index 69ec7fccfb3..e7e0896fceb 100644 --- a/near/src/runtime.rs +++ b/near/src/runtime.rs @@ -29,6 +29,7 @@ use near_primitives::types::{ StateRootNode, ValidatorStake, }; use near_primitives::utils::{prefix_for_access_key, ACCOUNT_DATA_SEPARATOR}; +use near_primitives::views::AccountView; use near_primitives::views::{ AccessKeyInfoView, CallResult, EpochValidatorInfo, QueryError, QueryResponse, QueryResponseKind, ViewStateResult, @@ -898,13 +899,25 @@ impl RuntimeAdapter for NightshadeRuntime { return Err("Path must contain at least single token".into()); } match path_parts[0] { - "account" => match self.view_account(*state_root, &AccountId::from(path_parts[1])) { - Ok(r) => Ok(QueryResponse { - kind: QueryResponseKind::ViewAccount(r.into()), - block_height, - }), - Err(e) => Err(e), - }, + "account" => { + let account_id = AccountId::from(path_parts[1]); + match self.view_account(*state_root, &account_id) { + Ok(account) => { + let runtime_config = &self.genesis_config.runtime_config; + Ok(QueryResponse { + kind: QueryResponseKind::ViewAccount(AccountView::from_account( + &account_id, + &account, + block_height, + runtime_config.account_length_baseline_cost_per_block, + runtime_config.storage_cost_byte_per_block, + )), + block_height, + }) + } + Err(e) => Err(e), + } + } "call" => { let mut logs = vec![]; match self.call_function( @@ -1393,10 +1406,16 @@ mod test { pub fn view_account(&self, account_id: &str) -> AccountView { let shard_id = self.runtime.account_id_to_shard_id(&account_id.to_string()); - self.runtime - .view_account(self.state_roots[shard_id as usize], &account_id.to_string()) - .unwrap() - .into() + AccountView::from_account( + &account_id.to_string(), + &self + .runtime + .view_account(self.state_roots[shard_id as usize], &account_id.to_string()) + .unwrap(), + 0, + 0, + 0, + ) } /// Compute per epoch per validator reward and per epoch protocol treasury reward diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index 0c55a7d4a95..0b12c499917 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use borsh::BorshSerialize; use log::debug; -use near_primitives::account::Account; +use near_primitives::account::{calculate_rent, cost_per_block, Account}; use near_primitives::contract::ContractCode; use near_primitives::hash::CryptoHash; use near_primitives::receipt::{ActionReceipt, Receipt}; @@ -33,24 +33,6 @@ use near_vm_runner::VMError; /// Number of epochs it takes to unstake. const NUM_UNSTAKING_EPOCHS: u64 = 3; -fn cost_per_block( - account_id: &AccountId, - account: &Account, - runtime_config: &RuntimeConfig, -) -> Balance { - let account_length_cost_per_block = if account_id.len() > 10 { - 0 - } else { - runtime_config.account_length_baseline_cost_per_block - / 3_u128.pow(account_id.len() as u32 - 2) - }; - - let storage_cost_per_block = u128::from(total_account_storage(account_id, account)) - * runtime_config.storage_cost_byte_per_block; - - account_length_cost_per_block + storage_cost_per_block -} - /// Returns Ok if the account has enough balance to pay storage rent for at least required number of blocks. /// Otherwise returns the amount required. /// Validators must have at least enough for `NUM_UNSTAKING_EPOCHS` * epoch_length of blocks, @@ -66,8 +48,13 @@ pub(crate) fn check_rent( } else { runtime_config.poke_threshold }; - let buffer_amount = - u128::from(buffer_length) * cost_per_block(account_id, account, runtime_config); + let buffer_amount = u128::from(buffer_length) + * cost_per_block( + account_id, + account, + runtime_config.account_length_baseline_cost_per_block, + runtime_config.storage_cost_byte_per_block, + ); if account.amount >= buffer_amount { Ok(()) } else { @@ -83,12 +70,16 @@ pub(crate) fn apply_rent( block_index: BlockHeight, runtime_config: &RuntimeConfig, ) -> Balance { - let charge = u128::from(block_index - account.storage_paid_at) - * cost_per_block(account_id, account, runtime_config); - let actual_charge = std::cmp::min(account.amount, charge); - account.amount -= actual_charge; + let rent = calculate_rent( + account_id, + account, + block_index, + runtime_config.account_length_baseline_cost_per_block, + runtime_config.storage_cost_byte_per_block, + ); + account.amount -= rent; account.storage_paid_at = block_index; - actual_charge + rent } pub(crate) fn get_code_with_cache( diff --git a/runtime/runtime/src/store.rs b/runtime/runtime/src/store.rs index 25c5e31b93f..696d349a330 100644 --- a/runtime/runtime/src/store.rs +++ b/runtime/runtime/src/store.rs @@ -1,14 +1,15 @@ use near_crypto::PublicKey; +use near_primitives::account::Account; use near_primitives::hash::CryptoHash; use near_primitives::serialize::option_base64_format; use near_primitives::types::AccountId; -use near_primitives::views::{AccessKeyView, AccountView, ReceiptView}; +use near_primitives::views::{AccessKeyView, ReceiptView}; /// Record in the state storage. #[derive(Serialize, Deserialize, Clone, Debug)] pub enum StateRecord { /// Account information. - Account { account_id: AccountId, account: AccountView }, + Account { account_id: AccountId, account: Account }, /// Data records inside the contract, encoded in base64. Data { key: String, value: String }, /// Contract code encoded in base64. diff --git a/runtime/runtime/tests/runtime_group_tools/mod.rs b/runtime/runtime/tests/runtime_group_tools/mod.rs index dd70ac674a2..b51d622e5d2 100644 --- a/runtime/runtime/tests/runtime_group_tools/mod.rs +++ b/runtime/runtime/tests/runtime_group_tools/mod.rs @@ -1,11 +1,10 @@ use near_crypto::{InMemorySigner, KeyType}; -use near_primitives::account::AccessKey; +use near_primitives::account::{AccessKey, Account}; use near_primitives::hash::{hash, CryptoHash}; use near_primitives::receipt::Receipt; use near_primitives::serialize::to_base64; use near_primitives::transaction::{ExecutionOutcomeWithId, SignedTransaction}; use near_primitives::types::{Balance, MerkleHash}; -use near_primitives::views::AccountView; use near_store::test_utils::create_trie; use near_store::{Trie, TrieUpdate}; use node_runtime::{ApplyState, Runtime, StateRecord}; @@ -144,7 +143,7 @@ impl RuntimeGroup { if i < num_existing_accounts { state_records.push(StateRecord::Account { account_id: account_id.to_string(), - account: AccountView { + account: Account { amount: TESTING_INIT_BALANCE, locked: TESTING_INIT_STAKE, code_hash: code_hash.clone().into(), diff --git a/runtime/runtime/tests/test_regression.rs b/runtime/runtime/tests/test_regression.rs index 272d638a20e..b8a42881d74 100644 --- a/runtime/runtime/tests/test_regression.rs +++ b/runtime/runtime/tests/test_regression.rs @@ -7,14 +7,13 @@ use runtime_group_tools::StandaloneRuntime; use indicatif::{ProgressBar, ProgressStyle}; use near_crypto::{InMemorySigner, KeyType}; -use near_primitives::account::AccessKey; +use near_primitives::account::{AccessKey, Account}; use near_primitives::contract::ContractCode; use near_primitives::hash::{hash, CryptoHash}; use near_primitives::serialize::to_base64; use near_primitives::transaction::{ Action, ExecutionStatus, FunctionCallAction, SignedTransaction, TransferAction, }; -use near_primitives::views::AccountView; use near_store::test_utils::create_trie; use near_store::{ create_store, get_account, set_access_key, set_account, set_code, Trie, TrieUpdate, @@ -100,7 +99,7 @@ fn template_test(transaction_type: TransactionType, db_type: DataBaseType, expec for account_index in chunk { let account_id = get_account_id(*account_index); let signer = InMemorySigner::from_seed(&account_id, KeyType::ED25519, &account_id); - let account = AccountView { + let account = Account { amount: TESTING_INIT_BALANCE, locked: TESTING_INIT_STAKE, code_hash: code_hash.clone().into(), diff --git a/test-utils/testlib/src/user/runtime_user.rs b/test-utils/testlib/src/user/runtime_user.rs index c5877d13aad..743a32c241d 100644 --- a/test-utils/testlib/src/user/runtime_user.rs +++ b/test-utils/testlib/src/user/runtime_user.rs @@ -186,7 +186,14 @@ impl User for RuntimeUser { let state_update = self.client.read().expect(POISONED_LOCK_ERR).get_state_update(); self.trie_viewer .view_account(&state_update, account_id) - .map(|account| account.into()) + .map(|account| AccountView { + code_hash: account.code_hash, + storage_usage: account.storage_usage, + storage_paid_at: account.storage_paid_at, + locked: account.locked, + actual_amount: account.amount, + amount: account.amount, + }) .map_err(|err| err.to_string()) } From 6308e84838ad2b0eb0b78b4df9b576e88974c81a Mon Sep 17 00:00:00 2001 From: Alexey Date: Wed, 22 Jan 2020 20:56:24 +0300 Subject: [PATCH 2/7] update doc comment Co-Authored-By: Maksym Zavershynskyi <35039879+nearmax@users.noreply.github.com> --- core/primitives/src/account.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/primitives/src/account.rs b/core/primitives/src/account.rs index adfc7f89199..262091b9409 100644 --- a/core/primitives/src/account.rs +++ b/core/primitives/src/account.rs @@ -28,7 +28,7 @@ impl Account { } } -/// Calculates the storage rent for the given account +/// Calculates the storage and the name rent for the given account pub fn calculate_rent( account_id: &AccountId, account: &Account, From 519fa848a623f6efe8a498b1aa9d837202dfeb1f Mon Sep 17 00:00:00 2001 From: Alexey Date: Thu, 23 Jan 2020 17:23:04 +0300 Subject: [PATCH 3/7] fix panic --- near/src/runtime.rs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/near/src/runtime.rs b/near/src/runtime.rs index e7e0896fceb..23ca2b87d7d 100644 --- a/near/src/runtime.rs +++ b/near/src/runtime.rs @@ -1173,6 +1173,7 @@ mod test { use near_chain::{ReceiptResult, RuntimeAdapter, Tip}; use near_client::BlockProducer; use near_crypto::{InMemorySigner, KeyType, Signer}; + use near_primitives::account::Account; use near_primitives::block::WeightAndScore; use near_primitives::challenge::{ChallengesResult, SlashedValidator}; use near_primitives::hash::{hash, CryptoHash}; @@ -1186,7 +1187,7 @@ mod test { StateRoot, ValidatorId, ValidatorStake, }; use near_primitives::utils::key_for_account; - use near_primitives::views::{AccountView, CurrentEpochValidatorInfo, EpochValidatorInfo}; + use near_primitives::views::{CurrentEpochValidatorInfo, EpochValidatorInfo}; use near_store::create_store; use node_runtime::adapter::ViewRuntimeAdapter; use node_runtime::config::RuntimeConfig; @@ -1404,18 +1405,11 @@ mod test { self.step(vec![transactions], vec![true], ChallengesResult::default()); } - pub fn view_account(&self, account_id: &str) -> AccountView { + pub fn view_account(&self, account_id: &str) -> Account { let shard_id = self.runtime.account_id_to_shard_id(&account_id.to_string()); - AccountView::from_account( - &account_id.to_string(), - &self - .runtime - .view_account(self.state_roots[shard_id as usize], &account_id.to_string()) - .unwrap(), - 0, - 0, - 0, - ) + self.runtime + .view_account(self.state_roots[shard_id as usize], &account_id.to_string()) + .unwrap() } /// Compute per epoch per validator reward and per epoch protocol treasury reward From 8c2b03fa022bca1ddc15acdcfdd48dc4c5623237 Mon Sep 17 00:00:00 2001 From: Alexey Date: Thu, 23 Jan 2020 18:08:43 +0300 Subject: [PATCH 4/7] fix grumbles --- core/primitives/src/account.rs | 6 ++++-- runtime/runtime/src/actions.rs | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/core/primitives/src/account.rs b/core/primitives/src/account.rs index 262091b9409..13d46a41325 100644 --- a/core/primitives/src/account.rs +++ b/core/primitives/src/account.rs @@ -29,6 +29,7 @@ impl Account { } /// Calculates the storage and the name rent for the given account +/// for period of account.storage_paid_at to current block_height pub fn calculate_rent( account_id: &AccountId, account: &Account, @@ -38,7 +39,7 @@ pub fn calculate_rent( storage_cost_byte_per_block: Balance, ) -> Balance { let charge = u128::from(block_index - account.storage_paid_at) - * cost_per_block( + * rent_per_block( account_id, account, account_length_baseline_cost_per_block, @@ -48,7 +49,8 @@ pub fn calculate_rent( actual_charge } -pub fn cost_per_block( +/// Calculates an account rent per block +pub fn rent_per_block( account_id: &AccountId, account: &Account, account_length_baseline_cost_per_block: Balance, diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index fd995cb2845..9005a1aee1a 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use borsh::BorshSerialize; use log::debug; -use near_primitives::account::{calculate_rent, cost_per_block, Account}; +use near_primitives::account::{calculate_rent, rent_per_block, Account}; use near_primitives::contract::ContractCode; use near_primitives::hash::CryptoHash; use near_primitives::receipt::{ActionReceipt, Receipt}; @@ -48,7 +48,7 @@ pub(crate) fn check_rent( runtime_config.poke_threshold }; let buffer_amount = u128::from(buffer_length) - * cost_per_block( + * rent_per_block( account_id, account, runtime_config.account_length_baseline_cost_per_block, From 3c8155aed1f79db781338cc2247c40bb975d8fd0 Mon Sep 17 00:00:00 2001 From: Alexey Date: Fri, 24 Jan 2020 15:38:22 +0300 Subject: [PATCH 5/7] fix grumbles --- chain/chain/src/test_utils.rs | 2 +- core/primitives/src/account.rs | 7 +++--- core/primitives/src/utils.rs | 4 +-- core/primitives/src/views.rs | 28 ++++++++++----------- near/src/runtime.rs | 2 +- test-utils/testlib/src/user/runtime_user.rs | 9 +------ 6 files changed, 21 insertions(+), 31 deletions(-) diff --git a/chain/chain/src/test_utils.rs b/chain/chain/src/test_utils.rs index d03de7c82a2..bce1069e414 100644 --- a/chain/chain/src/test_utils.rs +++ b/chain/chain/src/test_utils.rs @@ -682,7 +682,7 @@ impl RuntimeAdapter for KeyValueRuntime { Ok(QueryResponse { kind: QueryResponseKind::ViewAccount(AccountView { amount, - actual_amount: amount, + rent: 0, locked: 0, code_hash: CryptoHash::default(), storage_usage: 0, diff --git a/core/primitives/src/account.rs b/core/primitives/src/account.rs index 13d46a41325..fe9e2f96387 100644 --- a/core/primitives/src/account.rs +++ b/core/primitives/src/account.rs @@ -29,16 +29,15 @@ impl Account { } /// Calculates the storage and the name rent for the given account -/// for period of account.storage_paid_at to current block_height +/// for period from `account.storage_paid_at` to the current `block_height` pub fn calculate_rent( account_id: &AccountId, account: &Account, - // TODO #1903 block_height: BlockHeight, - block_index: BlockHeight, + block_height: BlockHeight, account_length_baseline_cost_per_block: Balance, storage_cost_byte_per_block: Balance, ) -> Balance { - let charge = u128::from(block_index - account.storage_paid_at) + let charge = u128::from(block_height.saturating_sub(account.storage_paid_at)) * rent_per_block( account_id, account, diff --git a/core/primitives/src/utils.rs b/core/primitives/src/utils.rs index e55e07dbeee..699941f53b3 100644 --- a/core/primitives/src/utils.rs +++ b/core/primitives/src/utils.rs @@ -307,8 +307,8 @@ where /// it shows its json representation. It is used to display complex /// objects using tracing. /// -/// ``` -/// // tracing::debug!(target: "diagnostic", value=%ser(&object)); +/// ```ignore +/// tracing::debug!(target: "diagnostic", value=%ser(&object)); /// ``` pub fn ser<'a, T>(object: &'a T) -> Serializable<'a, T> where diff --git a/core/primitives/src/views.rs b/core/primitives/src/views.rs index ae104dfabfa..33484826b8a 100644 --- a/core/primitives/src/views.rs +++ b/core/primitives/src/views.rs @@ -34,12 +34,12 @@ use crate::types::{ /// A view of the account #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct AccountView { - /// A spendable balance (before state rent charge) + /// A balance from storage #[serde(with = "u128_dec_format")] pub amount: Balance, - /// An actual balance in storage + /// Storage rent to pay on next transaction #[serde(with = "u128_dec_format")] - pub actual_amount: Balance, + pub rent: Balance, /// The amount locked due to staking #[serde(with = "u128_dec_format")] pub locked: Balance, @@ -60,18 +60,16 @@ impl AccountView { account_length_baseline_cost_per_block: Balance, storage_cost_byte_per_block: Balance, ) -> AccountView { - let actual_amount = account.amount; - let amount = actual_amount - - calculate_rent( - account_id, - account, - block_height, - account_length_baseline_cost_per_block, - storage_cost_byte_per_block, - ); + let rent = calculate_rent( + account_id, + account, + block_height, + account_length_baseline_cost_per_block, + storage_cost_byte_per_block, + ); AccountView { - amount, - actual_amount, + amount: account.amount, + rent, code_hash: account.code_hash, storage_usage: account.storage_usage, storage_paid_at: account.storage_paid_at, @@ -83,7 +81,7 @@ impl AccountView { impl From for Account { fn from(view: AccountView) -> Self { Self { - amount: view.actual_amount, + amount: view.amount, locked: view.locked, code_hash: view.code_hash, storage_usage: view.storage_usage, diff --git a/near/src/runtime.rs b/near/src/runtime.rs index 4efc5853ae3..731e3ea496f 100644 --- a/near/src/runtime.rs +++ b/near/src/runtime.rs @@ -1211,7 +1211,7 @@ mod test { }; use near_primitives::utils::key_for_account; use near_primitives::views::{ - AccountView, CurrentEpochValidatorInfo, EpochValidatorInfo, NextEpochValidatorInfo, + CurrentEpochValidatorInfo, EpochValidatorInfo, NextEpochValidatorInfo, }; use near_store::create_store; use node_runtime::adapter::ViewRuntimeAdapter; diff --git a/test-utils/testlib/src/user/runtime_user.rs b/test-utils/testlib/src/user/runtime_user.rs index 760c0a92790..388eb5ff913 100644 --- a/test-utils/testlib/src/user/runtime_user.rs +++ b/test-utils/testlib/src/user/runtime_user.rs @@ -189,14 +189,7 @@ impl User for RuntimeUser { let state_update = self.client.read().expect(POISONED_LOCK_ERR).get_state_update(); self.trie_viewer .view_account(&state_update, account_id) - .map(|account| AccountView { - code_hash: account.code_hash, - storage_usage: account.storage_usage, - storage_paid_at: account.storage_paid_at, - locked: account.locked, - actual_amount: account.amount, - amount: account.amount, - }) + .map(|account| AccountView::from_account(account_id, &account, 0, 0, 0)) .map_err(|err| err.to_string()) } From 5359f8b391848eaa0151c430741ee6a2162e15c5 Mon Sep 17 00:00:00 2001 From: Alexey Date: Fri, 24 Jan 2020 22:02:07 +0300 Subject: [PATCH 6/7] move let actual_charge = std::cmp::min(account.amount, rent) --- core/primitives/src/account.rs | 6 ++---- runtime/runtime/src/actions.rs | 3 ++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/core/primitives/src/account.rs b/core/primitives/src/account.rs index fe9e2f96387..f6d163bfde2 100644 --- a/core/primitives/src/account.rs +++ b/core/primitives/src/account.rs @@ -37,15 +37,13 @@ pub fn calculate_rent( account_length_baseline_cost_per_block: Balance, storage_cost_byte_per_block: Balance, ) -> Balance { - let charge = u128::from(block_height.saturating_sub(account.storage_paid_at)) + u128::from(block_height.saturating_sub(account.storage_paid_at)) * rent_per_block( account_id, account, account_length_baseline_cost_per_block, storage_cost_byte_per_block, - ); - let actual_charge = std::cmp::min(account.amount, charge); - actual_charge + ) } /// Calculates an account rent per block diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index 9005a1aee1a..5950e19fe7c 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -76,7 +76,8 @@ pub(crate) fn apply_rent( runtime_config.account_length_baseline_cost_per_block, runtime_config.storage_cost_byte_per_block, ); - account.amount -= rent; + let actual_charge = std::cmp::min(account.amount, rent); + account.amount -= actual_charge; account.storage_paid_at = block_index; rent } From abdd330a44e93a0cc5870d67a1d6984ae934d48d Mon Sep 17 00:00:00 2001 From: Alexey Date: Fri, 24 Jan 2020 22:40:14 +0300 Subject: [PATCH 7/7] return actual_charge --- runtime/runtime/src/actions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index 5950e19fe7c..9e15bab386a 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -79,7 +79,7 @@ pub(crate) fn apply_rent( let actual_charge = std::cmp::min(account.amount, rent); account.amount -= actual_charge; account.storage_paid_at = block_index; - rent + actual_charge } pub(crate) fn get_code_with_cache(