Skip to content

Commit

Permalink
pruntime: Address mapping from H160 in query
Browse files Browse the repository at this point in the history
  • Loading branch information
kvinwang committed Dec 26, 2023
1 parent b027efd commit e11e27a
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 39 deletions.
21 changes: 20 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/phactory/api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
92 changes: 70 additions & 22 deletions crates/phactory/api/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -72,7 +74,7 @@ impl Signature {
msg_type: MessageType,
current_block: u32,
max_depth: u32,
) -> Result<Vec<Vec<u8>>, SignatureVerifyError> {
) -> Result<Vec<AccountId32>, SignatureVerifyError> {
if max_depth == 0 {
return Err(SignatureVerifyError::TooLongCertificateChain);
}
Expand All @@ -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),
}
Expand All @@ -129,14 +131,17 @@ where
}

/// Dummy "recover" function to verify the Substrate signatures and return the public key
fn recover<T>(pubkey: &[u8], sig: &[u8], msg: &[u8]) -> Result<Vec<u8>, SignatureVerifyError>
fn recover<T>(pubkey: &[u8], sig: &[u8], msg: &[u8]) -> Result<T::Public, SignatureVerifyError>
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::<T>(pubkey, sig, msg)
.then_some(pubkey.to_vec())
.then_some(public)
.ok_or(SignatureVerifyError::InvalidSignature)
}

Expand All @@ -153,15 +158,47 @@ fn wrap_bytes(msg: &[u8]) -> Vec<u8> {
fn evm_ecdsa_recover(
mut signature: [u8; 65],
message_hash: [u8; 32],
) -> Result<Vec<u8>, SignatureVerifyError> {
) -> Result<sp_core::ecdsa::Public, SignatureVerifyError> {
if signature[64] >= 27 {
signature[64] -= 27;
}
let signature = sp_core::ecdsa::Signature::from_raw(signature);
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)]
Expand All @@ -178,28 +215,39 @@ impl CertificateBody {
msg_type: MessageType,
sig_type: SignatureType,
signature: &[u8],
) -> Result<Vec<u8>, SignatureVerifyError> {
match sig_type {
) -> Result<AccountId32, SignatureVerifyError> {
let signer = match sig_type {
SignatureType::Ed25519 => {
recover::<sp_core::ed25519::Pair>(&self.pubkey, signature, msg)
recover::<sp_core::ed25519::Pair>(&self.pubkey, signature, msg)?.into()
}
SignatureType::Sr25519 => {
recover::<sp_core::sr25519::Pair>(&self.pubkey, signature, msg)
recover::<sp_core::sr25519::Pair>(&self.pubkey, signature, msg)?.into()
}
SignatureType::Ecdsa => recover::<sp_core::ecdsa::Pair>(&self.pubkey, signature, msg),
SignatureType::Ecdsa => account_id_from_evm_pubkey(recover::<sp_core::ecdsa::Pair>(
&self.pubkey,
signature,
msg,
)?),
SignatureType::Ed25519WrapBytes => {
let wrapped = wrap_bytes(msg);
recover::<sp_core::ed25519::Pair>(&self.pubkey, signature, &wrapped)
recover::<sp_core::ed25519::Pair>(&self.pubkey, signature, &wrapped)?.into()
}
SignatureType::Sr25519WrapBytes => {
let wrapped = wrap_bytes(msg);
recover::<sp_core::sr25519::Pair>(&self.pubkey, signature, &wrapped)
recover::<sp_core::sr25519::Pair>(&self.pubkey, signature, &wrapped)?.into()
}
SignatureType::EcdsaWrapBytes => {
let wrapped = wrap_bytes(msg);
recover::<sp_core::ecdsa::Pair>(&self.pubkey, signature, &wrapped)
account_id_from_evm_pubkey(recover::<sp_core::ecdsa::Pair>(
&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)
}
}
7 changes: 4 additions & 3 deletions crates/phactory/api/src/crypto/eip712.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -57,7 +58,7 @@ pub(crate) fn recover(
signature: &[u8],
msg: &[u8],
msg_type: MessageType,
) -> Result<Vec<u8>, SignatureVerifyError> {
) -> Result<Public, SignatureVerifyError> {
let signature = signature
.try_into()
.or(Err(SignatureVerifyError::InvalidSignature))?;
Expand All @@ -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]
Expand Down
13 changes: 1 addition & 12 deletions crates/phactory/src/prpc_service.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::borrow::Cow;
use std::convert::TryFrom;
use std::future::Future;
use std::io::Read;
use std::str::FromStr;
Expand Down Expand Up @@ -631,16 +630,6 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> Phactory<Platform>
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
Expand All @@ -650,7 +639,7 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> Phactory<Platform>
.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
Expand Down
21 changes: 20 additions & 1 deletion standalone/pruntime/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit e11e27a

Please sign in to comment.