From 28ce9c4020e5b6311d136f319c5ffd30373558f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Holm=20Gj=C3=B8rup?= Date: Thu, 26 Sep 2024 15:22:48 +0200 Subject: [PATCH 01/14] Add set_slot_time and unit test --- concordium-std/src/prims.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/concordium-std/src/prims.rs b/concordium-std/src/prims.rs index aa2d5808..c3527bd8 100644 --- a/concordium-std/src/prims.rs +++ b/concordium-std/src/prims.rs @@ -288,6 +288,10 @@ extern "C" { column: u32, ); + /// TODO + #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] + pub(crate) fn set_slot_time(slot_time: u64); + #[cfg(feature = "debug")] /// Emit text together with the source location. /// This is used as the equivalent of the `dbg!` macro when the @@ -513,3 +517,18 @@ mod host_dummy_functions { unimplemented!("Dummy function! Not to be executed") } } + +#[cfg(feature = "internal-wasm-test")] +mod wasm_test { + use super::*; + use crate::{claim_eq, concordium_test}; + + #[concordium_test] + fn test() { + let slot_time = unsafe { + set_slot_time(10); + get_slot_time() + }; + claim_eq!(slot_time, 10) + } +} From 93331c690402483d3af1d7a802caa19371bef5e1 Mon Sep 17 00:00:00 2001 From: rasmus-kirk Date: Thu, 3 Oct 2024 16:29:27 +0200 Subject: [PATCH 02/14] Tested get/set_receive_self_address and cleaned --- .gitignore | 7 +++++++ concordium-std/src/prims.rs | 39 +++++++++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index dfa98a04..f306210e 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,10 @@ Cargo.lock *.wasm.v1 *.wasm.v0 + +# Editor specific +**/.helix + +# Nix artifacts +**/*.nix +**/flake.lock diff --git a/concordium-std/src/prims.rs b/concordium-std/src/prims.rs index c3527bd8..dbd35e5a 100644 --- a/concordium-std/src/prims.rs +++ b/concordium-std/src/prims.rs @@ -288,10 +288,19 @@ extern "C" { column: u32, ); - /// TODO + /// Set the slot time in milliseconds. + /// The slot time represents the beginning of the smart contract's block. #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] pub(crate) fn set_slot_time(slot_time: u64); + /// Sets the address of this smart contract + #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] + pub(crate) fn set_receive_self_balance(balance: u64); + + /// Sets the current balance of this smart contract + #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] + pub(crate) fn set_receive_self_address(start: *const u8); + #[cfg(feature = "debug")] /// Emit text together with the source location. /// This is used as the equivalent of the `dbg!` macro when the @@ -520,15 +529,41 @@ mod host_dummy_functions { #[cfg(feature = "internal-wasm-test")] mod wasm_test { + use concordium_contracts_common::{from_bytes, to_bytes, ContractAddress}; + use super::*; use crate::{claim_eq, concordium_test}; #[concordium_test] - fn test() { + fn set_get_slot_time() { let slot_time = unsafe { set_slot_time(10); get_slot_time() }; claim_eq!(slot_time, 10) } + + #[concordium_test] + fn set_get_receive_self_balance() { + let balance = unsafe { + set_receive_self_balance(1729); + get_receive_self_balance() + }; + claim_eq!(balance, 1729) + } + + #[concordium_test] + fn set_get_receive_self_address() { + let address = ContractAddress::new(5040, 12); + let address_bytes = to_bytes(&address); + let mut out_bytes = [0u8; 16]; + + unsafe { + set_receive_self_address(address_bytes.as_ptr()); + get_receive_self_address(out_bytes.as_mut_ptr()); + }; + + let out_address = from_bytes(&out_bytes).unwrap(); + claim_eq!(address, out_address); + } } From bf4676c452f1476bf46ae917a9e3519c2fc068fe Mon Sep 17 00:00:00 2001 From: rasmus-kirk Date: Thu, 3 Oct 2024 16:34:13 +0200 Subject: [PATCH 03/14] Changelog --- concordium-std/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/concordium-std/CHANGELOG.md b/concordium-std/CHANGELOG.md index ca9ba040..617fda61 100644 --- a/concordium-std/CHANGELOG.md +++ b/concordium-std/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## Unreleased + +- Added the following functions in the primitive interface: + - `set_slot_time` + - `set_receive_self_address` + - `set_receive_self_balance` + ## concordium-std 10.1.0 (2024-04-04) - Add support for querying the module reference and contract name of an instance, From 13a2e4cf93effa003876dcccd95ba17be29a740b Mon Sep 17 00:00:00 2001 From: rasmus-kirk Date: Fri, 11 Oct 2024 15:46:03 +0200 Subject: [PATCH 04/14] Created TestEnv --- concordium-std/src/lib.rs | 1 + concordium-std/src/prims.rs | 41 --------------------- concordium-std/src/test_env.rs | 67 ++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 41 deletions(-) create mode 100644 concordium-std/src/test_env.rs diff --git a/concordium-std/src/lib.rs b/concordium-std/src/lib.rs index 913fdc4d..357bd12f 100644 --- a/concordium-std/src/lib.rs +++ b/concordium-std/src/lib.rs @@ -463,6 +463,7 @@ pub mod constants; mod impls; pub mod prims; mod state_btree; +pub mod test_env; mod traits; mod types; pub use concordium_contracts_common::*; diff --git a/concordium-std/src/prims.rs b/concordium-std/src/prims.rs index dbd35e5a..184b2a99 100644 --- a/concordium-std/src/prims.rs +++ b/concordium-std/src/prims.rs @@ -526,44 +526,3 @@ mod host_dummy_functions { unimplemented!("Dummy function! Not to be executed") } } - -#[cfg(feature = "internal-wasm-test")] -mod wasm_test { - use concordium_contracts_common::{from_bytes, to_bytes, ContractAddress}; - - use super::*; - use crate::{claim_eq, concordium_test}; - - #[concordium_test] - fn set_get_slot_time() { - let slot_time = unsafe { - set_slot_time(10); - get_slot_time() - }; - claim_eq!(slot_time, 10) - } - - #[concordium_test] - fn set_get_receive_self_balance() { - let balance = unsafe { - set_receive_self_balance(1729); - get_receive_self_balance() - }; - claim_eq!(balance, 1729) - } - - #[concordium_test] - fn set_get_receive_self_address() { - let address = ContractAddress::new(5040, 12); - let address_bytes = to_bytes(&address); - let mut out_bytes = [0u8; 16]; - - unsafe { - set_receive_self_address(address_bytes.as_ptr()); - get_receive_self_address(out_bytes.as_mut_ptr()); - }; - - let out_address = from_bytes(&out_bytes).unwrap(); - claim_eq!(address, out_address); - } -} diff --git a/concordium-std/src/test_env.rs b/concordium-std/src/test_env.rs new file mode 100644 index 00000000..89160700 --- /dev/null +++ b/concordium-std/src/test_env.rs @@ -0,0 +1,67 @@ +use concordium_contracts_common::{Amount, ContractAddress, SlotTime}; + +use crate::{from_bytes, prims, to_bytes}; + +struct TestEnv; + +impl TestEnv { + pub fn set_slot_time(self, slot_time: SlotTime) -> Self { + unsafe { prims::set_slot_time(slot_time.timestamp_millis()) }; + self + } + + pub fn get_slot_time(self) -> SlotTime { + unsafe { SlotTime::from_timestamp_millis(prims::get_slot_time()) } + } + + pub fn set_receive_balance(self, balance: Amount) -> Self { + unsafe { prims::set_receive_self_balance(balance.micro_ccd) }; + self + } + + pub fn get_receive_balance(self) -> Amount { + let raw_balance = unsafe { prims::get_receive_self_balance() }; + Amount::from_micro_ccd(raw_balance) + } + + pub fn set_receive_self_address(self, address: ContractAddress) -> Self { + let address_bytes = to_bytes(&address); + unsafe { prims::set_receive_self_address(address_bytes.as_ptr()) }; + self + } + + pub fn get_receive_self_address(self) -> ContractAddress { + let mut out_bytes = [0u8; 16]; + unsafe { prims::get_receive_self_address(out_bytes.as_mut_ptr()) } + from_bytes(&out_bytes).unwrap() + } +} + +#[cfg(feature = "internal-wasm-test")] +mod wasm_test { + use concordium_contracts_common::{ContractAddress, Timestamp}; + + use super::*; + use crate::{claim_eq, concordium_test}; + + #[concordium_test] + fn set_get_slot_time() { + let original = Timestamp::from_timestamp_millis(10); + let stored = TestEnv.set_slot_time(original).get_slot_time(); + claim_eq!(original, stored) + } + + #[concordium_test] + fn set_get_receive_self_balance() { + let original = Amount::from_micro_ccd(1729); + let stored = TestEnv.set_receive_balance(original).get_receive_balance(); + claim_eq!(original, stored) + } + + #[concordium_test] + fn set_get_receive_self_address() { + let original = ContractAddress::new(5040, 12); + let stored = TestEnv.set_receive_self_address(original).get_receive_self_address(); + claim_eq!(original, stored); + } +} From 83aea0402285e2b32cfc62ac129fe15d869978b9 Mon Sep 17 00:00:00 2001 From: rasmus-kirk Date: Sat, 12 Oct 2024 16:24:58 +0200 Subject: [PATCH 05/14] Finished param methods --- concordium-std/src/prims.rs | 4 ++ concordium-std/src/test_env.rs | 71 ++++++++++++++++++++++++---------- 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/concordium-std/src/prims.rs b/concordium-std/src/prims.rs index 184b2a99..5c932ed6 100644 --- a/concordium-std/src/prims.rs +++ b/concordium-std/src/prims.rs @@ -301,6 +301,10 @@ extern "C" { #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] pub(crate) fn set_receive_self_address(start: *const u8); + /// Sets parameter `i` of the smart contract to the given value. + #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] + pub(crate) fn set_parameter(i: u32, start: *const u8, length: u32); + #[cfg(feature = "debug")] /// Emit text together with the source location. /// This is used as the equivalent of the `dbg!` macro when the diff --git a/concordium-std/src/test_env.rs b/concordium-std/src/test_env.rs index 89160700..07dbcc1b 100644 --- a/concordium-std/src/test_env.rs +++ b/concordium-std/src/test_env.rs @@ -1,6 +1,6 @@ use concordium_contracts_common::{Amount, ContractAddress, SlotTime}; -use crate::{from_bytes, prims, to_bytes}; +use crate::{prims, to_bytes}; struct TestEnv; @@ -10,58 +10,89 @@ impl TestEnv { self } - pub fn get_slot_time(self) -> SlotTime { - unsafe { SlotTime::from_timestamp_millis(prims::get_slot_time()) } - } - pub fn set_receive_balance(self, balance: Amount) -> Self { unsafe { prims::set_receive_self_balance(balance.micro_ccd) }; self } - pub fn get_receive_balance(self) -> Amount { - let raw_balance = unsafe { prims::get_receive_self_balance() }; - Amount::from_micro_ccd(raw_balance) - } - pub fn set_receive_self_address(self, address: ContractAddress) -> Self { - let address_bytes = to_bytes(&address); - unsafe { prims::set_receive_self_address(address_bytes.as_ptr()) }; + unsafe { prims::set_receive_self_address(to_bytes(&address).as_ptr()) }; self } - pub fn get_receive_self_address(self) -> ContractAddress { - let mut out_bytes = [0u8; 16]; - unsafe { prims::get_receive_self_address(out_bytes.as_mut_ptr()) } - from_bytes(&out_bytes).unwrap() + pub fn set_parameter(self, param_index: u32, bytes: &[u8]) -> Self { + unsafe { prims::set_parameter(param_index, bytes.as_ptr(), bytes.len() as u32) }; + self } } #[cfg(feature = "internal-wasm-test")] mod wasm_test { + use core::num::NonZeroU32; + use concordium_contracts_common::{ContractAddress, Timestamp}; use super::*; - use crate::{claim_eq, concordium_test}; + use crate::*; + + // Helper functions to get host data, as a real smart contract would + fn extern_host() -> ExternHost<()> { + let state_api = ExternStateApi::open(); + let state_builder = StateBuilder::open(state_api); + ExternHost { + state: (), + state_builder, + } + } + + fn extern_chain_meta() -> ExternChainMeta { ExternChainMeta {} } + + fn external_call_response() -> ExternCallResponse { + ExternCallResponse::new(unsafe { NonZeroU32::new_unchecked(1) }) + } + + fn receive_context() -> ReceiveContext { ExternContext::default() } #[concordium_test] fn set_get_slot_time() { let original = Timestamp::from_timestamp_millis(10); - let stored = TestEnv.set_slot_time(original).get_slot_time(); + TestEnv.set_slot_time(original); + let stored = extern_chain_meta().block_time(); claim_eq!(original, stored) } #[concordium_test] fn set_get_receive_self_balance() { let original = Amount::from_micro_ccd(1729); - let stored = TestEnv.set_receive_balance(original).get_receive_balance(); + TestEnv.set_receive_balance(original); + let stored = extern_host().self_balance(); claim_eq!(original, stored) } #[concordium_test] fn set_get_receive_self_address() { let original = ContractAddress::new(5040, 12); - let stored = TestEnv.set_receive_self_address(original).get_receive_self_address(); + TestEnv.set_receive_self_address(original); + let stored = receive_context().self_address(); claim_eq!(original, stored); } + + #[concordium_test] + fn set_get_parameter() { + let param = vec![3u8; 7]; + + TestEnv.set_parameter(0, ¶m); + + let mut buf = vec![0u8; 10]; + let bytes_read = external_call_response().read(&mut stored).unwrap(); + + let param_size = unsafe { prims::get_parameter_size(0) }; + let bytes_written = unsafe { prims::get_parameter_section(0, buf.as_mut_ptr(), 5, 2) }; + + let expected = vec![0, 0, 3, 3, 3, 3, 3, 0, 0, 0]; + + claim_eq!(param_size, 7); + claim_eq!(bytes_written, 5); + claim_eq!(buf, expected); + } } From b4d6213aa93e5ba58c2c45d705a4eea97136fd58 Mon Sep 17 00:00:00 2001 From: rasmus-kirk Date: Wed, 16 Oct 2024 16:35:20 +0200 Subject: [PATCH 06/14] Fixed test and updated changelog --- concordium-std/CHANGELOG.md | 9 +++++++++ concordium-std/src/test_env.rs | 21 +++++++++++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/concordium-std/CHANGELOG.md b/concordium-std/CHANGELOG.md index 617fda61..82f0ba1f 100644 --- a/concordium-std/CHANGELOG.md +++ b/concordium-std/CHANGELOG.md @@ -6,6 +6,15 @@ - `set_slot_time` - `set_receive_self_address` - `set_receive_self_balance` + - `set_parameter` + +- Added a more user-friendly interface `TestEnv` that allows users to build + a test host environment using method chaining and proper types. It supports + the following operations: + - `set_slot_time` + - `set_receive_balance` + - `set_receive_self_address` + - `set_parameter` ## concordium-std 10.1.0 (2024-04-04) diff --git a/concordium-std/src/test_env.rs b/concordium-std/src/test_env.rs index 07dbcc1b..61333297 100644 --- a/concordium-std/src/test_env.rs +++ b/concordium-std/src/test_env.rs @@ -79,20 +79,29 @@ mod wasm_test { #[concordium_test] fn set_get_parameter() { + let i = 1; let param = vec![3u8; 7]; - - TestEnv.set_parameter(0, ¶m); - let mut buf = vec![0u8; 10]; - let bytes_read = external_call_response().read(&mut stored).unwrap(); - let param_size = unsafe { prims::get_parameter_size(0) }; - let bytes_written = unsafe { prims::get_parameter_section(0, buf.as_mut_ptr(), 5, 2) }; + TestEnv.set_parameter(i, ¶m); + // Use the prims call to test length and offset + let param_size = unsafe { prims::get_parameter_size(i) }; + let bytes_written = unsafe { prims::get_parameter_section(i, buf.as_mut_ptr(), 5, 2) }; let expected = vec![0, 0, 3, 3, 3, 3, 3, 0, 0, 0]; claim_eq!(param_size, 7); claim_eq!(bytes_written, 5); claim_eq!(buf, expected); + + // Use the external call to test the actual function that would be called in + // most real scenarios + buf = vec![0u8; 7]; + let bytes_written = + external_call_response().read(&mut buf).expect("Unable to read bytes to buffer"); + let expected = param; + + claim_eq!(buf, expected); + claim_eq!(bytes_written, 7); } } From 1973a629c61de393c485d1ed72e0b80415f5acc7 Mon Sep 17 00:00:00 2001 From: rasmus-kirk Date: Thu, 17 Oct 2024 15:33:46 +0200 Subject: [PATCH 07/14] Implemented functions for event logging --- concordium-std/CHANGELOG.md | 3 ++ concordium-std/src/prims.rs | 10 +++++ concordium-std/src/test_env.rs | 81 ++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) diff --git a/concordium-std/CHANGELOG.md b/concordium-std/CHANGELOG.md index 82f0ba1f..5e6df9dd 100644 --- a/concordium-std/CHANGELOG.md +++ b/concordium-std/CHANGELOG.md @@ -7,6 +7,8 @@ - `set_receive_self_address` - `set_receive_self_balance` - `set_parameter` + - `get_event` + - `get_event_size` - Added a more user-friendly interface `TestEnv` that allows users to build a test host environment using method chaining and proper types. It supports @@ -15,6 +17,7 @@ - `set_receive_balance` - `set_receive_self_address` - `set_parameter` + - `get_event` ## concordium-std 10.1.0 (2024-04-04) diff --git a/concordium-std/src/prims.rs b/concordium-std/src/prims.rs index 5c932ed6..776976bd 100644 --- a/concordium-std/src/prims.rs +++ b/concordium-std/src/prims.rs @@ -305,6 +305,16 @@ extern "C" { #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] pub(crate) fn set_parameter(i: u32, start: *const u8, length: u32); + /// Gets event number `i` in the smart contract state. Returns `-1` if `i` + /// is an invalid index. Otherwise returns bytes written. + #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] + pub(crate) fn get_event(i: u32, start: *const u8) -> i32; + + /// Gets the size of event number `i` in the smart contract state. Returns `-1` if `i` + /// is an invalid index. + #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] + pub(crate) fn get_event_size(i: u32) -> i32; + #[cfg(feature = "debug")] /// Emit text together with the source location. /// This is used as the equivalent of the `dbg!` macro when the diff --git a/concordium-std/src/test_env.rs b/concordium-std/src/test_env.rs index 61333297..76a305d4 100644 --- a/concordium-std/src/test_env.rs +++ b/concordium-std/src/test_env.rs @@ -5,25 +5,50 @@ use crate::{prims, to_bytes}; struct TestEnv; impl TestEnv { + /// Set the slot time in milliseconds. + /// The slot time represents the beginning of the smart contract's block. pub fn set_slot_time(self, slot_time: SlotTime) -> Self { unsafe { prims::set_slot_time(slot_time.timestamp_millis()) }; self } + /// Sets the current balance of this smart contract pub fn set_receive_balance(self, balance: Amount) -> Self { unsafe { prims::set_receive_self_balance(balance.micro_ccd) }; self } + /// Sets the address of this smart contract pub fn set_receive_self_address(self, address: ContractAddress) -> Self { unsafe { prims::set_receive_self_address(to_bytes(&address).as_ptr()) }; self } + /// Sets parameter with `param_index` of the smart contract to the given + /// value. pub fn set_parameter(self, param_index: u32, bytes: &[u8]) -> Self { unsafe { prims::set_parameter(param_index, bytes.as_ptr(), bytes.len() as u32) }; self } + + /// Gets event number `i` in the smart contract state. Returns None if `i` + /// is an invalid index. + pub fn get_event(self, index: u32) -> Option> { + let event_len = unsafe { prims::get_event_size(index) }; + + if event_len < 0 { + return None; + } + + let mut buf = vec![0; event_len.try_into().unwrap()]; + let bytes_written = unsafe { prims::get_event(index, buf.as_mut_ptr()) }; + + if bytes_written < 0 { + return None; + } else { + Some(buf) + } + } } #[cfg(feature = "internal-wasm-test")] @@ -104,4 +129,60 @@ mod wasm_test { claim_eq!(buf, expected); claim_eq!(bytes_written, 7); } + + #[concordium_test] + fn get_empty_parameter() { + let i = 1; + let mut buf = vec![0u8; 10]; + + let param_size = unsafe { prims::get_parameter_size(i) }; + let bytes_written = unsafe { prims::get_parameter_section(i, buf.as_mut_ptr(), 5, 2) }; + + claim_eq!(param_size, -1); + claim_eq!(param_size, bytes_written); + } + + #[concordium_test] + fn set_get_events() { + // Testing primitive calls + let event_prim = vec![1u8, 2, 3, 4]; + let store_status = + unsafe { prims::log_event(event_prim.as_ptr(), event_prim.len().try_into().unwrap()) }; + let event_size = unsafe { prims::get_event_size(0) }; + + claim_eq!(store_status, 1); + claim_eq!(event_size, event_prim.len().try_into().unwrap()); + + let mut buf = vec![0; event_prim.len()]; + let bytes_written = unsafe { prims::get_event(0, buf.as_mut_ptr()) }; + + claim_eq!(bytes_written as usize, event_prim.len()); + claim_eq!(buf, event_prim); + + // Use the external call to test the actual function that would be called in + // most real scenarios + let mut logger = Logger::default(); + let event1 = "Hello, World!".to_owned(); + let event2 = "How are you today?".to_owned(); + + logger.log(&event1).unwrap(); + logger.log(&event2).unwrap(); + + let stored1 = TestEnv.get_event(1).unwrap(); + let stored2 = TestEnv.get_event(2).unwrap(); + + let mut expected1 = Vec::new(); + let mut expected2 = Vec::new(); + event1.serial(&mut expected1).unwrap(); + event2.serial(&mut expected2).unwrap(); + + claim_eq!(stored1, expected1); + claim_eq!(stored2, expected2); + } + + #[concordium_test] + fn get_empty_events() { + let stored = TestEnv.get_event(0); + claim_eq!(stored, None); + } } From 4527ec08dc05a2f7e9387d5b5253a2532db39285 Mon Sep 17 00:00:00 2001 From: rasmus-kirk Date: Thu, 17 Oct 2024 17:30:48 +0200 Subject: [PATCH 08/14] Added init_origin functions --- concordium-std/CHANGELOG.md | 2 ++ concordium-std/src/prims.rs | 6 ++++- concordium-std/src/test_env.rs | 46 +++++++++++++++++++++++----------- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/concordium-std/CHANGELOG.md b/concordium-std/CHANGELOG.md index 5e6df9dd..be0e7e8a 100644 --- a/concordium-std/CHANGELOG.md +++ b/concordium-std/CHANGELOG.md @@ -7,6 +7,7 @@ - `set_receive_self_address` - `set_receive_self_balance` - `set_parameter` + - `set_init_origin` - `get_event` - `get_event_size` @@ -17,6 +18,7 @@ - `set_receive_balance` - `set_receive_self_address` - `set_parameter` + - `set_init_origin` - `get_event` ## concordium-std 10.1.0 (2024-04-04) diff --git a/concordium-std/src/prims.rs b/concordium-std/src/prims.rs index 776976bd..efb88c9f 100644 --- a/concordium-std/src/prims.rs +++ b/concordium-std/src/prims.rs @@ -305,10 +305,14 @@ extern "C" { #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] pub(crate) fn set_parameter(i: u32, start: *const u8, length: u32); + /// Sets the address of the sender, 32 bytes + #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] + pub(crate) fn set_init_origin(start: *const u8); + /// Gets event number `i` in the smart contract state. Returns `-1` if `i` /// is an invalid index. Otherwise returns bytes written. #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] - pub(crate) fn get_event(i: u32, start: *const u8) -> i32; + pub(crate) fn get_event(i: u32, start: *mut u8) -> i32; /// Gets the size of event number `i` in the smart contract state. Returns `-1` if `i` /// is an invalid index. diff --git a/concordium-std/src/test_env.rs b/concordium-std/src/test_env.rs index 76a305d4..8954ea4b 100644 --- a/concordium-std/src/test_env.rs +++ b/concordium-std/src/test_env.rs @@ -1,4 +1,6 @@ -use concordium_contracts_common::{Amount, ContractAddress, SlotTime}; +use concordium_contracts_common::{ + AccountAddress, Amount, ContractAddress, Serial, SlotTime, +}; use crate::{prims, to_bytes}; @@ -49,6 +51,11 @@ impl TestEnv { Some(buf) } } + + pub fn set_init_origin(self, address: AccountAddress) -> Self { + unsafe { prims::set_init_origin(address.0.as_ptr()) }; + self + } } #[cfg(feature = "internal-wasm-test")] @@ -70,19 +77,12 @@ mod wasm_test { } } - fn extern_chain_meta() -> ExternChainMeta { ExternChainMeta {} } - - fn external_call_response() -> ExternCallResponse { - ExternCallResponse::new(unsafe { NonZeroU32::new_unchecked(1) }) - } - - fn receive_context() -> ReceiveContext { ExternContext::default() } - #[concordium_test] fn set_get_slot_time() { + let extern_chain_meta = ExternChainMeta {}; let original = Timestamp::from_timestamp_millis(10); TestEnv.set_slot_time(original); - let stored = extern_chain_meta().block_time(); + let stored = extern_chain_meta.block_time(); claim_eq!(original, stored) } @@ -96,14 +96,17 @@ mod wasm_test { #[concordium_test] fn set_get_receive_self_address() { + let receive_context: ReceiveContext = ExternContext::default(); let original = ContractAddress::new(5040, 12); TestEnv.set_receive_self_address(original); - let stored = receive_context().self_address(); + let stored = receive_context.self_address(); claim_eq!(original, stored); } #[concordium_test] fn set_get_parameter() { + let mut external_call_response = + ExternCallResponse::new(unsafe { NonZeroU32::new_unchecked(1) }); let i = 1; let param = vec![3u8; 7]; let mut buf = vec![0u8; 10]; @@ -122,8 +125,7 @@ mod wasm_test { // Use the external call to test the actual function that would be called in // most real scenarios buf = vec![0u8; 7]; - let bytes_written = - external_call_response().read(&mut buf).expect("Unable to read bytes to buffer"); + let bytes_written = external_call_response.read(&mut buf).unwrap(); let expected = param; claim_eq!(buf, expected); @@ -136,7 +138,7 @@ mod wasm_test { let mut buf = vec![0u8; 10]; let param_size = unsafe { prims::get_parameter_size(i) }; - let bytes_written = unsafe { prims::get_parameter_section(i, buf.as_mut_ptr(), 5, 2) }; + let bytes_written = unsafe { prims::get_parameter_section(i, buf.as_mut_ptr(), 0, 0) }; claim_eq!(param_size, -1); claim_eq!(param_size, bytes_written); @@ -185,4 +187,20 @@ mod wasm_test { let stored = TestEnv.get_event(0); claim_eq!(stored, None); } + + #[concordium_test] + fn set_get_init_origin() { + let init_context: InitContext = ExternContext::default(); + // 3kBx2h5Y2veb4hZgAJWPrr8RyQESKm5TjzF3ti1QQ4VSYLwK1G + let address = AccountAddress([ + 105, 117, 36, 6, 204, 147, 159, 201, 12, 166, 167, 59, 87, 206, 225, 9, 150, 53, 71, + 249, 66, 0, 109, 33, 145, 68, 146, 79, 132, 133, 251, 13, + ]); + TestEnv.set_init_origin(address); + + let stored = init_context.init_origin(); + let expected = address; + + claim_eq!(stored, expected); + } } From d1c56c6df511d46ad4dfa851a22998d252352fff Mon Sep 17 00:00:00 2001 From: rasmus-kirk Date: Fri, 18 Oct 2024 10:41:02 +0200 Subject: [PATCH 09/14] Completed `receive_invoker` and `receive_sender` --- concordium-std/src/prims.rs | 15 +++++-- concordium-std/src/test_env.rs | 73 ++++++++++++++++++++++++++-------- 2 files changed, 69 insertions(+), 19 deletions(-) diff --git a/concordium-std/src/prims.rs b/concordium-std/src/prims.rs index efb88c9f..2fdd333c 100644 --- a/concordium-std/src/prims.rs +++ b/concordium-std/src/prims.rs @@ -205,7 +205,7 @@ extern "C" { pub fn state_entry_resize(entry: u64, new_size: u32) -> u32; // Getter for the init context. - /// Address of the sender, 32 bytes + /// Address of the sender, AccountAddress. pub fn get_init_origin(start: *mut u8); // Getters for the receive context @@ -215,7 +215,7 @@ extern "C" { pub fn get_receive_self_address(start: *mut u8); /// Self-balance of the contract, returns the amount pub fn get_receive_self_balance() -> u64; - /// Immediate sender of the message (either contract or account). + /// Immediate sender of the message, Address (either contract or account). pub fn get_receive_sender(start: *mut u8); /// Owner of the contract, AccountAddress. pub fn get_receive_owner(start: *mut u8); @@ -305,10 +305,19 @@ extern "C" { #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] pub(crate) fn set_parameter(i: u32, start: *const u8, length: u32); - /// Sets the address of the sender, 32 bytes + /// Sets the address of the sender, AccountAddress #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] pub(crate) fn set_init_origin(start: *const u8); + /// Set the invoker of the top-level transaction, AccountAddress. + #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] + pub(crate) fn set_receive_invoker(start: *const u8); + + /// Set the immediate sender of the message, Address (either contract or account). + #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] + pub(crate) fn set_receive_sender(start: *const u8); + + /// Gets event number `i` in the smart contract state. Returns `-1` if `i` /// is an invalid index. Otherwise returns bytes written. #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] diff --git a/concordium-std/src/test_env.rs b/concordium-std/src/test_env.rs index 8954ea4b..6e80145d 100644 --- a/concordium-std/src/test_env.rs +++ b/concordium-std/src/test_env.rs @@ -1,6 +1,4 @@ -use concordium_contracts_common::{ - AccountAddress, Amount, ContractAddress, Serial, SlotTime, -}; +use concordium_contracts_common::{AccountAddress, Amount, ContractAddress, Serial, SlotTime, Address}; use crate::{prims, to_bytes}; @@ -14,13 +12,13 @@ impl TestEnv { self } - /// Sets the current balance of this smart contract + /// Sets the current balance of this smart contract. pub fn set_receive_balance(self, balance: Amount) -> Self { unsafe { prims::set_receive_self_balance(balance.micro_ccd) }; self } - /// Sets the address of this smart contract + /// Sets the address of this smart contract. pub fn set_receive_self_address(self, address: ContractAddress) -> Self { unsafe { prims::set_receive_self_address(to_bytes(&address).as_ptr()) }; self @@ -52,10 +50,25 @@ impl TestEnv { } } + /// Set the address of the sender. pub fn set_init_origin(self, address: AccountAddress) -> Self { unsafe { prims::set_init_origin(address.0.as_ptr()) }; self } + + /// Set the invoker of the top-level transaction. + pub fn set_receive_invoker(self, address: AccountAddress) -> Self { + unsafe { prims::set_receive_invoker(address.0.as_ptr()) }; + self + } + + /// Immediate sender of the message (either contract or account). + pub fn set_receive_sender(self, address: Address) -> Self { + let mut buf = Vec::new(); + address.serial(&mut buf).unwrap(); + unsafe { prims::set_receive_sender(buf.as_ptr()) }; + self + } } #[cfg(feature = "internal-wasm-test")] @@ -67,7 +80,9 @@ mod wasm_test { use super::*; use crate::*; + // ----- Helper Functions ----- // Helper functions to get host data, as a real smart contract would + fn extern_host() -> ExternHost<()> { let state_api = ExternStateApi::open(); let state_builder = StateBuilder::open(state_api); @@ -77,6 +92,20 @@ mod wasm_test { } } + fn receive_context() -> ReceiveContext { ExternContext::default() } + + fn init_context() -> InitContext { ExternContext::default() } + + fn account_address() -> AccountAddress { + // 3kBx2h5Y2veb4hZgAJWPrr8RyQESKm5TjzF3ti1QQ4VSYLwK1G + AccountAddress([ + 105, 117, 36, 6, 204, 147, 159, 201, 12, 166, 167, 59, 87, 206, 225, 9, 150, 53, 71, + 249, 66, 0, 109, 33, 145, 68, 146, 79, 132, 133, 251, 13, + ]) + } + + // ----- Tests ----- + #[concordium_test] fn set_get_slot_time() { let extern_chain_meta = ExternChainMeta {}; @@ -96,10 +125,9 @@ mod wasm_test { #[concordium_test] fn set_get_receive_self_address() { - let receive_context: ReceiveContext = ExternContext::default(); let original = ContractAddress::new(5040, 12); TestEnv.set_receive_self_address(original); - let stored = receive_context.self_address(); + let stored = receive_context().self_address(); claim_eq!(original, stored); } @@ -190,17 +218,30 @@ mod wasm_test { #[concordium_test] fn set_get_init_origin() { - let init_context: InitContext = ExternContext::default(); - // 3kBx2h5Y2veb4hZgAJWPrr8RyQESKm5TjzF3ti1QQ4VSYLwK1G - let address = AccountAddress([ - 105, 117, 36, 6, 204, 147, 159, 201, 12, 166, 167, 59, 87, 206, 225, 9, 150, 53, 71, - 249, 66, 0, 109, 33, 145, 68, 146, 79, 132, 133, 251, 13, - ]); + let address = account_address(); TestEnv.set_init_origin(address); + let stored = init_context().init_origin(); + claim_eq!(stored, address); + } - let stored = init_context.init_origin(); - let expected = address; + #[concordium_test] + fn set_get_receive_invoker() { + let address = account_address(); + TestEnv.set_receive_invoker(address); + let stored = receive_context().invoker(); + claim_eq!(stored, address); + } - claim_eq!(stored, expected); + #[concordium_test] + fn set_get_receive_sender() { + let address = Address::Account(account_address()); + TestEnv.set_receive_sender(address); + let stored = receive_context().sender(); + claim_eq!(stored, address); + + let address = Address::Contract(ContractAddress::new(3, 7)); + TestEnv.set_receive_sender(address); + let stored = receive_context().sender(); + claim_eq!(stored, address); } } From 54109efab841bb800259687903f0d009eb0eeff3 Mon Sep 17 00:00:00 2001 From: rasmus-kirk Date: Fri, 18 Oct 2024 13:40:08 +0200 Subject: [PATCH 10/14] Implemented `receive_owner` and `receive_entrypoint` functionality --- concordium-std/CHANGELOG.md | 11 ++++++++- concordium-std/src/prims.rs | 18 +++++++++++--- concordium-std/src/test_env.rs | 43 +++++++++++++++++++++++++++++++--- 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/concordium-std/CHANGELOG.md b/concordium-std/CHANGELOG.md index be0e7e8a..81ef53ba 100644 --- a/concordium-std/CHANGELOG.md +++ b/concordium-std/CHANGELOG.md @@ -2,12 +2,17 @@ ## Unreleased -- Added the following functions in the primitive interface: +- Added the following functions in the primitive interface, that can only + be called in testing environments: - `set_slot_time` - `set_receive_self_address` - `set_receive_self_balance` - `set_parameter` - `set_init_origin` + - `set_receive_invoker` + - `set_receive_sender` + - `set_receive_owner` + - `set_receive_entrypoint` - `get_event` - `get_event_size` @@ -19,6 +24,10 @@ - `set_receive_self_address` - `set_parameter` - `set_init_origin` + - `set_receive_invoker` + - `set_receive_sender` + - `set_receive_owner` + - `set_receive_entrypoint` - `get_event` ## concordium-std 10.1.0 (2024-04-04) diff --git a/concordium-std/src/prims.rs b/concordium-std/src/prims.rs index 2fdd333c..bbeb6f83 100644 --- a/concordium-std/src/prims.rs +++ b/concordium-std/src/prims.rs @@ -225,6 +225,10 @@ extern "C" { /// Write the receive entrypoint name into the given location. /// It is assumed that the location contains enough space to write the name. + /// + /// Note that the name is expected to be the receive name encoded as bytes + /// without the length, i.e. not a serialized EntrypointName (since it's + /// byte-encoding has 2 length bytes) but a String. pub fn get_receive_entrypoint(start: *mut u8); // Getters for the chain meta data @@ -313,18 +317,26 @@ extern "C" { #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] pub(crate) fn set_receive_invoker(start: *const u8); - /// Set the immediate sender of the message, Address (either contract or account). + /// Set the immediate sender of the message, Address (either contract or + /// account). #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] pub(crate) fn set_receive_sender(start: *const u8); + /// Owner of the contract, AccountAddress. + #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] + pub(crate) fn set_receive_owner(start: *const u8); + + /// Set the receive entrypoint name, EntryPointName. + #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] + pub(crate) fn set_receive_entrypoint(start: *const u8); /// Gets event number `i` in the smart contract state. Returns `-1` if `i` /// is an invalid index. Otherwise returns bytes written. #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] pub(crate) fn get_event(i: u32, start: *mut u8) -> i32; - /// Gets the size of event number `i` in the smart contract state. Returns `-1` if `i` - /// is an invalid index. + /// Gets the size of event number `i` in the smart contract state. Returns + /// `-1` if `i` is an invalid index. #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))] pub(crate) fn get_event_size(i: u32) -> i32; diff --git a/concordium-std/src/test_env.rs b/concordium-std/src/test_env.rs index 6e80145d..358aaec8 100644 --- a/concordium-std/src/test_env.rs +++ b/concordium-std/src/test_env.rs @@ -1,4 +1,6 @@ -use concordium_contracts_common::{AccountAddress, Amount, ContractAddress, Serial, SlotTime, Address}; +use concordium_contracts_common::{ + AccountAddress, Address, Amount, ContractAddress, EntrypointName, Serial, SlotTime, +}; use crate::{prims, to_bytes}; @@ -62,13 +64,27 @@ impl TestEnv { self } - /// Immediate sender of the message (either contract or account). + /// Set the immediate sender of the message (either contract or account). pub fn set_receive_sender(self, address: Address) -> Self { let mut buf = Vec::new(); address.serial(&mut buf).unwrap(); unsafe { prims::set_receive_sender(buf.as_ptr()) }; self } + + /// Set the owner of the contract. + pub fn set_receive_owner(self, address: AccountAddress) -> Self { + unsafe { prims::set_receive_owner(address.0.as_ptr()) }; + self + } + + /// Set the receive entrypoint name. + pub fn set_receive_entrypoint(self, entrypoint: EntrypointName) -> Self { + let mut buf = Vec::new(); + entrypoint.serial(&mut buf).unwrap(); + unsafe { prims::set_receive_entrypoint(buf.as_ptr()) }; + self + } } #[cfg(feature = "internal-wasm-test")] @@ -174,7 +190,7 @@ mod wasm_test { #[concordium_test] fn set_get_events() { - // Testing primitive calls + // Testing primitive calls for testing offset and length parameters let event_prim = vec![1u8, 2, 3, 4]; let store_status = unsafe { prims::log_event(event_prim.as_ptr(), event_prim.len().try_into().unwrap()) }; @@ -244,4 +260,25 @@ mod wasm_test { let stored = receive_context().sender(); claim_eq!(stored, address); } + + #[concordium_test] + fn set_get_receive_owner() { + let address = account_address(); + TestEnv.set_receive_owner(address); + let stored = receive_context().owner(); + claim_eq!(stored, address); + } + + #[concordium_test] + fn set_get_receive_entrypoint() { + let entrypoint = EntrypointName::new("some_entry_point").unwrap(); + + TestEnv.set_receive_entrypoint(entrypoint); + + let size = unsafe { prims::get_receive_entrypoint_size() }; + let stored = receive_context().named_entrypoint(); + + claim_eq!(size, entrypoint.size()); + claim_eq!(stored, entrypoint.to_owned()); + } } From 4e0b17fd4648a4d384c4e1568e119a5d13faecf1 Mon Sep 17 00:00:00 2001 From: rasmus-kirk Date: Fri, 18 Oct 2024 14:39:46 +0200 Subject: [PATCH 11/14] Implemented `verify_ed25519_signature` --- concordium-std/src/test_env.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/concordium-std/src/test_env.rs b/concordium-std/src/test_env.rs index 358aaec8..7b1b34e0 100644 --- a/concordium-std/src/test_env.rs +++ b/concordium-std/src/test_env.rs @@ -89,7 +89,7 @@ impl TestEnv { #[cfg(feature = "internal-wasm-test")] mod wasm_test { - use core::num::NonZeroU32; + use core::{num::NonZeroU32, str::FromStr}; use concordium_contracts_common::{ContractAddress, Timestamp}; @@ -108,6 +108,8 @@ mod wasm_test { } } + fn crypto_primitives() -> CryptoPrimitives { CryptoPrimitives {} } + fn receive_context() -> ReceiveContext { ExternContext::default() } fn init_context() -> InitContext { ExternContext::default() } @@ -281,4 +283,24 @@ mod wasm_test { claim_eq!(size, entrypoint.size()); claim_eq!(stored, entrypoint.to_owned()); } + + #[concordium_test] + fn verify_ed25519_signature() { + let _sk_hex = "7eee273f83906eb9a673c0119553b416aa515fc870a730b4e70cdf1a11dc17d3"; + let pk_hex = "d2af46bb1bd8d656c29a62bda2ca66bd26a0f0aea1e0988c7044003e630ff895"; + let sig_hex = "99e3c8b2cf832c3c0f6e8031466fe259b1bf86a4309386418cebb6cd7859d62b3431250e54c9cac7659b36743d1c272514ece30c1ce37d4f422d42f84069c007"; + let msg = b"Hello, this is a test message!"; + + // Check valid signature + let pk = PublicKeyEd25519::from_str(pk_hex).unwrap(); + let sig = SignatureEd25519::from_str(sig_hex).unwrap(); + let is_verified = crypto_primitives().verify_ed25519_signature(pk, sig, msg); + claim_eq!(is_verified, true); + + // Check invalid signature + let wrong_sig_hex = "1111111111832c3c0f6e8031466fe259b1bf86a4309386418cebb6cd7859d62b3431250e54c9cac7659b36743d1c272514ece30c1ce37d4f422d42f84069c007"; + let wrong_sig = SignatureEd25519::from_str(wrong_sig_hex).unwrap(); + let is_verified = crypto_primitives().verify_ed25519_signature(pk, wrong_sig, msg); + claim_eq!(is_verified, false); + } } From cde2909318ce4bf2e9d9decbd652ce1afd6477ee Mon Sep 17 00:00:00 2001 From: rasmus-kirk Date: Tue, 22 Oct 2024 14:44:10 +0200 Subject: [PATCH 12/14] Replace `.unwrap` with `.unwrap_abort` --- concordium-std/src/test_env.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/concordium-std/src/test_env.rs b/concordium-std/src/test_env.rs index 7b1b34e0..8f2d7c99 100644 --- a/concordium-std/src/test_env.rs +++ b/concordium-std/src/test_env.rs @@ -171,7 +171,7 @@ mod wasm_test { // Use the external call to test the actual function that would be called in // most real scenarios buf = vec![0u8; 7]; - let bytes_written = external_call_response.read(&mut buf).unwrap(); + let bytes_written = external_call_response.read(&mut buf).unwrap_abort(); let expected = param; claim_eq!(buf, expected); @@ -195,11 +195,11 @@ mod wasm_test { // Testing primitive calls for testing offset and length parameters let event_prim = vec![1u8, 2, 3, 4]; let store_status = - unsafe { prims::log_event(event_prim.as_ptr(), event_prim.len().try_into().unwrap()) }; + unsafe { prims::log_event(event_prim.as_ptr(), event_prim.len().try_into().unwrap_abort()) }; let event_size = unsafe { prims::get_event_size(0) }; claim_eq!(store_status, 1); - claim_eq!(event_size, event_prim.len().try_into().unwrap()); + claim_eq!(event_size, event_prim.len().try_into().unwrap_abort()); let mut buf = vec![0; event_prim.len()]; let bytes_written = unsafe { prims::get_event(0, buf.as_mut_ptr()) }; @@ -213,16 +213,16 @@ mod wasm_test { let event1 = "Hello, World!".to_owned(); let event2 = "How are you today?".to_owned(); - logger.log(&event1).unwrap(); - logger.log(&event2).unwrap(); + logger.log(&event1).unwrap_abort(); + logger.log(&event2).unwrap_abort(); - let stored1 = TestEnv.get_event(1).unwrap(); - let stored2 = TestEnv.get_event(2).unwrap(); + let stored1 = TestEnv.get_event(1).unwrap_abort(); + let stored2 = TestEnv.get_event(2).unwrap_abort(); let mut expected1 = Vec::new(); let mut expected2 = Vec::new(); - event1.serial(&mut expected1).unwrap(); - event2.serial(&mut expected2).unwrap(); + event1.serial(&mut expected1).unwrap_abort(); + event2.serial(&mut expected2).unwrap_abort(); claim_eq!(stored1, expected1); claim_eq!(stored2, expected2); @@ -273,7 +273,7 @@ mod wasm_test { #[concordium_test] fn set_get_receive_entrypoint() { - let entrypoint = EntrypointName::new("some_entry_point").unwrap(); + let entrypoint = EntrypointName::new("some_entry_point").unwrap_abort(); TestEnv.set_receive_entrypoint(entrypoint); @@ -292,14 +292,14 @@ mod wasm_test { let msg = b"Hello, this is a test message!"; // Check valid signature - let pk = PublicKeyEd25519::from_str(pk_hex).unwrap(); - let sig = SignatureEd25519::from_str(sig_hex).unwrap(); + let pk = PublicKeyEd25519::from_str(pk_hex).unwrap_abort(); + let sig = SignatureEd25519::from_str(sig_hex).unwrap_abort(); let is_verified = crypto_primitives().verify_ed25519_signature(pk, sig, msg); claim_eq!(is_verified, true); // Check invalid signature let wrong_sig_hex = "1111111111832c3c0f6e8031466fe259b1bf86a4309386418cebb6cd7859d62b3431250e54c9cac7659b36743d1c272514ece30c1ce37d4f422d42f84069c007"; - let wrong_sig = SignatureEd25519::from_str(wrong_sig_hex).unwrap(); + let wrong_sig = SignatureEd25519::from_str(wrong_sig_hex).unwrap_abort(); let is_verified = crypto_primitives().verify_ed25519_signature(pk, wrong_sig, msg); claim_eq!(is_verified, false); } From 86fff4990dfe4ec0970258727d123106c9b86c3e Mon Sep 17 00:00:00 2001 From: rasmus-kirk Date: Tue, 22 Oct 2024 15:54:47 +0200 Subject: [PATCH 13/14] Tested `verify_ecdsa_secp256k1_signature` in TestHost --- concordium-std/src/test_env.rs | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/concordium-std/src/test_env.rs b/concordium-std/src/test_env.rs index 8f2d7c99..94b3ae78 100644 --- a/concordium-std/src/test_env.rs +++ b/concordium-std/src/test_env.rs @@ -194,8 +194,9 @@ mod wasm_test { fn set_get_events() { // Testing primitive calls for testing offset and length parameters let event_prim = vec![1u8, 2, 3, 4]; - let store_status = - unsafe { prims::log_event(event_prim.as_ptr(), event_prim.len().try_into().unwrap_abort()) }; + let store_status = unsafe { + prims::log_event(event_prim.as_ptr(), event_prim.len().try_into().unwrap_abort()) + }; let event_size = unsafe { prims::get_event_size(0) }; claim_eq!(store_status, 1); @@ -303,4 +304,28 @@ mod wasm_test { let is_verified = crypto_primitives().verify_ed25519_signature(pk, wrong_sig, msg); claim_eq!(is_verified, false); } + + #[concordium_test] + fn verify_ecdsa_secp256k_signature() { + let _sk_hex = "49f386482744ea6ea0d92b17c73fbc1729e3c061dd9ddf02e85db8d88b2a157b"; + let pk_hex = "03b8fa66dda8feccbfcf15fcab18d2b124570f4af23b7961bfbd61f8c1967aca12"; + let sig_hex = "a9170fc158e040f68dd59ab6c0415cf0b8a8811f92294696aa13dfdc7671407732cb6de20f39ca1fdb159cef3213d980fb32b82b8851c847e8168e125fd20c1c"; + let msg_hash = [ + 11u8, 236, 151, 183, 34, 12, 80, 68, 186, 215, 67, 68, 119, 118, 54, 234, 68, 106, 196, + 109, 214, 155, 169, 75, 236, 168, 229, 227, 168, 60, 84, 140, + ]; + + // Check valid signature + let pk = PublicKeyEcdsaSecp256k1::from_str(pk_hex).unwrap_abort(); + let sig = SignatureEcdsaSecp256k1::from_str(sig_hex).unwrap_abort(); + let is_verified = crypto_primitives().verify_ecdsa_secp256k1_signature(pk, sig, msg_hash); + claim_eq!(is_verified, true); + + // Check invalid signature + let wrong_sig_hex = "111111111111111111111111c0415cf0b8a8811f92294696aa13dfdc7671407732cb6de20f39ca1fdb159cef3213d980fb32b82b8851c847e8168e125fd20c1c"; + let wrong_sig = SignatureEcdsaSecp256k1::from_str(wrong_sig_hex).unwrap_abort(); + let is_verified = + crypto_primitives().verify_ecdsa_secp256k1_signature(pk, wrong_sig, msg_hash); + claim_eq!(is_verified, false); + } } From c9b939821bda64a8281512d8321bca5f249e49aa Mon Sep 17 00:00:00 2001 From: rasmus-kirk Date: Tue, 22 Oct 2024 17:20:53 +0200 Subject: [PATCH 14/14] Tested hashing functions - `hash_sha2_256` - `hash_sha3_256` - `hash_keccak_256` --- concordium-std/src/test_env.rs | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/concordium-std/src/test_env.rs b/concordium-std/src/test_env.rs index 94b3ae78..f3398a40 100644 --- a/concordium-std/src/test_env.rs +++ b/concordium-std/src/test_env.rs @@ -328,4 +328,40 @@ mod wasm_test { crypto_primitives().verify_ecdsa_secp256k1_signature(pk, wrong_sig, msg_hash); claim_eq!(is_verified, false); } + + #[concordium_test] + fn verify_sha2_256_hash() { + let message = b"Si hortum in bibliotheca habes, deerit nihil."; + let expected_hash = [ + 87, 255, 24, 254, 129, 99, 56, 112, 99, 91, 127, 204, 207, 212, 94, 87, 174, 104, 43, + 225, 164, 154, 189, 255, 118, 128, 35, 190, 165, 216, 92, 195, + ]; + + let received_hash = crypto_primitives().hash_sha2_256(message).0; + claim_eq!(expected_hash, received_hash); + } + + #[concordium_test] + fn verify_sha3_256_hash() { + let message = b"In vino veritas."; + let expected_hash = [ + 15, 198, 250, 247, 115, 23, 211, 238, 182, 202, 61, 129, 9, 106, 1, 221, 34, 107, 110, + 179, 65, 220, 70, 86, 157, 168, 34, 133, 148, 209, 196, 104, + ]; + + let received_hash = crypto_primitives().hash_sha3_256(message).0; + claim_eq!(expected_hash, received_hash); + } + + #[concordium_test] + fn verify_keccak_hash() { + let message = b"Non exiguum temporis habemus, sed multum perdidimus. Satis longa vita."; + let expected_hash = [ + 123, 67, 197, 112, 252, 146, 236, 171, 213, 100, 175, 224, 79, 157, 159, 58, 207, 154, + 172, 183, 40, 84, 74, 29, 199, 139, 112, 49, 159, 244, 42, 67, + ]; + + let received_hash = crypto_primitives().hash_keccak_256(message).0; + claim_eq!(expected_hash, received_hash); + } }