Skip to content

Commit

Permalink
piecrust: change caller import to return integer
Browse files Browse the repository at this point in the history
The integer signals whether there is actually a caller or not. It will
be 1 if there is a caller, 0 if no caller, and the contract is the first
in the call chain.

This allows for contracts to more easily handle the situation in which
they're the first to be called, a situation which happens often
downstream in e.g. queries.
  • Loading branch information
Eduardo Leegwater Simões committed Jul 29, 2024
1 parent 43c0dc4 commit 133b378
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 27 deletions.
4 changes: 4 additions & 0 deletions piecrust/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- Change `callee` import to return an integer

## [0.22.0] - 2024-07-03

### Added
Expand Down
53 changes: 30 additions & 23 deletions piecrust/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ pub(crate) fn hd(

pub(crate) fn c(
mut fenv: Caller<Env>,
mod_id_ofs: usize,
callee_ofs: usize,
name_ofs: usize,
name_len: u32,
arg_len: u32,
Expand All @@ -229,7 +229,7 @@ pub(crate) fn c(

let name_len = name_len as usize;

check_ptr(instance, mod_id_ofs, CONTRACT_ID_BYTES)?;
check_ptr(instance, callee_ofs, CONTRACT_ID_BYTES)?;
check_ptr(instance, name_ofs, name_len)?;
check_arg(instance, arg_len)?;

Expand All @@ -248,13 +248,14 @@ pub(crate) fn c(
let with_memory = |memory: &mut [u8]| -> Result<_, Error> {
let arg_buf = &memory[argbuf_ofs..][..ARGBUF_LEN];

let mut mod_id = ContractId::uninitialized();
mod_id.as_bytes_mut().copy_from_slice(
&memory[mod_id_ofs..][..std::mem::size_of::<ContractId>()],
let mut callee_bytes = [0; CONTRACT_ID_BYTES];
callee_bytes.copy_from_slice(
&memory[callee_ofs..callee_ofs + CONTRACT_ID_BYTES],
);
let callee_id = ContractId::from_bytes(callee_bytes);

let callee_stack_element = env
.push_callstack(mod_id, callee_limit)
.push_callstack(callee_id, callee_limit)
.expect("pushing to the callstack should succeed");
let callee = env
.instance(&callee_stack_element.contract_id)
Expand Down Expand Up @@ -351,17 +352,20 @@ pub(crate) fn emit(
Ok(())
}

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

let mod_id = env
.nth_from_top(1)
.map_or(ContractId::uninitialized(), |elem| elem.contract_id);

env.self_instance().with_arg_buf_mut(|arg| {
arg[..std::mem::size_of::<ContractId>()]
.copy_from_slice(mod_id.as_bytes())
})
match env.nth_from_top(1) {
Some(call_tree_elem) => {
let instance = env.self_instance();
instance.with_arg_buf_mut(|buf| {
let caller = call_tree_elem.contract_id;
buf[..CONTRACT_ID_BYTES].copy_from_slice(caller.as_bytes());
});
1
}
None => 0,
}
}

fn feed(mut fenv: Caller<Env>, arg_len: u32) -> WasmtimeResult<()> {
Expand Down Expand Up @@ -432,10 +436,13 @@ fn panic(fenv: Caller<Env>, arg_len: u32) -> WasmtimeResult<()> {
})?)
}

fn get_metadata(env: &mut Env, mod_id_ofs: usize) -> Option<&ContractMetadata> {
fn get_metadata(
env: &mut Env,
contract_id_ofs: usize,
) -> Option<&ContractMetadata> {
// The null pointer is always zero, so we can use this to check if the
// caller wants their own ID.
if mod_id_ofs == 0 {
if contract_id_ofs == 0 {
let self_id = env.self_contract_id().to_owned();

let contract_metadata = env
Expand All @@ -446,15 +453,15 @@ fn get_metadata(env: &mut Env, mod_id_ofs: usize) -> Option<&ContractMetadata> {
} else {
let instance = env.self_instance();

let mod_id = instance.with_memory(|memory| {
let mut mod_id = ContractId::uninitialized();
mod_id.as_bytes_mut().copy_from_slice(
&memory[mod_id_ofs..][..std::mem::size_of::<ContractId>()],
let contract_id = instance.with_memory(|memory| {
let mut contract_id_bytes = [0u8; CONTRACT_ID_BYTES];
contract_id_bytes.copy_from_slice(
&memory[contract_id_ofs..][..CONTRACT_ID_BYTES],
);
mod_id
ContractId::from_bytes(contract_id_bytes)
});

env.contract_metadata(&mod_id)
env.contract_metadata(&contract_id)
}
}

Expand Down
6 changes: 4 additions & 2 deletions piecrust/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ use std::sync::{mpsc, Arc};

use bytecheck::CheckBytes;
use dusk_wasmtime::{Engine, LinearMemory, MemoryCreator, MemoryType};
use piecrust_uplink::{ContractId, Event, ARGBUF_LEN, SCRATCH_BUF_BYTES};
use piecrust_uplink::{
ContractId, Event, ARGBUF_LEN, CONTRACT_ID_BYTES, SCRATCH_BUF_BYTES,
};
use rkyv::ser::serializers::{
BufferScratch, BufferSerializer, CompositeSerializer,
};
Expand Down Expand Up @@ -138,7 +140,7 @@ impl Session {
data: SessionData,
) -> Self {
let inner = SessionInner {
current: ContractId::uninitialized(),
current: ContractId::from_bytes([0; CONTRACT_ID_BYTES]),
call_tree: CallTree::new(),
instances: BTreeMap::new(),
debug: vec![],
Expand Down
4 changes: 2 additions & 2 deletions piecrust/tests/callcenter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,9 +235,9 @@ pub fn cc_caller_uninit() -> Result<(), Error> {
LIMIT,
)?;

let caller: ContractId =
let caller: Option<ContractId> =
session.call(center_id, "return_caller", &(), LIMIT)?.data;
assert_eq!(caller, ContractId::uninitialized());
assert_eq!(caller, None);

Ok(())
}
Expand Down

0 comments on commit 133b378

Please sign in to comment.