Skip to content
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

Corrected state size calculation logic #371

Merged
merged 4 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ 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
Expand Down
4 changes: 4 additions & 0 deletions rpc-server/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,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)),
Expand Down
10 changes: 9 additions & 1 deletion rpc-server/src/metrics.rs
Original file line number Diff line number Diff line change
@@ -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<T, E> = std::result::Result<T, E>;

Expand Down Expand Up @@ -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",
Expand Down
9 changes: 0 additions & 9 deletions rpc-server/src/modules/blocks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down
24 changes: 21 additions & 3 deletions rpc-server/src/modules/queries/contract_runner/mod.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -137,20 +136,39 @@ 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(),
account_id.clone(),
block.block_height,
validators,
optimistic_data,
contract.data.storage_usage() <= prefetch_state_size_limit,
state_size <= prefetch_state_size_limit,
)
.await;

Expand Down
14 changes: 13 additions & 1 deletion rpc-server/src/modules/queries/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
Loading