From e11e27aed612526ef6bc096a1d94139185047085 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Tue, 26 Dec 2023 00:50:05 +0000 Subject: [PATCH] pruntime: Address mapping from H160 in query --- Cargo.lock | 21 +++++- crates/phactory/api/Cargo.toml | 1 + crates/phactory/api/src/crypto.rs | 92 ++++++++++++++++++------ crates/phactory/api/src/crypto/eip712.rs | 7 +- crates/phactory/src/prpc_service.rs | 13 +--- standalone/pruntime/Cargo.lock | 21 +++++- 6 files changed, 116 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ce8dedbfab..6fd5c83431 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9369,6 +9369,7 @@ dependencies = [ "prpc-build", "reqwest", "scale-info", + "secp256k1 0.28.0", "serde", "serde_json", "sp-consensus-grandpa", @@ -13274,6 +13275,15 @@ dependencies = [ "secp256k1-sys 0.8.1", ] +[[package]] +name = "secp256k1" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acea373acb8c21ecb5a23741452acd2593ed44ee3d343e72baaa143bc89d0d5" +dependencies = [ + "secp256k1-sys 0.9.1", +] + [[package]] name = "secp256k1-sys" version = "0.6.0" @@ -13292,6 +13302,15 @@ dependencies = [ "cc", ] +[[package]] +name = "secp256k1-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dd97a086ec737e30053fd5c46f097465d25bb81dd3608825f65298c4c98be83" +dependencies = [ + "cc", +] + [[package]] name = "secrecy" version = "0.8.0" @@ -16241,7 +16260,7 @@ checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", "digest 0.10.7", - "rand 0.4.6", + "rand 0.8.5", "static_assertions", ] diff --git a/crates/phactory/api/Cargo.toml b/crates/phactory/api/Cargo.toml index 4587e9f59e..541e1d0698 100644 --- a/crates/phactory/api/Cargo.toml +++ b/crates/phactory/api/Cargo.toml @@ -35,6 +35,7 @@ im = "15" ethers = "2.0.8" hex-literal = "0.4.1" +secp256k1 = "0.28.0" [dev-dependencies] insta = "1.13.0" diff --git a/crates/phactory/api/src/crypto.rs b/crates/phactory/api/src/crypto.rs index 3466e2e11a..01d99f7306 100644 --- a/crates/phactory/api/src/crypto.rs +++ b/crates/phactory/api/src/crypto.rs @@ -3,6 +3,8 @@ use std::convert::TryFrom; use alloc::vec; use alloc::vec::Vec; use parity_scale_codec::{Decode, Encode, Error as CodecError}; +use sp_core::{H160, H256}; +use sp_runtime::AccountId32; use crate::prpc::{Signature, SignatureType}; pub use phala_crypto::{aead, ecdh, CryptoError}; @@ -72,7 +74,7 @@ impl Signature { msg_type: MessageType, current_block: u32, max_depth: u32, - ) -> Result>, SignatureVerifyError> { + ) -> Result, SignatureVerifyError> { if max_depth == 0 { return Err(SignatureVerifyError::TooLongCertificateChain); } @@ -92,21 +94,21 @@ impl Signature { return Err(SignatureVerifyError::CertificateExpired); } - let pubkey = body.recover(msg, msg_type, sig_type, &self.signature)?; + let body_signer = body.recover(msg, msg_type, sig_type, &self.signature)?; - let key_chain = if let Some(cert_sig) = &cert.signature { - let mut key_chain = cert_sig.verify( + let signers = if let Some(cert_sig) = &cert.signature { + let mut signers = cert_sig.verify( &body.encode(), MessageType::Certificate { ttl: body.ttl }, current_block, max_depth - 1, )?; - key_chain.push(pubkey); - key_chain + signers.push(body_signer); + signers } else { - vec![pubkey] + vec![body_signer] }; - Ok(key_chain) + Ok(signers) } None => Err(SignatureVerifyError::CertificateMissing), } @@ -129,14 +131,17 @@ where } /// Dummy "recover" function to verify the Substrate signatures and return the public key -fn recover(pubkey: &[u8], sig: &[u8], msg: &[u8]) -> Result, SignatureVerifyError> +fn recover(pubkey: &[u8], sig: &[u8], msg: &[u8]) -> Result where T: sp_core::crypto::Pair, T::Public: for<'a> TryFrom<&'a [u8]>, T::Signature: for<'a> TryFrom<&'a [u8]>, { + let Ok(public) = T::Public::try_from(pubkey) else { + return Err(SignatureVerifyError::InvalidPublicKey); + }; verify::(pubkey, sig, msg) - .then_some(pubkey.to_vec()) + .then_some(public) .ok_or(SignatureVerifyError::InvalidSignature) } @@ -153,7 +158,7 @@ fn wrap_bytes(msg: &[u8]) -> Vec { fn evm_ecdsa_recover( mut signature: [u8; 65], message_hash: [u8; 32], -) -> Result, SignatureVerifyError> { +) -> Result { if signature[64] >= 27 { signature[64] -= 27; } @@ -161,7 +166,39 @@ fn evm_ecdsa_recover( let recovered_pubkey = signature .recover_prehashed(&message_hash) .ok_or(SignatureVerifyError::InvalidSignature)?; - Ok(recovered_pubkey.as_ref().to_vec()) + Ok(recovered_pubkey) +} + +/// Convert EVM public key to Substrate account ID. +/// +/// account_id = keccak256(pubkey)[12..] + b"@evm_address" +fn account_id_from_evm_pubkey(pubkey: sp_core::ecdsa::Public) -> AccountId32 { + let pubkey = + secp256k1::PublicKey::from_slice(pubkey.as_ref()).expect("Should always be a valid pubkey"); + let h32 = H256(sp_core::hashing::keccak_256( + &pubkey.serialize_uncompressed()[1..], + )); + let h20 = H160::from(h32); + let mut raw_account: [u8; 32] = [0; 32]; + let postfix = b"@evm_address"; + raw_account[..20].copy_from_slice(h20.as_bytes()); + raw_account[20..].copy_from_slice(postfix); + AccountId32::from(raw_account) +} + +#[test] +fn test_account_id_from_evm_pubkey() { + let pubkey = sp_core::ecdsa::Public(hex_literal::hex!( + "029df1e69b8b7c2da2efe0069dc141c2cec0317bf3fd135abaeb69ee33801f5970" + )); + let account_id = account_id_from_evm_pubkey(pubkey); + assert_eq!( + hex::encode(account_id), + format!( + "77bb3d64ea13e4f0beafdd5d92508d4643bb09cb{}", + hex::encode(b"@evm_address") + ) + ); } #[derive(Clone, Encode, Decode, Debug)] @@ -178,28 +215,39 @@ impl CertificateBody { msg_type: MessageType, sig_type: SignatureType, signature: &[u8], - ) -> Result, SignatureVerifyError> { - match sig_type { + ) -> Result { + let signer = match sig_type { SignatureType::Ed25519 => { - recover::(&self.pubkey, signature, msg) + recover::(&self.pubkey, signature, msg)?.into() } SignatureType::Sr25519 => { - recover::(&self.pubkey, signature, msg) + recover::(&self.pubkey, signature, msg)?.into() } - SignatureType::Ecdsa => recover::(&self.pubkey, signature, msg), + SignatureType::Ecdsa => account_id_from_evm_pubkey(recover::( + &self.pubkey, + signature, + msg, + )?), SignatureType::Ed25519WrapBytes => { let wrapped = wrap_bytes(msg); - recover::(&self.pubkey, signature, &wrapped) + recover::(&self.pubkey, signature, &wrapped)?.into() } SignatureType::Sr25519WrapBytes => { let wrapped = wrap_bytes(msg); - recover::(&self.pubkey, signature, &wrapped) + recover::(&self.pubkey, signature, &wrapped)?.into() } SignatureType::EcdsaWrapBytes => { let wrapped = wrap_bytes(msg); - recover::(&self.pubkey, signature, &wrapped) + account_id_from_evm_pubkey(recover::( + &self.pubkey, + signature, + &wrapped, + )?) } - SignatureType::Eip712 => eip712::recover(&self.pubkey, signature, msg, msg_type), - } + SignatureType::Eip712 => { + account_id_from_evm_pubkey(eip712::recover(&self.pubkey, signature, msg, msg_type)?) + } + }; + Ok(signer) } } diff --git a/crates/phactory/api/src/crypto/eip712.rs b/crates/phactory/api/src/crypto/eip712.rs index 2c7b28e8b2..8372a454e7 100644 --- a/crates/phactory/api/src/crypto/eip712.rs +++ b/crates/phactory/api/src/crypto/eip712.rs @@ -6,6 +6,7 @@ use ethers::{ contract::{Eip712, EthAbiType}, types::{transaction::eip712::Eip712, Bytes}, }; +use sp_core::ecdsa::Public; #[derive(Debug, Clone, Eip712, EthAbiType)] #[eip712( @@ -57,7 +58,7 @@ pub(crate) fn recover( signature: &[u8], msg: &[u8], msg_type: MessageType, -) -> Result, SignatureVerifyError> { +) -> Result { let signature = signature .try_into() .or(Err(SignatureVerifyError::InvalidSignature))?; @@ -70,10 +71,10 @@ pub(crate) fn recover( } .or(Err(SignatureVerifyError::Eip712EncodingError))?; let recovered_pubkey = evm_ecdsa_recover(signature, message_hash)?; - if recovered_pubkey != pubkey { + if recovered_pubkey.as_ref() != pubkey { return Err(SignatureVerifyError::InvalidSignature); } - Ok(sp_core::blake2_256(&recovered_pubkey).to_vec()) + Ok(recovered_pubkey) } #[test] diff --git a/crates/phactory/src/prpc_service.rs b/crates/phactory/src/prpc_service.rs index da606116c9..cac3dfd364 100644 --- a/crates/phactory/src/prpc_service.rs +++ b/crates/phactory/src/prpc_service.rs @@ -1,5 +1,4 @@ use std::borrow::Cow; -use std::convert::TryFrom; use std::future::Future; use std::io::Read; use std::str::FromStr; @@ -631,16 +630,6 @@ impl Phactory let head = contract::ContractQueryHead::decode(&mut data_cursor)?; let rest = data_cursor.len(); - // Origin - let accid_origin = match origin { - Some(origin) => { - let accid = chain::AccountId::try_from(origin.as_slice()) - .map_err(|_| from_display("Bad account id"))?; - Some(accid) - } - None => None, - }; - let query_scheduler = self.query_scheduler.clone(); // Dispatch let query_future = self @@ -650,7 +639,7 @@ impl Phactory .make_query( req_id, &AccountId::unchecked_from(head.id), - accid_origin.as_ref(), + origin.as_ref(), data[data.len() - rest..].to_vec(), query_scheduler, &self diff --git a/standalone/pruntime/Cargo.lock b/standalone/pruntime/Cargo.lock index 0be7a552af..3e921b09ef 100644 --- a/standalone/pruntime/Cargo.lock +++ b/standalone/pruntime/Cargo.lock @@ -5756,6 +5756,7 @@ dependencies = [ "prpc-build", "reqwest", "scale-info", + "secp256k1 0.28.0", "serde", "serde_json", "sp-consensus-grandpa", @@ -7654,6 +7655,15 @@ dependencies = [ "secp256k1-sys 0.8.1", ] +[[package]] +name = "secp256k1" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acea373acb8c21ecb5a23741452acd2593ed44ee3d343e72baaa143bc89d0d5" +dependencies = [ + "secp256k1-sys 0.9.1", +] + [[package]] name = "secp256k1-sys" version = "0.6.0" @@ -7672,6 +7682,15 @@ dependencies = [ "cc", ] +[[package]] +name = "secp256k1-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dd97a086ec737e30053fd5c46f097465d25bb81dd3608825f65298c4c98be83" +dependencies = [ + "cc", +] + [[package]] name = "secrecy" version = "0.8.0" @@ -9588,7 +9607,7 @@ checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", "digest 0.10.7", - "rand 0.4.6", + "rand 0.8.5", "static_assertions", ]