Skip to content

Commit 23b58e6

Browse files
authored
Merge pull request #5241 from mpapierski/core-68-fix-code-not-found-error-panic
CORE-68: Fix code not found error panic
2 parents 38a8ee0 + 57d857f commit 23b58e6

File tree

22 files changed

+301
-266
lines changed

22 files changed

+301
-266
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

binary_port/src/error_code.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,8 @@ pub enum ErrorCode {
370370
InvalidDelegationAmount = 116,
371371
#[error("Calling a stored contract by targeting it's `version` is not supported")]
372372
TargetingPackageVersionNotSupported = 117,
373+
#[error("the transaction invocation target is unsupported under V2 runtime")]
374+
UnsupportedInvocationTarget = 118,
373375
}
374376

375377
impl TryFrom<u16> for ErrorCode {
@@ -574,6 +576,9 @@ impl From<InvalidTransactionV1> for ErrorCode {
574576
InvalidTransactionV1::TargetingPackageVersionNotSupported => {
575577
ErrorCode::TargetingPackageVersionNotSupported
576578
}
579+
InvalidTransactionV1::UnsupportedInvocationTarget { .. } => {
580+
ErrorCode::UnsupportedInvocationTarget
581+
}
577582
_other => ErrorCode::InvalidTransactionUnspecified,
578583
}
579584
}
@@ -594,12 +599,12 @@ mod tests {
594599
assert_ne!(
595600
code,
596601
ErrorCode::InvalidTransactionUnspecified,
597-
"Seems like InvalidTransactionV1 {error} has no corresponding error code"
602+
"Seems like InvalidTransactionV1 {error:?} has no corresponding error code"
598603
);
599604
assert_ne!(
600605
code,
601606
ErrorCode::InvalidDeployUnspecified,
602-
"Seems like InvalidTransactionV1 {error} has no corresponding error code"
607+
"Seems like InvalidTransactionV1 {error:?} has no corresponding error code"
603608
)
604609
}
605610
}

executor/wasm/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,10 @@ casper-execution-engine = { version = "8.1.0", path = "../../execution_engine",
2222
"test-support",
2323
] }
2424
digest = "0.10.7"
25-
either = "1.10"
2625
parking_lot = "0.12.1"
2726
thiserror = "2.0"
2827
tracing = "0.1.40"
29-
28+
base16 = "0.2.1"
3029

3130
[dev-dependencies]
3231
tempfile = "3.10.1"

executor/wasm/src/lib.rs

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ use casper_types::{
4141
MessageLimits, Package, PackageHash, PackageStatus, Phase, ProtocolVersion, StorageCosts,
4242
StoredValue, TransactionInvocationTarget, URef, WasmV2Config, U512,
4343
};
44-
use either::Either;
4544
use install::{InstallContractError, InstallContractRequest, InstallContractResult};
4645
use parking_lot::RwLock;
4746
use system::{MintArgs, MintTransferArgs};
@@ -201,14 +200,13 @@ impl ExecutorV2 {
201200
);
202201

203202
let protocol_version = ProtocolVersion::V2_0_0;
204-
205203
let protocol_version_major = protocol_version.value().major;
204+
206205
let next_version = smart_contract.next_entity_version_for(protocol_version_major);
207-
let entity_hash =
208-
chain_utils::compute_next_contract_hash_version(smart_contract_addr, next_version);
206+
209207
let entity_version_key = smart_contract.insert_entity_version(
210208
protocol_version_major,
211-
EntityAddr::SmartContract(entity_hash),
209+
EntityAddr::SmartContract(smart_contract_addr),
212210
);
213211
debug_assert_eq!(entity_version_key.entity_version(), next_version);
214212

@@ -235,7 +233,8 @@ impl ExecutorV2 {
235233
);
236234

237235
// 3. Store addressable entity
238-
let addressable_entity_key = Key::AddressableEntity(EntityAddr::SmartContract(entity_hash));
236+
let addressable_entity_key =
237+
Key::AddressableEntity(EntityAddr::SmartContract(smart_contract_addr));
239238

240239
// TODO: abort(str) as an alternative to trap
241240
let main_purse: URef = match system::mint_mint(
@@ -316,9 +315,9 @@ impl ExecutorV2 {
316315

317316
gas_usage
318317
}
319-
Err(error) => {
320-
error!(%error, "unable to execute constructor");
321-
return Err(InstallContractError::Execute(error));
318+
Err(execute_error) => {
319+
error!(%execute_error, "unable to execute constructor");
320+
return Err(InstallContractError::Execute(execute_error));
322321
}
323322
}
324323
}
@@ -367,10 +366,10 @@ impl ExecutorV2 {
367366
// supported. let caller_entity_addr = EntityAddr::new_account(caller);
368367
let source_purse = get_purse_for_entity(&mut tracking_copy, caller_key);
369368

370-
let (wasm_bytes, export_or_selector): (_, Either<&str, u32>) = match &execution_kind {
369+
let (wasm_bytes, export_name) = match &execution_kind {
371370
ExecutionKind::SessionBytes(wasm_bytes) => {
372371
// self.execute_wasm(tracking_copy, address, gas_limit, wasm_bytes, input)
373-
(wasm_bytes.clone(), Either::Left(DEFAULT_WASM_ENTRY_POINT))
372+
(wasm_bytes.clone(), DEFAULT_WASM_ENTRY_POINT)
374373
}
375374
ExecutionKind::Stored {
376375
address: smart_contract_addr,
@@ -383,19 +382,14 @@ impl ExecutorV2 {
383382
.read_first(&[&legacy_key, &smart_contract_key])
384383
.expect("should read contract");
385384

386-
// let entity_addr: EntityAddr;
387-
388-
// Resolve indirection - get the latest version from the smart contract package
389-
// versions. let old_contract = contract.clone();
390-
// let latest_version_key;
391385
if let Some(StoredValue::SmartContract(smart_contract_package)) = &contract {
392386
let contract_hash = smart_contract_package
393387
.versions()
394388
.latest()
395389
.expect("should have last entry");
396390
let entity_addr = EntityAddr::SmartContract(contract_hash.value());
397391
let latest_version_key = Key::AddressableEntity(entity_addr);
398-
assert_ne!(&entity_addr.value(), smart_contract_addr);
392+
assert_eq!(&entity_addr.value(), smart_contract_addr);
399393
let new_contract = tracking_copy
400394
.read(&latest_version_key)
401395
.expect("should read latest version");
@@ -491,7 +485,7 @@ impl ExecutorV2 {
491485
}
492486
}
493487

494-
(Bytes::from(wasm_bytes), Either::Left(entry_point.as_str()))
488+
(Bytes::from(wasm_bytes), entry_point.as_str())
495489
}
496490
Some(StoredValue::Contract(_legacy_contract)) => {
497491
let block_info = BlockInfo::new(
@@ -522,7 +516,12 @@ impl ExecutorV2 {
522516
);
523517
}
524518
None => {
525-
panic!("No code found in {smart_contract_key:?}");
519+
error!(
520+
smart_contract_addr = base16::encode_lower(&smart_contract_addr),
521+
?execution_kind,
522+
"No contract code found",
523+
);
524+
return Err(ExecuteError::CodeNotFound(*smart_contract_addr));
526525
}
527526
}
528527
}
@@ -566,11 +565,7 @@ impl ExecutorV2 {
566565
let mut instance = vm.instantiate(wasm_bytes, context, wasm_instance_config)?;
567566

568567
self.push_execution_stack(execution_kind.clone());
569-
let (vm_result, gas_usage) = match export_or_selector {
570-
Either::Left(export_name) => instance.call_export(export_name),
571-
Either::Right(_entry_point) => todo!("Restore selectors"), /* instance.call_export(&
572-
* entry_point), */
573-
};
568+
let (vm_result, gas_usage) = instance.call_export(export_name);
574569

575570
let top_execution_kind = self
576571
.pop_execution_stack()
@@ -644,16 +639,23 @@ impl ExecutorV2 {
644639
messages: initial_tracking_copy.messages(),
645640
})
646641
}
647-
Err(VMError::Internal(host_error)) => {
648-
error!(?host_error, "host error");
649-
Ok(ExecuteResult {
650-
host_error: Some(CallError::InternalHost),
651-
output: None,
652-
gas_usage,
653-
effects: initial_tracking_copy.effects(),
654-
cache: initial_tracking_copy.cache(),
655-
messages: initial_tracking_copy.messages(),
656-
})
642+
Err(VMError::Execute(execute_error)) => {
643+
let effects = initial_tracking_copy.effects();
644+
let cache = initial_tracking_copy.cache();
645+
let messages = initial_tracking_copy.messages();
646+
error!(
647+
?execute_error,
648+
?gas_usage,
649+
?effects,
650+
?cache,
651+
?messages,
652+
"host error"
653+
);
654+
Err(execute_error)
655+
}
656+
Err(VMError::Internal(internal_error)) => {
657+
error!(?internal_error, "internal host error");
658+
Err(ExecuteError::InternalHost(internal_error))
657659
}
658660
}
659661
}

executor/wasm/tests/integration.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ use casper_executor_wasm::{
1616
};
1717
use casper_executor_wasm_common::error::CallError;
1818
use casper_executor_wasm_interface::executor::{
19-
ExecuteRequest, ExecuteRequestBuilder, ExecuteWithProviderResult, ExecutionKind,
19+
ExecuteError, ExecuteRequest, ExecuteRequestBuilder, ExecuteWithProviderError,
20+
ExecuteWithProviderResult, ExecutionKind,
2021
};
2122
use casper_storage::{
2223
data_access_layer::{
@@ -987,3 +988,31 @@ fn write_n_bytes_at_limit(
987988
// _ => false,
988989
// }));
989990
// }
991+
992+
#[test]
993+
fn non_existing_smart_contract_does_not_panic() {
994+
let address_generator = make_address_generator();
995+
let executor = make_executor();
996+
let (mut global_state, state_root_hash, _tempdir) = make_global_state_with_genesis();
997+
998+
let non_existing_address = [255; 32];
999+
let execute_request = base_execute_builder()
1000+
.with_target(ExecutionKind::Stored {
1001+
address: non_existing_address,
1002+
entry_point: "non_existing".to_string(),
1003+
})
1004+
.with_input(Bytes::new())
1005+
.with_gas_limit(DEFAULT_GAS_LIMIT)
1006+
.with_transferred_value(0)
1007+
.with_shared_address_generator(Arc::clone(&address_generator))
1008+
.build()
1009+
.expect("should build");
1010+
1011+
let result = executor
1012+
.execute_with_provider(state_root_hash, &mut global_state, execute_request)
1013+
.expect_err("Failure");
1014+
1015+
assert!(matches!(
1016+
result,
1017+
ExecuteWithProviderError::Execute(execute_error) if matches!(execute_error, ExecuteError::CodeNotFound(address) if address == non_existing_address)));
1018+
}

executor/wasm_common/src/chain_utils.rs

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,6 @@ pub fn compute_wasm_bytecode_hash<T: AsRef<[u8]>>(wasm_bytes: T) -> [u8; 32] {
3030
hash.into()
3131
}
3232

33-
#[must_use]
34-
pub fn compute_next_contract_hash_version(
35-
smart_contract_addr: [u8; 32],
36-
next_version: u32,
37-
) -> [u8; 32] {
38-
let mut hasher = Blake2b::<U32>::new();
39-
40-
hasher.update(smart_contract_addr);
41-
hasher.update(next_version.to_le_bytes());
42-
43-
hasher.finalize().into()
44-
}
45-
4633
#[cfg(test)]
4734
mod tests {
4835
const SEED: [u8; 32] = [1u8; 32];
@@ -58,16 +45,4 @@ mod tests {
5845
super::compute_predictable_address("mainnet", initiator, bytecode_hash, Some(SEED));
5946
assert_ne!(predictable_address_1, predictable_address_2);
6047
}
61-
62-
#[test]
63-
fn test_compute_nth_version_hash() {
64-
let smart_contract_addr = [1u8; 32];
65-
let mut next_version = 1;
66-
67-
let hash_1 = super::compute_next_contract_hash_version(smart_contract_addr, next_version);
68-
next_version += 1;
69-
70-
let hash_2 = super::compute_next_contract_hash_version(smart_contract_addr, next_version);
71-
assert_ne!(hash_1, hash_2);
72-
}
7348
}

executor/wasm_common/src/error.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,6 @@ pub enum CallError {
127127
/// Called contract is not callable.
128128
#[error("not callable")]
129129
NotCallable,
130-
/// Encountered a host function error.
131-
#[error("internal host")]
132-
InternalHost,
133130
}
134131

135132
impl CallError {
@@ -141,7 +138,6 @@ impl CallError {
141138
Self::CalleeTrapped(_) => CALLEE_TRAPPED,
142139
Self::CalleeGasDepleted => CALLEE_GAS_DEPLETED,
143140
Self::NotCallable => CALLEE_NOT_CALLABLE,
144-
Self::InternalHost => CALLEE_HOST_ERROR,
145141
}
146142
}
147143
}

executor/wasm_common/src/keyspace.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub enum Keyspace<'a> {
2424
///
2525
/// There's no additional payload for this variant as the host implies the contract's address.
2626
State,
27-
/// Stores contract's context date. Bytes can be any value as long as it uniquely identifies a
27+
/// Stores contract's context data. Bytes can be any value as long as it uniquely identifies a
2828
/// value.
2929
Context(&'a [u8]),
3030
/// Stores contract's named keys.

0 commit comments

Comments
 (0)