From b5b01443a553fa105f15eb192bea8cc8a026cc4c Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Wed, 3 Jan 2024 02:08:51 +0000 Subject: [PATCH] pruntime: Address mapping from H160 in query --- Cargo.lock | 75 +++++++++---------- 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 +--- 5 files changed, 114 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 71eebfa941..6219eaead5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1421,7 +1421,7 @@ checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f" dependencies = [ "bitcoin_hashes", "rand 0.8.5", - "rand_core 0.6.4", + "rand_core 0.4.2", "serde", "unicode-normalization", ] @@ -2076,9 +2076,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.11" +version = "4.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" +checksum = "dcfab8ba68f3668e89f6ff60f5b205cea56aa7b769451a59f34b8682f51c056d" dependencies = [ "clap_builder", "clap_derive", @@ -2086,9 +2086,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.11" +version = "4.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" +checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9" dependencies = [ "anstream", "anstyle", @@ -2105,7 +2105,7 @@ version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfe581a2035db4174cdbdc91265e1aba50f381577f0510d0ad36c7bc59cc84a3" dependencies = [ - "clap 4.4.11", + "clap 4.4.12", ] [[package]] @@ -3135,7 +3135,7 @@ version = "0.1.0" dependencies = [ "anyhow", "base64 0.11.0", - "clap 4.4.11", + "clap 4.4.12", "frame-support", "hex", "parity-scale-codec", @@ -4561,7 +4561,7 @@ dependencies = [ "Inflector", "array-bytes 6.1.0", "chrono", - "clap 4.4.11", + "clap 4.4.12", "comfy-table", "frame-benchmarking", "frame-support", @@ -5411,7 +5411,7 @@ name = "headers-cache" version = "0.1.2" dependencies = [ "anyhow", - "clap 4.4.11", + "clap 4.4.12", "env_logger 0.9.0", "futures", "hex", @@ -6446,7 +6446,7 @@ dependencies = [ name = "justification-validate" version = "0.1.0" dependencies = [ - "clap 4.4.11", + "clap 4.4.12", "crossbeam", "env_logger 0.9.0", "log", @@ -9693,6 +9693,7 @@ dependencies = [ "prpc-build", "reqwest", "scale-info", + "secp256k1 0.28.0", "serde", "serde_json", "sp-consensus-grandpa", @@ -9771,7 +9772,7 @@ name = "phala-node" version = "3.0.0" dependencies = [ "assert_cmd", - "clap 4.4.11", + "clap 4.4.12", "clap_complete", "criterion", "frame-benchmarking", @@ -10144,7 +10145,7 @@ dependencies = [ "abort-on-drop", "anyhow", "chrono", - "clap 4.4.11", + "clap 4.4.12", "futures", "hex", "once_cell", @@ -10193,7 +10194,7 @@ version = "0.1.2" dependencies = [ "anyhow", "async-stream", - "clap 4.4.11", + "clap 4.4.12", "env_logger 0.9.0", "futures", "hex", @@ -10704,7 +10705,7 @@ dependencies = [ "async-trait", "axum", "chrono", - "clap 4.4.11", + "clap 4.4.12", "env_logger 0.10.0", "futures", "hex", @@ -11619,7 +11620,7 @@ dependencies = [ "actix-web", "anyhow", "chrono", - "clap 4.4.11", + "clap 4.4.12", "env_logger 0.9.0", "hex", "hex_fmt", @@ -12420,7 +12421,7 @@ dependencies = [ "array-bytes 6.1.0", "bip39", "chrono", - "clap 4.4.11", + "clap 4.4.12", "fdlimit", "futures", "itertools", @@ -13903,7 +13904,7 @@ dependencies = [ name = "sfq-test" version = "0.1.0" dependencies = [ - "clap 4.4.11", + "clap 4.4.12", "phala-scheduler", "rocket", ] @@ -14613,7 +14614,7 @@ dependencies = [ [[package]] name = "sp-crypto-ec-utils" version = "0.4.1" -source = "git+https://github.com/paritytech/polkadot-sdk#b4c816665bd094b6ad703f1d11291c49bf66408f" +source = "git+https://github.com/paritytech/polkadot-sdk#cad947951d9e4b2b4b9308db987c0153506f853e" dependencies = [ "ark-bls12-377", "ark-bls12-377-ext", @@ -14653,7 +14654,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "8.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#b4c816665bd094b6ad703f1d11291c49bf66408f" +source = "git+https://github.com/paritytech/polkadot-sdk#cad947951d9e4b2b4b9308db987c0153506f853e" dependencies = [ "proc-macro2", "quote", @@ -14674,7 +14675,7 @@ dependencies = [ [[package]] name = "sp-externalities" version = "0.19.0" -source = "git+https://github.com/paritytech/polkadot-sdk#b4c816665bd094b6ad703f1d11291c49bf66408f" +source = "git+https://github.com/paritytech/polkadot-sdk#cad947951d9e4b2b4b9308db987c0153506f853e" dependencies = [ "environmental", "parity-scale-codec", @@ -14875,7 +14876,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#b4c816665bd094b6ad703f1d11291c49bf66408f" +source = "git+https://github.com/paritytech/polkadot-sdk#cad947951d9e4b2b4b9308db987c0153506f853e" dependencies = [ "bytes", "impl-trait-for-tuples", @@ -14906,7 +14907,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#b4c816665bd094b6ad703f1d11291c49bf66408f" +source = "git+https://github.com/paritytech/polkadot-sdk#cad947951d9e4b2b4b9308db987c0153506f853e" dependencies = [ "Inflector", "expander", @@ -14998,7 +14999,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polk [[package]] name = "sp-std" version = "8.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#b4c816665bd094b6ad703f1d11291c49bf66408f" +source = "git+https://github.com/paritytech/polkadot-sdk#cad947951d9e4b2b4b9308db987c0153506f853e" [[package]] name = "sp-storage" @@ -15016,7 +15017,7 @@ dependencies = [ [[package]] name = "sp-storage" version = "13.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#b4c816665bd094b6ad703f1d11291c49bf66408f" +source = "git+https://github.com/paritytech/polkadot-sdk#cad947951d9e4b2b4b9308db987c0153506f853e" dependencies = [ "impl-serde", "parity-scale-codec", @@ -15054,7 +15055,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "10.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#b4c816665bd094b6ad703f1d11291c49bf66408f" +source = "git+https://github.com/paritytech/polkadot-sdk#cad947951d9e4b2b4b9308db987c0153506f853e" dependencies = [ "parity-scale-codec", "sp-std 8.0.0 (git+https://github.com/paritytech/polkadot-sdk)", @@ -15156,7 +15157,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#b4c816665bd094b6ad703f1d11291c49bf66408f" +source = "git+https://github.com/paritytech/polkadot-sdk#cad947951d9e4b2b4b9308db987c0153506f853e" dependencies = [ "anyhow", "impl-trait-for-tuples", @@ -15365,7 +15366,7 @@ name = "staging-node-inspect" version = "0.9.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ - "clap 4.4.11", + "clap 4.4.12", "parity-scale-codec", "sc-cli", "sc-client-api", @@ -15667,7 +15668,7 @@ name = "substrate-frame-cli" version = "4.0.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ - "clap 4.4.11", + "clap 4.4.12", "frame-support", "frame-system", "sc-cli", @@ -16154,18 +16155,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.51" +version = "1.0.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7" +checksum = "6e3de26b0965292219b4287ff031fcba86837900fe9cd2b34ea8ad893c0953d2" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.51" +version = "1.0.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df" +checksum = "268026685b2be38d7103e9e507c938a1fcb3d7e6eb15e87870b617bf37b6d581" dependencies = [ "proc-macro2", "quote", @@ -16513,7 +16514,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow 0.5.30", + "winnow 0.5.31", ] [[package]] @@ -16813,7 +16814,7 @@ version = "0.10.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ "async-trait", - "clap 4.4.11", + "clap 4.4.12", "frame-remote-externalities", "frame-try-runtime", "hex", @@ -16913,7 +16914,7 @@ checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", "digest 0.10.7", - "rand 0.8.5", + "rand 0.4.6", "static_assertions", ] @@ -18647,9 +18648,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.5.30" +version = "0.5.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b5c3db89721d50d0e2a673f5043fc4722f76dcc352d7b1ab8b8288bed4ed2c5" +checksum = "97a4882e6b134d6c28953a387571f1acdd3496830d5e36c5e3a1075580ea641c" dependencies = [ "memchr", ] diff --git a/crates/phactory/api/Cargo.toml b/crates/phactory/api/Cargo.toml index d44caa471a..5400ae5593 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