From 65e52cfc4a6646a220f1adbba57fdaf10c1af753 Mon Sep 17 00:00:00 2001 From: Jose Garcia Crosta Date: Tue, 19 Sep 2023 12:03:31 -0300 Subject: [PATCH 1/4] Add test case for hash_bytes --- test-cases/hash-bytes/Cargo.toml | 32 +++++++++++++ test-cases/hash-bytes/lib.rs | 78 ++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 test-cases/hash-bytes/Cargo.toml create mode 100644 test-cases/hash-bytes/lib.rs diff --git a/test-cases/hash-bytes/Cargo.toml b/test-cases/hash-bytes/Cargo.toml new file mode 100644 index 0000000..244ba7e --- /dev/null +++ b/test-cases/hash-bytes/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "hash-bytes" +version = "0.1.0" +edition = "2021" +authors = ["[your_name] <[your_email]>"] + +[lib] +path = "lib.rs" + +[features] +default = ["std"] +std = [ + "ink/std", + "scale/std", + "scale-info/std", +] +ink-as-dependency = [] +e2e-tests = [] + +[dependencies] +ink = { version = "4.2.1", default-features = false } +scale = { package = "parity-scale-codec", version = "=3.6.5", default-features = false, features = ["derive"] } +scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } + +[dev-dependencies] +ink_e2e = "4.2.1" + +[profile.dev] +overflow-checks = false + +[profile.release] +overflow-checks = false diff --git a/test-cases/hash-bytes/lib.rs b/test-cases/hash-bytes/lib.rs new file mode 100644 index 0000000..ed2de47 --- /dev/null +++ b/test-cases/hash-bytes/lib.rs @@ -0,0 +1,78 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +#[ink::contract] +mod hash_bytes { + use ink::env::hash::Blake2x256; + + #[ink(storage)] + pub struct HashBytes {} + + impl HashBytes { + #[ink(constructor)] + pub fn new() -> Self { + Self {} + } + + #[ink(message)] + pub fn get_hash_bytes(&self, input: [u8; 32]) -> [u8; 32] { + self.env().hash_bytes::(&input) + } + } + + impl Default for HashBytes { + fn default() -> Self { + Self::new() + } + } + + #[cfg(test)] + mod tests { + use super::*; + + #[ink::test] + fn hash_bytes_works() { + // Given + let contract = HashBytes::new(); + + // When + let hash_bytes = contract.get_hash_bytes([0x01; 32]); + + // Then + assert!(hash_bytes.len() == 32); + } + } + + #[cfg(all(test, feature = "e2e-tests"))] + mod e2e_tests { + use ink_e2e::build_message; + + use super::*; + + type E2EResult = std::result::Result>; + + #[ink_e2e::test] + async fn hash_bytes_works(mut client: ink_e2e::Client) -> E2EResult<()> { + // Given + let constructor = HashBytesRef::new(); + let contract_acc_id = client + .instantiate("hash_bytes", &ink_e2e::bob(), constructor, 0, None) + .await + .expect("instantiate failed") + .account_id; + + // When + let hash_bytes_call = build_message::(contract_acc_id) + .call(|contract| contract.get_hash_bytes([0x01; 32])); + let hash_bytes_res = client + .call(&ink_e2e::bob(), hash_bytes_call, 0, None) + .await + .expect("hash_bytes failed"); + + // Then + assert!(!hash_bytes_res.dry_run.is_err()); + assert!(hash_bytes_res.return_value().len() == 32); + + Ok(()) + } + } +} From db6c0fd163b8e34f0e8d478faf0b848beaf99948 Mon Sep 17 00:00:00 2001 From: Jose Garcia Crosta Date: Tue, 19 Sep 2023 12:17:41 -0300 Subject: [PATCH 2/4] Update readme --- test-cases/hash-bytes/README.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 test-cases/hash-bytes/README.md diff --git a/test-cases/hash-bytes/README.md b/test-cases/hash-bytes/README.md new file mode 100644 index 0000000..6ced6e5 --- /dev/null +++ b/test-cases/hash-bytes/README.md @@ -0,0 +1,29 @@ +# Function `hash_bytes` + +```rust +pub fn hash_bytes(input: &[u8], output: &mut ::Type) +``` + +## Description + +The `hash_bytes` module provides functionality to compute the hash of a given byte array using the designated hash function. The method `get_hash_bytes` accepts an array of bytes and returns its hash. This function is essential for cryptographic operations where data integrity and verification are crucial. + +## Related ink! functions + +- [`hash_bytes`](https://paritytech.github.io/ink/ink_env/fn.hash_bytes.html) + +## Test case + +Both test cases instantiate the `HashBytes` contract and attempt to compute the hash of a given byte array. The tests then validate the result based on the expected hash length, ensuring the correctness of the hash computation. + +## Comparison Integration vs E2E + +The function `get_hash_bytes` has been successfully validated in both integration and end-to-end test scenarios, demonstrating its robustness and consistent implementation. + +| \# | Test | Integration | E2E | +| --- | ------------------------------------------------- | :---------: | :-: | +| 1 | Attempts to retrieve the code hash given an input | ✅ | ✅ | + +## Result + +- This functionality is implemented and works as expected From 68d5cf1c08cbac62ed23853a9cce5da2de0177d9 Mon Sep 17 00:00:00 2001 From: Jose Garcia Crosta Date: Wed, 20 Sep 2023 12:04:23 -0300 Subject: [PATCH 3/4] PR stuff --- test-cases/hash-bytes/lib.rs | 166 +++++++++++++++++++++++++++++++++-- 1 file changed, 157 insertions(+), 9 deletions(-) diff --git a/test-cases/hash-bytes/lib.rs b/test-cases/hash-bytes/lib.rs index ed2de47..436e6ae 100644 --- a/test-cases/hash-bytes/lib.rs +++ b/test-cases/hash-bytes/lib.rs @@ -2,7 +2,7 @@ #[ink::contract] mod hash_bytes { - use ink::env::hash::Blake2x256; + use ink::env::hash::{Blake2x128, Blake2x256, Keccak256, Sha2x256}; #[ink(storage)] pub struct HashBytes {} @@ -14,9 +14,24 @@ mod hash_bytes { } #[ink(message)] - pub fn get_hash_bytes(&self, input: [u8; 32]) -> [u8; 32] { + pub fn hash_sha_256(&self, input: [u8; 32]) -> [u8; 32] { + self.env().hash_bytes::(&input) + } + + #[ink(message)] + pub fn hash_blake_128(&self, input: [u8; 32]) -> [u8; 16] { + self.env().hash_bytes::(&input) + } + + #[ink(message)] + pub fn hash_blake_256(&self, input: [u8; 32]) -> [u8; 32] { self.env().hash_bytes::(&input) } + + #[ink(message)] + pub fn hash_keccak_256(&self, input: [u8; 32]) -> [u8; 32] { + self.env().hash_bytes::(&input) + } } impl Default for HashBytes { @@ -25,20 +40,78 @@ mod hash_bytes { } } + #[cfg(test)] + const HASH_INPUT: [u8; 32] = [0x01; 32]; + #[cfg(test)] + const EXPECTED_SHA256_OUTPUT: [u8; 32] = [ + 114, 205, 110, 132, 34, 196, 7, 251, 109, 9, 134, 144, 241, 19, 11, 125, 237, 126, 194, + 247, 245, 225, 211, 11, 217, 213, 33, 240, 21, 54, 55, 147, + ]; + #[cfg(test)] + const EXPECTED_BLAKE128_OUTPUT: [u8; 16] = [ + 192, 53, 248, 83, 252, 208, 240, 88, 158, 48, 201, 226, 220, 26, 15, 87, + ]; + #[cfg(test)] + const EXPECTED_BLAKE256_OUTPUT: [u8; 32] = [ + 244, 12, 234, 248, 110, 87, 118, 146, 51, 50, 184, 216, 253, 59, 239, 132, 156, 173, 177, + 156, 105, 150, 188, 39, 42, 241, 246, 72, 217, 86, 106, 76, + ]; + #[cfg(test)] + const EXPECTED_KECCAK256_OUTPUT: [u8; 32] = [ + 206, 188, 136, 130, 254, 203, 236, 127, 184, 13, 44, 244, 179, 18, 190, 192, 24, 136, 76, + 45, 102, 102, 124, 103, 169, 5, 8, 33, 75, 216, 186, 252, + ]; + #[cfg(test)] mod tests { use super::*; #[ink::test] - fn hash_bytes_works() { + fn hash_sha_256() { + // Given + let contract = HashBytes::new(); + + // When + let hash_bytes = contract.hash_sha_256(HASH_INPUT); + + // Then + assert_eq!(hash_bytes, EXPECTED_SHA256_OUTPUT); + } + + #[ink::test] + fn hash_blake_128() { // Given let contract = HashBytes::new(); // When - let hash_bytes = contract.get_hash_bytes([0x01; 32]); + let hash_bytes = contract.hash_blake_128(HASH_INPUT); // Then - assert!(hash_bytes.len() == 32); + assert_eq!(hash_bytes, EXPECTED_BLAKE128_OUTPUT); + } + + #[ink::test] + fn hash_blake_256() { + // Given + let contract = HashBytes::new(); + + // When + let hash_bytes = contract.hash_blake_256(HASH_INPUT); + + // Then + assert_eq!(hash_bytes, EXPECTED_BLAKE256_OUTPUT); + } + + #[ink::test] + fn hash_keccak_256() { + // Given + let contract = HashBytes::new(); + + // When + let hash_bytes = contract.hash_keccak_256(HASH_INPUT); + + // Then + assert_eq!(hash_bytes, EXPECTED_KECCAK256_OUTPUT); } } @@ -51,9 +124,85 @@ mod hash_bytes { type E2EResult = std::result::Result>; #[ink_e2e::test] - async fn hash_bytes_works(mut client: ink_e2e::Client) -> E2EResult<()> { + async fn hash_sha_256(mut client: ink_e2e::Client) -> E2EResult<()> { // Given let constructor = HashBytesRef::new(); + + let contract_acc_id = client + .instantiate("hash_bytes", &ink_e2e::bob(), constructor, 0, None) + .await + .expect("instantiate failed") + .account_id; + + // When + let hash_bytes_call = build_message::(contract_acc_id) + .call(|contract| contract.hash_sha_256(HASH_INPUT)); + let hash_bytes_res = client + .call(&ink_e2e::bob(), hash_bytes_call, 0, None) + .await + .expect("hash_bytes failed"); + + // Then + assert_eq!(hash_bytes_res.return_value(), EXPECTED_SHA256_OUTPUT); + + Ok(()) + } + + #[ink_e2e::test] + async fn hash_blake_128(mut client: ink_e2e::Client) -> E2EResult<()> { + // Given + let constructor = HashBytesRef::new(); + + let contract_acc_id = client + .instantiate("hash_bytes", &ink_e2e::bob(), constructor, 0, None) + .await + .expect("instantiate failed") + .account_id; + + // When + let hash_bytes_call = build_message::(contract_acc_id) + .call(|contract| contract.hash_blake_128(HASH_INPUT)); + let hash_bytes_res = client + .call(&ink_e2e::bob(), hash_bytes_call, 0, None) + .await + .expect("hash_bytes failed"); + + // Then + assert_eq!(hash_bytes_res.return_value(), EXPECTED_BLAKE128_OUTPUT); + + Ok(()) + } + + #[ink_e2e::test] + async fn hash_blake_256(mut client: ink_e2e::Client) -> E2EResult<()> { + // Given + let constructor = HashBytesRef::new(); + + let contract_acc_id = client + .instantiate("hash_bytes", &ink_e2e::bob(), constructor, 0, None) + .await + .expect("instantiate failed") + .account_id; + + // When + let hash_bytes_call = build_message::(contract_acc_id) + .call(|contract| contract.hash_blake_256(HASH_INPUT)); + let hash_bytes_res = client + .call(&ink_e2e::bob(), hash_bytes_call, 0, None) + .await + .expect("hash_bytes failed"); + + // Then + assert_eq!(hash_bytes_res.return_value(), EXPECTED_BLAKE256_OUTPUT); + + Ok(()) + } + + #[ink_e2e::test] + async fn hash_keccak_256(mut client: ink_e2e::Client) -> E2EResult<()> { + // Given + let constructor = HashBytesRef::new(); + let contract_acc_id = client .instantiate("hash_bytes", &ink_e2e::bob(), constructor, 0, None) .await @@ -62,15 +211,14 @@ mod hash_bytes { // When let hash_bytes_call = build_message::(contract_acc_id) - .call(|contract| contract.get_hash_bytes([0x01; 32])); + .call(|contract| contract.hash_keccak_256(HASH_INPUT)); let hash_bytes_res = client .call(&ink_e2e::bob(), hash_bytes_call, 0, None) .await .expect("hash_bytes failed"); // Then - assert!(!hash_bytes_res.dry_run.is_err()); - assert!(hash_bytes_res.return_value().len() == 32); + assert_eq!(hash_bytes_res.return_value(), EXPECTED_KECCAK256_OUTPUT); Ok(()) } From 2ef9445cccb56d8587ece4ab61d1f5310b9b3181 Mon Sep 17 00:00:00 2001 From: Jose Garcia Crosta Date: Wed, 20 Sep 2023 13:55:08 -0300 Subject: [PATCH 4/4] Update readme --- test-cases/hash-bytes/README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/test-cases/hash-bytes/README.md b/test-cases/hash-bytes/README.md index 6ced6e5..6cf3abf 100644 --- a/test-cases/hash-bytes/README.md +++ b/test-cases/hash-bytes/README.md @@ -14,15 +14,18 @@ The `hash_bytes` module provides functionality to compute the hash of a given by ## Test case -Both test cases instantiate the `HashBytes` contract and attempt to compute the hash of a given byte array. The tests then validate the result based on the expected hash length, ensuring the correctness of the hash computation. +Both the integration tests and end-to-end tests in the `hash_bytes` module verify the hashing functionality of the contract. Each test ensures that the corresponding hash function produces the expected hash output for a given input. ## Comparison Integration vs E2E The function `get_hash_bytes` has been successfully validated in both integration and end-to-end test scenarios, demonstrating its robustness and consistent implementation. -| \# | Test | Integration | E2E | -| --- | ------------------------------------------------- | :---------: | :-: | -| 1 | Attempts to retrieve the code hash given an input | ✅ | ✅ | +| # | Test | Integration | E2E | +| --- | ------------------------------------------------------ | :---------: | :-: | +| 1 | Attempts to get the hash using the method `sha_256` | ✅ | ✅ | +| 2 | Attempts to get the hash using the method `blake_128` | ✅ | ✅ | +| 3 | Attempts to get the hash using the method `blake_256` | ✅ | ✅ | +| 4 | Attempts to get the hash using the method `keccak_256` | ✅ | ✅ | ## Result