diff --git a/Cargo.lock b/Cargo.lock index 11dfbb9366..54cbafebd2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1529,12 +1529,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "ethaddr" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecbcc1770d1b2e3fb83915c80c47a10efbe1964544a40e0211fe40274f8363c8" - [[package]] name = "event-listener" version = "2.5.3" @@ -4913,7 +4907,6 @@ dependencies = [ "bip39", "cfg-if", "derive_more", - "ethaddr", "getrandom", "hex", "hex-literal", diff --git a/signer/Cargo.toml b/signer/Cargo.toml index 625c8b96bf..dca475008a 100644 --- a/signer/Cargo.toml +++ b/signer/Cargo.toml @@ -24,7 +24,7 @@ std = ["regex/std", "sp-crypto-hashing/std", "pbkdf2/std", "sha2/std", "hmac/std # https://github.com/rust-bitcoin/rust-bitcoin/issues/930#issuecomment-1215538699 sr25519 = ["schnorrkel"] ecdsa = ["secp256k1"] -eth = ["keccak-hash", "secp256k1", "bip32", "ethaddr"] +eth = ["keccak-hash", "secp256k1", "bip32"] # Make the keypair algorithms here compatible with Subxt's Signer trait, # so that they can be used to sign transactions for compatible chains. @@ -52,7 +52,6 @@ bip32 = { workspace = true, features = ["alloc", "secp256k1"], optional = true } schnorrkel = { workspace = true, optional = true } secp256k1 = { workspace = true, optional = true, features = ["alloc", "recovery"] } keccak-hash = { workspace = true, optional = true } -ethaddr = { workspace = true, optional = true } # We only pull this in to enable the JS flag for schnorrkel to use. getrandom = { workspace = true, optional = true } diff --git a/signer/src/eth.rs b/signer/src/eth.rs index 5488031852..cb80c9f03c 100644 --- a/signer/src/eth.rs +++ b/signer/src/eth.rs @@ -124,6 +124,29 @@ impl AsRef<[u8; 65]> for Signature { #[derive(Debug, Copy, Clone, PartialEq, Eq, codec::Encode)] pub struct AccountId20(pub [u8; 20]); +impl AccountId20 { + fn checksum(&self) -> String { + let hex_address = hex::encode(self.0); + let hash = keccak(hex_address.as_bytes()); + + let mut checksum_address = String::with_capacity(42); + checksum_address.push_str("0x"); + + for (i, ch) in hex_address.chars().enumerate() { + // Get the corresponding nibble from the hash + let nibble = hash[i / 2] >> (if i % 2 == 0 { 4 } else { 0 }) & 0xf; + + if nibble >= 8 { + checksum_address.push(ch.to_ascii_uppercase()); + } else { + checksum_address.push(ch); + } + } + + checksum_address + } +} + impl AsRef<[u8]> for AccountId20 { fn as_ref(&self) -> &[u8] { &self.0 @@ -132,7 +155,7 @@ impl AsRef<[u8]> for AccountId20 { impl Display for AccountId20 { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { - write!(f, "{}", ethaddr::Address::from_slice(&self.0)) + write!(f, "{}", self.checksum()) } } @@ -386,6 +409,7 @@ mod test { hex!("0f02ba4d7f83e59eaa32eae9c3c4d99b68ce76decade21cdab7ecce8f4aef81a"); const KEY_3: [u8; 32] = hex!("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); + #[test] fn test_account_derivation_1() { let kp = Keypair::from_seed(KEY_1).expect("valid keypair");