Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store merkle positions in binary formant rather than using rkyv #411

Merged
merged 10 commits into from
Dec 4, 2024
1 change: 1 addition & 0 deletions contracts/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ members = [
"box",
"c-example",
"callcenter",
"callstack",
"initializer",
"counter",
"counter_float",
Expand Down
27 changes: 27 additions & 0 deletions contracts/callcenter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ impl Callcenter {
uplink::caller()
}

/// Return the entire call stack of this contract
pub fn return_callstack(&self) -> Vec<ContractId> {
uplink::callstack()
}

/// Make sure that the caller of this contract is the contract itself
pub fn call_self(&self) -> Result<bool, ContractError> {
let self_id = uplink::self_id();
Expand All @@ -90,6 +95,16 @@ impl Callcenter {
}
}

/// Return a call stack after calling itself n times
pub fn call_self_n_times(&self, n: u32) -> Vec<ContractId> {
let self_id = uplink::self_id();
match n {
0 => uplink::callstack(),
_ => uplink::call(self_id, "call_self_n_times", &(n - 1))
.expect("calling self should succeed")
}
}

/// Calls the `spend` function of the `contract` with no arguments, and the
/// given `gas_limit`, assuming the called function returns `()`. It will
/// then return the call's result itself.
Expand Down Expand Up @@ -133,6 +148,12 @@ unsafe fn call_self(arg_len: u32) -> u32 {
wrap_call(arg_len, |_: ()| STATE.call_self())
}

/// Expose `Callcenter::call_self_n_times()` to the host
#[no_mangle]
unsafe fn call_self_n_times(arg_len: u32) -> u32 {
wrap_call(arg_len, |n: u32| STATE.call_self_n_times(n))
}

/// Expose `Callcenter::call_spend_with_limit` to the host
#[no_mangle]
unsafe fn call_spend_with_limit(arg_len: u32) -> u32 {
Expand All @@ -153,6 +174,12 @@ unsafe fn return_caller(arg_len: u32) -> u32 {
wrap_call(arg_len, |_: ()| STATE.return_caller())
}

/// Expose `Callcenter::return_callstack()` to the host
#[no_mangle]
unsafe fn return_callstack(arg_len: u32) -> u32 {
wrap_call(arg_len, |_: ()| STATE.return_callstack())
}

/// Expose `Callcenter::delegate_query()` to the host
#[no_mangle]
unsafe fn delegate_query(arg_len: u32) -> u32 {
Expand Down
15 changes: 15 additions & 0 deletions contracts/callstack/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "callstack"
version = "0.1.0"
authors = [
"Milosz Muszynski <[email protected]>",
]
edition = "2021"

license = "MPL-2.0"

[dependencies]
piecrust-uplink = { path = "../../piecrust-uplink", features = ["abi", "dlmalloc"] }

[lib]
crate-type = ["cdylib", "rlib"]
34 changes: 34 additions & 0 deletions contracts/callstack/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) DUSK NETWORK. All rights reserved.

//! Contract which exposes the call stack

#![no_std]

extern crate alloc;

use piecrust_uplink as uplink;
use alloc::vec::Vec;
use uplink::ContractId;

/// Struct that describes the state of the contract
pub struct CallStack;

/// State of the Counter contract
static mut STATE: CallStack = CallStack;

impl CallStack {
/// Return the call stack
pub fn return_callstack(&self) -> Vec<ContractId> {
uplink::callstack()
}
}

/// Expose `CallStack::read_callstack()` to the host
#[no_mangle]
unsafe fn return_callstack(arg_len: u32) -> u32 {
uplink::wrap_call_unchecked(arg_len, |_: ()| STATE.return_callstack())
}
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
2 changes: 1 addition & 1 deletion piecrust-uplink/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ categories = ["wasm", "no-std", "cryptography::cryptocurrencies"]
keywords = ["virtual", "machine", "smart", "contract", "wasm"]

repository = "https://github.com/dusk-network/piecrust"
version = "0.17.1"
version = "0.17.2-rc.0"

edition = "2021"
license = "MPL-2.0"
Expand Down
17 changes: 17 additions & 0 deletions piecrust-uplink/src/abi/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ mod ext {
pub fn feed(arg_len: u32);

pub fn caller() -> i32;
pub fn callstack() -> i32;
pub fn limit() -> u64;
pub fn spent() -> u64;
pub fn owner(contract_id: *const u8) -> i32;
Expand Down Expand Up @@ -289,6 +290,22 @@ pub fn caller() -> Option<ContractId> {
}
}

/// Returns IDs of all calling contracts present in the calling stack
pub fn callstack() -> Vec<ContractId> {
let n = unsafe { ext::callstack() };
with_arg_buf(|buf| {
let mut v = Vec::new();
for i in 0..n as usize {
let mut bytes = [0; CONTRACT_ID_BYTES];
bytes.copy_from_slice(
&buf[i * CONTRACT_ID_BYTES..(i + 1) * CONTRACT_ID_BYTES],
);
v.push(ContractId::from_bytes(bytes));
}
v
})
}

/// Returns the gas limit with which the contact was called.
pub fn limit() -> u64 {
unsafe { ext::limit() }
Expand Down
4 changes: 2 additions & 2 deletions piecrust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ categories = ["wasm", "no-std", "cryptography::cryptocurrencies"]
keywords = ["virtual", "machine", "smart", "contract", "wasm"]

repository = "https://github.com/dusk-network/piecrust"
version = "0.26.1-rc.3"
version = "0.27.0-rc.0"

edition = "2021"
license = "MPL-2.0"

[dependencies]
crumbles = { version = "0.3", path = "../crumbles" }
piecrust-uplink = { version = "0.17", path = "../piecrust-uplink" }
piecrust-uplink = { version = "0.17.2-rc.0", path = "../piecrust-uplink" }

dusk-wasmtime = { version = "21.0.0-alpha", default-features = false, features = ["cranelift", "runtime", "parallel-compilation"] }
bytecheck = "0.6"
Expand Down
14 changes: 14 additions & 0 deletions piecrust/src/call_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,20 @@ impl CallTree {
current.map(|inner| unsafe { (*inner).elem })
}

/// Returns all call ids.
pub(crate) fn call_ids(&self) -> Vec<&ContractId> {
let mut v = Vec::new();
let mut current = self.0;

while current.is_some() {
let p = *current.as_ref().unwrap();
v.push(unsafe { &(*p).elem.contract_id });
current = current.and_then(|inner| unsafe { (*inner).parent });
}

v
}

/// Clears the call tree of all elements.
pub(crate) fn clear(&mut self) {
unsafe {
Expand Down
16 changes: 16 additions & 0 deletions piecrust/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ impl Imports {
fn import(store: &mut Store<Env>, name: &str, is_64: bool) -> Option<Func> {
Some(match name {
"caller" => Func::wrap(store, caller),
"callstack" => Func::wrap(store, callstack),
"c" => match is_64 {
false => Func::wrap(store, wasm32::c),
true => Func::wrap(store, wasm64::c),
Expand Down Expand Up @@ -386,6 +387,21 @@ fn caller(env: Caller<Env>) -> i32 {
}
}

fn callstack(env: Caller<Env>) -> i32 {
let env = env.data();
let instance = env.self_instance();

let mut i = 0usize;
for contract_id in env.call_ids() {
instance.with_arg_buf_mut(|buf| {
buf[i * CONTRACT_ID_BYTES..(i + 1) * CONTRACT_ID_BYTES]
.copy_from_slice(contract_id.as_bytes());
});
i += 1;
}
i as i32
}

fn feed(mut fenv: Caller<Env>, arg_len: u32) -> WasmtimeResult<()> {
let env = fenv.data_mut();
let instance = env.self_instance();
Expand Down
4 changes: 4 additions & 0 deletions piecrust/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,10 @@ impl Session {
self.inner.call_tree.nth_parent(n)
}

pub(crate) fn call_ids(&self) -> Vec<&ContractId> {
self.inner.call_tree.call_ids()
}

/// Creates a new instance of the given contract, returning its memory
/// length.
fn create_instance(
Expand Down
Loading
Loading