[Ethereum] Ethereum HD address generator

hd-walletswallets

I'm writing a library for Ethereum BIP44 address trees and comparing it against https://iancoleman.io/bip39/ using the same mnemonic phrase.

Given this mnemonic (just a test)

report dash combine correct until media shrimp wide about remain accuse sound solar lawsuit chest myth layer always style filter farm prison will brief

I correctly derived the seed

df9abf945edf79b2fff7b5bae337828daffac5ef49fc79d3cde032785ffe88c9f32a9ce32c48deb8b59c6efd85d599825377d233d5e6501d5acb87841f0af122

The BIP32 Root Key matches as well:

xprv9s21ZrQH143K49pE1HfQVEDXWn5e1poPa3qzNaREfAcosRdVb3Rw8zVefLthvpNf8kP66HpWLN4c9XdqtVc56yK1AauKBxagf6rY3bpne5e

This is for ETH, so I'm using the following path to get the Account Extended keys: m/44'/60'/0' (also matching)

# Account extended private key
xprv9ynU3F8fffBXZ462Y8HeMSaCjVrdQRFd2Le3jkf69kLRxvXbvhnrda7v5jFewACzMiYUUZFFc6QX9PcD3rTRkVcvjqbZvW1n1fAhk92YYHB

# Account extended public key
xpub6CmpSkfZW2jpmYAVe9peiaWwHXh7osyUPZZeY94hi5sQqirkUF77BNSPw2EiQ2Zzn5pARf1e5MAHDyM3xv8gzKcf82GSKxv8E8xoLX5hS7A

The BIP32 derivation path looks correct as well (m/44'/60'/0'/0)

BIP32 Extended private key
xprvA1wMCRgBn4WmoYqzVgXmsCQwXGcJ7FSeXEF2gVDaSYXPG1zePz7JuCVUcJzhU59ZRrwg1uF7SszEX3D38QwfQdxMHBYxHM2rGd2QXnQ96c6

BIP32 Extended public key
xpub6EvhbwD5cS5522vTbi4nELMg5JSnWiAVtTAdUsdBzt4N8pKnwXRZSzoxTZGD1FHURpXexK1BBRmRZrPTZPm15hBH2aWTRH55VUFtECtC7uX

Everything checks but the generation of the ethereum addresses.

M/44'/60'/0'/0/0

0x9545D807e40ff22F1EdC9Ede0d8bd383b53Bdf07

Question: Is this correct ?

  • The above address is generated from the BIP32 root key using the specified path following these steps.

  • The resulting extended public key (note the M) is Base58 decoded

  • The compressed public key is recovered, using EC curve calculation we recover the Y coordinate and append X and Y together to get the uncompressed public key

    • The standard steps to get 20 byte address (keccak sha3, keep just the tail 20 bytes and append "0x")

I double checked my Keccak hash function and it returns the correct hash for the "" value:

c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470

Best Answer

This is silly but I found what the problem was. After I ran the libsecp256k1 point multiplication to obtain the second coordinate of the public key I was discarding the first 8 bytes of the resulting public key instead of just the first ("0x04" prefix).

Related Topic