From 57c27e3227de146990114a492580c2ccf79cefdd Mon Sep 17 00:00:00 2001 From: kziemianek Date: Tue, 18 Apr 2023 14:10:04 +0200 Subject: [PATCH 01/32] sr25519 signature verification --- crates/engine/src/ext.rs | 2 ++ crates/env/src/api.rs | 34 +++++++++++++++++++ crates/env/src/backend.rs | 7 ++++ crates/env/src/engine/off_chain/impls.rs | 12 +++++++ crates/env/src/engine/on_chain/ext/riscv32.rs | 15 ++++++++ crates/env/src/engine/on_chain/ext/wasm32.rs | 24 +++++++++++++ crates/env/src/engine/on_chain/impls.rs | 9 +++++ crates/env/src/error.rs | 2 ++ crates/ink/src/env_access.rs | 10 ++++++ 9 files changed, 115 insertions(+) diff --git a/crates/engine/src/ext.rs b/crates/engine/src/ext.rs index 49d74c38c2..22b0eafa70 100644 --- a/crates/engine/src/ext.rs +++ b/crates/engine/src/ext.rs @@ -97,6 +97,8 @@ define_error_codes! { LoggingDisabled = 9, /// ECDSA public key recovery failed. Most probably wrong recovery id or signature. EcdsaRecoveryFailed = 11, + /// sr25519 signature verification failed. + Sr25519VerifyFailed = 12, } /// The raw return code returned by the host side. diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index c1a9a660ff..784329015f 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -550,6 +550,40 @@ pub fn ecdsa_to_eth_address(pubkey: &[u8; 33], output: &mut [u8; 20]) -> Result< }) } +/// Verifies a sr25519 signature +/// +/// # Example +/// +/// ``` +/// let signature: [u8; 64] = [ +/// 184, 49, 74, 238, 78, 165, 102, 252, 22, 92, 156, 176, 124, 118, 168, 116, 247, +/// 99, 0, 94, 2, 45, 9, 170, 73, 222, 182, 74, 60, 32, 75, 64, 98, 174, 69, 55, 83, +/// 85, 180, 98, 208, 75, 231, 57, 205, 62, 4, 105, 26, 136, 172, 17, 123, 99, 90, 255, +/// 228, 54, 115, 63, 30, 207, 205, 131, +/// ]; +/// let message: &[u8; 11] = b"hello world"; +/// let pub_key: [u8; 32] = [ +/// 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, +/// 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125, +/// ]; +/// +/// let result = ink::env::sr25519_verify(&signature, message.as_slice(), &pub_key); +/// assert!(result.is_ok()) +/// ``` +/// +/// # Errors +/// +/// - If sr25519 signature cannot be verified. +pub fn sr25519_verify( + signature: &[u8; 64], + message: &[u8], + pub_key: &[u8; 32] +) -> Result<()> { + ::on_instance(|instance| { + instance.sr25519_verify(signature, message, pub_key) + }) +} + /// Checks whether the specified account is a contract. /// /// # Errors diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index fb6b00350c..b776afe888 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -290,6 +290,13 @@ pub trait EnvBackend { output: &mut [u8; 20], ) -> Result<()>; + fn sr25519_verify( + &mut self, + signature: &[u8; 64], + message: &[u8], + pub_key: &[u8; 32] + ) -> Result<()>; + /// Low-level interface to call a chain extension method. /// /// Returns the output of the chain extension of the specified type. diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 5dbdf6a773..a0e28f803c 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -115,6 +115,7 @@ impl From for crate::Error { ext::Error::NotCallable => Self::NotCallable, ext::Error::LoggingDisabled => Self::LoggingDisabled, ext::Error::EcdsaRecoveryFailed => Self::EcdsaRecoveryFailed, + ext::Error::Sr25519VerifyFailed => Self::Sr25519VerifyFailed, } } } @@ -333,6 +334,17 @@ impl EnvBackend for EnvInstance { Ok(()) } + + fn sr25519_verify( + &mut self, + signature: &[u8; 64], + message: &[u8], + pub_key: &[u8; 32] + ) -> Result<()> { + // todo: impl + Ok(()) + } + fn call_chain_extension( &mut self, func_id: u32, diff --git a/crates/env/src/engine/on_chain/ext/riscv32.rs b/crates/env/src/engine/on_chain/ext/riscv32.rs index ba030eb3d9..d4492f3370 100644 --- a/crates/env/src/engine/on_chain/ext/riscv32.rs +++ b/crates/env/src/engine/on_chain/ext/riscv32.rs @@ -372,6 +372,21 @@ pub fn ecdsa_to_eth_address(pubkey: &[u8; 33], output: &mut [u8; 20]) -> Result ret_code.into() } +pub fn sr25519_verify( + signature: &[u8; 64], + message: &[u8], + pub_key: &[u8; 32] +) -> Result { + let ret_code = ( + Ptr32::from_slice(signature), + Ptr32::from_slice(pub_key), + input.len() as u32, + Ptr32::from_slice(message), + ) + .using_encoded(|in_data| sys::call(FUNC_ID, Ptr32::from_slice(in_data))); + ret_code.into() +} + pub fn is_contract(account_id: &[u8]) -> bool { let ret_val = sys::call(FUNC_ID, Ptr32::from_slice(account_id)); ret_val.into_bool() diff --git a/crates/env/src/engine/on_chain/ext/wasm32.rs b/crates/env/src/engine/on_chain/ext/wasm32.rs index 790eabc0d3..997ed25686 100644 --- a/crates/env/src/engine/on_chain/ext/wasm32.rs +++ b/crates/env/src/engine/on_chain/ext/wasm32.rs @@ -146,6 +146,13 @@ mod sys { output_ptr: Ptr32Mut<[u8]>, ) -> ReturnCode; + pub fn sr25519_verify( + signature_ptr: Ptr32<[u8]>, + public_key_ptr: Ptr32<[u8]>, + message_len: u32, + message_ptr: Ptr32<[u8]>, + ) -> ReturnCode; + pub fn take_storage( key_ptr: Ptr32<[u8]>, key_len: u32, @@ -597,6 +604,23 @@ pub fn ecdsa_to_eth_address(pubkey: &[u8; 33], output: &mut [u8; 20]) -> Result ret_code.into() } +pub fn sr25519_verify( + signature: &[u8; 64], + message: &[u8], + pub_key: &[u8; 32], +) -> Result { + let ret_code = unsafe { + sys::sr25519_verify( + Ptr32::from_slice(signature), + Ptr32::from_slice(pub_key), + message.len() as u32, + Ptr32::from_slice(message), + + ) + }; + ret_code.into() +} + pub fn is_contract(account_id: &[u8]) -> bool { let ret_val = unsafe { sys::is_contract(Ptr32::from_slice(account_id)) }; ret_val.into_bool() diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 69747bba5c..51a7212ef2 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -330,6 +330,15 @@ impl EnvBackend for EnvInstance { ext::ecdsa_to_eth_address(pubkey, output).map_err(Into::into) } + fn sr25519_verify( + &mut self, + signature: &[u8; 64], + message: &[u8], + pub_key: &[u8; 32] + ) -> Result<()> { + ext::sr25519_verify(signature, message, pub_key).map_err(Into::into) + } + fn call_chain_extension( &mut self, func_id: u32, diff --git a/crates/env/src/error.rs b/crates/env/src/error.rs index 6db524b966..5e7a6a2f47 100644 --- a/crates/env/src/error.rs +++ b/crates/env/src/error.rs @@ -51,6 +51,8 @@ pub enum Error { CallRuntimeFailed, /// ECDSA pubkey recovery failed. Most probably wrong recovery id or signature. EcdsaRecoveryFailed, + /// sr25519 signature verification failed. + Sr25519VerifyFailed } /// A result of environmental operations. diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 63c42d01f8..0f55fd9125 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -880,6 +880,16 @@ where .map_err(|_| Error::EcdsaRecoveryFailed) } + pub fn sr25519_verify( + self, + signature: &[u8; 64], + message: &[u8], + pub_key: &[u8; 32], + ) -> Result<()> { + ink_env::sr25519_verify(signature, message, pub_key) + .map_err(|_| Error::Sr25519VerifyFailed) + } + /// Checks whether a specified account belongs to a contract. /// /// # Example From 5d9cbee3462923b37abc8cd9db5db6bdff662acd Mon Sep 17 00:00:00 2001 From: kziemianek Date: Wed, 19 Apr 2023 15:02:37 +0200 Subject: [PATCH 02/32] offchain signature verification --- crates/env/Cargo.toml | 2 ++ crates/env/src/engine/off_chain/impls.rs | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/crates/env/Cargo.toml b/crates/env/Cargo.toml index d9c662ec2f..bdf2a3c371 100644 --- a/crates/env/Cargo.toml +++ b/crates/env/Cargo.toml @@ -42,6 +42,8 @@ blake2 = { version = "0.10", optional = true } # ECDSA for the off-chain environment. secp256k1 = { version = "0.27.0", features = ["recovery", "global-context"], optional = true } +# schnorrkel for the off-chain environment. +schnorrkel = { version = "0.10.2"} # Only used in the off-chain environment. # diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index a0e28f803c..0c0a3434d2 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -47,6 +47,8 @@ use ink_engine::{ ext::Engine, }; use ink_storage_traits::Storable; +use schnorrkel::{signing_context, PublicKey, Signature}; + /// The capacity of the static buffer. /// This is the same size as the ink! on-chain environment. We chose to use the same size @@ -334,15 +336,18 @@ impl EnvBackend for EnvInstance { Ok(()) } - fn sr25519_verify( &mut self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32] ) -> Result<()> { - // todo: impl - Ok(()) + let context = signing_context(b"substrate"); + let signature: Signature = Signature::from_bytes(signature).unwrap(); + let public_key: PublicKey = PublicKey::from_bytes(pub_key).unwrap(); + + public_key.verify(context.bytes(message), &signature) + .map_err(|_| Error::Sr25519VerifyFailed) } fn call_chain_extension( From 37fa4797a74a42e28f233a38220b6ed33b422f9f Mon Sep 17 00:00:00 2001 From: kziemianek Date: Wed, 19 Apr 2023 17:40:28 +0200 Subject: [PATCH 03/32] fmt --- crates/e2e/macro/src/config.rs | 4 ++-- crates/env/src/api.rs | 24 +++++++++---------- crates/env/src/backend.rs | 4 ++-- crates/env/src/engine/off_chain/impls.rs | 16 ++++++++----- crates/env/src/engine/on_chain/ext/riscv32.rs | 6 ++--- crates/env/src/engine/on_chain/ext/wasm32.rs | 11 ++++----- crates/env/src/engine/on_chain/impls.rs | 4 ++-- crates/env/src/error.rs | 2 +- crates/ink/ir/src/ir/item_mod.rs | 4 ++-- crates/ink/ir/src/ir/trait_def/item/mod.rs | 2 +- crates/ink/src/env_access.rs | 6 ++--- 11 files changed, 43 insertions(+), 40 deletions(-) diff --git a/crates/e2e/macro/src/config.rs b/crates/e2e/macro/src/config.rs index a97c09e454..9754aaab13 100644 --- a/crates/e2e/macro/src/config.rs +++ b/crates/e2e/macro/src/config.rs @@ -63,7 +63,7 @@ impl TryFrom for E2EConfig { return Err(format_err_spanned!( arg, "expected a string literal for `additional_contracts` ink! E2E test configuration argument", - )) + )); } } else if arg.name.is_ident("environment") { if let Some((_, ast)) = environment { @@ -75,7 +75,7 @@ impl TryFrom for E2EConfig { return Err(format_err_spanned!( arg, "expected a path for `environment` ink! E2E test configuration argument", - )) + )); } } else { return Err(format_err_spanned!( diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index 784329015f..09a7adee01 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -551,33 +551,33 @@ pub fn ecdsa_to_eth_address(pubkey: &[u8; 33], output: &mut [u8; 20]) -> Result< } /// Verifies a sr25519 signature -/// +/// /// # Example -/// +/// /// ``` /// let signature: [u8; 64] = [ -/// 184, 49, 74, 238, 78, 165, 102, 252, 22, 92, 156, 176, 124, 118, 168, 116, 247, -/// 99, 0, 94, 2, 45, 9, 170, 73, 222, 182, 74, 60, 32, 75, 64, 98, 174, 69, 55, 83, -/// 85, 180, 98, 208, 75, 231, 57, 205, 62, 4, 105, 26, 136, 172, 17, 123, 99, 90, 255, -/// 228, 54, 115, 63, 30, 207, 205, 131, +/// 184, 49, 74, 238, 78, 165, 102, 252, 22, 92, 156, 176, 124, 118, 168, 116, 247, +/// 99, 0, 94, 2, 45, 9, 170, 73, 222, 182, 74, 60, 32, 75, 64, 98, 174, 69, 55, 83, +/// 85, 180, 98, 208, 75, 231, 57, 205, 62, 4, 105, 26, 136, 172, 17, 123, 99, 90, +/// 255, 228, 54, 115, 63, 30, 207, 205, 131, /// ]; /// let message: &[u8; 11] = b"hello world"; /// let pub_key: [u8; 32] = [ -/// 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, -/// 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125, +/// 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, +/// 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125, /// ]; /// /// let result = ink::env::sr25519_verify(&signature, message.as_slice(), &pub_key); /// assert!(result.is_ok()) /// ``` -/// +/// /// # Errors -/// +/// /// - If sr25519 signature cannot be verified. pub fn sr25519_verify( - signature: &[u8; 64], + signature: &[u8; 64], message: &[u8], - pub_key: &[u8; 32] + pub_key: &[u8; 32], ) -> Result<()> { ::on_instance(|instance| { instance.sr25519_verify(signature, message, pub_key) diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index b776afe888..68e6c33c08 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -292,9 +292,9 @@ pub trait EnvBackend { fn sr25519_verify( &mut self, - signature: &[u8; 64], + signature: &[u8; 64], message: &[u8], - pub_key: &[u8; 32] + pub_key: &[u8; 32], ) -> Result<()>; /// Low-level interface to call a chain extension method. diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 0c0a3434d2..c7017341fb 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -47,8 +47,11 @@ use ink_engine::{ ext::Engine, }; use ink_storage_traits::Storable; -use schnorrkel::{signing_context, PublicKey, Signature}; - +use schnorrkel::{ + signing_context, + PublicKey, + Signature, +}; /// The capacity of the static buffer. /// This is the same size as the ink! on-chain environment. We chose to use the same size @@ -338,15 +341,16 @@ impl EnvBackend for EnvInstance { fn sr25519_verify( &mut self, - signature: &[u8; 64], + signature: &[u8; 64], message: &[u8], - pub_key: &[u8; 32] + pub_key: &[u8; 32], ) -> Result<()> { let context = signing_context(b"substrate"); - let signature: Signature = Signature::from_bytes(signature).unwrap(); + let signature: Signature = Signature::from_bytes(signature).unwrap(); let public_key: PublicKey = PublicKey::from_bytes(pub_key).unwrap(); - public_key.verify(context.bytes(message), &signature) + public_key + .verify(context.bytes(message), &signature) .map_err(|_| Error::Sr25519VerifyFailed) } diff --git a/crates/env/src/engine/on_chain/ext/riscv32.rs b/crates/env/src/engine/on_chain/ext/riscv32.rs index d4492f3370..4a63d73dbc 100644 --- a/crates/env/src/engine/on_chain/ext/riscv32.rs +++ b/crates/env/src/engine/on_chain/ext/riscv32.rs @@ -373,13 +373,13 @@ pub fn ecdsa_to_eth_address(pubkey: &[u8; 33], output: &mut [u8; 20]) -> Result } pub fn sr25519_verify( - signature: &[u8; 64], + signature: &[u8; 64], message: &[u8], - pub_key: &[u8; 32] + pub_key: &[u8; 32], ) -> Result { let ret_code = ( Ptr32::from_slice(signature), - Ptr32::from_slice(pub_key), + Ptr32::from_slice(pub_key), input.len() as u32, Ptr32::from_slice(message), ) diff --git a/crates/env/src/engine/on_chain/ext/wasm32.rs b/crates/env/src/engine/on_chain/ext/wasm32.rs index 997ed25686..f975b1b37b 100644 --- a/crates/env/src/engine/on_chain/ext/wasm32.rs +++ b/crates/env/src/engine/on_chain/ext/wasm32.rs @@ -150,7 +150,7 @@ mod sys { signature_ptr: Ptr32<[u8]>, public_key_ptr: Ptr32<[u8]>, message_len: u32, - message_ptr: Ptr32<[u8]>, + message_ptr: Ptr32<[u8]>, ) -> ReturnCode; pub fn take_storage( @@ -605,17 +605,16 @@ pub fn ecdsa_to_eth_address(pubkey: &[u8; 33], output: &mut [u8; 20]) -> Result } pub fn sr25519_verify( - signature: &[u8; 64], + signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32], ) -> Result { let ret_code = unsafe { sys::sr25519_verify( - Ptr32::from_slice(signature), - Ptr32::from_slice(pub_key), + Ptr32::from_slice(signature), + Ptr32::from_slice(pub_key), message.len() as u32, - Ptr32::from_slice(message), - + Ptr32::from_slice(message), ) }; ret_code.into() diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs index 51a7212ef2..86cda89a3a 100644 --- a/crates/env/src/engine/on_chain/impls.rs +++ b/crates/env/src/engine/on_chain/impls.rs @@ -332,9 +332,9 @@ impl EnvBackend for EnvInstance { fn sr25519_verify( &mut self, - signature: &[u8; 64], + signature: &[u8; 64], message: &[u8], - pub_key: &[u8; 32] + pub_key: &[u8; 32], ) -> Result<()> { ext::sr25519_verify(signature, message, pub_key).map_err(Into::into) } diff --git a/crates/env/src/error.rs b/crates/env/src/error.rs index 5e7a6a2f47..f4ece5f8fe 100644 --- a/crates/env/src/error.rs +++ b/crates/env/src/error.rs @@ -52,7 +52,7 @@ pub enum Error { /// ECDSA pubkey recovery failed. Most probably wrong recovery id or signature. EcdsaRecoveryFailed, /// sr25519 signature verification failed. - Sr25519VerifyFailed + Sr25519VerifyFailed, } /// A result of environmental operations. diff --git a/crates/ink/ir/src/ir/item_mod.rs b/crates/ink/ir/src/ir/item_mod.rs index 58f1920ae9..664ca2e352 100644 --- a/crates/ink/ir/src/ir/item_mod.rs +++ b/crates/ink/ir/src/ir/item_mod.rs @@ -263,7 +263,7 @@ impl ItemMod { .into_combine(format_err!( overlap.span(), "first ink! message with overlapping wildcard selector here", - ))) + ))); } } } @@ -283,7 +283,7 @@ impl ItemMod { .into_combine(format_err!( overlap.span(), "first ink! constructor with overlapping wildcard selector here", - ))) + ))); } } } diff --git a/crates/ink/ir/src/ir/trait_def/item/mod.rs b/crates/ink/ir/src/ir/trait_def/item/mod.rs index 69b8f95b26..6297a20acc 100644 --- a/crates/ink/ir/src/ir/trait_def/item/mod.rs +++ b/crates/ink/ir/src/ir/trait_def/item/mod.rs @@ -384,7 +384,7 @@ impl InkItemTrait { ).into_combine(format_err_spanned!( duplicate_selector, "first ink! trait constructor or message with same selector found here", - ))) + ))); } assert!( duplicate_ident.is_none(), diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 0f55fd9125..0ec7f6bf53 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -882,10 +882,10 @@ where pub fn sr25519_verify( self, - signature: &[u8; 64], + signature: &[u8; 64], message: &[u8], - pub_key: &[u8; 32], - ) -> Result<()> { + pub_key: &[u8; 32], + ) -> Result<()> { ink_env::sr25519_verify(signature, message, pub_key) .map_err(|_| Error::Sr25519VerifyFailed) } From 0a910e19a8c3ece3067cf9d933feefc63f1d5a95 Mon Sep 17 00:00:00 2001 From: kziemianek Date: Wed, 19 Apr 2023 17:47:45 +0200 Subject: [PATCH 04/32] schnorrkel optional --- crates/env/Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/env/Cargo.toml b/crates/env/Cargo.toml index bdf2a3c371..57ed563bab 100644 --- a/crates/env/Cargo.toml +++ b/crates/env/Cargo.toml @@ -43,7 +43,7 @@ blake2 = { version = "0.10", optional = true } # ECDSA for the off-chain environment. secp256k1 = { version = "0.27.0", features = ["recovery", "global-context"], optional = true } # schnorrkel for the off-chain environment. -schnorrkel = { version = "0.10.2"} +schnorrkel = { version = "0.10.2", optional = true } # Only used in the off-chain environment. # @@ -69,6 +69,7 @@ std = [ "scale-encode", "scale-info/std", "secp256k1", + "schnorrkel", "num-traits/std", # Enables hashing crates for off-chain environment. "sha2", From b2224d66701ea173b1d7fd4510ae7ee2f1469e70 Mon Sep 17 00:00:00 2001 From: kziemianek Date: Wed, 19 Apr 2023 23:35:42 +0200 Subject: [PATCH 05/32] update dictionary --- .config/cargo_spellcheck.dic | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/cargo_spellcheck.dic b/.config/cargo_spellcheck.dic index 284c18234a..15a24e5d69 100644 --- a/.config/cargo_spellcheck.dic +++ b/.config/cargo_spellcheck.dic @@ -60,6 +60,7 @@ reentrancy refcount scalability scalable +sr25519 stdin stdout tuple From d6a9f7c7573f35f426e56b5e43f0174b8aaad5c9 Mon Sep 17 00:00:00 2001 From: kziemianek Date: Wed, 19 Apr 2023 23:37:42 +0200 Subject: [PATCH 06/32] fix --- crates/env/src/engine/on_chain/ext/riscv32.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/env/src/engine/on_chain/ext/riscv32.rs b/crates/env/src/engine/on_chain/ext/riscv32.rs index 4a63d73dbc..090f989012 100644 --- a/crates/env/src/engine/on_chain/ext/riscv32.rs +++ b/crates/env/src/engine/on_chain/ext/riscv32.rs @@ -380,7 +380,7 @@ pub fn sr25519_verify( let ret_code = ( Ptr32::from_slice(signature), Ptr32::from_slice(pub_key), - input.len() as u32, + message.len() as u32, Ptr32::from_slice(message), ) .using_encoded(|in_data| sys::call(FUNC_ID, Ptr32::from_slice(in_data))); From 9d00c92d9096643130fc1686da95c001be367f8d Mon Sep 17 00:00:00 2001 From: kziemianek Date: Wed, 19 Apr 2023 23:47:45 +0200 Subject: [PATCH 07/32] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 213c1c0eb3..ccdc62edb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Persist `Environment` in metadata - [#1741](https://github.com/paritytech/ink/pull/1741) +- Added `sr25519_verify` function to `ink_env` [#1757](https://github.com/paritytech/ink/pull/1757) ### Changed - Upgraded `syn` to version `2` - [#1731](https://github.com/paritytech/ink/pull/1731) From da71ca2a997ce7ed11fcc6cfbd4a389df1bf0c34 Mon Sep 17 00:00:00 2001 From: kziemianek Date: Wed, 19 Apr 2023 23:51:56 +0200 Subject: [PATCH 08/32] add info about unstable function usage --- crates/env/src/engine/on_chain/ext/riscv32.rs | 2 ++ crates/env/src/engine/on_chain/ext/wasm32.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/crates/env/src/engine/on_chain/ext/riscv32.rs b/crates/env/src/engine/on_chain/ext/riscv32.rs index 090f989012..b8aa433990 100644 --- a/crates/env/src/engine/on_chain/ext/riscv32.rs +++ b/crates/env/src/engine/on_chain/ext/riscv32.rs @@ -372,6 +372,8 @@ pub fn ecdsa_to_eth_address(pubkey: &[u8; 33], output: &mut [u8; 20]) -> Result ret_code.into() } +/// **WARNING**: this function is from the [unstable interface](https://github.com/paritytech/substrate/tree/master/frame/contracts#unstable-interfaces), +/// which is unsafe and normally is not available on production chains. pub fn sr25519_verify( signature: &[u8; 64], message: &[u8], diff --git a/crates/env/src/engine/on_chain/ext/wasm32.rs b/crates/env/src/engine/on_chain/ext/wasm32.rs index f975b1b37b..cf5c60353c 100644 --- a/crates/env/src/engine/on_chain/ext/wasm32.rs +++ b/crates/env/src/engine/on_chain/ext/wasm32.rs @@ -146,6 +146,8 @@ mod sys { output_ptr: Ptr32Mut<[u8]>, ) -> ReturnCode; + /// **WARNING**: this function is from the [unstable interface](https://github.com/paritytech/substrate/tree/master/frame/contracts#unstable-interfaces), + /// which is unsafe and normally is not available on production chains. pub fn sr25519_verify( signature_ptr: Ptr32<[u8]>, public_key_ptr: Ptr32<[u8]>, From eb93905cee504ac9af6656c7593b3835be4277bb Mon Sep 17 00:00:00 2001 From: kziemianek Date: Thu, 20 Apr 2023 08:42:32 +0200 Subject: [PATCH 09/32] missing docs --- crates/env/src/backend.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index 68e6c33c08..4599849742 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -290,6 +290,11 @@ pub trait EnvBackend { output: &mut [u8; 20], ) -> Result<()>; + /// Verifies a sr25519 signature. + /// + /// # Errors + /// + /// - If the signature verification failed. fn sr25519_verify( &mut self, signature: &[u8; 64], From 9ca19c462d5f5d1572ddce595d2698207241fd4a Mon Sep 17 00:00:00 2001 From: kziemianek Date: Thu, 20 Apr 2023 08:53:18 +0200 Subject: [PATCH 10/32] review suggestions --- crates/env/src/api.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index 09a7adee01..a2ef8899c3 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -550,7 +550,7 @@ pub fn ecdsa_to_eth_address(pubkey: &[u8; 33], output: &mut [u8; 20]) -> Result< }) } -/// Verifies a sr25519 signature +/// Verifies a sr25519 signature. /// /// # Example /// From 9b074f1948c10697f9034b4688ed4197f6f45383 Mon Sep 17 00:00:00 2001 From: George Oastler Date: Wed, 5 Jul 2023 16:26:53 +0100 Subject: [PATCH 11/32] added catch for invalid public key or signature in sr25519 verification public key byte[] and/or signature byte[] may not be constructed into a PublicKey or Signature if it's in the wrong format. These errors originate from the schnorrkel library and need to be caught, otherwise it'll panic and propagate up to smart contracts in ink. --- crates/env/src/engine/off_chain/impls.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index c7017341fb..553517fdba 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -345,10 +345,14 @@ impl EnvBackend for EnvInstance { message: &[u8], pub_key: &[u8; 32], ) -> Result<()> { + // the context associated with the signing (specific to the sr25519 algorithm) + // defaults to "substrate" in substrate, but could be different elsewhere let context = signing_context(b"substrate"); - let signature: Signature = Signature::from_bytes(signature).unwrap(); - let public_key: PublicKey = PublicKey::from_bytes(pub_key).unwrap(); - + // attempt to parse a signature from bytes + let signature: Signature = Signature::from_bytes(signature).map_err(|_| Error::Sr25519VerifyFailed)?; + // attempt to parse a public key from bytes + let public_key: PublicKey = PublicKey::from_bytes(pub_key).map_err(|_| Error::Sr25519VerifyFailed)?; + // verify the signature public_key .verify(context.bytes(message), &signature) .map_err(|_| Error::Sr25519VerifyFailed) From b4a65d2c3914a62c302192cc83a93511b134f1bf Mon Sep 17 00:00:00 2001 From: George Oastler Date: Wed, 5 Jul 2023 16:59:19 +0100 Subject: [PATCH 12/32] switched to simple signing context in sr25519_verify fn there is no need to make the context directly, we can delegate that to the schnorrkel library --- crates/env/src/engine/off_chain/impls.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 553517fdba..7ca2836c02 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -48,7 +48,6 @@ use ink_engine::{ }; use ink_storage_traits::Storable; use schnorrkel::{ - signing_context, PublicKey, Signature, }; @@ -347,14 +346,14 @@ impl EnvBackend for EnvInstance { ) -> Result<()> { // the context associated with the signing (specific to the sr25519 algorithm) // defaults to "substrate" in substrate, but could be different elsewhere - let context = signing_context(b"substrate"); + let context = b"substrate"; // attempt to parse a signature from bytes let signature: Signature = Signature::from_bytes(signature).map_err(|_| Error::Sr25519VerifyFailed)?; // attempt to parse a public key from bytes let public_key: PublicKey = PublicKey::from_bytes(pub_key).map_err(|_| Error::Sr25519VerifyFailed)?; // verify the signature public_key - .verify(context.bytes(message), &signature) + .verify_simple(context, &message, &signature) .map_err(|_| Error::Sr25519VerifyFailed) } From 548fe270f25f843bf3ecd4745e9e6e7059f48182 Mon Sep 17 00:00:00 2001 From: George Oastler Date: Thu, 6 Jul 2023 08:38:57 +0100 Subject: [PATCH 13/32] Added docs for sr25519_verify() Docs + example + notes about context set to "substrate" --- crates/ink/src/env_access.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 0ec7f6bf53..326adc6105 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -880,6 +880,40 @@ where .map_err(|_| Error::EcdsaRecoveryFailed) } + /// Verifies a SR25519 signature against a message and a public key. + /// + /// # Example + /// + /// ``` + /// # #[ink::contract] + /// # pub mod my_contract { + /// # #[ink(storage)] + /// # pub struct MyContract { } + /// # + /// # impl MyContract { + /// # #[ink(constructor)] + /// # pub fn new() -> Self { + /// # Self {} + /// # } + /// # + /// #[ink(message)] + /// pub fn sr25519_verify(&self) { + /// let mut signature: [u8; 64] = [10, 125, 162, 182, 49, 112, 76, 220, 254, 147, 199, 64, 228, 18, 23, 185, 172, 102, 122, 12, 135, 85, 216, 218, 26, 130, 50, 219, 82, 127, 72, 124, 135, 231, 128, 210, 237, 193, 137, 106, 235, 107, 27, 239, 11, 199, 195, 141, 157, 242, 19, 91, 99, 62, 171, 139, 251, 23, 119, 232, 47, 173, 58, 143]; + /// let mut message: [u8; 49] = [60, 66, 121, 116, 101, 115, 62, 48, 120, 52, 54, 102, 98, 55, 52, 48, 56, 100, 52, 102, 50, 56, 53, 50, 50, 56, 102, 52, 97, 102, 53, 49, 54, 101, 97, 50, 53, 56, 53, 49, 98, 60, 47, 66, 121, 116, 101, 115, 62]; + /// let mut public_key: [u8; 32] = [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125]; + /// let result = ink::env::sr25519_verify(&signature, &message, &public_key); + /// assert_eq!(result, Ok(())); + /// } + /// # + /// # } + /// # } + /// ``` + /// + /// # Note + /// + /// The context for sr25519 signing is hard-coded to "substrate" to match sr25519 signing in substrate. + /// + /// For more details visit: [`ink_env::sr25519_verify`] pub fn sr25519_verify( self, signature: &[u8; 64], From 53c2442f34426253ebdb02ef08aad63fb1355efe Mon Sep 17 00:00:00 2001 From: George Oastler Date: Thu, 6 Jul 2023 08:40:52 +0100 Subject: [PATCH 14/32] Added docs to sr25519VerifyFailed error Helpful for debugging why the error has occurred, as there is only ever one of 3 reasons: invalid public key, invalid message or invalid signature --- crates/engine/src/ext.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/engine/src/ext.rs b/crates/engine/src/ext.rs index 22b0eafa70..c017cf8331 100644 --- a/crates/engine/src/ext.rs +++ b/crates/engine/src/ext.rs @@ -97,7 +97,7 @@ define_error_codes! { LoggingDisabled = 9, /// ECDSA public key recovery failed. Most probably wrong recovery id or signature. EcdsaRecoveryFailed = 11, - /// sr25519 signature verification failed. + /// sr25519 signature verification failed. This may be because of an invalid public key, invalid message or invalid signature. Sr25519VerifyFailed = 12, } From 6ce47f4fae2aff1ee34124c2e1a6e92a4cc62dcf Mon Sep 17 00:00:00 2001 From: George Oastler Date: Thu, 6 Jul 2023 11:15:28 +0100 Subject: [PATCH 15/32] Added docs link to substrate sr25519 signing context --- crates/env/src/engine/off_chain/impls.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 7ca2836c02..e8befa65aa 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -346,6 +346,7 @@ impl EnvBackend for EnvInstance { ) -> Result<()> { // the context associated with the signing (specific to the sr25519 algorithm) // defaults to "substrate" in substrate, but could be different elsewhere + // https://github.com/paritytech/substrate/blob/c32f5ed2ae6746d6f791f08cecbfc22fa188f5f9/primitives/core/src/sr25519.rs#L60 let context = b"substrate"; // attempt to parse a signature from bytes let signature: Signature = Signature::from_bytes(signature).map_err(|_| Error::Sr25519VerifyFailed)?; From b9cfbf58dfd716d0f76e0e224c7a4c869f372411 Mon Sep 17 00:00:00 2001 From: George Oastler Date: Thu, 6 Jul 2023 11:26:17 +0100 Subject: [PATCH 16/32] cargo fmt --- crates/env/src/engine/off_chain/impls.rs | 6 ++++-- crates/ink/src/env_access.rs | 25 ++++++++++++++++++------ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index e8befa65aa..d1b7775d77 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -349,9 +349,11 @@ impl EnvBackend for EnvInstance { // https://github.com/paritytech/substrate/blob/c32f5ed2ae6746d6f791f08cecbfc22fa188f5f9/primitives/core/src/sr25519.rs#L60 let context = b"substrate"; // attempt to parse a signature from bytes - let signature: Signature = Signature::from_bytes(signature).map_err(|_| Error::Sr25519VerifyFailed)?; + let signature: Signature = + Signature::from_bytes(signature).map_err(|_| Error::Sr25519VerifyFailed)?; // attempt to parse a public key from bytes - let public_key: PublicKey = PublicKey::from_bytes(pub_key).map_err(|_| Error::Sr25519VerifyFailed)?; + let public_key: PublicKey = + PublicKey::from_bytes(pub_key).map_err(|_| Error::Sr25519VerifyFailed)?; // verify the signature public_key .verify_simple(context, &message, &signature) diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 326adc6105..4b5dcb2d84 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -881,7 +881,7 @@ where } /// Verifies a SR25519 signature against a message and a public key. - /// + /// /// # Example /// /// ``` @@ -898,9 +898,21 @@ where /// # /// #[ink(message)] /// pub fn sr25519_verify(&self) { - /// let mut signature: [u8; 64] = [10, 125, 162, 182, 49, 112, 76, 220, 254, 147, 199, 64, 228, 18, 23, 185, 172, 102, 122, 12, 135, 85, 216, 218, 26, 130, 50, 219, 82, 127, 72, 124, 135, 231, 128, 210, 237, 193, 137, 106, 235, 107, 27, 239, 11, 199, 195, 141, 157, 242, 19, 91, 99, 62, 171, 139, 251, 23, 119, 232, 47, 173, 58, 143]; - /// let mut message: [u8; 49] = [60, 66, 121, 116, 101, 115, 62, 48, 120, 52, 54, 102, 98, 55, 52, 48, 56, 100, 52, 102, 50, 56, 53, 50, 50, 56, 102, 52, 97, 102, 53, 49, 54, 101, 97, 50, 53, 56, 53, 49, 98, 60, 47, 66, 121, 116, 101, 115, 62]; - /// let mut public_key: [u8; 32] = [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125]; + /// let mut signature: [u8; 64] = [ + /// 10, 125, 162, 182, 49, 112, 76, 220, 254, 147, 199, 64, 228, 18, 23, 185, + /// 172, 102, 122, 12, 135, 85, 216, 218, 26, 130, 50, 219, 82, 127, 72, 124, + /// 135, 231, 128, 210, 237, 193, 137, 106, 235, 107, 27, 239, 11, 199, 195, 141, + /// 157, 242, 19, 91, 99, 62, 171, 139, 251, 23, 119, 232, 47, 173, 58, 143, + /// ]; + /// let mut message: [u8; 49] = [ + /// 60, 66, 121, 116, 101, 115, 62, 48, 120, 52, 54, 102, 98, 55, 52, 48, 56, + /// 100, 52, 102, 50, 56, 53, 50, 50, 56, 102, 52, 97, 102, 53, 49, 54, 101, 97, + /// 50, 53, 56, 53, 49, 98, 60, 47, 66, 121, 116, 101, 115, 62, + /// ]; + /// let mut public_key: [u8; 32] = [ + /// 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, + /// 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125, + /// ]; /// let result = ink::env::sr25519_verify(&signature, &message, &public_key); /// assert_eq!(result, Ok(())); /// } @@ -911,8 +923,9 @@ where /// /// # Note /// - /// The context for sr25519 signing is hard-coded to "substrate" to match sr25519 signing in substrate. - /// + /// The context for sr25519 signing is hard-coded to "substrate" to match sr25519 + /// signing in substrate. + /// /// For more details visit: [`ink_env::sr25519_verify`] pub fn sr25519_verify( self, From a33283ee28adce294dcf18492f5e16d909773d74 Mon Sep 17 00:00:00 2001 From: George Oastler Date: Thu, 6 Jul 2023 11:49:09 +0100 Subject: [PATCH 17/32] Remove reference on message variable of sr25519_verify() Not required according to clippy --- crates/env/src/engine/off_chain/impls.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index d1b7775d77..9793d8f9fc 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -356,7 +356,7 @@ impl EnvBackend for EnvInstance { PublicKey::from_bytes(pub_key).map_err(|_| Error::Sr25519VerifyFailed)?; // verify the signature public_key - .verify_simple(context, &message, &signature) + .verify_simple(context, message, &signature) .map_err(|_| Error::Sr25519VerifyFailed) } From 35175bb2348d41382ab2ef074f257a8e2559ca2d Mon Sep 17 00:00:00 2001 From: George Oastler Date: Thu, 6 Jul 2023 11:49:54 +0100 Subject: [PATCH 18/32] Clippy embed error in panic statement during metadata execution Clippy's advice --- crates/e2e/macro/src/codegen.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/e2e/macro/src/codegen.rs b/crates/e2e/macro/src/codegen.rs index 7711f07bc5..97f5f46814 100644 --- a/crates/e2e/macro/src/codegen.rs +++ b/crates/e2e/macro/src/codegen.rs @@ -215,7 +215,7 @@ impl ContractManifests { let cmd = cargo_metadata::MetadataCommand::new(); let metadata = cmd .exec() - .unwrap_or_else(|err| panic!("Error invoking `cargo metadata`: {}", err)); + .unwrap_or_else(|err| panic!("Error invoking `cargo metadata`: {err}")); fn maybe_contract_package(package: &cargo_metadata::Package) -> Option { package From 7fd25ba083c623a5c5429d4296090d3e5018f1b0 Mon Sep 17 00:00:00 2001 From: George Oastler Date: Thu, 6 Jul 2023 12:17:38 +0100 Subject: [PATCH 19/32] sr25519 verification tests Tested invalid public key, invalid signature, invalid message and valid case --- .../sr25519-verification/.gitignore | 9 ++ .../sr25519-verification/Cargo.toml | 28 ++++ integration-tests/sr25519-verification/lib.rs | 128 ++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 integration-tests/sr25519-verification/.gitignore create mode 100644 integration-tests/sr25519-verification/Cargo.toml create mode 100644 integration-tests/sr25519-verification/lib.rs diff --git a/integration-tests/sr25519-verification/.gitignore b/integration-tests/sr25519-verification/.gitignore new file mode 100644 index 0000000000..bf910de10a --- /dev/null +++ b/integration-tests/sr25519-verification/.gitignore @@ -0,0 +1,9 @@ +# Ignore build artifacts from the local tests sub-crate. +/target/ + +# Ignore backup files creates by cargo fmt. +**/*.rs.bk + +# Remove Cargo.lock when creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +Cargo.lock \ No newline at end of file diff --git a/integration-tests/sr25519-verification/Cargo.toml b/integration-tests/sr25519-verification/Cargo.toml new file mode 100644 index 0000000000..37cbb9892d --- /dev/null +++ b/integration-tests/sr25519-verification/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "sr25519_verification" +version = "4.1.0" +authors = ["George Oastler "] +edition = "2021" +publish = false + +[dependencies] +ink = { path = "../../crates/ink", default-features = false } + +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2.5", default-features = false, features = ["derive"], optional = true } + +[dev-dependencies] +ink_e2e = { path = "../../crates/e2e" } + +[lib] +path = "lib.rs" + +[features] +default = ["std"] +std = [ + "ink/std", + "scale/std", + "scale-info/std", +] +ink-as-dependency = [] +e2e-tests = [] diff --git a/integration-tests/sr25519-verification/lib.rs b/integration-tests/sr25519-verification/lib.rs new file mode 100644 index 0000000000..046323187d --- /dev/null +++ b/integration-tests/sr25519-verification/lib.rs @@ -0,0 +1,128 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +#[ink::contract] +pub mod sr25519_verification { + #[ink(storage)] + #[derive(Default)] + pub struct Sr25519Verification {} + + impl Sr25519Verification { + /// Creates a new sr25519_verification smart contract initialized with the given + /// value. + #[ink(constructor)] + pub fn new() -> Self { + Self {} + } + + #[ink(message)] + pub fn noop(&self) {} + } + + #[cfg(test)] + mod tests { + + #[ink::test] + fn test_sr25519_verify_valid() { + // "hello" as bytes + let message: [u8; 49] = [ + 60, 66, 121, 116, 101, 115, 62, 48, 120, 52, 54, 102, 98, 55, 52, 48, 56, + 100, 52, 102, 50, 56, 53, 50, 50, 56, 102, 52, 97, 102, 53, 49, 54, 101, + 97, 50, 53, 56, 53, 49, 98, 60, 47, 66, 121, 116, 101, 115, 62, + ]; + // alice + let public_key: [u8; 32] = [ + 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, + 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, + 125, + ]; + // alice's signature of the message + let signature: [u8; 64] = [ + 10, 125, 162, 182, 49, 112, 76, 220, 254, 147, 199, 64, 228, 18, 23, 185, + 172, 102, 122, 12, 135, 85, 216, 218, 26, 130, 50, 219, 82, 127, 72, 124, + 135, 231, 128, 210, 237, 193, 137, 106, 235, 107, 27, 239, 11, 199, 195, + 141, 157, 242, 19, 91, 99, 62, 171, 139, 251, 23, 119, 232, 47, 173, 58, + 143, + ]; + let result = ink::env::sr25519_verify(&signature, &message, &public_key); + assert_eq!(result, Ok(())); + } + + #[ink::test] + fn test_sr25519_verify_invalid_public_key() { + // "hello" as bytes + let message: [u8; 49] = [ + 60, 66, 121, 116, 101, 115, 62, 48, 120, 52, 54, 102, 98, 55, 52, 48, 56, + 100, 52, 102, 50, 56, 53, 50, 50, 56, 102, 52, 97, 102, 53, 49, 54, 101, + 97, 50, 53, 56, 53, 49, 98, 60, 47, 66, 121, 116, 101, 115, 62, + ]; + // alice - off by 1 at start + let public_key: [u8; 32] = [ + 213, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, + 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, + 125, + ]; + // alice's signature of the message + let signature: [u8; 64] = [ + 10, 125, 162, 182, 49, 112, 76, 220, 254, 147, 199, 64, 228, 18, 23, 185, + 172, 102, 122, 12, 135, 85, 216, 218, 26, 130, 50, 219, 82, 127, 72, 124, + 135, 231, 128, 210, 237, 193, 137, 106, 235, 107, 27, 239, 11, 199, 195, + 141, 157, 242, 19, 91, 99, 62, 171, 139, 251, 23, 119, 232, 47, 173, 58, + 143, + ]; + let result = ink::env::sr25519_verify(&signature, &message, &public_key); + assert_eq!(result, Err(ink::env::Error::Sr25519VerifyFailed)); + } + + #[ink::test] + fn test_sr25519_verify_invalid_message() { + // "hello" as bytes - off by 1 at start + let message: [u8; 49] = [ + 61, 66, 121, 116, 101, 115, 62, 48, 120, 52, 54, 102, 98, 55, 52, 48, 56, + 100, 52, 102, 50, 56, 53, 50, 50, 56, 102, 52, 97, 102, 53, 49, 54, 101, + 97, 50, 53, 56, 53, 49, 98, 60, 47, 66, 121, 116, 101, 115, 62, + ]; + // alice + let public_key: [u8; 32] = [ + 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, + 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, + 125, + ]; + // alice's signature of the message + let signature: [u8; 64] = [ + 10, 125, 162, 182, 49, 112, 76, 220, 254, 147, 199, 64, 228, 18, 23, 185, + 172, 102, 122, 12, 135, 85, 216, 218, 26, 130, 50, 219, 82, 127, 72, 124, + 135, 231, 128, 210, 237, 193, 137, 106, 235, 107, 27, 239, 11, 199, 195, + 141, 157, 242, 19, 91, 99, 62, 171, 139, 251, 23, 119, 232, 47, 173, 58, + 143, + ]; + let result = ink::env::sr25519_verify(&signature, &message, &public_key); + assert_eq!(result, Err(ink::env::Error::Sr25519VerifyFailed)); + } + + #[ink::test] + fn test_sr25519_verify_invalid_signature() { + // "hello" as bytes + let message: [u8; 49] = [ + 60, 66, 121, 116, 101, 115, 62, 48, 120, 52, 54, 102, 98, 55, 52, 48, 56, + 100, 52, 102, 50, 56, 53, 50, 50, 56, 102, 52, 97, 102, 53, 49, 54, 101, + 97, 50, 53, 56, 53, 49, 98, 60, 47, 66, 121, 116, 101, 115, 62, + ]; + // alice + let public_key: [u8; 32] = [ + 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, + 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, + 125, + ]; + // alice's signature of the message - off by 1 at start + let signature: [u8; 64] = [ + 11, 125, 162, 182, 49, 112, 76, 220, 254, 147, 199, 64, 228, 18, 23, 185, + 172, 102, 122, 12, 135, 85, 216, 218, 26, 130, 50, 219, 82, 127, 72, 124, + 135, 231, 128, 210, 237, 193, 137, 106, 235, 107, 27, 239, 11, 199, 195, + 141, 157, 242, 19, 91, 99, 62, 171, 139, 251, 23, 119, 232, 47, 173, 58, + 143, + ]; + let result = ink::env::sr25519_verify(&signature, &message, &public_key); + assert_eq!(result, Err(ink::env::Error::Sr25519VerifyFailed)); + } + } +} From fda5ab15ba612830338393afb35cfee1fe3e89cf Mon Sep 17 00:00:00 2001 From: George Oastler Date: Thu, 6 Jul 2023 14:35:31 +0100 Subject: [PATCH 20/32] Updated sr25519_verify PR number in CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ccdc62edb5..05347f83d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Persist `Environment` in metadata - [#1741](https://github.com/paritytech/ink/pull/1741) -- Added `sr25519_verify` function to `ink_env` [#1757](https://github.com/paritytech/ink/pull/1757) +- Added `sr25519_verify` function to `ink_env` [#1840](https://github.com/paritytech/ink/pull/1840) ### Changed - Upgraded `syn` to version `2` - [#1731](https://github.com/paritytech/ink/pull/1731) From fd914dfb0cc5618cb8e339a5cb33e8b4a6194041 Mon Sep 17 00:00:00 2001 From: George Oastler Date: Thu, 6 Jul 2023 16:15:15 +0100 Subject: [PATCH 21/32] Fix comment to adhere to spell check in sr25519 verification tests --- integration-tests/sr25519-verification/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/sr25519-verification/lib.rs b/integration-tests/sr25519-verification/lib.rs index 046323187d..35444302cb 100644 --- a/integration-tests/sr25519-verification/lib.rs +++ b/integration-tests/sr25519-verification/lib.rs @@ -7,7 +7,7 @@ pub mod sr25519_verification { pub struct Sr25519Verification {} impl Sr25519Verification { - /// Creates a new sr25519_verification smart contract initialized with the given + /// Creates a new sr25519 verification smart contract initialized with the given /// value. #[ink(constructor)] pub fn new() -> Self { From 8866fdb9f95876edd24149b2baf1e094b3de52bd Mon Sep 17 00:00:00 2001 From: George Oastler Date: Tue, 18 Jul 2023 09:35:32 +0100 Subject: [PATCH 22/32] add parity as author of sr25519 module Co-authored-by: Green Baneling --- integration-tests/sr25519-verification/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/sr25519-verification/Cargo.toml b/integration-tests/sr25519-verification/Cargo.toml index 37cbb9892d..9281779661 100644 --- a/integration-tests/sr25519-verification/Cargo.toml +++ b/integration-tests/sr25519-verification/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "sr25519_verification" version = "4.1.0" -authors = ["George Oastler "] +authors = ["Parity Technologies ", "George Oastler "] edition = "2021" publish = false From 79bea8a070ad20917e8b7c410a426b6d53d3c1ed Mon Sep 17 00:00:00 2001 From: George Oastler Date: Fri, 28 Jul 2023 11:31:51 +0100 Subject: [PATCH 23/32] ignore semicolon correction in item module --- crates/ink/ir/src/ir/item_mod.rs | 2 +- crates/ink/ir/src/ir/trait_def/item/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ink/ir/src/ir/item_mod.rs b/crates/ink/ir/src/ir/item_mod.rs index de750ae6e5..5d70a43bb2 100644 --- a/crates/ink/ir/src/ir/item_mod.rs +++ b/crates/ink/ir/src/ir/item_mod.rs @@ -336,7 +336,7 @@ impl ItemMod { .into_combine(format_err!( overlap.span(), "first ink! constructor with overlapping wildcard selector here", - ))); + ))) } } } diff --git a/crates/ink/ir/src/ir/trait_def/item/mod.rs b/crates/ink/ir/src/ir/trait_def/item/mod.rs index 6297a20acc..69b8f95b26 100644 --- a/crates/ink/ir/src/ir/trait_def/item/mod.rs +++ b/crates/ink/ir/src/ir/trait_def/item/mod.rs @@ -384,7 +384,7 @@ impl InkItemTrait { ).into_combine(format_err_spanned!( duplicate_selector, "first ink! trait constructor or message with same selector found here", - ))); + ))) } assert!( duplicate_ident.is_none(), From 2aef6a8245bbf2a4a843284952893e93634f9e60 Mon Sep 17 00:00:00 2001 From: George Oastler Date: Fri, 28 Jul 2023 11:41:17 +0100 Subject: [PATCH 24/32] add warning to docs for sr25519_verify() depending on unstable interfaces --- crates/env/src/api.rs | 3 +++ crates/env/src/backend.rs | 3 +++ crates/ink/src/env_access.rs | 3 +++ 3 files changed, 9 insertions(+) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index 7aa6980676..b8ed989d1b 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -574,6 +574,9 @@ pub fn ecdsa_to_eth_address(pubkey: &[u8; 33], output: &mut [u8; 20]) -> Result< /// # Errors /// /// - If sr25519 signature cannot be verified. +/// +/// **WARNING**: this function is from the [unstable interface](https://github.com/paritytech/substrate/tree/master/frame/contracts#unstable-interfaces), +/// which is unsafe and normally is not available on production chains. pub fn sr25519_verify( signature: &[u8; 64], message: &[u8], diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index 0646d0d902..e463122689 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -295,6 +295,9 @@ pub trait EnvBackend { /// # Errors /// /// - If the signature verification failed. + /// + /// **WARNING**: this function is from the [unstable interface](https://github.com/paritytech/substrate/tree/master/frame/contracts#unstable-interfaces), + /// which is unsafe and normally is not available on production chains. fn sr25519_verify( &mut self, signature: &[u8; 64], diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index 749d36110a..a46670a43e 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -928,6 +928,9 @@ where /// signing in substrate. /// /// For more details visit: [`ink_env::sr25519_verify`] + /// + /// **WARNING**: this function is from the [unstable interface](https://github.com/paritytech/substrate/tree/master/frame/contracts#unstable-interfaces), + /// which is unsafe and normally is not available on production chains. pub fn sr25519_verify( self, signature: &[u8; 64], From 97e2d23c2d925f7cca7c1ca672a1aac892320366 Mon Sep 17 00:00:00 2001 From: George Oastler Date: Fri, 28 Jul 2023 11:59:40 +0100 Subject: [PATCH 25/32] remove space typo from sr25519 docs --- crates/env/src/api.rs | 2 +- crates/env/src/backend.rs | 2 +- crates/ink/src/env_access.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index 4f75427934..3050c21df7 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -574,7 +574,7 @@ pub fn ecdsa_to_eth_address(pubkey: &[u8; 33], output: &mut [u8; 20]) -> Result< /// # Errors /// /// - If sr25519 signature cannot be verified. -/// +/// /// **WARNING**: this function is from the [unstable interface](https://github.com/paritytech/substrate/tree/master/frame/contracts#unstable-interfaces), /// which is unsafe and normally is not available on production chains. pub fn sr25519_verify( diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index 2a4fc337c9..99455b5786 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -295,7 +295,7 @@ pub trait EnvBackend { /// # Errors /// /// - If the signature verification failed. - /// + /// /// **WARNING**: this function is from the [unstable interface](https://github.com/paritytech/substrate/tree/master/frame/contracts#unstable-interfaces), /// which is unsafe and normally is not available on production chains. fn sr25519_verify( diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index ec218209d0..71aac43ffb 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -936,7 +936,7 @@ where /// signing in substrate. /// /// For more details visit: [`ink_env::sr25519_verify`] - /// + /// /// **WARNING**: this function is from the [unstable interface](https://github.com/paritytech/substrate/tree/master/frame/contracts#unstable-interfaces), /// which is unsafe and normally is not available on production chains. pub fn sr25519_verify( From cf04d6df9c39177a54326b72c9700622ac98a6ba Mon Sep 17 00:00:00 2001 From: George Oastler Date: Mon, 31 Jul 2023 17:48:40 +0100 Subject: [PATCH 26/32] remove #1741 from changelog --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 695596baeb..30033c52ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Version 4.2.0 ### Added -- Persist `Environment` in metadata ‒ [#1741](https://github.com/paritytech/ink/pull/1741) - Added possibility for `runtime_call` in E2E tests ‒ [#1736](https://github.com/paritytech/ink/pull/1736) - Added `default` attribute to constructors and messages ‒ [#1724](https://github.com/paritytech/ink/pull/1724) - Added clarification about `Mapping::size` unit ‒ [#1735](https://github.com/paritytech/ink/pull/1735) From c500a03e354b7353f767100696ac43ca7c4c1fb9 Mon Sep 17 00:00:00 2001 From: George Oastler Date: Mon, 31 Jul 2023 17:53:15 +0100 Subject: [PATCH 27/32] added documentation to the dummy method in sr25519_verification example --- integration-tests/sr25519-verification/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/integration-tests/sr25519-verification/lib.rs b/integration-tests/sr25519-verification/lib.rs index 35444302cb..e453d55f83 100644 --- a/integration-tests/sr25519-verification/lib.rs +++ b/integration-tests/sr25519-verification/lib.rs @@ -14,8 +14,11 @@ pub mod sr25519_verification { Self {} } + /// Dummy method to satisfy constaint of >0 messages per contract. #[ink(message)] - pub fn noop(&self) {} + pub fn foobar(&self) { + ink_env::debug_println!("foobar - this method does nothing"); + } } #[cfg(test)] From 4c3cbc863fc1e29202f738a660b3744ef9c43c4d Mon Sep 17 00:00:00 2001 From: George Oastler Date: Tue, 1 Aug 2023 08:02:31 +0100 Subject: [PATCH 28/32] typo in sr25519 example contract dummy method --- integration-tests/sr25519-verification/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/sr25519-verification/lib.rs b/integration-tests/sr25519-verification/lib.rs index e453d55f83..377967a8f8 100644 --- a/integration-tests/sr25519-verification/lib.rs +++ b/integration-tests/sr25519-verification/lib.rs @@ -17,7 +17,7 @@ pub mod sr25519_verification { /// Dummy method to satisfy constaint of >0 messages per contract. #[ink(message)] pub fn foobar(&self) { - ink_env::debug_println!("foobar - this method does nothing"); + ink::env::debug_println!("foobar - this method does nothing"); } } From bba49eae28524a546cbd8ed1135eca040f1f4901 Mon Sep 17 00:00:00 2001 From: George Oastler Date: Tue, 1 Aug 2023 08:07:31 +0100 Subject: [PATCH 29/32] spell check fix in method doc for sr25519 --- integration-tests/sr25519-verification/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/sr25519-verification/lib.rs b/integration-tests/sr25519-verification/lib.rs index 377967a8f8..7714c62a14 100644 --- a/integration-tests/sr25519-verification/lib.rs +++ b/integration-tests/sr25519-verification/lib.rs @@ -14,7 +14,7 @@ pub mod sr25519_verification { Self {} } - /// Dummy method to satisfy constaint of >0 messages per contract. + /// Dummy method to satisfy constaint of > 0 messages per contract. #[ink(message)] pub fn foobar(&self) { ink::env::debug_println!("foobar - this method does nothing"); From 18104683cadfd7f27b052955e668adf3db047b28 Mon Sep 17 00:00:00 2001 From: George Oastler Date: Tue, 1 Aug 2023 08:10:59 +0100 Subject: [PATCH 30/32] spell check fix in method doc for sr25519 --- integration-tests/sr25519-verification/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/sr25519-verification/lib.rs b/integration-tests/sr25519-verification/lib.rs index 7714c62a14..a8322b0149 100644 --- a/integration-tests/sr25519-verification/lib.rs +++ b/integration-tests/sr25519-verification/lib.rs @@ -14,7 +14,7 @@ pub mod sr25519_verification { Self {} } - /// Dummy method to satisfy constaint of > 0 messages per contract. + /// Dummy method to satisfy constaint of more than 0 messages per contract. #[ink(message)] pub fn foobar(&self) { ink::env::debug_println!("foobar - this method does nothing"); From eeee6d4c9f6a85f859b0888c037149568e8bb6cf Mon Sep 17 00:00:00 2001 From: George Oastler Date: Wed, 2 Aug 2023 11:52:04 +0100 Subject: [PATCH 31/32] move changelog entry for #1741 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30033c52ee..99997b67be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Stabilize `call_runtime` ‒ [#1749](https://github.com/paritytech/ink/pull/1749) ### Added -- Persist `Environment` in metadata - [#1741](https://github.com/paritytech/ink/pull/1741) - Schema generation - [#1765](https://github.com/paritytech/ink/pull/1765) - Add `set_block_number` to off-chain test api `Engine` - [#1806](https://github.com/paritytech/ink/pull/1806) - Added `sr25519_verify` function to `ink_env` [#1840](https://github.com/paritytech/ink/pull/1840) @@ -19,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Version 4.2.0 ### Added +- Persist `Environment` in metadata - [#1741](https://github.com/paritytech/ink/pull/1741) - Added possibility for `runtime_call` in E2E tests ‒ [#1736](https://github.com/paritytech/ink/pull/1736) - Added `default` attribute to constructors and messages ‒ [#1724](https://github.com/paritytech/ink/pull/1724) - Added clarification about `Mapping::size` unit ‒ [#1735](https://github.com/paritytech/ink/pull/1735) From 77044d26292da0cad5cf512b83a627ee2baf7381 Mon Sep 17 00:00:00 2001 From: George Oastler Date: Wed, 2 Aug 2023 11:52:58 +0100 Subject: [PATCH 32/32] changelog typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99997b67be..cfd18def71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Version 4.2.0 ### Added -- Persist `Environment` in metadata - [#1741](https://github.com/paritytech/ink/pull/1741) +- Persist `Environment` in metadata ‒ [#1741](https://github.com/paritytech/ink/pull/1741) - Added possibility for `runtime_call` in E2E tests ‒ [#1736](https://github.com/paritytech/ink/pull/1736) - Added `default` attribute to constructors and messages ‒ [#1724](https://github.com/paritytech/ink/pull/1724) - Added clarification about `Mapping::size` unit ‒ [#1735](https://github.com/paritytech/ink/pull/1735)