Skip to content

Commit

Permalink
Merge pull request #409 from dusk-network/issue-408-icc-rollback-test
Browse files Browse the repository at this point in the history
piecrust: added test for ICCs not rolled back when panic
  • Loading branch information
miloszm authored Nov 28, 2024
2 parents b41d205 + 9b5b43e commit 7f86f61
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 0 deletions.
29 changes: 29 additions & 0 deletions contracts/crossover/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,27 @@ impl Crossover {
self.set_crossover(value_to_set);
}

// Chain of ICC is not being rolled back when a callee panics and its panic
// is not propagated up the call chain.
pub fn check_iccs_dont_rollback(
&mut self,
contract: ContractId,
value_to_set: i32,
) {
self.set_crossover(value_to_set);

const ANY_VALUE_1: i32 = 5;
const ANY_VALUE_2: i32 = 6;

uplink::debug!("calling panicking contract {contract:?}");
uplink::call::<_, ()>(
contract,
"set_back_and_panic",
&(ANY_VALUE_1, ANY_VALUE_2),
)
.expect_err("should give an error on a panic");
}

// Sets the contract's value and then calls its caller's [`set_crossover`]
// call to set their value. The caller is assumed to be another crossover
// contract.
Expand Down Expand Up @@ -125,6 +146,14 @@ unsafe fn check_consistent_state_on_errors(arg_len: u32) -> u32 {
})
}

/// Expose `Crossover::check_iccs_dont_rollback()` to the host
#[no_mangle]
unsafe fn check_iccs_dont_rollback(arg_len: u32) -> u32 {
uplink::wrap_call(arg_len, |(contract, s)| {
STATE.check_iccs_dont_rollback(contract, s)
})
}

/// Expose `Crossover::set_back_and_panic()` to the host
#[no_mangle]
unsafe fn set_back_and_panic(arg_len: u32) -> u32 {
Expand Down
39 changes: 39 additions & 0 deletions piecrust/tests/crossover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,42 @@ fn crossover() -> Result<(), Error> {

Ok(())
}

#[test]
fn iccs_dont_rollback() -> Result<(), Error> {
let vm = VM::ephemeral()?;

let mut session = vm.session(SessionData::builder())?;

session.deploy(
contract_bytecode!("crossover"),
ContractData::builder()
.owner(OWNER)
.contract_id(CROSSOVER_ONE),
LIMIT,
)?;
session.deploy(
contract_bytecode!("crossover"),
ContractData::builder()
.owner(OWNER)
.contract_id(CROSSOVER_TWO),
LIMIT,
)?;
// These value should not be set to `INITIAL_VALUE` in the contract.
const CROSSOVER_TO_SET: i32 = 42;

session.call::<_, ()>(
CROSSOVER_ONE,
"check_iccs_dont_rollback",
&(CROSSOVER_TWO, CROSSOVER_TO_SET),
LIMIT,
)?;

assert_eq!(
session.call::<_, i32>(CROSSOVER_ONE, "crossover", &(), LIMIT)?.data,
CROSSOVER_TO_SET,
"The crossover should still be set even though the other contract panicked"
);

Ok(())
}

0 comments on commit 7f86f61

Please sign in to comment.