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

Implemented TestHost functions: #563

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e4aa6ab
Support get_slot_time in test host
limemloh Sep 26, 2024
581809b
Refactored
rasmus-kirk Oct 3, 2024
77945dc
Added get/set_receive_address
rasmus-kirk Oct 3, 2024
aa91a43
Format+clippy
rasmus-kirk Oct 3, 2024
d0fbd3d
Added get/set_receive_self_address and cleaned
rasmus-kirk Oct 3, 2024
b3db747
changelog
rasmus-kirk Oct 3, 2024
076d0ec
Accidently removed a public function, undoing that...
rasmus-kirk Oct 3, 2024
6ba3d66
Update smart-contracts/wasm-chain-integration/CHANGELOG.md
rasmus-kirk Oct 11, 2024
2508aeb
Update smart-contracts/wasm-chain-integration/src/utils.rs
rasmus-kirk Oct 11, 2024
c67458a
Update smart-contracts/wasm-chain-integration/src/utils.rs
rasmus-kirk Oct 11, 2024
ba80d06
Update smart-contracts/wasm-chain-integration/src/utils.rs
rasmus-kirk Oct 11, 2024
4adb6f2
Fixed param methods
rasmus-kirk Oct 12, 2024
d7acecf
Updated changelog
rasmus-kirk Oct 16, 2024
acb1228
Added support for event logging
rasmus-kirk Oct 17, 2024
9ed61dd
Added init_origin functions
rasmus-kirk Oct 17, 2024
01fa40e
Completed `receive_invoker` and `receive_sender`
rasmus-kirk Oct 18, 2024
6297325
Implemented `receive_owner` and `receive_entrypoint` functionality
rasmus-kirk Oct 18, 2024
9ad51e2
Implemented `verify_ed25519_signature`
rasmus-kirk Oct 18, 2024
8277caf
Implemented `verify_ecdsa_secp256k1_signature` in TestHost
rasmus-kirk Oct 22, 2024
8f15889
Format
rasmus-kirk Oct 22, 2024
2cf809b
Implmented hashing functions
rasmus-kirk Oct 22, 2024
f3f3330
Updated changelog
rasmus-kirk Oct 22, 2024
021f7e3
Appeased clippy
rasmus-kirk Oct 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,7 @@ idiss-csharp/*/obj

/smart-contracts/rust-contracts/concordium-std/Cargo.lock
/smart-contracts/wasm-transform/Cargo.lock

# Nix
**/*.nix
**/flake.lock
8 changes: 8 additions & 0 deletions smart-contracts/wasm-chain-integration/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

## Unreleased changes

- Implemented the following `TestHost` functions:
- `set_slot_time`
- `get_slot_time`
- `set_receive_self_address`
- `get_receive_self_address`
- `set_receive_self_balance`
- `get_receive_self_balance`
rasmus-kirk marked this conversation as resolved.
Show resolved Hide resolved

## concordium-smart-contract-engine 6.0.0 (2024-09-09)

- Bump `concordium-wasm` to version 5 used by Concordium node version 7.0.0.
Expand Down
159 changes: 100 additions & 59 deletions smart-contracts/wasm-chain-integration/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ use crate::{
use anyhow::{anyhow, bail, ensure, Context};
pub use concordium_contracts_common::WasmVersion;
use concordium_contracts_common::{
self as concordium_std, from_bytes, hashes, schema, Cursor, Deserial,
self as concordium_std, from_bytes, hashes, schema, ContractAddress, Cursor, Deserial, Seek,
SeekFrom, Serial,
};
use concordium_wasm::{
artifact::{Artifact, ArtifactNamedImport, RunnableCode, TryFromImport},
Expand Down Expand Up @@ -57,6 +58,12 @@ pub struct TestHost<'a, R, BackingStore> {
pub debug_events: Vec<EmittedDebugStatement>,
/// In-memory instance state used for state-related host calls.
state: InstanceState<'a, BackingStore>,
/// Time in milliseconds at the beginning of the smart contract's block.
slot_time: Option<u64>,
/// The address of this smart contract
address: Option<ContractAddress>,
/// The current balance of this smart contract
balance: Option<u64>,
}

impl<'a, R: RngCore, BackingStore> TestHost<'a, R, BackingStore> {
Expand All @@ -69,6 +76,9 @@ impl<'a, R: RngCore, BackingStore> TestHost<'a, R, BackingStore> {
rng_used: false,
debug_events: Vec::new(),
state,
slot_time: None,
address: None,
balance: None,
}
}
}
Expand Down Expand Up @@ -175,66 +185,97 @@ impl<'a, R: RngCore, BackingStore: trie::BackingStoreLoad> machine::Host<Artifac
// We don't track the energy usage in this host, so to reuse code which does, we
// provide a really large amount of energy to preventing the case of
// running out of energy.
let mut energy = crate::InterpreterEnergy::new(u64::MAX);
if f.matches("concordium", "report_error") {
let (filename, line, column, msg) = extract_debug(memory, stack)?;
bail!(ReportError::Reported {
filename,
line,
column,
msg
})
} else if f.matches("concordium", "get_random") {
let size = unsafe { stack.pop_u32() } as usize;
let dest = unsafe { stack.pop_u32() } as usize;
ensure!(dest + size <= memory.len(), "Illegal memory access.");
self.rng_used = true;
match self.rng.as_mut() {
Some(r) => {
r.try_fill_bytes(&mut memory[dest..dest + size])?;
}
None => {
bail!("Expected an initialized RNG.");
}
let energy = &mut crate::InterpreterEnergy::new(u64::MAX);
let state = &mut self.state;

ensure!(f.get_mod_name() == "concordium", "Illegal module name! ({:?})", f.get_mod_name());
rasmus-kirk marked this conversation as resolved.
Show resolved Hide resolved

use host::*;
match f.get_item_name() {
"report_error" => {
let (filename, line, column, msg) = extract_debug(memory, stack)?;
bail!(ReportError::Reported {
filename,
line,
column,
msg
})
}
} else if f.matches("concordium", "debug_print") {
let (filename, line, column, msg) = extract_debug(memory, stack)?;
self.debug_events.push(EmittedDebugStatement {
filename,
line,
column,
msg,
remaining_energy: 0.into(), // debug host does not have energy.
});
} else if f.matches("concordium", "state_lookup_entry") {
host::state_lookup_entry(memory, stack, &mut energy, &mut self.state)?;
} else if f.matches("concordium", "state_create_entry") {
host::state_create_entry(memory, stack, &mut energy, &mut self.state)?;
} else if f.matches("concordium", "state_delete_entry") {
host::state_delete_entry(memory, stack, &mut energy, &mut self.state)?;
} else if f.matches("concordium", "state_delete_prefix") {
host::state_delete_prefix(memory, stack, &mut energy, &mut self.state)?;
} else if f.matches("concordium", "state_iterate_prefix") {
host::state_iterator(memory, stack, &mut energy, &mut self.state)?;
} else if f.matches("concordium", "state_iterator_next") {
host::state_iterator_next(stack, &mut energy, &mut self.state)?;
} else if f.matches("concordium", "state_iterator_delete") {
host::state_iterator_delete(stack, &mut energy, &mut self.state)?;
} else if f.matches("concordium", "state_iterator_key_size") {
host::state_iterator_key_size(stack, &mut energy, &mut self.state)?;
} else if f.matches("concordium", "state_iterator_key_read") {
host::state_iterator_key_read(memory, stack, &mut energy, &mut self.state)?;
} else if f.matches("concordium", "state_entry_read") {
host::state_entry_read(memory, stack, &mut energy, &mut self.state)?;
} else if f.matches("concordium", "state_entry_write") {
host::state_entry_write(memory, stack, &mut energy, &mut self.state)?;
} else if f.matches("concordium", "state_entry_size") {
host::state_entry_size(stack, &mut energy, &mut self.state)?;
} else if f.matches("concordium", "state_entry_resize") {
host::state_entry_resize(stack, &mut energy, &mut self.state)?;
} else {
bail!("Unsupported host function call.")
"get_random" => {
let size = unsafe { stack.pop_u32() } as usize;
let dest = unsafe { stack.pop_u32() } as usize;
ensure!(dest + size <= memory.len(), "Illegal memory access.");
self.rng_used = true;
self.rng
.as_mut()
.context("Expected an initialized RNG.")?
.try_fill_bytes(&mut memory[dest..dest + size])?
}
"debug_print" => {
let (filename, line, column, msg) = extract_debug(memory, stack)?;
self.debug_events.push(EmittedDebugStatement {
filename,
line,
column,
msg,
remaining_energy: 0.into(), // debug host does not have energy.
});
}
"state_lookup_entry" => state_lookup_entry(memory, stack, energy, state)?,
"state_create_entry" => state_create_entry(memory, stack, energy, state)?,
"state_delete_entry" => state_delete_entry(memory, stack, energy, state)?,
"state_delete_prefix" => state_delete_prefix(memory, stack, energy, state)?,
"state_iterate_prefix" => state_iterator(memory, stack, energy, state)?,
"state_iterator_next" => state_iterator_next(stack, energy, state)?,
"state_iterator_delete" => state_iterator_delete(stack, energy, state)?,
"state_iterator_key_size" => state_iterator_key_size(stack, energy, state)?,
"state_iterator_key_read" => state_iterator_key_read(memory, stack, energy, state)?,
"state_entry_read" => state_entry_read(memory, stack, energy, state)?,
"state_entry_write" => state_entry_write(memory, stack, energy, state)?,
"state_entry_size" => state_entry_size(stack, energy, state)?,
"state_entry_resize" => state_entry_resize(stack, energy, state)?,
"set_slot_time" => {
let slot_time = unsafe { stack.pop_u64() };
self.slot_time = Some(slot_time);
}
"get_slot_time" => {
let slot_time = self.slot_time.context("slot_time is not set")?;
rasmus-kirk marked this conversation as resolved.
Show resolved Hide resolved
stack.push_value(slot_time);
}
"set_receive_self_address" => {
let addr_ptr = unsafe { stack.pop_u32() };
let mut cursor = Cursor::new(memory);

cursor
.seek(SeekFrom::Start(addr_ptr))
.map_err(|_| anyhow!("unable to read bytes at the given position"))?;

self.address = Some(ContractAddress::deserial(&mut cursor)?);
}
"get_receive_self_address" => {
let addr_ptr = unsafe { stack.pop_u32() };
let mut cursor = Cursor::new(memory);

cursor
.seek(SeekFrom::Start(addr_ptr))
.map_err(|_| anyhow!("unable to read bytes at the given position"))?;

self.address
.context("self_address is not set")?
rasmus-kirk marked this conversation as resolved.
Show resolved Hide resolved
.serial(&mut cursor)
.map_err(|_| anyhow!("unable to serialize the self address"))?;
}
"set_receive_self_balance" => {
let balance = unsafe { stack.pop_u64() };
self.balance = Some(balance);
}
"get_receive_self_balance" => {
let balance = self.balance.context("no balance was set")?;
rasmus-kirk marked this conversation as resolved.
Show resolved Hide resolved
stack.push_value(balance);
}
item_name => bail!("Unsupported host function call ({:?}).", item_name),
rasmus-kirk marked this conversation as resolved.
Show resolved Hide resolved
}

Ok(None)
}

Expand Down
4 changes: 4 additions & 0 deletions smart-contracts/wasm-transform/src/artifact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,10 @@ impl ArtifactNamedImport {
pub fn matches(&self, mod_name: &str, item_name: &str) -> bool {
self.mod_name.as_ref() == mod_name && self.item_name.as_ref() == item_name
}

pub fn get_mod_name(&self) -> &str { self.mod_name.as_ref() }

pub fn get_item_name(&self) -> &str { self.item_name.as_ref() }
}

impl TryFromImport for ArtifactNamedImport {
Expand Down
Loading