From 81cc25414f3eb68b8bd8d3f12ed9bf8be5d4f922 Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Tue, 30 Jan 2024 17:50:00 -0500 Subject: [PATCH] fix: dynamic provider and test --- relay_rpc/Cargo.toml | 16 +++---- relay_rpc/src/auth/cacao.rs | 12 +++-- relay_rpc/src/auth/cacao/signature.rs | 64 ++++++++++++++++++++++----- relay_rpc/src/auth/cacao/tests.rs | 6 +-- 4 files changed, 72 insertions(+), 26 deletions(-) diff --git a/relay_rpc/Cargo.toml b/relay_rpc/Cargo.toml index 1cfe104..d0d3eb9 100644 --- a/relay_rpc/Cargo.toml +++ b/relay_rpc/Cargo.toml @@ -23,16 +23,16 @@ jsonwebtoken = "8.1" k256 = { version = "0.13", optional = true } sha3 = { version = "0.10", optional = true } sha2 = { version = "0.10.6" } -alloy-providers = { git = "https://github.com/alloy-rs/alloy.git", rev = "5ed60f8" } -alloy-transport = { git = "https://github.com/alloy-rs/alloy.git", rev = "5ed60f8" } -alloy-transport-http = { git = "https://github.com/alloy-rs/alloy.git", rev = "5ed60f8" } reqwest = { version = "0.11", features = ["default-tls"] } -alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy.git", rev = "5ed60f8" } -alloy-json-rpc = { git = "https://github.com/alloy-rs/alloy.git", rev = "5ed60f8" } -alloy-json-abi = "0.6" -alloy-sol-types = "0.6" -alloy-primitives = "0.6" url = "2" +alloy-providers = { git = "https://github.com/alloy-rs/alloy.git" } +alloy-transport = { git = "https://github.com/alloy-rs/alloy.git" } +alloy-transport-http = { git = "https://github.com/alloy-rs/alloy.git" } +alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy.git" } +alloy-json-rpc = { git = "https://github.com/alloy-rs/alloy.git" } +alloy-json-abi = "0.6.2" +alloy-sol-types = "0.6.2" +alloy-primitives = "0.6.2" [dev-dependencies] tokio = { version = "1.35.1", features = ["test-util", "macros"] } diff --git a/relay_rpc/src/auth/cacao.rs b/relay_rpc/src/auth/cacao.rs index e7c0378..1fa6887 100644 --- a/relay_rpc/src/auth/cacao.rs +++ b/relay_rpc/src/auth/cacao.rs @@ -1,10 +1,13 @@ use { - self::{header::Header, payload::Payload, signature::Signature}, + self::{ + header::Header, + payload::Payload, + signature::{GetProvider, Signature}, + }, core::fmt::Debug, serde::{Deserialize, Serialize}, serde_json::value::RawValue, std::fmt::{Display, Write}, - url::Url, }; pub mod header; @@ -29,6 +32,9 @@ pub enum CacaoError { #[error("Unsupported signature type")] UnsupportedSignature, + #[error("Provider not available for that chain")] + ProviderNotAvailable, + #[error("Unable to verify")] Verification, @@ -85,7 +91,7 @@ pub struct Cacao { impl Cacao { const ETHEREUM: &'static str = "Ethereum"; - pub async fn verify(&self, provider: Option) -> Result { + pub async fn verify(&self, provider: GetProvider) -> Result { self.p.validate()?; self.h.validate()?; self.s.verify(self, provider).await diff --git a/relay_rpc/src/auth/cacao/signature.rs b/relay_rpc/src/auth/cacao/signature.rs index 4429917..1474fd0 100644 --- a/relay_rpc/src/auth/cacao/signature.rs +++ b/relay_rpc/src/auth/cacao/signature.rs @@ -20,8 +20,14 @@ pub struct Signature { pub s: String, } +pub type GetProvider = fn(chain_id: String) -> Option; + impl Signature { - pub async fn verify(&self, cacao: &Cacao, provider: Option) -> Result { + pub async fn verify( + &self, + cacao: &Cacao, + get_provider: GetProvider, + ) -> Result { let address = cacao.p.address()?; let signature = data_encoding::HEXLOWER_PERMISSIVE @@ -32,17 +38,23 @@ impl Signature { match self.t.as_str() { EIP191 => Eip191.verify(&signature, &address, hash), - EIP1271 if provider.is_some() => { - Eip1271 - .verify( - signature, - Address::from_str(&address).map_err(|_| CacaoError::AddressInvalid)?, - &hash.finalize()[..] - .try_into() - .expect("hash length is 32 bytes"), - provider.expect("provider is some"), - ) - .await + EIP1271 => { + let chain_id = cacao.p.chain_id_reference()?; + let provider = get_provider(chain_id); + if let Some(provider) = provider { + Eip1271 + .verify( + signature, + Address::from_str(&address).map_err(|_| CacaoError::AddressInvalid)?, + &hash.finalize()[..] + .try_into() + .expect("hash length is 32 bytes"), + provider, + ) + .await + } else { + Err(CacaoError::ProviderNotAvailable) + } } _ => Err(CacaoError::UnsupportedSignature), } @@ -145,3 +157,31 @@ impl Eip1271 { } } } + +#[cfg(test)] +mod test { + use {super::*, alloy_primitives::address}; + + // Manual test. Paste address, signature, message, and project ID to verify function + #[tokio::test] + #[ignore] + async fn test_eip1271() { + let address = address!("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); + let signature = "xxx"; + let signature = data_encoding::HEXLOWER_PERMISSIVE + .decode(strip_hex_prefix(signature).as_bytes()) + .map_err(|_| CacaoError::Verification) + .unwrap(); + let message = "xxx"; + let hash = &Keccak256::new_with_prefix(eip191_bytes(message)).finalize()[..] + .try_into() + .unwrap(); + let provider = "https://rpc.walletconnect.com/v1?chainId=eip155:1&projectId=xxx" + .parse() + .unwrap(); + assert!(Eip1271 + .verify(signature, address, hash, provider) + .await + .unwrap()); + } +} diff --git a/relay_rpc/src/auth/cacao/tests.rs b/relay_rpc/src/auth/cacao/tests.rs index 8718483..29816fd 100644 --- a/relay_rpc/src/auth/cacao/tests.rs +++ b/relay_rpc/src/auth/cacao/tests.rs @@ -24,7 +24,7 @@ async fn cacao_verify_success() { } }"#; let cacao: Cacao = serde_json::from_str(cacao_serialized).unwrap(); - let result = cacao.verify(None).await; + let result = cacao.verify(|_| None).await; assert!(result.is_ok()); assert!(result.map_err(|_| false).unwrap()); @@ -61,7 +61,7 @@ async fn cacao_verify_success_identity_in_audience() { } }"#; let cacao: Cacao = serde_json::from_str(cacao_serialized).unwrap(); - let result = cacao.verify(None).await; + let result = cacao.verify(|_| None).await; assert!(result.is_ok()); assert!(result.map_err(|_| false).unwrap()); @@ -97,6 +97,6 @@ async fn cacao_verify_failure() { } }"#; let cacao: Cacao = serde_json::from_str(cacao_serialized).unwrap(); - let result = cacao.verify(None).await; + let result = cacao.verify(|_| None).await; assert!(result.is_err()); }