diff --git a/script/src/syscalls/load_cell.rs b/script/src/syscalls/load_cell.rs index c8fed1d814..596be0cb9c 100644 --- a/script/src/syscalls/load_cell.rs +++ b/script/src/syscalls/load_cell.rs @@ -1,4 +1,4 @@ -use crate::syscalls::{Source, LOAD_CELL_SYSCALL_NUMBER, SUCCESS}; +use crate::syscalls::{Source, ITEM_MISSING, LOAD_CELL_SYSCALL_NUMBER, SUCCESS}; use ckb_core::transaction::CellOutput; use ckb_protocol::CellOutput as FbsCellOutput; use ckb_vm::{CoreMachine, Error as VMError, Memory, Register, Syscalls, A0, A1, A2, A3, A4, A7}; @@ -51,9 +51,12 @@ impl<'a, R: Register, M: Memory> Syscalls for LoadCell<'a> { let index = machine.registers()[A3].to_usize(); let source = Source::parse_from_u64(machine.registers()[A4].to_u64())?; - let cell = self - .fetch_cell(source, index) - .ok_or_else(|| VMError::OutOfBound)?; + let cell = self.fetch_cell(source, index); + if cell.is_none() { + machine.registers_mut()[A0] = R::from_u8(ITEM_MISSING); + return Ok(true); + } + let cell = cell.unwrap(); // NOTE: this is a very expensive operation here since we need to copy // everything in a cell to a flatbuffer object, serialize the object diff --git a/script/src/syscalls/load_cell_by_field.rs b/script/src/syscalls/load_cell_by_field.rs index 8c4d40bfaa..5959afe0cd 100644 --- a/script/src/syscalls/load_cell_by_field.rs +++ b/script/src/syscalls/load_cell_by_field.rs @@ -50,9 +50,12 @@ impl<'a, R: Register, M: Memory> Syscalls for LoadCellByField<'a> { let source = Source::parse_from_u64(machine.registers()[A4].to_u64())?; let field = CellField::parse_from_u64(machine.registers()[A5].to_u64())?; - let cell = self - .fetch_cell(source, index) - .ok_or_else(|| VMError::OutOfBound)?; + let cell = self.fetch_cell(source, index); + if cell.is_none() { + machine.registers_mut()[A0] = R::from_u8(ITEM_MISSING); + return Ok(true); + } + let cell = cell.unwrap(); let return_code = match field { CellField::Capacity => { diff --git a/script/src/syscalls/mod.rs b/script/src/syscalls/mod.rs index e7479a23be..6bcc1437da 100644 --- a/script/src/syscalls/mod.rs +++ b/script/src/syscalls/mod.rs @@ -88,9 +88,7 @@ mod tests { use ckb_core::transaction::{CellInput, CellOutput, OutPoint}; use ckb_protocol::{CellOutput as FbsCellOutput, OutPoint as FbsOutPoint, Script as FbsScript}; use ckb_vm::machine::DefaultCoreMachine; - use ckb_vm::{ - CoreMachine, Error as VMError, Memory, SparseMemory, Syscalls, A0, A1, A2, A3, A4, A5, A7, - }; + use ckb_vm::{CoreMachine, Memory, SparseMemory, Syscalls, A0, A1, A2, A3, A4, A5, A7}; use flatbuffers::FlatBufferBuilder; use hash::sha3_256; use numext_fixed_hash::H256; @@ -163,7 +161,7 @@ mod tests { } } - fn _test_load_cell_out_of_bound(data: Vec) { + fn _test_load_cell_item_missing(data: Vec) { let mut machine = DefaultCoreMachine::::default(); let size_addr = 0; let addr = 100; @@ -191,13 +189,14 @@ mod tests { let input_cells = vec![&input_cell]; let mut load_cell = LoadCell::new(&outputs, &input_cells, &input_cell); - assert_eq!(load_cell.ecall(&mut machine), Err(VMError::OutOfBound)); // index out of bounds + assert!(load_cell.ecall(&mut machine).is_ok()); + assert_eq!(machine.registers()[A0], ITEM_MISSING as u64); } proptest! { #[test] - fn test_load_cell_out_of_bound(data in any_with::>(size_range(1000).lift())) { - _test_load_cell_out_of_bound(data); + fn test_load_cell_item_missing(data in any_with::>(size_range(1000).lift())) { + _test_load_cell_item_missing(data); } }