Skip to content

Instantly share code, notes, and snippets.

@d10r
Created February 5, 2022 21:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save d10r/f06be82992c8e8187bbd9fb4376505cd to your computer and use it in GitHub Desktop.
Save d10r/f06be82992c8e8187bbd9fb4376505cd to your computer and use it in GitHub Desktop.
exploring HD key derivation
/*
BIP32 - Hierarchical Deterministic Wallet defines the semantics of a derivation path
This is some examples for paths mapped to Ethereum addresses
0 invalid (must start with m)
m 0x9b4aeeec68a20e186e98a404312869ff3330eac3
m' 0x9b4aeeec68a20e186e98a404312869ff3330eac3 (there's only 1 master)
m/ invalid
m/0 0x80e76859d6615e17c3fef155903fa9062c7bacc7 - this is the default account (child 0)
m/0' 0xd93fb97bf78b67abb415d4e56fa040efbb6662da
m/44'/60'/0'/0 0xcdda29172785891bc5ab854817457ef51c74d7c5 (Ethereum default)
m/1337/0 0xa4033517055034e69e6f8981eb44cd1a026037ea
BIP43 - Purpose Field for Deterministic Wallets
Specified that the first level of the BIP32 tree structure shall denote the "purpose". m/0' is alread "taken" (default account)
BIP44 - Multi-Account Hierarchy for Deterministic Wallets
Specified that paths with purpose 44' (hardened) shall have paths according the BIP44 schema: m/44'/coin_type'/account'/change/address_index
This makes sense for UTXO, not so much for account based systems. Adopted anyway.
Ethereum default: m/44'/60'/0'/0
*/
// inspiration source: https://github.com/kennethhutw/BIP32/blob/master/index.js
W = require('ethereumjs-wallet');
bip39 = require('bip39');
HDKey = W.hdkey;
mnemonic = 'violin exact grit step ask enforce stock floor rival man trim actress';
bip39.mnemonicToSeed(mnemonic).then(s => {
seed = s;
nodeM = HDKey.fromMasterSeed(seed);
privExtKey = nodeM.privateExtendedKey();
console.log(`private extended key: ${privExtKey}`);
pubExtKey = nodeM.publicExtendedKey();
console.log(`public extended key: ${pubExtKey}`);
// every node is of type HDKey, has a method getWallet()
// deriveChild(0) is equivalent to derivePath("m/0")
console.log("nodeM.deriveChild(0): ", nodeM.deriveChild(0).getWallet().getAddressString());
console.log('nodeM.derivePath:("m/0") ', nodeM.derivePath("m/0").getWallet().getAddressString());
console.log("nodeM.derivePath(m/1337/0): ", nodeM.derivePath("m/1337/0").getWallet().getAddressString());
node1337 = nodeM.derivePath("m/1337");
console.log("node1337.deriveChild(0): ", node1337.deriveChild(0).getWallet().getAddressString());
});
// output:
/*
$ cat ~/bin/node-init-with
node -i --experimental-repl-await -e "`cat $1`"
$ node-init-with hdkeys.js
Welcome to Node.js v14.18.3.
Type ".help" for more information.
> private extended key: xprv9s21ZrQH143K25crXSo1GZmL4MXHJCyg8KRdJQyHPYLMwQYGQ7Gj8hTRokQLao8xTsNzC9Da4qnv4Fh4G19Jm2eQqBH8aAaF3
public extended key: xpub661MyMwAqRbcEZhKdUL1dhi4cPMmhfhXVYME6oNtwssLpCsQweaygVmuf1LtgjBENLf5LBD1MLx9UUsFDStmWtBF3maoS1wfC
nodeM.deriveChild(0): 0x80e76859d6615e17c3fef155903fa9062c7bacc7
nodeM.derivePath:("m/0") 0x80e76859d6615e17c3fef155903fa9062c7bacc7
nodeM.derivePath(m/1337/0): 0xa6b11544f9a540c1b320f06526d2742489b394c9
node1337.deriveChild(0): 0xa6b11544f9a540c1b320f06526d2742489b394c9
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment