Skip to content

Commit

Permalink
refactor(core, primitives): ContractCode getters (#4749)
Browse files Browse the repository at this point in the history
Resolves #4738
  • Loading branch information
shekhirin committed Sep 2, 2021
1 parent 264d2cb commit 1e5da20
Show file tree
Hide file tree
Showing 16 changed files with 49 additions and 44 deletions.
18 changes: 12 additions & 6 deletions core/primitives-core/src/contract.rs
@@ -1,21 +1,27 @@
use crate::hash::{hash as sha256, CryptoHash};

pub struct ContractCode {
pub code: Vec<u8>,
pub hash: CryptoHash,
code: Vec<u8>,
hash: CryptoHash,
}

impl ContractCode {
pub fn new(code: Vec<u8>, hash: Option<CryptoHash>) -> ContractCode {
let hash = hash.unwrap_or_else(|| sha256(&code));
debug_assert_eq!(hash, sha256(&code));

ContractCode { code, hash }
}

pub fn get_hash(&self) -> CryptoHash {
self.hash
pub fn code(&self) -> &[u8] {
self.code.as_slice()
}

pub fn into_code(self) -> Vec<u8> {
self.code
}

pub fn get_code(&self) -> &Vec<u8> {
&self.code
pub fn hash(&self) -> &CryptoHash {
&self.hash
}
}
6 changes: 4 additions & 2 deletions core/primitives/src/views.rs
Expand Up @@ -127,13 +127,15 @@ impl From<AccountView> for Account {

impl From<ContractCode> for ContractCodeView {
fn from(contract_code: ContractCode) -> Self {
ContractCodeView { code: contract_code.code, hash: contract_code.hash }
let hash = *contract_code.hash();
let code = contract_code.into_code();
ContractCodeView { code, hash }
}
}

impl From<ContractCodeView> for ContractCode {
fn from(contract_code: ContractCodeView) -> Self {
ContractCode { code: contract_code.code, hash: contract_code.hash }
ContractCode::new(contract_code.code, Some(contract_code.hash))
}
}

Expand Down
2 changes: 1 addition & 1 deletion core/store/src/lib.rs
Expand Up @@ -420,7 +420,7 @@ pub fn get_access_key_raw(
}

pub fn set_code(state_update: &mut TrieUpdate, account_id: AccountId, code: &ContractCode) {
state_update.set(TrieKey::ContractCode { account_id }, code.code.clone());
state_update.set(TrieKey::ContractCode { account_id }, code.code().to_vec());
}

pub fn get_code(
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/src/node/mod.rs
Expand Up @@ -158,7 +158,7 @@ pub fn create_nodes_from_seeds(seeds: Vec<String>) -> Vec<NodeConfig> {
{
if record_account_id.as_ref() == &seed {
is_account_record_found = true;
account.set_code_hash(ContractCode::new(code.to_vec(), None).get_hash());
account.set_code_hash(ContractCode::new(code.to_vec(), None).hash().clone());
}
}
}
Expand Down
9 changes: 4 additions & 5 deletions integration-tests/tests/runtime/state_viewer.rs
Expand Up @@ -3,6 +3,7 @@ use integration_tests::runtime_utils::{
};
use near_primitives::{
account::Account,
hash::hash as sha256,
hash::CryptoHash,
views::{StateItem, ViewApplyState},
};
Expand Down Expand Up @@ -168,15 +169,13 @@ fn test_view_state_too_large() {
fn test_view_state_with_large_contract() {
let (_, tries, root) = get_runtime_and_trie();
let mut state_update = tries.new_trie_update(TEST_SHARD_UID, root);
let contract_code = [0; Account::MAX_ACCOUNT_DELETION_STORAGE_USAGE as usize].to_vec();
set_account(
&mut state_update,
alice_account(),
&Account::new(0, 0, CryptoHash::default(), 50_001),
);
state_update.set(
TrieKey::ContractCode { account_id: alice_account() },
[0; Account::MAX_ACCOUNT_DELETION_STORAGE_USAGE as usize].to_vec(),
&Account::new(0, 0, sha256(&contract_code), 50_001),
);
state_update.set(TrieKey::ContractCode { account_id: alice_account() }, contract_code);
let trie_viewer = TrieViewer::new(Some(50_000), None);
let result = trie_viewer.view_state(&state_update, &alice_account(), b"");
assert!(result.is_ok());
Expand Down
28 changes: 13 additions & 15 deletions runtime/near-vm-runner/src/cache.rs
Expand Up @@ -56,7 +56,7 @@ pub fn get_contract_cache_key(
) -> CryptoHash {
let _span = tracing::debug_span!(target: "vm", "get_key").entered();
let key = ContractCacheKey::Version3 {
code_hash: code.hash,
code_hash: *code.hash(),
vm_config_non_crypto_hash: config.non_crypto_hash(),
vm_kind,
vm_hash: vm_hash(vm_kind),
Expand Down Expand Up @@ -211,9 +211,9 @@ pub mod wasmer0_cache {
) -> Result<wasmer_runtime::Module, VMError> {
let key = get_contract_cache_key(code, VMKind::Wasmer0, config);
#[cfg(not(feature = "no_cache"))]
return memcache_compile_module_cached_wasmer(key, &code.code, config, cache);
return memcache_compile_module_cached_wasmer(key, code.code(), config, cache);
#[cfg(feature = "no_cache")]
return compile_module_cached_wasmer_impl(key, &code.code, config, cache);
return compile_module_cached_wasmer_impl(key, code.code(), config, cache);
}
}

Expand Down Expand Up @@ -316,9 +316,9 @@ pub mod wasmer1_cache {
) -> Result<wasmer::Module, VMError> {
let key = get_contract_cache_key(code, VMKind::Wasmer1, config);
#[cfg(not(feature = "no_cache"))]
return memcache_compile_module_cached_wasmer1(key, &code.code, config, cache, store);
return memcache_compile_module_cached_wasmer1(key, code.code(), config, cache, store);
#[cfg(feature = "no_cache")]
return compile_module_cached_wasmer1_impl(key, &code.code, config, cache, store);
return compile_module_cached_wasmer1_impl(key, code.code(), config, cache, store);
}
}

Expand All @@ -340,19 +340,17 @@ pub fn precompile_contract_vm(
Ok(None) | Err(_) => {}
};
match vm_kind {
VMKind::Wasmer0 => match wasmer0_cache::compile_and_serialize_wasmer(
wasm_code.code.as_slice(),
config,
&key,
cache,
) {
Ok(_) => Ok(ContractPrecompilatonResult::ContractCompiled),
Err(err) => Err(ContractPrecompilatonError::new(err)),
},
VMKind::Wasmer0 => {
match wasmer0_cache::compile_and_serialize_wasmer(wasm_code.code(), config, &key, cache)
{
Ok(_) => Ok(ContractPrecompilatonResult::ContractCompiled),
Err(err) => Err(ContractPrecompilatonError::new(err)),
}
}
VMKind::Wasmer1 => {
let store = default_wasmer1_store();
match wasmer1_cache::compile_and_serialize_wasmer1(
wasm_code.code.as_slice(),
wasm_code.code(),
&key,
config,
cache,
Expand Down
2 changes: 1 addition & 1 deletion runtime/near-vm-runner/src/wasmer1_runner.rs
Expand Up @@ -241,7 +241,7 @@ pub fn run_wasmer1(
);

// TODO: remove, as those costs are incorrectly computed, and we shall account it on deployment.
if logic.add_contract_compile_fee(code.code.len() as u64).is_err() {
if logic.add_contract_compile_fee(code.code().len() as u64).is_err() {
return (
Some(logic.outcome()),
Some(VMError::FunctionCallError(FunctionCallError::HostError(
Expand Down
2 changes: 1 addition & 1 deletion runtime/near-vm-runner/src/wasmer_runner.rs
Expand Up @@ -265,7 +265,7 @@ pub fn run_wasmer<'a>(
);

// TODO: remove, as those costs are incorrectly computed, and we shall account it on deployment.
if logic.add_contract_compile_fee(code.code.len() as u64).is_err() {
if logic.add_contract_compile_fee(code.code().len() as u64).is_err() {
return (
Some(logic.outcome()),
Some(VMError::FunctionCallError(FunctionCallError::HostError(
Expand Down
4 changes: 2 additions & 2 deletions runtime/near-vm-runner/src/wasmtime_runner.rs
Expand Up @@ -161,7 +161,7 @@ pub mod wasmtime_runner {
wasm_config.limit_config.max_memory_pages,
)
.unwrap();
let prepared_code = match prepare::prepare_contract(&code.code, wasm_config) {
let prepared_code = match prepare::prepare_contract(code.code(), wasm_config) {
Ok(code) => code,
Err(err) => return (None, Some(VMError::from(err))),
};
Expand All @@ -182,7 +182,7 @@ pub mod wasmtime_runner {
current_protocol_version,
);
// TODO: remove, as those costs are incorrectly computed, and we shall account it on deployment.
if logic.add_contract_compile_fee(code.code.len() as u64).is_err() {
if logic.add_contract_compile_fee(code.code().len() as u64).is_err() {
return (
Some(logic.outcome()),
Some(VMError::FunctionCallError(FunctionCallError::HostError(
Expand Down
2 changes: 1 addition & 1 deletion runtime/runtime-params-estimator/src/function_call.rs
Expand Up @@ -21,7 +21,7 @@ fn test_function_call(metric: GasMetric, vm_kind: VMKind) {
let contract = make_many_methods_contract(method_count);
let cost = compute_function_call_cost(metric, vm_kind, REPEATS, &contract);
println!("{:?} {:?} {} {}", vm_kind, metric, method_count, cost / REPEATS);
xs.push(contract.get_code().len() as u64);
xs.push(contract.code().len() as u64);
ys.push(cost / REPEATS);
}

Expand Down
8 changes: 4 additions & 4 deletions runtime/runtime/src/actions.rs
Expand Up @@ -429,17 +429,17 @@ pub(crate) fn action_deploy_contract(
) -> Result<(), StorageError> {
let code = ContractCode::new(deploy_contract.code.clone(), None);
let prev_code = get_code(state_update, account_id, Some(account.code_hash()))?;
let prev_code_length = prev_code.map(|code| code.code.len() as u64).unwrap_or_default();
let prev_code_length = prev_code.map(|code| code.code().len() as u64).unwrap_or_default();
account.set_storage_usage(account.storage_usage().checked_sub(prev_code_length).unwrap_or(0));
account.set_storage_usage(
account.storage_usage().checked_add(code.code.len() as u64).ok_or_else(|| {
account.storage_usage().checked_add(code.code().len() as u64).ok_or_else(|| {
StorageError::StorageInconsistentState(format!(
"Storage usage integer overflow for account {}",
account_id
))
})?,
);
account.set_code_hash(code.get_hash());
account.set_code_hash(*code.hash());
set_code(state_update, account_id.clone(), &code);
// Precompile the contract and store result (compiled code or error) in the database.
// Note, that contract compilation costs are already accounted in deploy cost using
Expand All @@ -464,7 +464,7 @@ pub(crate) fn action_delete_account(
let contract_code = get_code(state_update, account_id, Some(account.code_hash()))?;
if let Some(code) = contract_code {
// account storage usage should be larger than code size
let code_len = code.code.len() as u64;
let code_len = code.code().len() as u64;
debug_assert!(account_storage_usage > code_len);
account_storage_usage = account_storage_usage.saturating_sub(code_len);
}
Expand Down
2 changes: 1 addition & 1 deletion runtime/runtime/src/cache.rs
Expand Up @@ -10,7 +10,7 @@ pub(crate) fn get_code(
) -> Result<Option<Arc<ContractCode>>, StorageError> {
let code = f()?;
Ok(code.map(|code| {
assert_eq!(code_hash, code.get_hash());
assert_eq!(code_hash, *code.hash());
Arc::new(code)
}))
}
2 changes: 1 addition & 1 deletion runtime/runtime/src/genesis.rs
Expand Up @@ -126,7 +126,7 @@ impl GenesisStateApplier {
// Recompute contract code hash.
let code = ContractCode::new(code, None);
set_code(&mut state_update, account_id, &code);
assert_eq!(code.get_hash(), acc.code_hash());
assert_eq!(*code.hash(), acc.code_hash());
}
StateRecord::AccessKey { account_id, public_key, access_key } => {
set_access_key(&mut state_update, account_id, public_key, &access_key);
Expand Down
2 changes: 1 addition & 1 deletion runtime/runtime/src/lib.rs
Expand Up @@ -1421,7 +1421,7 @@ impl Runtime {
// Recompute contract code hash.
let code = ContractCode::new(code, None);
set_code(state_update, account_id, &code);
assert_eq!(code.get_hash(), acc.code_hash());
assert_eq!(*code.hash(), acc.code_hash());
}
StateRecord::AccessKey { account_id, public_key, access_key } => {
set_access_key(state_update, account_id, public_key, &access_key);
Expand Down
2 changes: 1 addition & 1 deletion runtime/runtime/src/state_viewer/mod.rs
Expand Up @@ -120,7 +120,7 @@ impl TrieViewer {
match get_account(state_update, account_id)? {
Some(account) => {
let code_len = get_code(state_update, account_id, Some(account.code_hash()))?
.map(|c| c.code.len() as u64)
.map(|c| c.code().len() as u64)
.unwrap_or_default();
if let Some(limit) = self.state_size_limit {
if account.storage_usage().saturating_sub(code_len) > limit {
Expand Down
2 changes: 1 addition & 1 deletion test-utils/state-viewer/src/main.rs
Expand Up @@ -645,7 +645,7 @@ fn check_block_chunk_existence(store: Arc<Store>, near_config: &NearConfig) {

fn dump_code(account: &str, contract_code: ContractCode, output: &str) {
let mut file = File::create(output).unwrap();
file.write_all(&contract_code.code).unwrap();
file.write_all(contract_code.code()).unwrap();
println!("Dump contract of account {} into file {}", account, output);
}

Expand Down

0 comments on commit 1e5da20

Please sign in to comment.