mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-20 09:21:02 +00:00
Add frame_support::crypto::ecdsa::Public.to_eth_address() (k256-based) and use it in pallets (#11087)
* `ecdsa::Public::to_eth_address` + test, beefy-mmr `convert()` to use it, contracts Ext interface * `seal_ecdsa_to_eth_address` all but benchmark done * `seal_ecdsa_to_eth_address` + wasm test * `seal_ecdsa_to_eth_address` + benchmark * fixed dependencies * Apply suggestions from code review Co-authored-by: Alexander Theißen <alex.theissen@me.com> * fixes from review #1 * ecdsa::Public(*pk).to_eth_address() moved to frame_support and contracts to use it * beefy-mmr to use newly added frame_support function for convertion * a doc fix * import fix * benchmark fix-1 (still fails) * benchmark fixed * Apply suggestions from code review Co-authored-by: Alexander Theißen <alex.theissen@me.com> * fixes on Alex T feedback * to_eth_address() put into extension trait for sp-core::ecdsa::Public * Update frame/support/src/crypto/ecdsa.rs Co-authored-by: Alexander Theißen <alex.theissen@me.com> * Update frame/contracts/src/wasm/mod.rs Co-authored-by: Alexander Theißen <alex.theissen@me.com> * fixes on issues pointed out in review * benchmark errors fixed * fmt fix * EcdsaRecoverFailed err docs updated * Apply suggestions from code review Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * make applied suggestions compile * get rid of unwrap() in runtime * Remove expect Co-authored-by: Alexander Theißen <alex.theissen@me.com> Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> Co-authored-by: Bastian Köcher <info@kchr.de>
This commit is contained in:
committed by
GitHub
parent
c6e452108b
commit
9676ce6f36
@@ -503,6 +503,9 @@ mod tests {
|
||||
fn contract_info(&mut self) -> &mut crate::ContractInfo<Self::T> {
|
||||
unimplemented!()
|
||||
}
|
||||
fn ecdsa_to_eth_address(&self, _pk: &[u8; 33]) -> Result<[u8; 20], ()> {
|
||||
Ok([2u8; 20])
|
||||
}
|
||||
}
|
||||
|
||||
fn execute<E: BorrowMut<MockExt>>(wat: &str, input_data: Vec<u8>, mut ext: E) -> ExecResult {
|
||||
@@ -1085,6 +1088,42 @@ mod tests {
|
||||
assert_eq!(mock_ext.ecdsa_recover.into_inner(), [([1; 65], [1; 32])]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "unstable-interface")]
|
||||
fn contract_ecdsa_to_eth_address() {
|
||||
/// calls `seal_ecdsa_to_eth_address` for the contstant and ensures the result equals the
|
||||
/// expected one.
|
||||
const CODE_ECDSA_TO_ETH_ADDRESS: &str = r#"
|
||||
(module
|
||||
(import "__unstable__" "seal_ecdsa_to_eth_address" (func $seal_ecdsa_to_eth_address (param i32 i32) (result i32)))
|
||||
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
|
||||
(import "env" "memory" (memory 1 1))
|
||||
|
||||
(func (export "call")
|
||||
;; fill the buffer with the eth address.
|
||||
(call $seal_ecdsa_to_eth_address (i32.const 0) (i32.const 0))
|
||||
|
||||
;; Return the contents of the buffer
|
||||
(call $seal_return
|
||||
(i32.const 0)
|
||||
(i32.const 0)
|
||||
(i32.const 20)
|
||||
)
|
||||
|
||||
;; seal_return doesn't return, so this is effectively unreachable.
|
||||
(unreachable)
|
||||
)
|
||||
(func (export "deploy"))
|
||||
)
|
||||
"#;
|
||||
|
||||
let output = execute(CODE_ECDSA_TO_ETH_ADDRESS, vec![], MockExt::default()).unwrap();
|
||||
assert_eq!(
|
||||
output,
|
||||
ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes([0x02; 20].to_vec()) }
|
||||
);
|
||||
}
|
||||
|
||||
const CODE_GET_STORAGE: &str = r#"
|
||||
(module
|
||||
(import "seal0" "seal_get_storage" (func $seal_get_storage (param i32 i32 i32) (result i32)))
|
||||
|
||||
@@ -71,7 +71,9 @@ pub enum ReturnCode {
|
||||
/// The call dispatched by `seal_call_runtime` was executed but returned an error.
|
||||
#[cfg(feature = "unstable-interface")]
|
||||
CallRuntimeReturnedError = 10,
|
||||
/// ECDSA pubkey recovery failed. Most probably wrong recovery id or signature.
|
||||
/// ECDSA pubkey recovery failed (most probably wrong recovery id or signature), or
|
||||
/// ECDSA compressed pubkey conversion into Ethereum address failed (most probably
|
||||
/// wrong pubkey provided).
|
||||
#[cfg(feature = "unstable-interface")]
|
||||
EcdsaRecoverFailed = 11,
|
||||
}
|
||||
@@ -225,6 +227,9 @@ pub enum RuntimeCosts {
|
||||
/// Weight of calling `seal_set_code_hash`
|
||||
#[cfg(feature = "unstable-interface")]
|
||||
SetCodeHash,
|
||||
/// Weight of calling `ecdsa_to_eth_address`
|
||||
#[cfg(feature = "unstable-interface")]
|
||||
EcdsaToEthAddress,
|
||||
}
|
||||
|
||||
impl RuntimeCosts {
|
||||
@@ -309,6 +314,8 @@ impl RuntimeCosts {
|
||||
CallRuntime(weight) => weight,
|
||||
#[cfg(feature = "unstable-interface")]
|
||||
SetCodeHash => s.set_code_hash,
|
||||
#[cfg(feature = "unstable-interface")]
|
||||
EcdsaToEthAddress => s.ecdsa_to_eth_address,
|
||||
};
|
||||
RuntimeToken {
|
||||
#[cfg(test)]
|
||||
@@ -1984,12 +1991,12 @@ define_env!(Env, <E: Ext>,
|
||||
// # Parameters
|
||||
//
|
||||
// - `signature_ptr`: the pointer into the linear memory where the signature
|
||||
// is placed. Should be decodable as a 65 bytes. Traps otherwise.
|
||||
// is placed. Should be decodable as a 65 bytes. Traps otherwise.
|
||||
// - `message_hash_ptr`: the pointer into the linear memory where the message
|
||||
// hash is placed. Should be decodable as a 32 bytes. Traps otherwise.
|
||||
// - `output_ptr`: the pointer into the linear memory where the output
|
||||
// data is placed. The buffer should be 33 bytes. Traps otherwise.
|
||||
// The function will write the result directly into this buffer.
|
||||
// data is placed. The buffer should be 33 bytes. The function
|
||||
// will write the result directly into this buffer.
|
||||
//
|
||||
// # Errors
|
||||
//
|
||||
@@ -2036,7 +2043,7 @@ define_env!(Env, <E: Ext>,
|
||||
//
|
||||
// # Parameters
|
||||
//
|
||||
// - code_hash_ptr: A pointer to the buffer that contains the new code hash.
|
||||
// - `code_hash_ptr`: A pointer to the buffer that contains the new code hash.
|
||||
//
|
||||
// # Errors
|
||||
//
|
||||
@@ -2052,4 +2059,35 @@ define_env!(Env, <E: Ext>,
|
||||
Ok(()) => Ok(ReturnCode::Success)
|
||||
}
|
||||
},
|
||||
|
||||
// Calculates Ethereum address from the ECDSA compressed public key and stores
|
||||
// it into the supplied buffer.
|
||||
//
|
||||
// # Parameters
|
||||
//
|
||||
// - `key_ptr`: a pointer to the ECDSA compressed public key. Should be decodable as a 33 bytes value.
|
||||
// Traps otherwise.
|
||||
// - `out_ptr`: the pointer into the linear memory where the output
|
||||
// data is placed. The function will write the result
|
||||
// directly into this buffer.
|
||||
//
|
||||
// The value is stored to linear memory at the address pointed to by `out_ptr`.
|
||||
// If the available space at `out_ptr` is less than the size of the value a trap is triggered.
|
||||
//
|
||||
// # Errors
|
||||
//
|
||||
// `ReturnCode::EcdsaRecoverFailed`
|
||||
[__unstable__] seal_ecdsa_to_eth_address(ctx, key_ptr: u32, out_ptr: u32) -> ReturnCode => {
|
||||
ctx.charge_gas(RuntimeCosts::EcdsaToEthAddress)?;
|
||||
let mut compressed_key: [u8; 33] = [0;33];
|
||||
ctx.read_sandbox_memory_into_buf(key_ptr, &mut compressed_key)?;
|
||||
let result = ctx.ext.ecdsa_to_eth_address(&compressed_key);
|
||||
match result {
|
||||
Ok(eth_address) => {
|
||||
ctx.write_sandbox_memory(out_ptr, eth_address.as_ref())?;
|
||||
Ok(ReturnCode::Success)
|
||||
},
|
||||
Err(_) => Ok(ReturnCode::EcdsaRecoverFailed),
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user