Skip to content

Commit b878477

Browse files
authored
Merge pull request #329 from dusk-network/issue-324
support bytecheck-based integrity check of contract calls' arguments
2 parents 33395d8 + 6efec4c commit b878477

File tree

7 files changed

+58
-7
lines changed

7 files changed

+58
-7
lines changed

contracts/counter/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ impl Counter {
3535
/// Expose `Counter::read_value()` to the host
3636
#[no_mangle]
3737
unsafe fn read_value(arg_len: u32) -> u32 {
38-
uplink::wrap_call(arg_len, |_: ()| STATE.read_value())
38+
uplink::wrap_call_unchecked(arg_len, |_: ()| STATE.read_value())
3939
}
4040

4141
/// Expose `Counter::increment()` to the host
4242
#[no_mangle]
4343
unsafe fn increment(arg_len: u32) -> u32 {
44-
uplink::wrap_call(arg_len, |_: ()| STATE.increment())
44+
uplink::wrap_call_unchecked(arg_len, |_: ()| STATE.increment())
4545
}

piecrust-uplink/CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Add `wrap_call_unchecked` function for calls with no argument checking [#324]
13+
14+
### Changed
15+
16+
- Change `wrap_call` function to support `bytecheck`-based integrity check of arguments [#324]
17+
1018
## [0.10.0] - 2024-01-24
1119

1220
### Added
@@ -152,6 +160,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
152160
- First `piecrust-uplink` release
153161

154162
<!-- ISSUES -->
163+
[#324]: https://github.com/dusk-network/piecrust/issues/324
155164
[#301]: https://github.com/dusk-network/piecrust/issues/301
156165
[#271]: https://github.com/dusk-network/piecrust/issues/271
157166
[#268]: https://github.com/dusk-network/piecrust/issues/268

piecrust-uplink/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ edition = "2021"
1313
license = "MPL-2.0"
1414

1515
[dependencies]
16-
rkyv = { version = "0.7", default-features = false, features = ["size_32", "alloc"] }
16+
rkyv = { version = "0.7", default-features = false, features = ["size_32", "alloc", "validation"] }
1717
bytecheck = { version = "0.6", default-features = false }
1818
dlmalloc = { version = "0.2", optional = true, features = ["global"] }
1919

piecrust-uplink/src/abi/helpers.rs

+36-1
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,49 @@ use rkyv::ser::serializers::{
1111
BufferScratch, BufferSerializer, CompositeSerializer,
1212
};
1313
use rkyv::ser::Serializer;
14-
use rkyv::{archived_root, Archive, Deserialize, Infallible, Serialize};
14+
use rkyv::validation::validators::DefaultValidator;
15+
use rkyv::{
16+
archived_root, check_archived_root, Archive, Deserialize, Infallible,
17+
Serialize,
18+
};
1519

1620
use crate::types::StandardBufSerializer;
1721

1822
/// Wrap a call with its respective (de)serializers.
23+
/// Checks integrity of the arguments.
1924
///
2025
/// Returns the length of result written to the buffer.
2126
pub fn wrap_call<A, R, F>(arg_len: u32, f: F) -> u32
27+
where
28+
A: Archive,
29+
A::Archived: Deserialize<A, Infallible>
30+
+ for<'b> bytecheck::CheckBytes<DefaultValidator<'b>>,
31+
R: for<'a> Serialize<StandardBufSerializer<'a>>,
32+
F: Fn(A) -> R,
33+
{
34+
with_arg_buf(|buf| {
35+
let slice = &buf[..arg_len as usize];
36+
37+
let aa: &A::Archived = check_archived_root::<A>(slice)
38+
.expect("Argument should correctly deserialize");
39+
let a: A = aa.deserialize(&mut Infallible).unwrap();
40+
41+
let ret = f(a);
42+
43+
let mut sbuf = [0u8; SCRATCH_BUF_BYTES];
44+
let scratch = BufferScratch::new(&mut sbuf);
45+
let ser = BufferSerializer::new(buf);
46+
let mut composite = CompositeSerializer::new(ser, scratch, Infallible);
47+
composite.serialize_value(&ret).expect("infallible");
48+
composite.pos() as u32
49+
})
50+
}
51+
52+
/// Wrap a call with its respective (de)serializers.
53+
/// Does not check the integrity of arguments.
54+
///
55+
/// Returns the length of result written to the buffer.
56+
pub fn wrap_call_unchecked<A, R, F>(arg_len: u32, f: F) -> u32
2257
where
2358
A: Archive,
2459
A::Archived: Deserialize<A, Infallible>,

piecrust/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Changed
11+
12+
- Change `call` and `feeder_call` functions to support `bytecheck`-based integrity check of arguments [#324]
13+
1014
### Added
1115

1216
- Add `Session::migrate` to allow for swapping contract code [#313]
@@ -362,6 +366,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
362366
<!-- ISSUES -->
363367
[#327]: https://github.com/dusk-network/piecrust/issues/327
364368
[#325]: https://github.com/dusk-network/piecrust/issues/325
369+
[#324]: https://github.com/dusk-network/piecrust/issues/324
365370
[#301]: https://github.com/dusk-network/piecrust/issues/313
366371
[#301]: https://github.com/dusk-network/piecrust/issues/301
367372
[#296]: https://github.com/dusk-network/piecrust/issues/296

piecrust/src/session.rs

+2
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ impl Session {
339339
) -> Result<CallReceipt<R>, Error>
340340
where
341341
A: for<'b> Serialize<StandardBufSerializer<'b>>,
342+
A::Archived: for<'b> CheckBytes<DefaultValidator<'b>>,
342343
R: Archive,
343344
R::Archived: Deserialize<R, Infallible>
344345
+ for<'b> CheckBytes<DefaultValidator<'b>>,
@@ -462,6 +463,7 @@ impl Session {
462463
) -> Result<CallReceipt<R>, Error>
463464
where
464465
A: for<'b> Serialize<StandardBufSerializer<'b>>,
466+
A::Archived: for<'b> CheckBytes<DefaultValidator<'b>>,
465467
R: Archive,
466468
R::Archived: Deserialize<R, Infallible>
467469
+ for<'b> CheckBytes<DefaultValidator<'b>>,

piecrust/tests/spender.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ pub fn panic_msg_gets_through() -> Result<(), Error> {
6464
let receipt = session.call::<_, Result<(), ContractError>>(
6565
callcenter_id,
6666
"call_spend_with_limit",
67-
&(spender_id, 1000u64),
67+
&(spender_id, 1175u64),
6868
LIMIT,
6969
)?;
7070

@@ -125,8 +125,8 @@ pub fn contract_sets_call_limit() -> Result<(), Error> {
125125
LIMIT,
126126
)?;
127127

128-
const FIRST_LIMIT: u64 = 1000;
129-
const SECOND_LIMIT: u64 = 2000;
128+
const FIRST_LIMIT: u64 = 1175;
129+
const SECOND_LIMIT: u64 = 2175;
130130

131131
let receipt = session_1st.call::<_, Result<(), ContractError>>(
132132
callcenter_id,

0 commit comments

Comments
 (0)