Skip to content

Commit

Permalink
feat: add dep cell loading support in syscalls
Browse files Browse the repository at this point in the history
  • Loading branch information
xxuejie committed Dec 18, 2018
1 parent 99f572c commit cae937f
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 23 deletions.
4 changes: 4 additions & 0 deletions script/src/syscalls/load_cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,21 @@ pub struct LoadCell<'a> {
outputs: &'a [&'a CellOutput],
input_cells: &'a [&'a CellOutput],
current: &'a CellOutput,
dep_cells: &'a [&'a CellOutput],
}

impl<'a> LoadCell<'a> {
pub fn new(
outputs: &'a [&'a CellOutput],
input_cells: &'a [&'a CellOutput],
current: &'a CellOutput,
dep_cells: &'a [&'a CellOutput],
) -> LoadCell<'a> {
LoadCell {
outputs,
input_cells,
current,
dep_cells,
}
}

Expand All @@ -30,6 +33,7 @@ impl<'a> LoadCell<'a> {
Source::Input => self.input_cells.get(index).cloned(),
Source::Output => self.outputs.get(index).cloned(),
Source::Current => Some(self.current),
Source::Dep => self.dep_cells.get(index).cloned(),
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions script/src/syscalls/load_cell_by_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,21 @@ pub struct LoadCellByField<'a> {
outputs: &'a [&'a CellOutput],
input_cells: &'a [&'a CellOutput],
current: &'a CellOutput,
dep_cells: &'a [&'a CellOutput],
}

impl<'a> LoadCellByField<'a> {
pub fn new(
outputs: &'a [&'a CellOutput],
input_cells: &'a [&'a CellOutput],
current: &'a CellOutput,
dep_cells: &'a [&'a CellOutput],
) -> LoadCellByField<'a> {
LoadCellByField {
outputs,
input_cells,
current,
dep_cells,
}
}

Expand All @@ -32,6 +35,7 @@ impl<'a> LoadCellByField<'a> {
Source::Input => self.input_cells.get(index).cloned(),
Source::Output => self.outputs.get(index).cloned(),
Source::Current => Some(self.current),
Source::Dep => self.dep_cells.get(index).cloned(),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions script/src/syscalls/load_input_by_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ impl<'a> LoadInputByField<'a> {
Source::Input => self.inputs.get(index).cloned(),
Source::Output => None,
Source::Current => self.current,
Source::Dep => None,
}
}
}
Expand Down
65 changes: 57 additions & 8 deletions script/src/syscalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ enum Source {
Input,
Output,
Current,
Dep,
}

impl Source {
Expand All @@ -75,6 +76,7 @@ impl Source {
0 => Ok(Source::Input),
1 => Ok(Source::Output),
2 => Ok(Source::Current),
3 => Ok(Source::Dep),
_ => Err(Error::ParseError),
}
}
Expand Down Expand Up @@ -231,7 +233,8 @@ mod tests {
);
let outputs = vec![&output];
let input_cells = vec![&input_cell];
let mut load_cell = LoadCell::new(&outputs, &input_cells, &input_cell);
let dep_cells = vec![];
let mut load_cell = LoadCell::new(&outputs, &input_cells, &input_cell, &dep_cells);

assert!(load_cell.ecall(&mut machine).is_ok());
assert_eq!(machine.registers()[A0], ITEM_MISSING as u64);
Expand Down Expand Up @@ -265,7 +268,8 @@ mod tests {
);
let outputs = vec![&output];
let input_cells = vec![&input_cell];
let mut load_cell = LoadCell::new(&outputs, &input_cells, &input_cell);
let dep_cells = vec![];
let mut load_cell = LoadCell::new(&outputs, &input_cells, &input_cell, &dep_cells);

let mut builder = FlatBufferBuilder::new();
let fbs_offset = FbsCellOutput::build(&mut builder, &input_cell);
Expand Down Expand Up @@ -348,7 +352,8 @@ mod tests {
);
let outputs = vec![&output];
let input_cells = vec![&input_cell];
let mut load_cell = LoadCell::new(&outputs, &input_cells, &input_cell);
let dep_cells = vec![];
let mut load_cell = LoadCell::new(&outputs, &input_cells, &input_cell, &dep_cells);

let mut builder = FlatBufferBuilder::new();
let fbs_offset = FbsCellOutput::build(&mut builder, &input_cell);
Expand Down Expand Up @@ -395,7 +400,8 @@ mod tests {
);
let outputs = vec![&output];
let input_cells = vec![&input_cell];
let mut load_cell = LoadCell::new(&outputs, &input_cells, &input_cell);
let dep_cells = vec![];
let mut load_cell = LoadCell::new(&outputs, &input_cells, &input_cell, &dep_cells);

let mut builder = FlatBufferBuilder::new();
let fbs_offset = FbsCellOutput::build(&mut builder, &input_cell);
Expand Down Expand Up @@ -447,7 +453,8 @@ mod tests {
);
let outputs = vec![];
let input_cells = vec![];
let mut load_cell = LoadCell::new(&outputs, &input_cells, &input_cell);
let dep_cells = vec![];
let mut load_cell = LoadCell::new(&outputs, &input_cells, &input_cell, &dep_cells);

let mut builder = FlatBufferBuilder::new();
let fbs_offset = FbsCellOutput::build(&mut builder, &input_cell);
Expand Down Expand Up @@ -496,7 +503,8 @@ mod tests {
let input_cell = CellOutput::new(capacity, vec![], H256::zero(), None);
let outputs = vec![];
let input_cells = vec![&input_cell];
let mut load_cell = LoadCellByField::new(&outputs, &input_cells, &input_cell);
let dep_cells = vec![];
let mut load_cell = LoadCellByField::new(&outputs, &input_cells, &input_cell, &dep_cells);

assert!(machine.memory_mut().store64(size_addr as usize, 16).is_ok());

Expand Down Expand Up @@ -537,7 +545,8 @@ mod tests {
let input_cell = CellOutput::new(100, vec![], H256::from_slice(&sha3_data).unwrap(), None);
let outputs = vec![];
let input_cells = vec![];
let mut load_cell = LoadCellByField::new(&outputs, &input_cells, &input_cell);
let dep_cells = vec![];
let mut load_cell = LoadCellByField::new(&outputs, &input_cells, &input_cell, &dep_cells);

assert!(machine.memory_mut().store64(size_addr as usize, 64).is_ok());

Expand Down Expand Up @@ -589,7 +598,8 @@ mod tests {
let output_cell = CellOutput::new(100, vec![], H256::default(), None);
let outputs = vec![&output_cell];
let input_cells = vec![];
let mut load_cell = LoadCellByField::new(&outputs, &input_cells, &output_cell);
let dep_cells = vec![];
let mut load_cell = LoadCellByField::new(&outputs, &input_cells, &output_cell, &dep_cells);

assert!(machine
.memory_mut()
Expand Down Expand Up @@ -781,4 +791,43 @@ mod tests {
assert_eq!(machine.memory_mut().load8(addr), Ok(0));
}
}

fn _test_load_dep_cell_data(data: Vec<u8>) {
let mut machine = DefaultCoreMachine::<u64, SparseMemory>::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] = 3; //source: 3 dep
machine.registers_mut()[A5] = 1; //field: 1 data
machine.registers_mut()[A7] = LOAD_CELL_BY_FIELD_SYSCALL_NUMBER; // syscall number

let input_cell = CellOutput::new(1000, vec![], H256::zero(), None);
let dep_cell = CellOutput::new(1000, data.clone(), H256::zero(), None);
let outputs = vec![];
let input_cells = vec![&input_cell];
let dep_cells = vec![&dep_cell];
let mut load_cell = LoadCellByField::new(&outputs, &input_cells, &input_cell, &dep_cells);

assert!(machine.memory_mut().store64(size_addr as usize, data.len() as u64 + 20).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(data.len() as u64));

for (i, addr) in (addr as usize..addr as usize + data.len() as usize).enumerate() {
assert_eq!(machine.memory_mut().load8(addr), Ok(data[i]));
}
}

proptest! {
#[test]
fn test_load_dep_cell_data(data in any_with::<Vec<u8>>(size_range(1000).lift())) {
_test_load_dep_cell_data(data);
}
}
}
42 changes: 27 additions & 15 deletions script/src/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,30 @@ use numext_fixed_hash::H256;
// FlatBufferBuilder owned Vec<u8> that grows as needed, in the
// future, we might refactor this to share buffer to achive zero-copy
pub struct TransactionScriptsVerifier<'a> {
dep_cells: FnvHashMap<H256, &'a CellOutput>,
dep_cell_index: FnvHashMap<H256, &'a CellOutput>,
inputs: Vec<&'a CellInput>,
outputs: Vec<&'a CellOutput>,
tx_builder: FlatBufferBuilder<'a>,
input_cells: Vec<&'a CellOutput>,
dep_cells: Vec<&'a CellOutput>,
hash: H256,
}

impl<'a> TransactionScriptsVerifier<'a> {
pub fn new(rtx: &'a ResolvedTransaction) -> TransactionScriptsVerifier<'a> {
let dep_cells: FnvHashMap<H256, &'a CellOutput> = rtx
let dep_cells: Vec<&'a CellOutput> = rtx
.dep_cells
.iter()
.map(|cell| {
let output = cell
.get_current()
.expect("already verifies that all dep cells are valid");
let hash = output.data_hash();
(hash, output)
cell.get_current()
.expect("already verifies that all dep cells are valid")
})
.collect();
let dep_cell_index: FnvHashMap<H256, &'a CellOutput> = dep_cells
.iter()
.map(|cell| {
let hash = cell.data_hash();
(hash, *cell)
})
.collect();

Expand All @@ -52,11 +57,12 @@ impl<'a> TransactionScriptsVerifier<'a> {
tx_builder.finish(tx_offset, None);

TransactionScriptsVerifier {
dep_cells,
dep_cell_index,
inputs,
tx_builder,
outputs,
input_cells,
dep_cells,
hash: rtx.transaction.hash().clone(),
}
}
Expand All @@ -66,11 +72,21 @@ impl<'a> TransactionScriptsVerifier<'a> {
}

fn build_load_cell(&self, current_cell: &'a CellOutput) -> LoadCell {
LoadCell::new(&self.outputs, &self.input_cells, current_cell)
LoadCell::new(
&self.outputs,
&self.input_cells,
current_cell,
&self.dep_cells,
)
}

fn build_load_cell_by_field(&self, current_cell: &'a CellOutput) -> LoadCellByField {
LoadCellByField::new(&self.outputs, &self.input_cells, current_cell)
LoadCellByField::new(
&self.outputs,
&self.input_cells,
current_cell,
&self.dep_cells,
)
}

fn build_load_input_by_field(&self, current_input: Option<&'a CellInput>) -> LoadInputByField {
Expand All @@ -84,7 +100,7 @@ impl<'a> TransactionScriptsVerifier<'a> {
return Ok(data);
}
if let Some(ref hash) = script.reference {
return match self.dep_cells.get(hash) {
return match self.dep_cell_index.get(hash) {
Some(ref cell_output) => Ok(&cell_output.data),
None => Err(ScriptError::InvalidReferenceIndex),
};
Expand Down Expand Up @@ -153,7 +169,6 @@ mod tests {
use ckb_core::Capacity;
use crypto::secp::Generator;
use faster_hex::hex_to;
use fnv::FnvHashMap;
use hash::sha3_256;
use numext_fixed_hash::H256;
use std::fs::File;
Expand Down Expand Up @@ -290,9 +305,6 @@ mod tests {

let dep_out_point = OutPoint::new(H256::from_trimmed_hex_str("123").unwrap(), 8);
let dep_cell = CellOutput::new(buffer.len() as Capacity, buffer, H256::zero(), None);
let mut dep_cells = FnvHashMap::default();
dep_cells.insert(&dep_out_point, &dep_cell);

let privkey = privkey.pubkey().unwrap().serialize();
let mut hex_privkey = vec![0; privkey.len() * 2];
hex_to(&privkey, &mut hex_privkey).expect("hex privkey");
Expand Down

0 comments on commit cae937f

Please sign in to comment.