Skip to content

Commit

Permalink
Implement ecdsa_to_eth_address() and remove eth_compatibility cra…
Browse files Browse the repository at this point in the history
…te (#1233)

* ink_eth_compatibility::to_eth_address() removed, as well as libsecp256k1 dep

* added edcsa_to_eth_address() (except offchain env)

* added off-chain impl

* removed eth_compatibility crate

* removed dep on eth_compatibility

* fix: clean dependency on a struct from removed crate

* Apply suggestions from code review

Co-authored-by: Michael Müller <[email protected]>

* save

* bugfix for old offchain env impl of to_eth_address

* + doc comments

* ecdsa_to_default_account_id func ported from ink_eth_compatibility crate

* revert examples

* fix

* another fix

* more fix

* Apply suggestions from code review

Co-authored-by: Michael Müller <[email protected]>

* Revert "ecdsa_to_default_account_id func ported from ink_eth_compatibility crate"

This reverts commit 70a9189.

* missed clean up

Co-authored-by: Michael Müller <[email protected]>
  • Loading branch information
agryaznov and cmichi committed May 13, 2022
1 parent 2051044 commit 785a59e
Show file tree
Hide file tree
Showing 12 changed files with 124 additions and 187 deletions.
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ members = [
"crates/primitives",
"crates/engine",
"crates/env",
"crates/eth_compatibility",
"crates/storage",
"crates/storage/derive",
]
Expand Down
28 changes: 28 additions & 0 deletions crates/env/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,34 @@ pub fn ecdsa_recover(
})
}

/// Returns an Ethereum address from the ECDSA compressed public key.
///
/// # Example
///
/// ```
/// let pub_key = [
/// 2, 141, 181, 91, 5, 219, 134, 192, 177, 120, 108, 164, 159, 9, 93, 118,
/// 52, 76, 158, 96, 86, 178, 240, 39, 1, 167, 231, 243, 194, 10, 171, 253,
/// 145,
/// ];
/// let EXPECTED_ETH_ADDRESS = [
/// 9, 35, 29, 167, 177, 154, 1, 111, 158, 87, 109, 35, 177, 98, 119, 6, 47,
/// 77, 70, 168,
/// ];
/// let mut output = [0; 20];
/// ink_env::ecdsa_to_eth_address(&pub_key, &mut output);
/// assert_eq!(output, EXPECTED_ETH_ADDRESS);
/// ```
///
/// # Errors
///
/// - If the ECDSA public key cannot be recovered from the provided public key.
pub fn ecdsa_to_eth_address(pubkey: &[u8; 33], output: &mut [u8; 20]) -> Result<()> {
<EnvInstance as OnInstance>::on_instance(|instance| {
instance.ecdsa_to_eth_address(pubkey, output)
})
}

/// Checks whether the specified account is a contract.
///
/// # Errors
Expand Down
8 changes: 8 additions & 0 deletions crates/env/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,14 @@ pub trait EnvBackend {
output: &mut [u8; 33],
) -> Result<()>;

/// Retrieves an Ethereum address from the ECDSA compressed `pubkey`
/// and stores the result in `output`.
fn ecdsa_to_eth_address(
&mut self,
pubkey: &[u8; 33],
output: &mut [u8; 20],
) -> Result<()>;

/// Low-level interface to call a chain extension method.
///
/// Returns the output of the chain extension of the specified type.
Expand Down
14 changes: 14 additions & 0 deletions crates/env/src/engine/off_chain/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,20 @@ impl EnvBackend for EnvInstance {
}
}

fn ecdsa_to_eth_address(
&mut self,
pubkey: &[u8; 33],
output: &mut [u8; 20],
) -> Result<()> {
let pk = secp256k1::PublicKey::from_slice(pubkey)
.map_err(|_| Error::EcdsaRecoveryFailed)?;
let uncompressed = pk.serialize_uncompressed();
let mut hash = <Keccak256 as HashOutput>::Type::default();
<Keccak256>::hash(&uncompressed[1..], &mut hash);
output.as_mut().copy_from_slice(&hash[12..]);
Ok(())
}

fn call_chain_extension<I, T, E, ErrorCode, F, D>(
&mut self,
func_id: u32,
Expand Down
15 changes: 15 additions & 0 deletions crates/env/src/engine/on_chain/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,11 @@ mod sys {
message_hash_ptr: Ptr32<[u8]>,
output_ptr: Ptr32Mut<[u8]>,
) -> ReturnCode;

pub fn seal_ecdsa_to_eth_address(
public_key_ptr: Ptr32<[u8]>,
output_ptr: Ptr32Mut<[u8]>,
) -> ReturnCode;
}
}

Expand Down Expand Up @@ -704,6 +709,16 @@ pub fn ecdsa_recover(
ret_code.into()
}

pub fn ecdsa_to_eth_address(pubkey: &[u8; 33], output: &mut [u8; 20]) -> Result {
let ret_code = unsafe {
sys::seal_ecdsa_to_eth_address(
Ptr32::from_slice(pubkey),
Ptr32Mut::from_slice(output),
)
};
ret_code.into()
}

pub fn is_contract(account_id: &[u8]) -> bool {
let ret_val = unsafe { sys::seal_is_contract(Ptr32::from_slice(account_id)) };
ret_val.into_bool()
Expand Down
8 changes: 8 additions & 0 deletions crates/env/src/engine/on_chain/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,14 @@ impl EnvBackend for EnvInstance {
ext::ecdsa_recover(signature, message_hash, output).map_err(Into::into)
}

fn ecdsa_to_eth_address(
&mut self,
pubkey: &[u8; 33],
output: &mut [u8; 20],
) -> Result<()> {
ext::ecdsa_to_eth_address(pubkey, output).map_err(Into::into)
}

fn call_chain_extension<I, T, E, ErrorCode, F, D>(
&mut self,
func_id: u32,
Expand Down
30 changes: 0 additions & 30 deletions crates/eth_compatibility/Cargo.toml

This file was deleted.

1 change: 0 additions & 1 deletion crates/eth_compatibility/LICENSE

This file was deleted.

1 change: 0 additions & 1 deletion crates/eth_compatibility/README.md

This file was deleted.

150 changes: 0 additions & 150 deletions crates/eth_compatibility/src/lib.rs

This file was deleted.

1 change: 0 additions & 1 deletion crates/lang/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ ink_storage = { version = "3.0.1", path = "../storage", default-features = false
ink_primitives = { version = "3.0.1", path = "../primitives", default-features = false }
ink_metadata = { version = "3.0.1", path = "../metadata", default-features = false, optional = true }
ink_prelude = { version = "3.0.1", path = "../prelude", default-features = false }
ink_eth_compatibility = { version = "3.0.1", path = "../eth_compatibility", default-features = false }
ink_lang_macro = { version = "3.0.1", path = "macro", default-features = false }

scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive", "full"] }
Expand Down
54 changes: 51 additions & 3 deletions crates/lang/src/env_access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ use ink_env::{
Error,
Result,
};
use ink_eth_compatibility::ECDSAPublicKey;

/// The API behind the `self.env()` and `Self::env()` syntax in ink!.
///
Expand Down Expand Up @@ -831,10 +830,59 @@ where
self,
signature: &[u8; 65],
message_hash: &[u8; 32],
) -> Result<ECDSAPublicKey> {
) -> Result<[u8; 33]> {
let mut output = [0; 33];
ink_env::ecdsa_recover(signature, message_hash, &mut output)
.map(|_| output.into())
.map(|_| output)
.map_err(|_| Error::EcdsaRecoveryFailed)
}

/// Returns an Ethereum address from the ECDSA compressed public key.
///
/// # Example
///
/// ```
/// # use ink_lang as ink;
/// # #[ink::contract]
/// # pub mod my_contract {
/// # #[ink(storage)]
/// # pub struct MyContract { }
/// #
/// # impl MyContract {
/// # #[ink(constructor)]
/// # pub fn new() -> Self {
/// # Self {}
/// # }
/// #
/// #[ink(message)]
/// pub fn ecdsa_to_eth_address(&self) {
/// let pub_key = [
/// 2, 141, 181, 91, 5, 219, 134, 192, 177, 120, 108, 164, 159, 9, 93, 118,
/// 52, 76, 158, 96, 86, 178, 240, 39, 1, 167, 231, 243, 194, 10, 171, 253,
/// 145,
/// ];
/// let EXPECTED_ETH_ADDRESS = [
/// 9, 35, 29, 167, 177, 154, 1, 111, 158, 87, 109, 35, 177, 98, 119, 6, 47,
/// 77, 70, 168,
/// ];
/// let output = self
/// .env()
/// .ecdsa_to_eth_address(&pub_key)
/// .expect("must return an Ethereum address for the compressed public key");
/// assert_eq!(output, EXPECTED_ETH_ADDRESS);
/// }
/// #
/// # }
/// # }
/// ```
///
/// # Note
///
/// For more details visit: [`ink_env::ecdsa_to_eth_address`]
pub fn ecdsa_to_eth_address(self, pubkey: &[u8; 33]) -> Result<[u8; 20]> {
let mut output = [0; 20];
ink_env::ecdsa_to_eth_address(pubkey, &mut output)
.map(|_| output)
.map_err(|_| Error::EcdsaRecoveryFailed)
}

Expand Down

0 comments on commit 785a59e

Please sign in to comment.