diff --git a/CHANGELOG.md b/CHANGELOG.md index bad5c2fc..a0e51955 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased](https://github.com/near/read-rpc/compare/main...develop) +### What's Changed +* Corrected state size calculation logic. +* Integrated cargo_pkg_version metric to reflect the current server version. +* Delete unnecessary debug logs about update blocks by finalities + +## [0.3.1](https://github.com/near/read-rpc/releases/tag/v0.3.1) + +### Supported Nearcore Version +- nearcore v2.3.0 +- rust v1.81.0 + ### What's Changed * Improved bulk insertion of state_changes, reducing database requests from hundreds to a maximum of 7 per block. * Configuration improvement. Create default config.toml on start application to loaded parameters from the environment variables. diff --git a/rpc-server/src/config.rs b/rpc-server/src/config.rs index f3271afc..65dacdab 100644 --- a/rpc-server/src/config.rs +++ b/rpc-server/src/config.rs @@ -153,6 +153,10 @@ impl ServerContext { let compiled_contract_code_cache = std::sync::Arc::new(CompiledCodeCache::new(contract_code_cache_size_in_bytes)); + crate::metrics::CARGO_PKG_VERSION + .with_label_values(&[NEARD_VERSION]) + .inc(); + Ok(Self { s3_client, db_manager: std::sync::Arc::new(Box::new(db_manager)), diff --git a/rpc-server/src/metrics.rs b/rpc-server/src/metrics.rs index 206f3509..745b90a4 100644 --- a/rpc-server/src/metrics.rs +++ b/rpc-server/src/metrics.rs @@ -1,5 +1,5 @@ use actix_web::{get, Responder}; -use prometheus::{Encoder, IntCounterVec, IntGauge, IntGaugeVec, Opts}; +use prometheus::{CounterVec, Encoder, IntCounterVec, IntGauge, IntGaugeVec, Opts}; type Result = std::result::Result; @@ -113,6 +113,14 @@ lazy_static! { "Optimistic updating status. 0: working, 1: not working", ).unwrap(); + pub(crate) static ref CARGO_PKG_VERSION: CounterVec = { + let opts = Opts::new("cargo_pkg_version", "Cargo package version. This is used to track the version of the running server.") + .variable_label("version"); + let counter_vec = CounterVec::new(opts, &["version"]).expect("metric can be created"); + prometheus::register(Box::new(counter_vec.clone())).unwrap(); + counter_vec + }; + pub(crate) static ref LEGACY_DATABASE_TX_DETAILS: IntCounterVec = register_int_counter_vec( "legacy_database_tx_details", "Total number of calls to the legacy database for transaction details", diff --git a/rpc-server/src/modules/blocks/mod.rs b/rpc-server/src/modules/blocks/mod.rs index 7fb9e714..e4fac836 100644 --- a/rpc-server/src/modules/blocks/mod.rs +++ b/rpc-server/src/modules/blocks/mod.rs @@ -335,10 +335,6 @@ impl BlocksInfoByFinality { // Update final block info in the cache. // Executes every second. pub async fn update_final_block(&self, block_info: BlockInfo) { - tracing::debug!( - "Update final block info: {:?}", - block_info.block_cache.block_height - ); let mut final_block_lock = self.final_block.write().await; final_block_lock.block_cache = block_info.block_cache; final_block_lock.block_view = block_info.block_view; @@ -348,11 +344,6 @@ impl BlocksInfoByFinality { // Update optimistic block changes and optimistic block info in the cache. // Executes every second. pub async fn update_optimistic_block(&self, block_info: BlockInfo) { - tracing::debug!( - "Update optimistic block info: {:?}", - block_info.block_cache.block_height - ); - let mut optimistic_changes_lock = self.optimistic_changes.write().await; optimistic_changes_lock.account_changes = block_info.changes_in_block_account_map().await; diff --git a/rpc-server/src/modules/queries/contract_runner/mod.rs b/rpc-server/src/modules/queries/contract_runner/mod.rs index b21062d3..470e4f03 100644 --- a/rpc-server/src/modules/queries/contract_runner/mod.rs +++ b/rpc-server/src/modules/queries/contract_runner/mod.rs @@ -1,9 +1,8 @@ use std::collections::HashMap; -use near_vm_runner::ContractRuntimeCache; - use crate::modules::blocks::BlocksInfoByFinality; use code_storage::CodeStorage; +use near_vm_runner::ContractRuntimeCache; mod code_storage; @@ -137,12 +136,31 @@ pub async fn run_contract( block_hash: block.block_hash, } })?; + println!("Contract code len {}", code.data.len()); contract_code_cache.put(code_hash, code.data.clone()).await; Contract::new(Some(code.data), code_hash) } } }; + // We need to calculate the state size of the contract to determine if we should prefetch the state or not. + // The state size is the storage usage minus the code size. + // If the state size is less than the prefetch_state_size_limit, we prefetch the state. + let code_len = if let Some(contract_code) = &contract_code.contract_code { + contract_code.code().len() + } else if let Some(code) = contract_code_cache.get(&code_hash).await { + code.len() + } else { + db_manager + .get_contract_code(account_id, block.block_height, "query_call_function") + .await + .map(|code| code.data.len()) + .unwrap_or_default() + }; + let state_size = contract + .data + .storage_usage() + .saturating_sub(code_len as u64); // Init an external database interface for the Runtime logic let code_storage = CodeStorage::init( db_manager.clone(), @@ -150,7 +168,7 @@ pub async fn run_contract( block.block_height, validators, optimistic_data, - contract.data.storage_usage() <= prefetch_state_size_limit, + state_size <= prefetch_state_size_limit, ) .await; diff --git a/rpc-server/src/modules/queries/methods.rs b/rpc-server/src/modules/queries/methods.rs index 3d628b48..92d85d6b 100644 --- a/rpc-server/src/modules/queries/methods.rs +++ b/rpc-server/src/modules/queries/methods.rs @@ -443,7 +443,19 @@ async fn view_state( block_hash: block.block_hash, }, )?; - if prefix.is_empty() && account.data.storage_usage() > data.prefetch_state_size_limit { + + // Calculate the state size excluding the contract code size to check if it's too large to fetch. + // The state size is the storage usage minus the code size. + // more details: nearcore/runtime/runtime/src/state_viewer/mod.rs:150 + let code_len = data + .db_manager + .get_contract_code(account_id, block.block_height, "query_view_state") + .await + .map(|code| code.data.len() as u64) + .unwrap_or_default(); + let state_size = account.data.storage_usage().saturating_sub(code_len); + // If the prefix is empty and the state size is larger than the limit, return an error. + if prefix.is_empty() && state_size > data.prefetch_state_size_limit { return Err( near_jsonrpc::primitives::types::query::RpcQueryError::TooLargeContractState { contract_account_id: account_id.clone(),