Skip to content

Commit e11e27a

Browse files
committed
pruntime: Address mapping from H160 in query
1 parent b027efd commit e11e27a

File tree

6 files changed

+116
-39
lines changed

6 files changed

+116
-39
lines changed

Cargo.lock

Lines changed: 20 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/phactory/api/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ im = "15"
3535
ethers = "2.0.8"
3636

3737
hex-literal = "0.4.1"
38+
secp256k1 = "0.28.0"
3839

3940
[dev-dependencies]
4041
insta = "1.13.0"

crates/phactory/api/src/crypto.rs

Lines changed: 70 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use std::convert::TryFrom;
33
use alloc::vec;
44
use alloc::vec::Vec;
55
use parity_scale_codec::{Decode, Encode, Error as CodecError};
6+
use sp_core::{H160, H256};
7+
use sp_runtime::AccountId32;
68

79
use crate::prpc::{Signature, SignatureType};
810
pub use phala_crypto::{aead, ecdh, CryptoError};
@@ -72,7 +74,7 @@ impl Signature {
7274
msg_type: MessageType,
7375
current_block: u32,
7476
max_depth: u32,
75-
) -> Result<Vec<Vec<u8>>, SignatureVerifyError> {
77+
) -> Result<Vec<AccountId32>, SignatureVerifyError> {
7678
if max_depth == 0 {
7779
return Err(SignatureVerifyError::TooLongCertificateChain);
7880
}
@@ -92,21 +94,21 @@ impl Signature {
9294
return Err(SignatureVerifyError::CertificateExpired);
9395
}
9496

95-
let pubkey = body.recover(msg, msg_type, sig_type, &self.signature)?;
97+
let body_signer = body.recover(msg, msg_type, sig_type, &self.signature)?;
9698

97-
let key_chain = if let Some(cert_sig) = &cert.signature {
98-
let mut key_chain = cert_sig.verify(
99+
let signers = if let Some(cert_sig) = &cert.signature {
100+
let mut signers = cert_sig.verify(
99101
&body.encode(),
100102
MessageType::Certificate { ttl: body.ttl },
101103
current_block,
102104
max_depth - 1,
103105
)?;
104-
key_chain.push(pubkey);
105-
key_chain
106+
signers.push(body_signer);
107+
signers
106108
} else {
107-
vec![pubkey]
109+
vec![body_signer]
108110
};
109-
Ok(key_chain)
111+
Ok(signers)
110112
}
111113
None => Err(SignatureVerifyError::CertificateMissing),
112114
}
@@ -129,14 +131,17 @@ where
129131
}
130132

131133
/// Dummy "recover" function to verify the Substrate signatures and return the public key
132-
fn recover<T>(pubkey: &[u8], sig: &[u8], msg: &[u8]) -> Result<Vec<u8>, SignatureVerifyError>
134+
fn recover<T>(pubkey: &[u8], sig: &[u8], msg: &[u8]) -> Result<T::Public, SignatureVerifyError>
133135
where
134136
T: sp_core::crypto::Pair,
135137
T::Public: for<'a> TryFrom<&'a [u8]>,
136138
T::Signature: for<'a> TryFrom<&'a [u8]>,
137139
{
140+
let Ok(public) = T::Public::try_from(pubkey) else {
141+
return Err(SignatureVerifyError::InvalidPublicKey);
142+
};
138143
verify::<T>(pubkey, sig, msg)
139-
.then_some(pubkey.to_vec())
144+
.then_some(public)
140145
.ok_or(SignatureVerifyError::InvalidSignature)
141146
}
142147

@@ -153,15 +158,47 @@ fn wrap_bytes(msg: &[u8]) -> Vec<u8> {
153158
fn evm_ecdsa_recover(
154159
mut signature: [u8; 65],
155160
message_hash: [u8; 32],
156-
) -> Result<Vec<u8>, SignatureVerifyError> {
161+
) -> Result<sp_core::ecdsa::Public, SignatureVerifyError> {
157162
if signature[64] >= 27 {
158163
signature[64] -= 27;
159164
}
160165
let signature = sp_core::ecdsa::Signature::from_raw(signature);
161166
let recovered_pubkey = signature
162167
.recover_prehashed(&message_hash)
163168
.ok_or(SignatureVerifyError::InvalidSignature)?;
164-
Ok(recovered_pubkey.as_ref().to_vec())
169+
Ok(recovered_pubkey)
170+
}
171+
172+
/// Convert EVM public key to Substrate account ID.
173+
///
174+
/// account_id = keccak256(pubkey)[12..] + b"@evm_address"
175+
fn account_id_from_evm_pubkey(pubkey: sp_core::ecdsa::Public) -> AccountId32 {
176+
let pubkey =
177+
secp256k1::PublicKey::from_slice(pubkey.as_ref()).expect("Should always be a valid pubkey");
178+
let h32 = H256(sp_core::hashing::keccak_256(
179+
&pubkey.serialize_uncompressed()[1..],
180+
));
181+
let h20 = H160::from(h32);
182+
let mut raw_account: [u8; 32] = [0; 32];
183+
let postfix = b"@evm_address";
184+
raw_account[..20].copy_from_slice(h20.as_bytes());
185+
raw_account[20..].copy_from_slice(postfix);
186+
AccountId32::from(raw_account)
187+
}
188+
189+
#[test]
190+
fn test_account_id_from_evm_pubkey() {
191+
let pubkey = sp_core::ecdsa::Public(hex_literal::hex!(
192+
"029df1e69b8b7c2da2efe0069dc141c2cec0317bf3fd135abaeb69ee33801f5970"
193+
));
194+
let account_id = account_id_from_evm_pubkey(pubkey);
195+
assert_eq!(
196+
hex::encode(account_id),
197+
format!(
198+
"77bb3d64ea13e4f0beafdd5d92508d4643bb09cb{}",
199+
hex::encode(b"@evm_address")
200+
)
201+
);
165202
}
166203

167204
#[derive(Clone, Encode, Decode, Debug)]
@@ -178,28 +215,39 @@ impl CertificateBody {
178215
msg_type: MessageType,
179216
sig_type: SignatureType,
180217
signature: &[u8],
181-
) -> Result<Vec<u8>, SignatureVerifyError> {
182-
match sig_type {
218+
) -> Result<AccountId32, SignatureVerifyError> {
219+
let signer = match sig_type {
183220
SignatureType::Ed25519 => {
184-
recover::<sp_core::ed25519::Pair>(&self.pubkey, signature, msg)
221+
recover::<sp_core::ed25519::Pair>(&self.pubkey, signature, msg)?.into()
185222
}
186223
SignatureType::Sr25519 => {
187-
recover::<sp_core::sr25519::Pair>(&self.pubkey, signature, msg)
224+
recover::<sp_core::sr25519::Pair>(&self.pubkey, signature, msg)?.into()
188225
}
189-
SignatureType::Ecdsa => recover::<sp_core::ecdsa::Pair>(&self.pubkey, signature, msg),
226+
SignatureType::Ecdsa => account_id_from_evm_pubkey(recover::<sp_core::ecdsa::Pair>(
227+
&self.pubkey,
228+
signature,
229+
msg,
230+
)?),
190231
SignatureType::Ed25519WrapBytes => {
191232
let wrapped = wrap_bytes(msg);
192-
recover::<sp_core::ed25519::Pair>(&self.pubkey, signature, &wrapped)
233+
recover::<sp_core::ed25519::Pair>(&self.pubkey, signature, &wrapped)?.into()
193234
}
194235
SignatureType::Sr25519WrapBytes => {
195236
let wrapped = wrap_bytes(msg);
196-
recover::<sp_core::sr25519::Pair>(&self.pubkey, signature, &wrapped)
237+
recover::<sp_core::sr25519::Pair>(&self.pubkey, signature, &wrapped)?.into()
197238
}
198239
SignatureType::EcdsaWrapBytes => {
199240
let wrapped = wrap_bytes(msg);
200-
recover::<sp_core::ecdsa::Pair>(&self.pubkey, signature, &wrapped)
241+
account_id_from_evm_pubkey(recover::<sp_core::ecdsa::Pair>(
242+
&self.pubkey,
243+
signature,
244+
&wrapped,
245+
)?)
201246
}
202-
SignatureType::Eip712 => eip712::recover(&self.pubkey, signature, msg, msg_type),
203-
}
247+
SignatureType::Eip712 => {
248+
account_id_from_evm_pubkey(eip712::recover(&self.pubkey, signature, msg, msg_type)?)
249+
}
250+
};
251+
Ok(signer)
204252
}
205253
}

crates/phactory/api/src/crypto/eip712.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use ethers::{
66
contract::{Eip712, EthAbiType},
77
types::{transaction::eip712::Eip712, Bytes},
88
};
9+
use sp_core::ecdsa::Public;
910

1011
#[derive(Debug, Clone, Eip712, EthAbiType)]
1112
#[eip712(
@@ -57,7 +58,7 @@ pub(crate) fn recover(
5758
signature: &[u8],
5859
msg: &[u8],
5960
msg_type: MessageType,
60-
) -> Result<Vec<u8>, SignatureVerifyError> {
61+
) -> Result<Public, SignatureVerifyError> {
6162
let signature = signature
6263
.try_into()
6364
.or(Err(SignatureVerifyError::InvalidSignature))?;
@@ -70,10 +71,10 @@ pub(crate) fn recover(
7071
}
7172
.or(Err(SignatureVerifyError::Eip712EncodingError))?;
7273
let recovered_pubkey = evm_ecdsa_recover(signature, message_hash)?;
73-
if recovered_pubkey != pubkey {
74+
if recovered_pubkey.as_ref() != pubkey {
7475
return Err(SignatureVerifyError::InvalidSignature);
7576
}
76-
Ok(sp_core::blake2_256(&recovered_pubkey).to_vec())
77+
Ok(recovered_pubkey)
7778
}
7879

7980
#[test]

crates/phactory/src/prpc_service.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use std::borrow::Cow;
2-
use std::convert::TryFrom;
32
use std::future::Future;
43
use std::io::Read;
54
use std::str::FromStr;
@@ -631,16 +630,6 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> Phactory<Platform>
631630
let head = contract::ContractQueryHead::decode(&mut data_cursor)?;
632631
let rest = data_cursor.len();
633632

634-
// Origin
635-
let accid_origin = match origin {
636-
Some(origin) => {
637-
let accid = chain::AccountId::try_from(origin.as_slice())
638-
.map_err(|_| from_display("Bad account id"))?;
639-
Some(accid)
640-
}
641-
None => None,
642-
};
643-
644633
let query_scheduler = self.query_scheduler.clone();
645634
// Dispatch
646635
let query_future = self
@@ -650,7 +639,7 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> Phactory<Platform>
650639
.make_query(
651640
req_id,
652641
&AccountId::unchecked_from(head.id),
653-
accid_origin.as_ref(),
642+
origin.as_ref(),
654643
data[data.len() - rest..].to_vec(),
655644
query_scheduler,
656645
&self

standalone/pruntime/Cargo.lock

Lines changed: 20 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)