Skip to content

Commit f8a77cd

Browse files
Merge pull request #9 from yangby-cryptape/feature/testing-contract-security
feat: let the contract which for testing purpose only more security
2 parents f5a3441 + 49c2f17 commit f8a77cd

File tree

5 files changed

+163
-46
lines changed

5 files changed

+163
-46
lines changed

Cargo.lock

+2-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contracts/can-update-without-ownership-lock/Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "can-update-without-ownership-lock"
3-
version = "0.1.0"
3+
version = "0.2.0"
44
authors = ["Boyu Yang <[email protected]>"]
55
edition = "2021"
66
license = "MIT"
@@ -10,3 +10,4 @@ repository = "https://github.com/ckb-cell/ckb-bitcoin-spv-contracts"
1010

1111
[dependencies]
1212
ckb-std = "0.15.1"
13+
ckb-hash = { version = "0.112.1", default-features = false, features = ["ckb-contract"] }

contracts/can-update-without-ownership-lock/README.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@ them.
1717

1818
It will return success when any follow condition is satisfied:
1919

20-
- the witness for this lock script is reverse of the `args` in it.
20+
- the `args` for this lock script is the result of calling
21+
[`ckb_hash::blake2b_256`] on the `witness` of it.
2122

2223
- there is no witness for this lock script, but total capacity of cells
2324
which use this lock script are not greater than total capacity of cells
2425
which use this lock script after this transaction.
26+
27+
[`ckb_hash::blake2b_256`]: https://docs.rs/ckb-hash/0.112.1/ckb_hash/fn.blake2b_256.html

contracts/can-update-without-ownership-lock/src/entry.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use alloc::vec::Vec;
22

3+
use ckb_hash::blake2b_256;
34
#[cfg(debug_assertions)]
45
use ckb_std::ckb_types::prelude::*;
56
use ckb_std::{ckb_constants::Source, debug, high_level as hl};
@@ -12,7 +13,7 @@ pub fn main() -> Result<()> {
1213
let script_hash = hl::load_script_hash()?;
1314
debug!("script hash = {:#x}", script_hash.pack());
1415
let args = hl::load_script()?.args();
15-
let expected_witness = args.raw_data().iter().cloned().rev().collect::<Vec<u8>>();
16+
let expected_proof = args.raw_data().iter().cloned().collect::<Vec<u8>>();
1617

1718
let mut checked = false;
1819

@@ -34,12 +35,13 @@ pub fn main() -> Result<()> {
3435

3536
if let Ok(witness_args) = hl::load_witness_args(index, Source::Input) {
3637
if let Some(lock_witness) = witness_args.lock().to_opt() {
37-
if lock_witness.raw_data().as_ref() == expected_witness {
38+
let actual_proof = blake2b_256(lock_witness.raw_data().as_ref());
39+
if actual_proof[..] == expected_proof[..] {
3840
checked = true;
3941
debug!(">>> >>> passed to check witness");
4042
} else {
4143
debug!(
42-
">>> >>> failed to check witness: args: {:#x}, witness: {:#x}",
44+
">>> >>> failed to check witness: args: {}, witness: {}",
4345
args, lock_witness
4446
);
4547
return Err(Error::WitnessIsIncorrect);
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,41 @@
11
use ckb_testtool::{
2+
ckb_hash::blake2b_256,
23
ckb_types::{bytes::Bytes, core::TransactionBuilder, packed::*, prelude::*},
34
context::Context,
45
};
56

67
use crate::{prelude::*, utilities, Loader};
78

8-
fn run_test(inputs_capacity: &[u64], outputs_capacity: &[u64]) {
9+
struct Case {
10+
inputs_capacity: Vec<u64>,
11+
outputs_capacity: Vec<u64>,
12+
unlocked: bool,
13+
should_pass: bool,
14+
}
15+
16+
fn run_test(case: &Case) {
917
utilities::setup();
1018

1119
let loader = Loader::default();
1220
let mut context = Context::default();
1321

22+
const PASSWORD: &[u8] = &[0x12, 0x34, 0x56, 0x78];
23+
1424
// Deploy the lock script.
1525
let lock_script = {
1626
let lock_bin = loader.load_binary("can-update-without-ownership-lock");
1727
let lock_out_point = context.deploy_cell(lock_bin);
28+
let args = blake2b_256(PASSWORD);
1829
context
1930
.build_script(&lock_out_point, Default::default())
2031
.expect("script")
2132
.as_builder()
22-
.args([0u8, 1, 2, 3].pack())
33+
.args((args[..]).pack())
2334
.build()
2435
};
2536

26-
let inputs = inputs_capacity
37+
let inputs = case
38+
.inputs_capacity
2739
.iter()
2840
.map(|cap| {
2941
let output = CellOutput::new_builder()
@@ -35,7 +47,8 @@ fn run_test(inputs_capacity: &[u64], outputs_capacity: &[u64]) {
3547
})
3648
.collect::<Vec<_>>();
3749

38-
let outputs = outputs_capacity
50+
let outputs = case
51+
.outputs_capacity
3952
.iter()
4053
.map(|cap| {
4154
CellOutput::new_builder()
@@ -46,67 +59,164 @@ fn run_test(inputs_capacity: &[u64], outputs_capacity: &[u64]) {
4659
.collect::<Vec<_>>();
4760
let outputs_data = vec![Bytes::new(); outputs.len()];
4861

49-
let tx = TransactionBuilder::default()
62+
let tx_builder = TransactionBuilder::default()
5063
.inputs(inputs)
5164
.outputs(outputs)
52-
.outputs_data(outputs_data.pack())
53-
.build();
65+
.outputs_data(outputs_data.pack());
66+
let tx = if case.unlocked {
67+
let witness = {
68+
let type_args = BytesOpt::new_builder()
69+
.set(Some(Pack::pack(PASSWORD)))
70+
.build();
71+
let witness_args = WitnessArgs::new_builder().lock(type_args).build();
72+
witness_args.as_bytes()
73+
};
74+
tx_builder.witness(witness.pack())
75+
} else {
76+
tx_builder
77+
}
78+
.build();
5479
let tx = context.complete_tx(tx);
5580

56-
let inputs_total: u64 = inputs_capacity.iter().copied().sum();
57-
let outputs_total: u64 = outputs_capacity.iter().copied().sum();
58-
if inputs_total > outputs_total {
59-
let _ = context.should_be_failed(&tx, MAX_CYCLES);
60-
} else {
81+
let inputs_total: u64 = case.inputs_capacity.iter().copied().sum();
82+
let outputs_total: u64 = case.outputs_capacity.iter().copied().sum();
83+
let expected_result = case.unlocked || inputs_total <= outputs_total;
84+
assert_eq!(case.should_pass, expected_result);
85+
if case.should_pass {
6186
let _ = context.should_be_passed(&tx, MAX_CYCLES);
87+
} else {
88+
let _ = context.should_be_failed(&tx, MAX_CYCLES);
6289
}
6390
}
6491

6592
#[test]
66-
fn lost_capacity_case_1() {
67-
let inputs_capacity = vec![1000];
68-
let outputs_capacity = vec![1000];
69-
run_test(&inputs_capacity, &outputs_capacity);
93+
fn unchanged_case_1() {
94+
let case = Case {
95+
inputs_capacity: vec![1000],
96+
outputs_capacity: vec![1000],
97+
unlocked: false,
98+
should_pass: true,
99+
};
100+
run_test(&case);
70101
}
71102

72103
#[test]
73-
fn lost_capacity_case_2() {
74-
let inputs_capacity = vec![999];
75-
let outputs_capacity = vec![1000];
76-
run_test(&inputs_capacity, &outputs_capacity);
104+
fn unchanged_case_2() {
105+
let case = Case {
106+
inputs_capacity: vec![499, 501],
107+
outputs_capacity: vec![1000],
108+
unlocked: false,
109+
should_pass: true,
110+
};
111+
run_test(&case);
77112
}
78113

79114
#[test]
80-
fn lost_capacity_case_3() {
81-
let inputs_capacity = vec![1000];
82-
let outputs_capacity = vec![999];
83-
run_test(&inputs_capacity, &outputs_capacity);
115+
fn unchanged_case_3() {
116+
let case = Case {
117+
inputs_capacity: vec![1000],
118+
outputs_capacity: vec![499, 501],
119+
unlocked: false,
120+
should_pass: true,
121+
};
122+
run_test(&case);
84123
}
85124

86125
#[test]
87-
fn lost_capacity_case_4() {
88-
let inputs_capacity = vec![500, 500];
89-
let outputs_capacity = vec![999];
90-
run_test(&inputs_capacity, &outputs_capacity);
126+
fn increase_case_1() {
127+
let case = Case {
128+
inputs_capacity: vec![1000],
129+
outputs_capacity: vec![1001],
130+
unlocked: false,
131+
should_pass: true,
132+
};
133+
run_test(&case);
91134
}
92135

93136
#[test]
94-
fn lost_capacity_case_5() {
95-
let inputs_capacity = vec![500, 500];
96-
let outputs_capacity = vec![1001];
97-
run_test(&inputs_capacity, &outputs_capacity);
137+
fn increase_case_2() {
138+
let case = Case {
139+
inputs_capacity: vec![499, 501],
140+
outputs_capacity: vec![1001],
141+
unlocked: false,
142+
should_pass: true,
143+
};
144+
run_test(&case);
98145
}
99146

100147
#[test]
101-
fn lost_capacity_case_6() {
102-
let inputs_capacity = vec![250, 250, 250, 250];
103-
let outputs_capacity = vec![500, 501];
104-
run_test(&inputs_capacity, &outputs_capacity);
148+
fn increase_case_3() {
149+
let case = Case {
150+
inputs_capacity: vec![1000],
151+
outputs_capacity: vec![500, 501],
152+
unlocked: false,
153+
should_pass: true,
154+
};
155+
run_test(&case);
105156
}
106157

107158
#[test]
108-
fn lost_capacity_case_7() {
109-
let inputs_capacity = vec![250, 250, 250, 250];
110-
let outputs_capacity = vec![500, 499];
111-
run_test(&inputs_capacity, &outputs_capacity);
159+
fn decrease_case_1a() {
160+
let case = Case {
161+
inputs_capacity: vec![1000],
162+
outputs_capacity: vec![999],
163+
unlocked: false,
164+
should_pass: false,
165+
};
166+
run_test(&case);
167+
}
168+
169+
#[test]
170+
fn decrease_case_1b() {
171+
let case = Case {
172+
inputs_capacity: vec![1000],
173+
outputs_capacity: vec![999],
174+
unlocked: true,
175+
should_pass: true,
176+
};
177+
run_test(&case);
178+
}
179+
180+
#[test]
181+
fn decrease_case_2a() {
182+
let case = Case {
183+
inputs_capacity: vec![499, 501],
184+
outputs_capacity: vec![999],
185+
unlocked: false,
186+
should_pass: false,
187+
};
188+
run_test(&case);
189+
}
190+
191+
#[test]
192+
fn decrease_case_2b() {
193+
let case = Case {
194+
inputs_capacity: vec![499, 501],
195+
outputs_capacity: vec![999],
196+
unlocked: true,
197+
should_pass: true,
198+
};
199+
run_test(&case);
200+
}
201+
202+
#[test]
203+
fn decrease_case_3a() {
204+
let case = Case {
205+
inputs_capacity: vec![1000],
206+
outputs_capacity: vec![499, 500],
207+
unlocked: false,
208+
should_pass: false,
209+
};
210+
run_test(&case);
211+
}
212+
213+
#[test]
214+
fn decrease_case_3b() {
215+
let case = Case {
216+
inputs_capacity: vec![1000],
217+
outputs_capacity: vec![499, 500],
218+
unlocked: true,
219+
should_pass: true,
220+
};
221+
run_test(&case);
112222
}

0 commit comments

Comments
 (0)