Skip to content

Commit bf2ab2a

Browse files
committed
Generate different error codes when Rust assertions fail
1 parent 4ad1524 commit bf2ab2a

File tree

9 files changed

+332
-222
lines changed

9 files changed

+332
-222
lines changed

Cargo.lock

Lines changed: 126 additions & 126 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contracts/hybrid-sphincs-all-in-one-lock/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version = "0.1.0"
44
edition = "2021"
55

66
[dependencies]
7-
ckb-std = "0.17.0"
7+
ckb-std = "0.17.1"
88
ckb-gen-types = { version = "0.200.0-rc1", default-features = false }
99

1010
[dependencies.ckb-fips205-utils]

contracts/hybrid-sphincs-all-in-one-lock/src/main.rs

Lines changed: 100 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,12 @@ use ckb_fips205_utils::{
2323
iterate_public_key_with_optional_signature, Hasher, ParamId,
2424
};
2525
use ckb_gen_types::{core::ScriptHashType, packed::WitnessArgsReader, prelude::*};
26-
use ckb_std::{ckb_constants::Source, high_level, syscalls};
26+
use ckb_std::{
27+
assert_eq,
28+
asserts::{expect_result, unwrap_option},
29+
ckb_constants::Source,
30+
high_level, syscalls,
31+
};
2732
use core::ffi::CStr;
2833

2934
enum ParsedParamId {
@@ -32,21 +37,48 @@ enum ParsedParamId {
3237
Multiple,
3338
}
3439

40+
#[repr(i8)]
41+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
42+
pub enum Error {
43+
Syscall = 71,
44+
CkbTxMessageAll,
45+
LockMissing,
46+
SphincsplusVerify,
47+
ScriptArgsMismatch,
48+
Overflow,
49+
PipeCreationFailure,
50+
SpawnFailure,
51+
IOFailure,
52+
}
53+
54+
impl From<Error> for i8 {
55+
fn from(e: Error) -> i8 {
56+
e as i8
57+
}
58+
}
59+
3560
pub fn program_entry() -> i8 {
3661
// Unfortunately, till lazy reader with validator mode is coming, we will
3762
// have to stick with this. Fortunately, all data in the first witness will
3863
// be loaded one way or another. What we really pay here, is merely (*cough*)
3964
// ~600K memory space.
40-
let first_witness_data = high_level::load_witness(0, Source::GroupInput).expect("load witness");
65+
let first_witness_data = expect_result(
66+
Error::Syscall,
67+
high_level::load_witness(0, Source::GroupInput),
68+
"load witness",
69+
);
4170

4271
let mut message_hasher = Hasher::message_hasher();
43-
generate_ckb_tx_message_all_with_witness(&mut message_hasher, &first_witness_data)
44-
.expect("ckb tx message all");
72+
expect_result(
73+
Error::CkbTxMessageAll,
74+
generate_ckb_tx_message_all_with_witness(&mut message_hasher, &first_witness_data),
75+
"ckb tx message all",
76+
);
4577
let message = message_hasher.hash();
4678

4779
// The first witness is already validated to be in correct format
4880
let first_witness = WitnessArgsReader::new_unchecked(&first_witness_data);
49-
let lock = first_witness.lock().to_opt().unwrap().raw_data();
81+
let lock = unwrap_option(Error::LockMissing, first_witness.lock().to_opt()).raw_data();
5082

5183
let mut script_args_hasher = Hasher::script_args_hasher();
5284
script_args_hasher.update(&lock[0..4]);
@@ -75,23 +107,27 @@ pub fn program_entry() -> i8 {
75107
);
76108

77109
let actual_script_args_hash = script_args_hasher.hash();
78-
let current_script = high_level::load_script().expect("load script");
110+
let current_script = expect_result(Error::Syscall, high_level::load_script(), "load script");
79111
assert_eq!(
112+
Error::ScriptArgsMismatch,
80113
&current_script.args().raw_data(),
81114
&actual_script_args_hash[..]
82115
);
83-
let cell_index = high_level::look_for_dep_with_hash2(
84-
&current_script.code_hash().raw_data(),
85-
if current_script.hash_type().as_slice()[0]
86-
== core::convert::Into::<u8>::into(ScriptHashType::Type)
87-
{
88-
ScriptHashType::Type
89-
} else {
90-
// It does not really matter which dataN is used
91-
ScriptHashType::Data2
92-
},
93-
)
94-
.expect("look for current script");
116+
let cell_index = expect_result(
117+
Error::Syscall,
118+
high_level::look_for_dep_with_hash2(
119+
&current_script.code_hash().raw_data(),
120+
if current_script.hash_type().as_slice()[0]
121+
== core::convert::Into::<u8>::into(ScriptHashType::Type)
122+
{
123+
ScriptHashType::Type
124+
} else {
125+
// It does not really matter which dataN is used
126+
ScriptHashType::Data2
127+
},
128+
),
129+
"look for current script",
130+
);
95131

96132
match parsed_param_id {
97133
ParsedParamId::Single(param_id) => {
@@ -107,11 +143,14 @@ pub fn program_entry() -> i8 {
107143
encoder.extend(&(Source::GroupInput as u64).to_le_bytes()[..]);
108144
encoder.extend(&0u32.to_le_bytes()[..]);
109145

110-
let offset: u32 = (lock[4..].as_ptr() as usize - first_witness_data.as_ptr() as usize)
111-
.try_into()
112-
.expect("overflow");
146+
let offset: u32 = expect_result(
147+
Error::Overflow,
148+
(lock[4..].as_ptr() as usize - first_witness_data.as_ptr() as usize).try_into(),
149+
"overflow",
150+
);
113151
encoder.extend(&offset.to_le_bytes()[..]);
114-
let length: u32 = (lock.len() - 4).try_into().expect("overflow");
152+
let length: u32 =
153+
expect_result(Error::Overflow, (lock.len() - 4).try_into(), "overflow");
115154
encoder.extend(&length.to_le_bytes()[..]);
116155

117156
let (binary_offset, binary_length) = load_binary_infos(param_id);
@@ -150,9 +189,9 @@ pub fn program_entry() -> i8 {
150189
let bounds = ((binary_offset as u64) << 32) | (binary_length as u64);
151190

152191
let (root_to_leaf_fd0, root_to_leaf_fd1) =
153-
syscalls::pipe().expect("pipe");
192+
expect_result(Error::PipeCreationFailure, syscalls::pipe(), "pipe");
154193
let (leaf_to_root_fd0, leaf_to_root_fd1) =
155-
syscalls::pipe().expect("pipe");
194+
expect_result(Error::PipeCreationFailure, syscalls::pipe(), "pipe");
156195

157196
let mut process_id: u64 = 0;
158197
{
@@ -165,14 +204,17 @@ pub fn program_entry() -> i8 {
165204
process_id: &mut process_id as *mut u64,
166205
inherited_fds: inherited_fds.as_ptr(),
167206
};
168-
syscalls::spawn(
169-
cell_index,
170-
Source::CellDep,
171-
0,
172-
bounds as usize,
173-
&mut spgs,
174-
)
175-
.expect("spawn");
207+
expect_result(
208+
Error::SpawnFailure,
209+
syscalls::spawn(
210+
cell_index,
211+
Source::CellDep,
212+
0,
213+
bounds as usize,
214+
&mut spgs,
215+
),
216+
"spawn",
217+
);
176218
}
177219
spawned_vms[param_index] = Some((root_to_leaf_fd1, leaf_to_root_fd0));
178220
}
@@ -188,22 +230,29 @@ pub fn program_entry() -> i8 {
188230
data[3..3 + 8]
189231
.copy_from_slice(&(Source::GroupInput as u64).to_le_bytes()[..]);
190232

191-
let offset: u32 = (public_key.as_ptr() as u64
192-
- first_witness_data.as_ptr() as u64
193-
- 1)
194-
.try_into()
195-
.expect("overflow");
233+
let offset: u32 = expect_result(
234+
Error::Overflow,
235+
(public_key.as_ptr() as u64
236+
- first_witness_data.as_ptr() as u64
237+
- 1)
238+
.try_into(),
239+
"overflow",
240+
);
196241
data[3 + 8 + 4..3 + 8 + 4 + 4].copy_from_slice(&offset.to_le_bytes());
197-
let length: u32 = (1 + public_key.len() + signature.len())
198-
.try_into()
199-
.expect("overflow");
242+
let length: u32 = expect_result(
243+
Error::Overflow,
244+
(1 + public_key.len() + signature.len()).try_into(),
245+
"overflow",
246+
);
200247
data[3 + 8 + 4 + 4..].copy_from_slice(&length.to_le_bytes());
201248

202249
let mut written = 0;
203250
while written < data.len() {
204-
let current_written =
205-
syscalls::write(root_to_leaf_fd, &data[written..])
206-
.expect("write");
251+
let current_written = expect_result(
252+
Error::IOFailure,
253+
syscalls::write(root_to_leaf_fd, &data[written..]),
254+
"write",
255+
);
207256
written += current_written;
208257
}
209258
}
@@ -213,15 +262,17 @@ pub fn program_entry() -> i8 {
213262

214263
let mut read = 0;
215264
while read < response.len() {
216-
let current_read =
217-
syscalls::read(leaf_to_root_fd, &mut response[read..])
218-
.expect("read");
265+
let current_read = expect_result(
266+
Error::IOFailure,
267+
syscalls::read(leaf_to_root_fd, &mut response[read..]),
268+
"read",
269+
);
219270
read += current_read;
220271
}
221272

222-
assert_eq!(response[0], 0);
223-
assert_eq!(response[1], 0);
224-
assert_eq!(response[2], 0);
273+
assert_eq!(Error::SphincsplusVerify, response[0], 0);
274+
assert_eq!(Error::SphincsplusVerify, response[1], 0);
275+
assert_eq!(Error::SphincsplusVerify, response[2], 0);
225276
}
226277
}
227278
},

contracts/sphincs-all-in-one-lock/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version = "0.1.0"
44
edition = "2021"
55

66
[dependencies]
7-
ckb-std = "0.17.0"
7+
ckb-std = "0.17.1"
88
ckb-gen-types = { version = "0.200.0-rc1", default-features = false }
99

1010
[dependencies.ckb-fips205-utils]

contracts/sphincs-all-in-one-lock/src/main.rs

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,51 @@ use ckb_fips205_utils::{
2222
Hasher,
2323
};
2424
use ckb_gen_types::{packed::WitnessArgsReader, prelude::*};
25-
use ckb_std::{ckb_constants::Source, high_level};
25+
use ckb_std::{
26+
assert, assert_eq,
27+
asserts::{expect_result, unwrap_option},
28+
ckb_constants::Source,
29+
high_level,
30+
};
31+
32+
#[repr(i8)]
33+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
34+
pub enum Error {
35+
Syscall = 71,
36+
CkbTxMessageAll,
37+
LockMissing,
38+
Fips205Verify,
39+
ScriptArgsMismatch,
40+
}
41+
42+
impl From<Error> for i8 {
43+
fn from(e: Error) -> i8 {
44+
e as i8
45+
}
46+
}
2647

2748
pub fn program_entry() -> i8 {
2849
// Unfortunately, till lazy reader with validator mode is coming, we will
2950
// have to stick with this. Fortunately, all data in the first witness will
3051
// be loaded one way or another. What we really pay here, is merely (*cough*)
3152
// ~600K memory space.
32-
let first_witness_data = high_level::load_witness(0, Source::GroupInput).expect("load witness");
53+
let first_witness_data = expect_result(
54+
Error::Syscall,
55+
high_level::load_witness(0, Source::GroupInput),
56+
"load witness",
57+
);
3358

3459
let mut message_hasher = Hasher::message_hasher();
35-
generate_ckb_tx_message_all_with_witness(&mut message_hasher, &first_witness_data)
36-
.expect("ckb tx message all");
60+
expect_result(
61+
Error::CkbTxMessageAll,
62+
generate_ckb_tx_message_all_with_witness(&mut message_hasher, &first_witness_data),
63+
"ckb tx message all",
64+
);
3765
let message = message_hasher.hash();
3866

3967
// The first witness is already validated to be in correct format
4068
let first_witness = WitnessArgsReader::new_unchecked(&first_witness_data);
41-
let lock = first_witness.lock().to_opt().unwrap().raw_data();
69+
let lock = unwrap_option(Error::LockMissing, first_witness.lock().to_opt()).raw_data();
4270

4371
let mut script_args_hasher = Hasher::script_args_hasher();
4472
script_args_hasher.update(&lock[0..4]);
@@ -50,15 +78,19 @@ pub fn program_entry() -> i8 {
5078
script_args_hasher.update(public_key);
5179

5280
if let Some(signature) = signature {
53-
assert!(verify(param_id, public_key, signature, &message));
81+
assert!(
82+
Error::Fips205Verify,
83+
verify(param_id, public_key, signature, &message)
84+
);
5485
}
5586
},
5687
lengths,
5788
);
5889

5990
let actual_script_args_hash = script_args_hasher.hash();
60-
let current_script = high_level::load_script().expect("load script");
91+
let current_script = expect_result(Error::Syscall, high_level::load_script(), "load script");
6192
assert_eq!(
93+
Error::ScriptArgsMismatch,
6294
&current_script.args().raw_data(),
6395
&actual_script_args_hash[..]
6496
);

crates/ckb-fips205-utils/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ edition = "2021"
66

77
[dependencies]
88
int-enum = "1.1.2"
9-
ckb-std = "0.17.0"
9+
ckb-std = "0.17.1"
1010
ckb-rust-std = "1.0.0"
1111
ckb-gen-types = { version = "0.200.0-rc1", default-features = false }
1212
ckb-hash = { version = "0.200.0-rc1", default-features = false, features = ["ckb-contract"] }

0 commit comments

Comments
 (0)