bitcoinjs / bitcoinjs-lib

A javascript Bitcoin library for node.js and browsers.
MIT License
5.68k stars 2.1k forks source link

mnemonic+pass address derivation inconsistent with results from established wallet vendors #1684

Closed Phildo closed 3 years ago

Phildo commented 3 years ago

I've referenced this example as the only documentation I could find: https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/bip32.spec.ts

I'm using BIP44 to generate an address from a given mnemonic seed and passphrase, and am finding the resulting address does not match the first given by "myetherwallet.com" when using the same inputs.

Here is my (very simple) code:

 const bip39 = require('bip39')
 const bip32 = require('bip32')
 const bitcoinjs = require('bitcoinjs-lib')
 const bs58 = require('bs58')
 const secrets = require('./secrets')

 //I've tried both of the following- neither give the "correct" result
 var seed = bip39.mnemonicToSeedSync(secrets.mnemonic, secrets.pass);
 //var seed = bip39.mnemonicToSeedSync(secrets.mnemonic+" "+secrets.pass);

 var root = bip32.fromSeed(seed);
 var node = root.derivePath("m/44'/60'/0'/0");
 var payment = bitcoinjs.payments.p2pkh({pubkey:node.publicKey});
 var address = payment.address;
 console.log(bs58.decode(address).toString('hex'));

Any ideas where I might have gone wrong with such a simple derivation? Or is there something larger that's screwed up?

junderw commented 3 years ago

Closing as this is not an issue with bip32, bip39, bs58, or bitcoinjs-lib. This is an issue of misunderstanding.

tl;dr You have two problems, unrelated to this library:

  1. We are a bitcoin library, so using the payments API to generate an address will NOT generate an ETH address. Bitcoin addresses and ETH addresses are completely different.
  2. MyEtherWallet's default first address is m/44'/60'/0'/0/0 and not m/44'/60'/0'/0 you are missing a 0.

One problem related to the way you made your issue:

  1. When giving a snippet to reproduce an error, having secret info that I don't have doesn't help me at all. Please reproduce the problem using a new private key so that you can share the private key here. So that I can use the same key and verify the issue.

I went ahead and generated a new wallet with MEW just to verify, after adding the 0 and using the correct address format, and it verifies.

スクリーンショット_2021-03-17_08-48-27

const bip39 = require('bip39')
const bip32 = require('bip32')
const secrets = {
  mnemonic: 'wild trash shock humble broom garage anchor relief have lunch into neutral',
  pass: 'mhDdAeFEWSEuw6dvOSURV4gPf',
}
const EXPECTED_ADDRESS_ETHEREUM = '0x7c5B7BAA518AF9a9C387185F60576506986F8959'

const seed = bip39.mnemonicToSeedSync(secrets.mnemonic, secrets.pass);
const root = bip32.fromSeed(seed);
const node = root.derivePath("m/44'/60'/0'/0/0"); // MEW shows m/44'/60'/0'/0 but this is the "parent" path.
// The multiple addresses that show up below that path are the "children" so you must add another layer.
// First address is 0, second is 1 etc etc.

// ---- ETH stuff from here on out

const publicKeyToAddress = require('ethereum-public-key-to-address')

const resultAddress = publicKeyToAddress(node.publicKey)

console.log(EXPECTED_ADDRESS_ETHEREUM)
console.log(resultAddress)
console.log(resultAddress === EXPECTED_ADDRESS_ETHEREUM)