Skip to content

Commit e960e07

Browse files
committed
fix(runtime): clamp protocol version for view calls on archival nodes
1 parent 9c6e636 commit e960e07

4 files changed

Lines changed: 35 additions & 3 deletions

File tree

chain/chain/src/runtime/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ use near_primitives::types::{
3232
AccountId, Balance, BlockHeight, EpochHeight, EpochId, EpochInfoProvider, Gas, MerkleHash,
3333
Nonce, NonceIndex, NumShards, ShardId, StateRoot, StateRootNode,
3434
};
35-
use near_primitives::version::{ProtocolFeature, ProtocolVersion};
35+
use near_primitives::version::{
36+
ProtocolFeature, ProtocolVersion, clamp_to_supported_protocol_version,
37+
};
3638
use near_primitives::views::{
3739
AccessKeyInfoView, CallResult, ContractCodeView, GasKeyNoncesView, QueryRequest, QueryResponse,
3840
QueryResponseKind, ViewStateResult,
@@ -1690,7 +1692,7 @@ impl node_runtime::adapter::ViewRuntimeAdapter for NightshadeRuntime {
16901692
self.trie_viewer.view_account_contract_code(
16911693
&state_update,
16921694
account_id,
1693-
current_protocol_version,
1695+
clamp_to_supported_protocol_version(current_protocol_version),
16941696
&self.genesis_config.chain_id,
16951697
)
16961698
}
@@ -1719,7 +1721,7 @@ impl node_runtime::adapter::ViewRuntimeAdapter for NightshadeRuntime {
17191721
epoch_id: *epoch_id,
17201722
epoch_height,
17211723
block_timestamp,
1722-
current_protocol_version,
1724+
current_protocol_version: clamp_to_supported_protocol_version(current_protocol_version),
17231725
cache: Some(self.compiled_contract_cache.handle()),
17241726
};
17251727
self.trie_viewer.call_function(

core/primitives-core/src/version.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,31 @@ pub const PROD_GENESIS_PROTOCOL_VERSION: ProtocolVersion = 29;
504504
/// Minimum supported protocol version for the current binary
505505
pub const MIN_SUPPORTED_PROTOCOL_VERSION: ProtocolVersion = 80;
506506

507+
/// Returns the effective protocol version to use for processing a request.
508+
///
509+
/// Archival nodes can serve requests for blocks from protocol versions older than
510+
/// `MIN_SUPPORTED_PROTOCOL_VERSION`. Some features from those old versions may no longer be
511+
/// available in the current binary (e.g. the Wasmer0/Wasmer2 VM backends have been removed).
512+
/// For read-only view calls that don't produce on-chain state, it is safe to clamp the protocol
513+
/// version to `MIN_SUPPORTED_PROTOCOL_VERSION` so the request is processed with the config of
514+
/// the oldest fully-supported version.
515+
pub fn clamp_to_supported_protocol_version(
516+
current_protocol_version: ProtocolVersion,
517+
) -> ProtocolVersion {
518+
current_protocol_version.max(MIN_SUPPORTED_PROTOCOL_VERSION)
519+
}
520+
521+
/// Panics if `current_protocol_version` is below `MIN_SUPPORTED_PROTOCOL_VERSION`.
522+
///
523+
/// Use this at callee boundaries to enforce that the caller has already clamped the version
524+
/// via [`clamp_to_supported_protocol_version`].
525+
pub fn assert_supported_protocol_version(current_protocol_version: ProtocolVersion) {
526+
assert!(
527+
current_protocol_version >= MIN_SUPPORTED_PROTOCOL_VERSION,
528+
"protocol version {current_protocol_version} is below minimum supported {MIN_SUPPORTED_PROTOCOL_VERSION}"
529+
);
530+
}
531+
507532
/// Current protocol version used on the mainnet with all stable features.
508533
const STABLE_PROTOCOL_VERSION: ProtocolVersion = 83;
509534

core/primitives/src/version.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ pub use near_primitives_core::version::MIN_SUPPORTED_PROTOCOL_VERSION;
1919
pub use near_primitives_core::version::PROD_GENESIS_PROTOCOL_VERSION;
2020
pub use near_primitives_core::version::PROTOCOL_VERSION;
2121
pub use near_primitives_core::version::ProtocolFeature;
22+
pub use near_primitives_core::version::assert_supported_protocol_version;
23+
pub use near_primitives_core::version::clamp_to_supported_protocol_version;
2224

2325
/// Minimum gas price proposed in NEP 92 and the associated protocol version
2426
pub const MIN_GAS_PRICE_NEP_92: Balance = Balance::from_yoctonear(1_000_000_000);

runtime/runtime/src/state_viewer/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use near_primitives::trie_key::trie_key_parsers::{
2222
use near_primitives::types::{
2323
AccountId, Balance, BlockHeight, EpochHeight, EpochId, EpochInfoProvider, Gas, Nonce, ShardId,
2424
};
25+
use near_primitives::version::assert_supported_protocol_version;
2526
use near_primitives::views::{StateItem, ViewStateResult};
2627
use near_primitives_core::config::ViewConfig;
2728
use near_store::trie::AccessOptions;
@@ -97,6 +98,7 @@ impl TrieViewer {
9798
current_protocol_version: ProtocolVersion,
9899
chain_id: &str,
99100
) -> Result<ContractCode, errors::ViewContractCodeError> {
101+
assert_supported_protocol_version(current_protocol_version);
100102
let account = self.view_account(state_update, account_id)?;
101103
let wasm_config =
102104
&self.runtime_config_store.get_config(current_protocol_version).wasm_config;
@@ -271,6 +273,7 @@ impl TrieViewer {
271273
logs: &mut Vec<String>,
272274
epoch_info_provider: &dyn EpochInfoProvider,
273275
) -> Result<Vec<u8>, errors::CallFunctionError> {
276+
assert_supported_protocol_version(view_state.current_protocol_version);
274277
let now = Instant::now();
275278
let root = *state_update.get_root();
276279
let account = get_account(&state_update, contract_id)?.ok_or_else(|| {

0 commit comments

Comments
 (0)