From 9b9261b7fb2e0c88c211b8768cf9e54097296657 Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Mon, 17 Oct 2022 14:47:32 +0200 Subject: [PATCH 01/12] define CryptoProvider trait --- light-client-verifier/Cargo.toml | 4 ++++ light-client-verifier/src/host_functions.rs | 14 ++++++++++++++ light-client-verifier/src/lib.rs | 1 + 3 files changed, 19 insertions(+) create mode 100644 light-client-verifier/src/host_functions.rs diff --git a/light-client-verifier/Cargo.toml b/light-client-verifier/Cargo.toml index c5d33da2b..01c358bb1 100644 --- a/light-client-verifier/Cargo.toml +++ b/light-client-verifier/Cargo.toml @@ -33,5 +33,9 @@ serde = { version = "1.0.106", default-features = false } time = { version = "0.3", default-features = false } flex-error = { version = "0.4.4", default-features = false } +k256 = { version = "0.11", default-features = false, features = ["ecdsa", "sha256"] } +digest = { version = "0.10", default-features = false } +ed25519 = { version = "1.3", default-features = false } + [dev-dependencies] tendermint-testgen = { path = "../testgen", default-features = false } diff --git a/light-client-verifier/src/host_functions.rs b/light-client-verifier/src/host_functions.rs new file mode 100644 index 000000000..6341b9a8d --- /dev/null +++ b/light-client-verifier/src/host_functions.rs @@ -0,0 +1,14 @@ +use digest::FixedOutput; +use digest::{consts::U32, Digest}; +use tendermint::signature::Signer; +use tendermint::signature::Verifier; + +pub trait CryptoProvider { + type Sha256: Digest + FixedOutput; + + type EcdsaSecp256k1Signer: Signer; + type EcdsaSecp256k1Verifier: Verifier; + + type Ed25519Signer: Signer; + type Ed25519Verifier: Verifier; +} diff --git a/light-client-verifier/src/lib.rs b/light-client-verifier/src/lib.rs index ce413cefd..499c2f82e 100644 --- a/light-client-verifier/src/lib.rs +++ b/light-client-verifier/src/lib.rs @@ -5,6 +5,7 @@ extern crate alloc; mod prelude; pub mod errors; +pub mod host_functions; pub mod operations; pub mod options; pub mod predicates; From 8d4f61505e7b683c80e0b0e32be83fbf52ca0f6a Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Mon, 17 Oct 2022 21:35:58 +0200 Subject: [PATCH 02/12] wip --- light-client-verifier/Cargo.toml | 2 + light-client-verifier/src/host_functions.rs | 64 +++++++++++++++++++-- 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/light-client-verifier/Cargo.toml b/light-client-verifier/Cargo.toml index 01c358bb1..29aafa161 100644 --- a/light-client-verifier/Cargo.toml +++ b/light-client-verifier/Cargo.toml @@ -39,3 +39,5 @@ ed25519 = { version = "1.3", default-features = false } [dev-dependencies] tendermint-testgen = { path = "../testgen", default-features = false } +sha2 = { version = "0.9", default-features = false } + diff --git a/light-client-verifier/src/host_functions.rs b/light-client-verifier/src/host_functions.rs index 6341b9a8d..16511f93f 100644 --- a/light-client-verifier/src/host_functions.rs +++ b/light-client-verifier/src/host_functions.rs @@ -6,9 +6,65 @@ use tendermint::signature::Verifier; pub trait CryptoProvider { type Sha256: Digest + FixedOutput; - type EcdsaSecp256k1Signer: Signer; - type EcdsaSecp256k1Verifier: Verifier; + // type EcdsaSecp256k1Signer: Signer; + // type EcdsaSecp256k1Verifier: Verifier; - type Ed25519Signer: Signer; - type Ed25519Verifier: Verifier; + // type Ed25519Signer: Signer; + // type Ed25519Verifier: Verifier; +} + +#[cfg(test)] +mod tests { + + use super::*; + struct SubstrateHostFunctionsManager; + + trait SubstrateHostFunctions: CryptoProvider { + fn sha2_256(preimage: &[u8]) -> [u8; 32]; + fn ed25519_verify(sig: &[u8], msg: &[u8], pub_key: &[u8]) -> Result<(), ()>; + fn secp256k1_verify(sig: &[u8], message: &[u8], public: &[u8]) -> Result<(), ()>; + } + + impl SubstrateHostFunctionsManager for SubstrateHostFunctions { + type Sha256 = sha2::Sha256; + + fn sha2_256(preimage: &[u8]) -> [u8; 32] { + unimplemented!() + } + fn ed25519_verify(sig: &[u8], msg: &[u8], pub_key: &[u8]) -> Result<(), ()> { + unimplemented!() + } + fn secp256k1_verify(sig: &[u8], message: &[u8], public: &[u8]) -> Result<(), ()> { + unimplemented!() + } + } + + // impl CryptoProvider for CryptoManager { + // fn sha2_256(preimage: &[u8]) -> [u8; 32] { + // sp_core::hashing::sha2_256(preimage) + // } + + // fn ed25519_verify(sig: &[u8], msg: &[u8], pub_key: &[u8]) -> Result<(), ()> { + // use sp_core::{ed25519, ByteArray, Pair}; + + // let signature = ed25519::Signature::from_slice(sig).ok_or(())?; + + // let public_key = ed25519::Public::from_slice(pub_key).map_err(|_| ())?; + // if ed25519::Pair::verify(&signature, msg, &public_key) { + // return Ok(()); + // } + // Err(()) + // } + + // fn secp256k1_verify(sig: &[u8], message: &[u8], public: &[u8]) -> Result<(), ()> { + // use sp_core::{ecdsa, ByteArray, Pair}; + + // let public = ecdsa::Public::from_slice(public).map_err(|_| ())?; + // if ecdsa::Pair::verify_weak(&sig, message, &public) { + // return Ok(()); + // } + + // Err(()) + // } + // } } From d15583d47195036ae9b3deed556728077963a76f Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Wed, 19 Oct 2022 13:14:25 +0200 Subject: [PATCH 03/12] implement CryptoProvider for Substrate (WIP) --- light-client-verifier/Cargo.toml | 1 + light-client-verifier/src/host_functions.rs | 108 ++++++++++++++------ 2 files changed, 75 insertions(+), 34 deletions(-) diff --git a/light-client-verifier/Cargo.toml b/light-client-verifier/Cargo.toml index 29aafa161..763130342 100644 --- a/light-client-verifier/Cargo.toml +++ b/light-client-verifier/Cargo.toml @@ -36,6 +36,7 @@ flex-error = { version = "0.4.4", default-features = false } k256 = { version = "0.11", default-features = false, features = ["ecdsa", "sha256"] } digest = { version = "0.10", default-features = false } ed25519 = { version = "1.3", default-features = false } +signature = { version = "1", default-features = false } [dev-dependencies] tendermint-testgen = { path = "../testgen", default-features = false } diff --git a/light-client-verifier/src/host_functions.rs b/light-client-verifier/src/host_functions.rs index 16511f93f..8fdee922c 100644 --- a/light-client-verifier/src/host_functions.rs +++ b/light-client-verifier/src/host_functions.rs @@ -7,7 +7,7 @@ pub trait CryptoProvider { type Sha256: Digest + FixedOutput; // type EcdsaSecp256k1Signer: Signer; - // type EcdsaSecp256k1Verifier: Verifier; + type EcdsaSecp256k1Verifier: Verifier; // type Ed25519Signer: Signer; // type Ed25519Verifier: Verifier; @@ -16,55 +16,95 @@ pub trait CryptoProvider { #[cfg(test)] mod tests { + use core::marker::PhantomData; + + use signature::DigestVerifier; + use super::*; struct SubstrateHostFunctionsManager; + #[derive(Debug, Default)] + struct SubstrateSha256(sha2::Sha256); + #[derive(Debug)] + struct SubstrateSignatureVerifier { + inner: k256::ecdsa::VerifyingKey, + _d: PhantomData, + } + + impl SubstrateSignatureVerifier { + fn from_bytes(public_key: &[u8]) -> Result { + Ok(Self { + inner: k256::ecdsa::VerifyingKey::from_sec1_bytes(public_key)?, + _d: PhantomData::default(), + }) + } + } + + impl DigestVerifier for SubstrateSignatureVerifier { + fn verify_digest(&self, digest: D, signature: &S) -> Result<(), ed25519::Error> { + self.inner.verify_digest(digest, signature) + } + } + + impl tendermint::signature::Verifier + for SubstrateSignatureVerifier + { + fn verify(&self, msg: &[u8], signature: &S) -> Result<(), ed25519::Error> { + let mut hasher = D::new(); + hasher.update(msg); + self.verify_digest(hasher, signature) + } + } + + impl digest::OutputSizeUser for SubstrateSha256 { + type OutputSize = U32; + } + + impl digest::HashMarker for SubstrateSha256 {} + + impl digest::Update for SubstrateSha256 { + fn update(&mut self, data: &[u8]) { + use sha2::Digest; + self.0.update(data); + } + } + + impl digest::FixedOutput for SubstrateSha256 { + fn finalize_into(self, out: &mut digest::Output) { + use sha2::Digest; + self.0.finalize(); + } + } + trait SubstrateHostFunctions: CryptoProvider { fn sha2_256(preimage: &[u8]) -> [u8; 32]; fn ed25519_verify(sig: &[u8], msg: &[u8], pub_key: &[u8]) -> Result<(), ()>; fn secp256k1_verify(sig: &[u8], message: &[u8], public: &[u8]) -> Result<(), ()>; } - impl SubstrateHostFunctionsManager for SubstrateHostFunctions { - type Sha256 = sha2::Sha256; + impl CryptoProvider for SubstrateHostFunctionsManager { + type Sha256 = SubstrateSha256; + + type EcdsaSecp256k1Verifier = SubstrateSignatureVerifier; + } + impl SubstrateHostFunctions for SubstrateHostFunctionsManager { fn sha2_256(preimage: &[u8]) -> [u8; 32] { - unimplemented!() + let mut hasher = Self::Sha256::new(); + hasher.update(preimage); + let result = hasher.finalize().try_into().unwrap(); + result } fn ed25519_verify(sig: &[u8], msg: &[u8], pub_key: &[u8]) -> Result<(), ()> { unimplemented!() } fn secp256k1_verify(sig: &[u8], message: &[u8], public: &[u8]) -> Result<(), ()> { - unimplemented!() + // Self::secp256k1_verify(sig, message, public) + let verifier = + <::EcdsaSecp256k1Verifier>::from_bytes(public).unwrap(); + // TODO: probably should name the verifier properly - not sure how to do it better + let signature = k256::ecdsa::Signature::from_der(sig).unwrap(); + Ok(verifier.verify(message, &signature).unwrap()) } } - - // impl CryptoProvider for CryptoManager { - // fn sha2_256(preimage: &[u8]) -> [u8; 32] { - // sp_core::hashing::sha2_256(preimage) - // } - - // fn ed25519_verify(sig: &[u8], msg: &[u8], pub_key: &[u8]) -> Result<(), ()> { - // use sp_core::{ed25519, ByteArray, Pair}; - - // let signature = ed25519::Signature::from_slice(sig).ok_or(())?; - - // let public_key = ed25519::Public::from_slice(pub_key).map_err(|_| ())?; - // if ed25519::Pair::verify(&signature, msg, &public_key) { - // return Ok(()); - // } - // Err(()) - // } - - // fn secp256k1_verify(sig: &[u8], message: &[u8], public: &[u8]) -> Result<(), ()> { - // use sp_core::{ecdsa, ByteArray, Pair}; - - // let public = ecdsa::Public::from_slice(public).map_err(|_| ())?; - // if ecdsa::Pair::verify_weak(&sig, message, &public) { - // return Ok(()); - // } - - // Err(()) - // } - // } } From 0b44449b50b082e13ee22c01a2534344bcc768fe Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Wed, 19 Oct 2022 13:15:30 +0200 Subject: [PATCH 04/12] comment issues --- light-client-verifier/src/host_functions.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/light-client-verifier/src/host_functions.rs b/light-client-verifier/src/host_functions.rs index 8fdee922c..f98f94e67 100644 --- a/light-client-verifier/src/host_functions.rs +++ b/light-client-verifier/src/host_functions.rs @@ -42,6 +42,16 @@ mod tests { impl DigestVerifier for SubstrateSignatureVerifier { fn verify_digest(&self, digest: D, signature: &S) -> Result<(), ed25519::Error> { + // TODO; having issues here + /* + error[E0277]: the trait bound `VerifyingKey: DigestVerifier` is not satisfied + --> light-client-verifier/src/host_functions.rs:46:38 + | + 46 | self.inner.verify_digest(digest, signature) + | ------------- ^^^^^^ the trait `DigestVerifier` is not implemented for `VerifyingKey` + | | + | required by a bound introduced by this call + */ self.inner.verify_digest(digest, signature) } } @@ -102,7 +112,6 @@ mod tests { // Self::secp256k1_verify(sig, message, public) let verifier = <::EcdsaSecp256k1Verifier>::from_bytes(public).unwrap(); - // TODO: probably should name the verifier properly - not sure how to do it better let signature = k256::ecdsa::Signature::from_der(sig).unwrap(); Ok(verifier.verify(message, &signature).unwrap()) } From 72133d3e8da98f6bf865380b4f02356e8d07fb90 Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Wed, 19 Oct 2022 14:40:24 +0200 Subject: [PATCH 05/12] ed25519_verify implementation for SubstrateHostFunctionsManager --- light-client-verifier/src/host_functions.rs | 42 ++++++++++----------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/light-client-verifier/src/host_functions.rs b/light-client-verifier/src/host_functions.rs index f98f94e67..3d1faa081 100644 --- a/light-client-verifier/src/host_functions.rs +++ b/light-client-verifier/src/host_functions.rs @@ -1,6 +1,5 @@ use digest::FixedOutput; use digest::{consts::U32, Digest}; -use tendermint::signature::Signer; use tendermint::signature::Verifier; pub trait CryptoProvider { @@ -22,6 +21,7 @@ mod tests { use super::*; struct SubstrateHostFunctionsManager; + use k256::ecdsa::VerifyingKey; #[derive(Debug, Default)] struct SubstrateSha256(sha2::Sha256); @@ -31,7 +31,7 @@ mod tests { _d: PhantomData, } - impl SubstrateSignatureVerifier { + impl> SubstrateSignatureVerifier { fn from_bytes(public_key: &[u8]) -> Result { Ok(Self { inner: k256::ecdsa::VerifyingKey::from_sec1_bytes(public_key)?, @@ -40,28 +40,24 @@ mod tests { } } - impl DigestVerifier for SubstrateSignatureVerifier { + impl, S: signature::Signature> DigestVerifier + for SubstrateSignatureVerifier + where + VerifyingKey: DigestVerifier, + { fn verify_digest(&self, digest: D, signature: &S) -> Result<(), ed25519::Error> { - // TODO; having issues here - /* - error[E0277]: the trait bound `VerifyingKey: DigestVerifier` is not satisfied - --> light-client-verifier/src/host_functions.rs:46:38 - | - 46 | self.inner.verify_digest(digest, signature) - | ------------- ^^^^^^ the trait `DigestVerifier` is not implemented for `VerifyingKey` - | | - | required by a bound introduced by this call - */ self.inner.verify_digest(digest, signature) } } - impl tendermint::signature::Verifier - for SubstrateSignatureVerifier + impl> + tendermint::signature::Verifier for SubstrateSignatureVerifier + where + VerifyingKey: DigestVerifier, { fn verify(&self, msg: &[u8], signature: &S) -> Result<(), ed25519::Error> { let mut hasher = D::new(); - hasher.update(msg); + Digest::update(&mut hasher, msg); self.verify_digest(hasher, signature) } } @@ -82,7 +78,7 @@ mod tests { impl digest::FixedOutput for SubstrateSha256 { fn finalize_into(self, out: &mut digest::Output) { use sha2::Digest; - self.0.finalize(); + *out = self.0.finalize(); } } @@ -106,14 +102,14 @@ mod tests { result } fn ed25519_verify(sig: &[u8], msg: &[u8], pub_key: &[u8]) -> Result<(), ()> { - unimplemented!() - } - fn secp256k1_verify(sig: &[u8], message: &[u8], public: &[u8]) -> Result<(), ()> { - // Self::secp256k1_verify(sig, message, public) let verifier = - <::EcdsaSecp256k1Verifier>::from_bytes(public).unwrap(); + <::EcdsaSecp256k1Verifier>::from_bytes(pub_key).unwrap(); let signature = k256::ecdsa::Signature::from_der(sig).unwrap(); - Ok(verifier.verify(message, &signature).unwrap()) + Ok(verifier.verify(msg, &signature).unwrap()) + } + + fn secp256k1_verify(sig: &[u8], message: &[u8], public: &[u8]) -> Result<(), ()> { + unimplemented!() } } } From 88e9ff3dee49dde12d2aba75926cb0d917e1259b Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Wed, 19 Oct 2022 14:57:14 +0200 Subject: [PATCH 06/12] introduce EcdsaSecp256k1Signer --- light-client-verifier/src/host_functions.rs | 24 ++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/light-client-verifier/src/host_functions.rs b/light-client-verifier/src/host_functions.rs index 3d1faa081..59ad859a2 100644 --- a/light-client-verifier/src/host_functions.rs +++ b/light-client-verifier/src/host_functions.rs @@ -1,11 +1,12 @@ use digest::FixedOutput; use digest::{consts::U32, Digest}; +use signature::Signer; use tendermint::signature::Verifier; pub trait CryptoProvider { type Sha256: Digest + FixedOutput; - // type EcdsaSecp256k1Signer: Signer; + type EcdsaSecp256k1Signer: Signer; type EcdsaSecp256k1Verifier: Verifier; // type Ed25519Signer: Signer; @@ -17,14 +18,19 @@ mod tests { use core::marker::PhantomData; - use signature::DigestVerifier; + use signature::{DigestSigner, DigestVerifier}; use super::*; struct SubstrateHostFunctionsManager; - use k256::ecdsa::VerifyingKey; + use k256::ecdsa::{SigningKey, VerifyingKey}; #[derive(Debug, Default)] struct SubstrateSha256(sha2::Sha256); + + struct SubstrateSigner { + inner: k256::ecdsa::SigningKey, + _d: PhantomData, + } #[derive(Debug)] struct SubstrateSignatureVerifier { inner: k256::ecdsa::VerifyingKey, @@ -82,6 +88,17 @@ mod tests { } } + impl Signer for SubstrateSigner + where + SigningKey: DigestSigner, + { + fn try_sign(&self, msg: &[u8]) -> Result { + let mut hasher = D::new(); + Digest::update(&mut hasher, msg); + self.inner.try_sign_digest(hasher) + } + } + trait SubstrateHostFunctions: CryptoProvider { fn sha2_256(preimage: &[u8]) -> [u8; 32]; fn ed25519_verify(sig: &[u8], msg: &[u8], pub_key: &[u8]) -> Result<(), ()>; @@ -91,6 +108,7 @@ mod tests { impl CryptoProvider for SubstrateHostFunctionsManager { type Sha256 = SubstrateSha256; + type EcdsaSecp256k1Signer = SubstrateSigner; type EcdsaSecp256k1Verifier = SubstrateSignatureVerifier; } From a325f63b2432d5ab0e6d7a8c9f9b61e87cc62c2b Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Wed, 19 Oct 2022 14:59:54 +0200 Subject: [PATCH 07/12] doc a bit --- light-client-verifier/src/host_functions.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/light-client-verifier/src/host_functions.rs b/light-client-verifier/src/host_functions.rs index 59ad859a2..8298133a4 100644 --- a/light-client-verifier/src/host_functions.rs +++ b/light-client-verifier/src/host_functions.rs @@ -16,8 +16,9 @@ pub trait CryptoProvider { #[cfg(test)] mod tests { + /// A draft for an imlpementation of the HostFunctionManager for a specific chain (i.e. Polkadot/Substrate) + /// that uses the [`CryptoProvider`] trait use core::marker::PhantomData; - use signature::{DigestSigner, DigestVerifier}; use super::*; From 100fc53bb64fa706afde750029412e681dbffaa5 Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Thu, 20 Oct 2022 02:23:09 +0200 Subject: [PATCH 08/12] move CryptoProvider to tendermint crate instead --- light-client-verifier/Cargo.toml | 8 +------- light-client-verifier/src/lib.rs | 1 - tendermint/Cargo.toml | 5 +++-- .../src/host_functions.rs | 16 ++++++++-------- tendermint/src/lib.rs | 1 + 5 files changed, 13 insertions(+), 18 deletions(-) rename {light-client-verifier => tendermint}/src/host_functions.rs (90%) diff --git a/light-client-verifier/Cargo.toml b/light-client-verifier/Cargo.toml index 763130342..5fecf156e 100644 --- a/light-client-verifier/Cargo.toml +++ b/light-client-verifier/Cargo.toml @@ -33,12 +33,6 @@ serde = { version = "1.0.106", default-features = false } time = { version = "0.3", default-features = false } flex-error = { version = "0.4.4", default-features = false } -k256 = { version = "0.11", default-features = false, features = ["ecdsa", "sha256"] } -digest = { version = "0.10", default-features = false } -ed25519 = { version = "1.3", default-features = false } -signature = { version = "1", default-features = false } - [dev-dependencies] tendermint-testgen = { path = "../testgen", default-features = false } -sha2 = { version = "0.9", default-features = false } - +sha2 = { version = "0.9", default-features = false } \ No newline at end of file diff --git a/light-client-verifier/src/lib.rs b/light-client-verifier/src/lib.rs index 499c2f82e..ce413cefd 100644 --- a/light-client-verifier/src/lib.rs +++ b/light-client-verifier/src/lib.rs @@ -5,7 +5,6 @@ extern crate alloc; mod prelude; pub mod errors; -pub mod host_functions; pub mod operations; pub mod options; pub mod predicates; diff --git a/tendermint/Cargo.toml b/tendermint/Cargo.toml index 642a1a4a2..2c295877d 100644 --- a/tendermint/Cargo.toml +++ b/tendermint/Cargo.toml @@ -32,6 +32,7 @@ rustdoc-args = ["--cfg", "docsrs"] [dependencies] async-trait = { version = "0.1", default-features = false } bytes = { version = "1.0", default-features = false, features = ["serde"] } +digest = { version = "0.10", default-features = false } ed25519 = { version = "1.3", default-features = false } ed25519-dalek = { version = "1", default-features = false, features = ["u64_backend"] } futures = { version = "0.3", default-features = false } @@ -51,14 +52,14 @@ tendermint-proto = { version = "0.25.0", default-features = false, path = "../pr time = { version = "0.3", default-features = false, features = ["macros", "parsing"] } zeroize = { version = "1.1", default-features = false, features = ["zeroize_derive", "alloc"] } flex-error = { version = "0.4.4", default-features = false } -k256 = { version = "0.11", optional = true, default-features = false, features = ["ecdsa", "sha256"] } +k256 = { version = "0.11", default-features = false, features = ["ecdsa", "sha256"] } ripemd160 = { version = "0.9", default-features = false, optional = true } [features] default = ["std"] std = ["flex-error/std", "flex-error/eyre_tracer", "clock"] clock = ["time/std"] -secp256k1 = ["k256", "ripemd160"] +secp256k1 = ["ripemd160"] [dev-dependencies] pretty_assertions = "1.3.0" diff --git a/light-client-verifier/src/host_functions.rs b/tendermint/src/host_functions.rs similarity index 90% rename from light-client-verifier/src/host_functions.rs rename to tendermint/src/host_functions.rs index 8298133a4..61ddcbc6b 100644 --- a/light-client-verifier/src/host_functions.rs +++ b/tendermint/src/host_functions.rs @@ -1,7 +1,7 @@ +use crate::signature::Verifier; use digest::FixedOutput; use digest::{consts::U32, Digest}; use signature::Signer; -use tendermint::signature::Verifier; pub trait CryptoProvider { type Sha256: Digest + FixedOutput; @@ -29,19 +29,19 @@ mod tests { struct SubstrateSha256(sha2::Sha256); struct SubstrateSigner { - inner: k256::ecdsa::SigningKey, + inner: SigningKey, _d: PhantomData, } #[derive(Debug)] struct SubstrateSignatureVerifier { - inner: k256::ecdsa::VerifyingKey, + inner: VerifyingKey, _d: PhantomData, } impl> SubstrateSignatureVerifier { fn from_bytes(public_key: &[u8]) -> Result { Ok(Self { - inner: k256::ecdsa::VerifyingKey::from_sec1_bytes(public_key)?, + inner: VerifyingKey::from_sec1_bytes(public_key)?, _d: PhantomData::default(), }) } @@ -57,8 +57,8 @@ mod tests { } } - impl> - tendermint::signature::Verifier for SubstrateSignatureVerifier + impl> Verifier + for SubstrateSignatureVerifier where VerifyingKey: DigestVerifier, { @@ -82,7 +82,7 @@ mod tests { } } - impl digest::FixedOutput for SubstrateSha256 { + impl FixedOutput for SubstrateSha256 { fn finalize_into(self, out: &mut digest::Output) { use sha2::Digest; *out = self.0.finalize(); @@ -127,7 +127,7 @@ mod tests { Ok(verifier.verify(msg, &signature).unwrap()) } - fn secp256k1_verify(sig: &[u8], message: &[u8], public: &[u8]) -> Result<(), ()> { + fn secp256k1_verify(_sig: &[u8], _message: &[u8], _public: &[u8]) -> Result<(), ()> { unimplemented!() } } diff --git a/tendermint/src/lib.rs b/tendermint/src/lib.rs index f57f0ac56..161e0c86f 100644 --- a/tendermint/src/lib.rs +++ b/tendermint/src/lib.rs @@ -36,6 +36,7 @@ pub mod consensus; pub mod evidence; pub mod genesis; pub mod hash; +pub mod host_functions; pub mod merkle; mod moniker; pub mod node; From 8048e4de023cef94b59f3d526e24d612a88dd27b Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Mon, 31 Oct 2022 17:22:53 +0100 Subject: [PATCH 09/12] rename host_functions module to crypto --- tendermint/src/{host_functions.rs => crypto.rs} | 0 tendermint/src/lib.rs | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename tendermint/src/{host_functions.rs => crypto.rs} (100%) diff --git a/tendermint/src/host_functions.rs b/tendermint/src/crypto.rs similarity index 100% rename from tendermint/src/host_functions.rs rename to tendermint/src/crypto.rs diff --git a/tendermint/src/lib.rs b/tendermint/src/lib.rs index 161e0c86f..32c26d2f5 100644 --- a/tendermint/src/lib.rs +++ b/tendermint/src/lib.rs @@ -33,10 +33,10 @@ pub mod block; pub mod chain; pub mod channel; pub mod consensus; +pub mod crypto; pub mod evidence; pub mod genesis; pub mod hash; -pub mod host_functions; pub mod merkle; mod moniker; pub mod node; From 63a2d0e1bfffe1d68643628eda6c75eb99fcc9bc Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Wed, 9 Nov 2022 23:56:17 +0100 Subject: [PATCH 10/12] re implement ProdCommitValidator --- .../src/operations/commit_validator.rs | 79 ++++---- light-client-verifier/src/predicates.rs | 23 ++- light-client-verifier/src/verifier.rs | 42 ++-- light-client/src/builder/light_client.rs | 6 +- tendermint/src/crypto.rs | 185 +++++++++--------- 5 files changed, 176 insertions(+), 159 deletions(-) diff --git a/light-client-verifier/src/operations/commit_validator.rs b/light-client-verifier/src/operations/commit_validator.rs index db2f13882..8005c7520 100644 --- a/light-client-verifier/src/operations/commit_validator.rs +++ b/light-client-verifier/src/operations/commit_validator.rs @@ -1,5 +1,7 @@ //! Provides an interface and default implementation for the `CommitValidator` operation +use core::marker::PhantomData; + use tendermint::block::CommitSig; use crate::{ @@ -8,45 +10,14 @@ use crate::{ types::{SignedHeader, ValidatorSet}, }; -/// Validates the commit associated with a header against a validator set -pub trait CommitValidator: Send + Sync { - /// Perform basic validation - fn validate( - &self, - signed_header: &SignedHeader, - validators: &ValidatorSet, - ) -> Result<(), VerificationError>; - - /// Perform full validation, only necessary if we do full verification (2/3) - fn validate_full( - &self, - signed_header: &SignedHeader, - validator_set: &ValidatorSet, - ) -> Result<(), VerificationError>; -} - -/// Production-ready implementation of a commit validator #[derive(Debug, Clone, PartialEq, Eq)] -pub struct ProdCommitValidator { +pub struct CommitValidator { hasher: ProdHasher, + _c: PhantomData, } -impl ProdCommitValidator { - /// Create a new commit validator using the given [`Hasher`] - /// to compute the hash of headers and validator sets. - pub fn new(hasher: ProdHasher) -> Self { - Self { hasher } - } -} - -impl Default for ProdCommitValidator { - fn default() -> Self { - Self::new(ProdHasher::default()) - } -} - -impl CommitValidator for ProdCommitValidator { - fn validate( +impl CommitValidator { + pub fn validate( &self, signed_header: &SignedHeader, validator_set: &ValidatorSet, @@ -77,7 +48,7 @@ impl CommitValidator for ProdCommitValidator { // // It returns `ImplementationSpecific` error if it detects a signer // that is not present in the validator set - fn validate_full( + pub fn validate_full( &self, signed_header: &SignedHeader, validator_set: &ValidatorSet, @@ -104,3 +75,39 @@ impl CommitValidator for ProdCommitValidator { Ok(()) } } + +/// The batteries-included validator, for when you don't mind the dependencies on +/// the full rust-crypto stack. +#[cfg(feature = "rust-crypto")] +pub type ProdCommitValidator = CommitValidator; + +#[cfg(not(feature = "rust-crypto"))] +/// Production-ready implementation of a commit validator +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ProdCommitValidator { + inner: CommitValidator, +} + +impl AsRef> for ProdCommitValidator { + fn as_ref(&self) -> &CommitValidator { + &self.inner + } +} +impl ProdCommitValidator { + /// Create a new commit validator using the given [`Hasher`] + /// to compute the hash of headers and validator sets. + pub fn new(hasher: ProdHasher) -> Self { + Self { + inner: CommitValidator { + hasher, + _c: PhantomData::default(), + }, + } + } +} + +impl Default for ProdCommitValidator { + fn default() -> Self { + Self::new(ProdHasher::default()) + } +} diff --git a/light-client-verifier/src/predicates.rs b/light-client-verifier/src/predicates.rs index 0c8787d4f..9e6a3e420 100644 --- a/light-client-verifier/src/predicates.rs +++ b/light-client-verifier/src/predicates.rs @@ -2,7 +2,11 @@ use core::time::Duration; -use tendermint::{block::Height, hash::Hash}; +use tendermint::{ + block::Height, + crypto::{CryptoProvider, DefaultHostFunctionsManager}, + hash::Hash, +}; use crate::{ errors::VerificationError, @@ -15,7 +19,9 @@ use crate::{ /// of the `VerificationPredicates` trait. #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] pub struct ProdPredicates; -impl VerificationPredicates for ProdPredicates {} +impl VerificationPredicates for ProdPredicates { + type CryptoProvider = DefaultHostFunctionsManager; +} /// Defines the various predicates used to validate and verify light blocks. /// @@ -24,6 +30,7 @@ impl VerificationPredicates for ProdPredicates {} /// This enables test implementations to only override a single method rather than /// have to re-define every predicate. pub trait VerificationPredicates: Send + Sync { + type CryptoProvider: CryptoProvider; /// Compare the provided validator_set_hash against the hash produced from hashing the validator /// set. fn validator_sets_match( @@ -84,7 +91,7 @@ pub trait VerificationPredicates: Send + Sync { &self, signed_header: &SignedHeader, validators: &ValidatorSet, - commit_validator: &dyn CommitValidator, + commit_validator: &CommitValidator, ) -> Result<(), VerificationError> { commit_validator.validate(signed_header, validators)?; commit_validator.validate_full(signed_header, validators)?; @@ -471,7 +478,7 @@ mod tests { // Test scenarios --> // 1. valid commit - must result "Ok" - let mut result_ok = vp.valid_commit(&signed_header, &val_set, &commit_validator); + let mut result_ok = vp.valid_commit(&signed_header, &val_set, commit_validator.as_ref()); assert!(result_ok.is_ok()); @@ -479,7 +486,7 @@ mod tests { let signatures = signed_header.commit.signatures.clone(); signed_header.commit.signatures = vec![]; - let mut result_err = vp.valid_commit(&signed_header, &val_set, &commit_validator); + let mut result_err = vp.valid_commit(&signed_header, &val_set, commit_validator.as_ref()); match result_err { Err(VerificationError(VerificationErrorDetail::NoSignatureForCommit(_), _)) => {}, @@ -491,7 +498,7 @@ mod tests { let mut bad_sigs = vec![signatures.clone().swap_remove(1)]; signed_header.commit.signatures = bad_sigs.clone(); - result_err = vp.valid_commit(&signed_header, &val_set, &commit_validator); + result_err = vp.valid_commit(&signed_header, &val_set, commit_validator.as_ref()); match result_err { Err(VerificationError(VerificationErrorDetail::MismatchPreCommitLength(e), _)) => { @@ -504,7 +511,7 @@ mod tests { // 4. commit.BlockIdFlagAbsent - should be "Ok" bad_sigs.push(CommitSig::BlockIdFlagAbsent); signed_header.commit.signatures = bad_sigs; - result_ok = vp.valid_commit(&signed_header, &val_set, &commit_validator); + result_ok = vp.valid_commit(&signed_header, &val_set, commit_validator.as_ref()); assert!(result_ok.is_ok()); // 5. faulty signer - must return error @@ -523,7 +530,7 @@ mod tests { result_err = vp.valid_commit( &signed_header, &val_set_with_faulty_signer, - &commit_validator, + commit_validator.as_ref(), ); match result_err { diff --git a/light-client-verifier/src/verifier.rs b/light-client-verifier/src/verifier.rs index 8525cf666..0379f48ac 100644 --- a/light-client-verifier/src/verifier.rs +++ b/light-client-verifier/src/verifier.rs @@ -2,11 +2,12 @@ use preds::{ProdPredicates, VerificationPredicates}; use serde::{Deserialize, Serialize}; +use tendermint::crypto::{CryptoProvider, DefaultHostFunctionsManager}; use crate::{ errors::{ErrorExt, VerificationError, VerificationErrorDetail}, operations::{ - voting_power::VotingPowerTally, CommitValidator, Hasher, ProdCommitValidator, ProdHasher, + voting_power::VotingPowerTally, Hasher, ProdCommitValidator, ProdHasher, ProdVotingPowerCalculator, VotingPowerCalculator, }, options::Options, @@ -71,54 +72,59 @@ macro_rules! verdict { /// Predicate verifier encapsulating components necessary to facilitate /// verification. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct PredicateVerifier { +pub struct PredicateVerifier { predicates: P, voting_power_calculator: C, - commit_validator: V, + commit_validator: ProdCommitValidator, hasher: H, } -impl Default for PredicateVerifier +impl Default for PredicateVerifier where P: Default, C: Default, - V: Default, H: Default, + CP: CryptoProvider, { fn default() -> Self { Self { predicates: P::default(), voting_power_calculator: C::default(), - commit_validator: V::default(), + commit_validator: ProdCommitValidator::default(), hasher: H::default(), } } } -impl PredicateVerifier +impl PredicateVerifier where P: VerificationPredicates, C: VotingPowerCalculator, - V: CommitValidator, H: Hasher, + CP: CryptoProvider, { /// Constructor. - pub fn new(predicates: P, voting_power_calculator: C, commit_validator: V, hasher: H) -> Self { + pub fn new( + predicates: P, + voting_power_calculator: C, + commit_validator: ProdCommitValidator, + hasher: H, + ) -> Self { Self { predicates, voting_power_calculator, - commit_validator, hasher, + commit_validator, } } } -impl Verifier for PredicateVerifier +impl Verifier for PredicateVerifier where - P: VerificationPredicates, + P: VerificationPredicates + VerificationPredicates, C: VotingPowerCalculator, - V: CommitValidator, H: Hasher, + CP: CryptoProvider + Sync + Send, { /// Validate the given light block state. /// @@ -183,7 +189,7 @@ where verdict!(self.predicates.valid_commit( untrusted.signed_header, untrusted.validators, - &self.commit_validator, + self.commit_validator.as_ref(), )); // Check that the untrusted block is more recent than the trusted state @@ -229,5 +235,9 @@ where } /// The default production implementation of the [`PredicateVerifier`]. -pub type ProdVerifier = - PredicateVerifier; +pub type ProdVerifier = PredicateVerifier< + ProdPredicates, + ProdVotingPowerCalculator, + ProdHasher, + DefaultHostFunctionsManager, +>; diff --git a/light-client/src/builder/light_client.rs b/light-client/src/builder/light_client.rs index a428a5a2b..a571bcfb0 100644 --- a/light-client/src/builder/light_client.rs +++ b/light-client/src/builder/light_client.rs @@ -1,6 +1,6 @@ //! DSL for building a light client [`Instance`] -use tendermint::{block::Height, Hash}; +use tendermint::{block::Height, crypto::DefaultHostFunctionsManager, Hash}; #[cfg(feature = "rpc-client")] use { crate::components::clock::SystemClock, @@ -47,7 +47,7 @@ pub struct LightClientBuilder { hasher: Box, verifier: Box, scheduler: Box, - predicates: Box, + predicates: Box>, light_store: Box, #[allow(dead_code)] @@ -106,7 +106,7 @@ impl LightClientBuilder { clock: Box, verifier: Box, scheduler: Box, - predicates: Box, + predicates: Box>, ) -> Self { Self { peer_id, diff --git a/tendermint/src/crypto.rs b/tendermint/src/crypto.rs index 61ddcbc6b..07bfcca5b 100644 --- a/tendermint/src/crypto.rs +++ b/tendermint/src/crypto.rs @@ -1,7 +1,7 @@ use crate::signature::Verifier; use digest::FixedOutput; use digest::{consts::U32, Digest}; -use signature::Signer; +use signature::{DigestSigner, DigestVerifier, Signer}; pub trait CryptoProvider { type Sha256: Digest + FixedOutput; @@ -13,122 +13,115 @@ pub trait CryptoProvider { // type Ed25519Verifier: Verifier; } -#[cfg(test)] -mod tests { +/// A default implementation of the HostFunctionManager that uses the [`CryptoProvider`] trait +use core::marker::PhantomData; - /// A draft for an imlpementation of the HostFunctionManager for a specific chain (i.e. Polkadot/Substrate) - /// that uses the [`CryptoProvider`] trait - use core::marker::PhantomData; - use signature::{DigestSigner, DigestVerifier}; +pub struct DefaultHostFunctionsManager; +use k256::ecdsa::{SigningKey, VerifyingKey}; - use super::*; - struct SubstrateHostFunctionsManager; - use k256::ecdsa::{SigningKey, VerifyingKey}; +#[derive(Debug, Default)] +pub struct DefaultSha256(sha2::Sha256); - #[derive(Debug, Default)] - struct SubstrateSha256(sha2::Sha256); - - struct SubstrateSigner { - inner: SigningKey, - _d: PhantomData, - } - #[derive(Debug)] - struct SubstrateSignatureVerifier { - inner: VerifyingKey, - _d: PhantomData, - } +pub struct DefaultSigner { + inner: SigningKey, + _d: PhantomData, +} +#[derive(Debug)] +pub struct DefaultSignatureVerifier { + inner: VerifyingKey, + _d: PhantomData, +} - impl> SubstrateSignatureVerifier { - fn from_bytes(public_key: &[u8]) -> Result { - Ok(Self { - inner: VerifyingKey::from_sec1_bytes(public_key)?, - _d: PhantomData::default(), - }) - } +impl> DefaultSignatureVerifier { + fn from_bytes(public_key: &[u8]) -> Result { + Ok(Self { + inner: VerifyingKey::from_sec1_bytes(public_key)?, + _d: PhantomData::default(), + }) } +} - impl, S: signature::Signature> DigestVerifier - for SubstrateSignatureVerifier - where - VerifyingKey: DigestVerifier, - { - fn verify_digest(&self, digest: D, signature: &S) -> Result<(), ed25519::Error> { - self.inner.verify_digest(digest, signature) - } +impl, S: signature::Signature> DigestVerifier + for DefaultSignatureVerifier +where + VerifyingKey: DigestVerifier, +{ + fn verify_digest(&self, digest: D, signature: &S) -> Result<(), ed25519::Error> { + self.inner.verify_digest(digest, signature) } +} - impl> Verifier - for SubstrateSignatureVerifier - where - VerifyingKey: DigestVerifier, - { - fn verify(&self, msg: &[u8], signature: &S) -> Result<(), ed25519::Error> { - let mut hasher = D::new(); - Digest::update(&mut hasher, msg); - self.verify_digest(hasher, signature) - } +impl> Verifier + for DefaultSignatureVerifier +where + VerifyingKey: DigestVerifier, +{ + fn verify(&self, msg: &[u8], signature: &S) -> Result<(), ed25519::Error> { + let mut hasher = D::new(); + Digest::update(&mut hasher, msg); + self.verify_digest(hasher, signature) } +} - impl digest::OutputSizeUser for SubstrateSha256 { - type OutputSize = U32; - } +impl digest::OutputSizeUser for DefaultSha256 { + type OutputSize = U32; +} - impl digest::HashMarker for SubstrateSha256 {} +impl digest::HashMarker for DefaultSha256 {} - impl digest::Update for SubstrateSha256 { - fn update(&mut self, data: &[u8]) { - use sha2::Digest; - self.0.update(data); - } +impl digest::Update for DefaultSha256 { + fn update(&mut self, data: &[u8]) { + use sha2::Digest; + self.0.update(data); } +} - impl FixedOutput for SubstrateSha256 { - fn finalize_into(self, out: &mut digest::Output) { - use sha2::Digest; - *out = self.0.finalize(); - } +impl FixedOutput for DefaultSha256 { + fn finalize_into(self, out: &mut digest::Output) { + use sha2::Digest; + *out = self.0.finalize(); } +} - impl Signer for SubstrateSigner - where - SigningKey: DigestSigner, - { - fn try_sign(&self, msg: &[u8]) -> Result { - let mut hasher = D::new(); - Digest::update(&mut hasher, msg); - self.inner.try_sign_digest(hasher) - } +impl Signer for DefaultSigner +where + SigningKey: DigestSigner, +{ + fn try_sign(&self, msg: &[u8]) -> Result { + let mut hasher = D::new(); + Digest::update(&mut hasher, msg); + self.inner.try_sign_digest(hasher) } +} - trait SubstrateHostFunctions: CryptoProvider { - fn sha2_256(preimage: &[u8]) -> [u8; 32]; - fn ed25519_verify(sig: &[u8], msg: &[u8], pub_key: &[u8]) -> Result<(), ()>; - fn secp256k1_verify(sig: &[u8], message: &[u8], public: &[u8]) -> Result<(), ()>; - } +trait DefaultHostFunctions: CryptoProvider { + fn sha2_256(preimage: &[u8]) -> [u8; 32]; + fn ed25519_verify(sig: &[u8], msg: &[u8], pub_key: &[u8]) -> Result<(), ()>; + fn secp256k1_verify(sig: &[u8], message: &[u8], public: &[u8]) -> Result<(), ()>; +} - impl CryptoProvider for SubstrateHostFunctionsManager { - type Sha256 = SubstrateSha256; +impl CryptoProvider for DefaultHostFunctionsManager { + type Sha256 = DefaultSha256; + + type EcdsaSecp256k1Signer = DefaultSigner; + type EcdsaSecp256k1Verifier = DefaultSignatureVerifier; +} + +impl DefaultHostFunctions for DefaultHostFunctionsManager { + fn sha2_256(preimage: &[u8]) -> [u8; 32] { + let mut hasher = Self::Sha256::new(); + hasher.update(preimage); + hasher.finalize().try_into().unwrap() + } - type EcdsaSecp256k1Signer = SubstrateSigner; - type EcdsaSecp256k1Verifier = SubstrateSignatureVerifier; + fn ed25519_verify(sig: &[u8], msg: &[u8], pub_key: &[u8]) -> Result<(), ()> { + let verifier = + <::EcdsaSecp256k1Verifier>::from_bytes(pub_key).unwrap(); + let signature = k256::ecdsa::Signature::from_der(sig).unwrap(); + Ok(verifier.verify(msg, &signature).unwrap()) } - impl SubstrateHostFunctions for SubstrateHostFunctionsManager { - fn sha2_256(preimage: &[u8]) -> [u8; 32] { - let mut hasher = Self::Sha256::new(); - hasher.update(preimage); - let result = hasher.finalize().try_into().unwrap(); - result - } - fn ed25519_verify(sig: &[u8], msg: &[u8], pub_key: &[u8]) -> Result<(), ()> { - let verifier = - <::EcdsaSecp256k1Verifier>::from_bytes(pub_key).unwrap(); - let signature = k256::ecdsa::Signature::from_der(sig).unwrap(); - Ok(verifier.verify(msg, &signature).unwrap()) - } - - fn secp256k1_verify(_sig: &[u8], _message: &[u8], _public: &[u8]) -> Result<(), ()> { - unimplemented!() - } + fn secp256k1_verify(_sig: &[u8], _message: &[u8], _public: &[u8]) -> Result<(), ()> { + unimplemented!() } } From 3cce56fc956ef5880530a81d78509db48d4ddc51 Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Tue, 15 Nov 2022 17:32:24 +0100 Subject: [PATCH 11/12] re-define crypto provider --- tendermint/src/crypto.rs | 54 ++++++++-------------------------------- 1 file changed, 10 insertions(+), 44 deletions(-) diff --git a/tendermint/src/crypto.rs b/tendermint/src/crypto.rs index 07bfcca5b..51d5d67f3 100644 --- a/tendermint/src/crypto.rs +++ b/tendermint/src/crypto.rs @@ -1,16 +1,15 @@ +use digest::{consts::U32, Digest, FixedOutput}; +use signature::{DigestSigner, DigestVerifier, Signature, Signer}; + use crate::signature::Verifier; -use digest::FixedOutput; -use digest::{consts::U32, Digest}; -use signature::{DigestSigner, DigestVerifier, Signer}; pub trait CryptoProvider { - type Sha256: Digest + FixedOutput; + type S: Signature; - type EcdsaSecp256k1Signer: Signer; - type EcdsaSecp256k1Verifier: Verifier; + type Sha256: Digest + FixedOutput; - // type Ed25519Signer: Signer; - // type Ed25519Verifier: Verifier; + type EcdsaSecp256k1Signer: Signer; + type EcdsaSecp256k1Verifier: Verifier; } /// A default implementation of the HostFunctionManager that uses the [`CryptoProvider`] trait @@ -32,16 +31,7 @@ pub struct DefaultSignatureVerifier { _d: PhantomData, } -impl> DefaultSignatureVerifier { - fn from_bytes(public_key: &[u8]) -> Result { - Ok(Self { - inner: VerifyingKey::from_sec1_bytes(public_key)?, - _d: PhantomData::default(), - }) - } -} - -impl, S: signature::Signature> DigestVerifier +impl, S: Signature> DigestVerifier for DefaultSignatureVerifier where VerifyingKey: DigestVerifier, @@ -83,7 +73,7 @@ impl FixedOutput for DefaultSha256 { } } -impl Signer for DefaultSigner +impl Signer for DefaultSigner where SigningKey: DigestSigner, { @@ -94,34 +84,10 @@ where } } -trait DefaultHostFunctions: CryptoProvider { - fn sha2_256(preimage: &[u8]) -> [u8; 32]; - fn ed25519_verify(sig: &[u8], msg: &[u8], pub_key: &[u8]) -> Result<(), ()>; - fn secp256k1_verify(sig: &[u8], message: &[u8], public: &[u8]) -> Result<(), ()>; -} - impl CryptoProvider for DefaultHostFunctionsManager { + type S = k256::ecdsa::Signature; type Sha256 = DefaultSha256; type EcdsaSecp256k1Signer = DefaultSigner; type EcdsaSecp256k1Verifier = DefaultSignatureVerifier; } - -impl DefaultHostFunctions for DefaultHostFunctionsManager { - fn sha2_256(preimage: &[u8]) -> [u8; 32] { - let mut hasher = Self::Sha256::new(); - hasher.update(preimage); - hasher.finalize().try_into().unwrap() - } - - fn ed25519_verify(sig: &[u8], msg: &[u8], pub_key: &[u8]) -> Result<(), ()> { - let verifier = - <::EcdsaSecp256k1Verifier>::from_bytes(pub_key).unwrap(); - let signature = k256::ecdsa::Signature::from_der(sig).unwrap(); - Ok(verifier.verify(msg, &signature).unwrap()) - } - - fn secp256k1_verify(_sig: &[u8], _message: &[u8], _public: &[u8]) -> Result<(), ()> { - unimplemented!() - } -} From 0cafbb9a8b6cb0aca1cf9deaf1e5ce78e2a93f89 Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Tue, 15 Nov 2022 17:48:17 +0100 Subject: [PATCH 12/12] distinguish implementations based on feature flag --- light-client-verifier/Cargo.toml | 2 +- .../src/operations/commit_validator.rs | 34 ++++++++++- light-client-verifier/src/predicates.rs | 15 +++++ light-client-verifier/src/verifier.rs | 60 +++++++++++++++++++ tendermint/src/crypto.rs | 1 + 5 files changed, 110 insertions(+), 2 deletions(-) diff --git a/light-client-verifier/Cargo.toml b/light-client-verifier/Cargo.toml index 5e25c018c..1c53fdb02 100644 --- a/light-client-verifier/Cargo.toml +++ b/light-client-verifier/Cargo.toml @@ -24,7 +24,7 @@ rustdoc-args = ["--cfg", "docsrs"] [features] default = ["flex-error/std", "flex-error/eyre_tracer"] - +rust-crypto = [] [dependencies] tendermint = { version = "0.26.0", path = "../tendermint", default-features = false } diff --git a/light-client-verifier/src/operations/commit_validator.rs b/light-client-verifier/src/operations/commit_validator.rs index 62ba45a7b..23a876bd2 100644 --- a/light-client-verifier/src/operations/commit_validator.rs +++ b/light-client-verifier/src/operations/commit_validator.rs @@ -3,6 +3,8 @@ use core::marker::PhantomData; use tendermint::block::CommitSig; +#[cfg(feature = "rust-crypto")] +use tendermint::crypto::DefaultHostFunctionsManager; use crate::{ errors::VerificationError, @@ -79,7 +81,7 @@ impl CommitValidator { /// The batteries-included validator, for when you don't mind the dependencies on /// the full rust-crypto stack. #[cfg(feature = "rust-crypto")] -pub type ProdCommitValidator = CommitValidator; +pub type ProdCommitValidator = CommitValidator; #[cfg(not(feature = "rust-crypto"))] /// Production-ready implementation of a commit validator @@ -88,11 +90,21 @@ pub struct ProdCommitValidator { inner: CommitValidator, } +#[cfg(not(feature = "rust-crypto"))] impl AsRef> for ProdCommitValidator { fn as_ref(&self) -> &CommitValidator { &self.inner } } + +#[cfg(feature = "rust-crypto")] +impl AsRef> for ProdCommitValidator { + fn as_ref(&self) -> &CommitValidator { + self + } +} + +#[cfg(not(feature = "rust-crypto"))] impl ProdCommitValidator { /// Create a new commit validator using the given [`Hasher`] /// to compute the hash of headers and validator sets. @@ -106,8 +118,28 @@ impl ProdCommitValidator { } } +#[cfg(feature = "rust-crypto")] +impl ProdCommitValidator { + /// Create a new commit validator using the given [`Hasher`] + /// to compute the hash of headers and validator sets. + pub fn new(hasher: ProdHasher) -> Self { + CommitValidator { + hasher, + _c: PhantomData::default(), + } + } +} + +#[cfg(not(feature = "rust-crypto"))] impl Default for ProdCommitValidator { fn default() -> Self { Self::new(ProdHasher::default()) } } + +#[cfg(feature = "rust-crypto")] +impl Default for ProdCommitValidator { + fn default() -> Self { + Self::new(ProdHasher::default()) + } +} diff --git a/light-client-verifier/src/predicates.rs b/light-client-verifier/src/predicates.rs index 9e6a3e420..fc2511cc3 100644 --- a/light-client-verifier/src/predicates.rs +++ b/light-client-verifier/src/predicates.rs @@ -86,6 +86,7 @@ pub trait VerificationPredicates: Send + Sync { } } + #[cfg(not(feature = "rust-crypto"))] /// Validate the commit using the given commit validator. fn valid_commit( &self, @@ -99,6 +100,20 @@ pub trait VerificationPredicates: Send + Sync { Ok(()) } + #[cfg(feature = "rust-crypto")] + /// Validate the commit using the given commit validator. + fn valid_commit( + &self, + signed_header: &SignedHeader, + validators: &ValidatorSet, + commit_validator: &CommitValidator, + ) -> Result<(), VerificationError> { + commit_validator.validate(signed_header, validators)?; + commit_validator.validate_full(signed_header, validators)?; + + Ok(()) + } + /// Check that the trusted header is within the trusting period, adjusting for clock drift. fn is_within_trust_period( &self, diff --git a/light-client-verifier/src/verifier.rs b/light-client-verifier/src/verifier.rs index 0379f48ac..fb1469b66 100644 --- a/light-client-verifier/src/verifier.rs +++ b/light-client-verifier/src/verifier.rs @@ -1,5 +1,8 @@ //! Provides an interface and default implementation of the `Verifier` component +#[cfg(feature = "rust-crypto")] +use core::marker::PhantomData; + use preds::{ProdPredicates, VerificationPredicates}; use serde::{Deserialize, Serialize}; use tendermint::crypto::{CryptoProvider, DefaultHostFunctionsManager}; @@ -69,6 +72,7 @@ macro_rules! verdict { }; } +#[cfg(not(feature = "rust-crypto"))] /// Predicate verifier encapsulating components necessary to facilitate /// verification. #[derive(Debug, Clone, PartialEq, Eq)] @@ -78,7 +82,19 @@ pub struct PredicateVerifier { commit_validator: ProdCommitValidator, hasher: H, } +#[cfg(feature = "rust-crypto")] +/// Predicate verifier encapsulating components necessary to facilitate +/// verification. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct PredicateVerifier { + predicates: P, + voting_power_calculator: C, + commit_validator: ProdCommitValidator, + hasher: H, + _p: PhantomData, +} +#[cfg(not(feature = "rust-crypto"))] impl Default for PredicateVerifier where P: Default, @@ -96,6 +112,25 @@ where } } +#[cfg(feature = "rust-crypto")] +impl Default for PredicateVerifier +where + P: Default, + C: Default, + H: Default, +{ + fn default() -> Self { + Self { + predicates: P::default(), + voting_power_calculator: C::default(), + commit_validator: ProdCommitValidator::default(), + hasher: H::default(), + _p: PhantomData::default(), + } + } +} + +#[cfg(not(feature = "rust-crypto"))] impl PredicateVerifier where P: VerificationPredicates, @@ -119,6 +154,31 @@ where } } +#[cfg(feature = "rust-crypto")] +impl PredicateVerifier +where + P: VerificationPredicates, + C: VotingPowerCalculator, + H: Hasher, + CP: CryptoProvider, +{ + /// Constructor. + pub fn new( + predicates: P, + voting_power_calculator: C, + commit_validator: ProdCommitValidator, + hasher: H, + ) -> Self { + Self { + predicates, + voting_power_calculator, + hasher, + commit_validator, + _p: PhantomData::default(), + } + } +} + impl Verifier for PredicateVerifier where P: VerificationPredicates + VerificationPredicates, diff --git a/tendermint/src/crypto.rs b/tendermint/src/crypto.rs index 51d5d67f3..63fc10995 100644 --- a/tendermint/src/crypto.rs +++ b/tendermint/src/crypto.rs @@ -15,6 +15,7 @@ pub trait CryptoProvider { /// A default implementation of the HostFunctionManager that uses the [`CryptoProvider`] trait use core::marker::PhantomData; +#[derive(Debug, Clone, PartialEq, Eq)] pub struct DefaultHostFunctionsManager; use k256::ecdsa::{SigningKey, VerifyingKey};