diff --git a/script/src/syscalls/load_cell.rs b/script/src/syscalls/load_cell.rs index 596be0cb9c..1f79530da5 100644 --- a/script/src/syscalls/load_cell.rs +++ b/script/src/syscalls/load_cell.rs @@ -73,8 +73,9 @@ impl<'a, R: Register, M: Memory> Syscalls for LoadCell<'a> { let data = builder.finished_data(); let offset = machine.registers()[A2].to_usize(); - let real_size = cmp::min(size, data.len() - offset); - machine.memory_mut().store64(size_addr, real_size as u64)?; + let full_size = data.len() - offset; + let real_size = cmp::min(size, full_size); + machine.memory_mut().store64(size_addr, full_size as u64)?; machine .memory_mut() .store_bytes(addr, &data[offset..offset + real_size])?; diff --git a/script/src/syscalls/load_tx.rs b/script/src/syscalls/load_tx.rs index b3c5cca658..066195b8dd 100644 --- a/script/src/syscalls/load_tx.rs +++ b/script/src/syscalls/load_tx.rs @@ -29,8 +29,9 @@ impl<'a, R: Register, M: Memory> Syscalls for LoadTx<'a> { let data = self.tx; let offset = machine.registers()[A2].to_usize(); - let real_size = cmp::min(size, data.len() - offset); - machine.memory_mut().store64(size_addr, real_size as u64)?; + let full_size = data.len() - offset; + let real_size = cmp::min(size, full_size); + machine.memory_mut().store64(size_addr, full_size as u64)?; machine .memory_mut() .store_bytes(addr, &data[offset..offset + real_size])?; diff --git a/script/src/syscalls/mod.rs b/script/src/syscalls/mod.rs index fdf643e139..8130963ba6 100644 --- a/script/src/syscalls/mod.rs +++ b/script/src/syscalls/mod.rs @@ -127,6 +127,48 @@ mod tests { } } + fn _test_load_tx_length(tx: &Vec) { + let mut machine = DefaultCoreMachine::::default(); + let size_addr = 0; + let addr = 100; + + machine.registers_mut()[A0] = addr; // addr + machine.registers_mut()[A1] = size_addr; // size_addr + machine.registers_mut()[A2] = 0; // offset + machine.registers_mut()[A7] = LOAD_TX_SYSCALL_NUMBER; // syscall number + + assert!(machine.memory_mut().store64(size_addr as usize, 0).is_ok()); + + let mut load_tx = LoadTx::new(tx); + assert!(load_tx.ecall(&mut machine).is_ok()); + + assert_eq!(machine.registers()[A0], SUCCESS as u64); + assert_eq!( + machine.memory_mut().load64(size_addr as usize), + Ok(tx.len() as u64) + ); + + machine.registers_mut()[A0] = addr; // addr + machine.registers_mut()[A2] = 100; // offset + + assert!(machine.memory_mut().store64(size_addr as usize, 0).is_ok()); + + assert!(load_tx.ecall(&mut machine).is_ok()); + + assert_eq!(machine.registers()[A0], SUCCESS as u64); + assert_eq!( + machine.memory_mut().load64(size_addr as usize), + Ok(tx.len() as u64 - 100) + ); + } + + proptest! { + #[test] + fn test_load_tx_length(ref tx in any_with::>(size_range(1000).lift())) { + _test_load_tx_length(tx); + } + } + fn _test_load_tx_partial(tx: &Vec) { let mut machine = DefaultCoreMachine::::default(); let size_addr = 0; @@ -285,6 +327,52 @@ mod tests { } } + fn _test_load_cell_length(data: Vec) { + let mut machine = DefaultCoreMachine::::default(); + let size_addr = 0; + let addr = 100; + + machine.registers_mut()[A0] = addr; // addr + machine.registers_mut()[A1] = size_addr; // size_addr + machine.registers_mut()[A2] = 0; // offset + machine.registers_mut()[A3] = 0; //index + machine.registers_mut()[A4] = 0; //source: 0 input + machine.registers_mut()[A7] = LOAD_CELL_SYSCALL_NUMBER; // syscall number + + let output = CellOutput::new(100, data.clone(), H256::zero(), None); + let input_cell = CellOutput::new( + 100, + data.iter().rev().cloned().collect(), + H256::zero(), + None, + ); + let outputs = vec![&output]; + let input_cells = vec![&input_cell]; + let mut load_cell = LoadCell::new(&outputs, &input_cells, &input_cell); + + let mut builder = FlatBufferBuilder::new(); + let fbs_offset = FbsCellOutput::build(&mut builder, &input_cell); + builder.finish(fbs_offset, None); + let input_correct_data = builder.finished_data(); + + assert!(machine.memory_mut().store64(size_addr as usize, 0).is_ok()); + + assert!(load_cell.ecall(&mut machine).is_ok()); + assert_eq!(machine.registers()[A0], SUCCESS as u64); + + assert_eq!( + machine.memory_mut().load64(size_addr as usize), + Ok(input_correct_data.len() as u64) + ); + } + + proptest! { + #[test] + fn test_load_cell_length(tx in any_with::>(size_range(1000).lift())) { + _test_load_cell_length(tx); + } + } + fn _test_load_cell_partial(data: Vec) { let mut machine = DefaultCoreMachine::::default(); let size_addr = 0; @@ -464,6 +552,17 @@ mod tests { for (i, addr) in (addr as usize..addr as usize + sha3_data.len() as usize).enumerate() { assert_eq!(machine.memory_mut().load8(addr), Ok(sha3_data[i])); } + + machine.registers_mut()[A0] = addr; // addr + assert!(machine.memory_mut().store64(size_addr as usize, 0).is_ok()); + + assert!(load_cell.ecall(&mut machine).is_ok()); + assert_eq!(machine.registers()[A0], SUCCESS as u64); + + assert_eq!( + machine.memory_mut().load64(size_addr as usize), + Ok(sha3_data.len() as u64) + ); } proptest! { diff --git a/script/src/syscalls/utils.rs b/script/src/syscalls/utils.rs index 221c0b89fe..acb5aef5fb 100644 --- a/script/src/syscalls/utils.rs +++ b/script/src/syscalls/utils.rs @@ -10,8 +10,9 @@ pub fn store_data( let offset = machine.registers()[A2].to_usize(); let size = machine.memory_mut().load64(size_addr)? as usize; - let real_size = cmp::min(size, data.len() - offset); - machine.memory_mut().store64(size_addr, real_size as u64)?; + let full_size = data.len() - offset; + let real_size = cmp::min(size, full_size); + machine.memory_mut().store64(size_addr, full_size as u64)?; machine .memory_mut() .store_bytes(addr, &data[offset..offset + real_size])?;