diff --git a/hdkeychain/example_test.go b/hdkeychain/example_test.go index 26f8459..63d369f 100644 --- a/hdkeychain/example_test.go +++ b/hdkeychain/example_test.go @@ -22,7 +22,7 @@ func ExampleNewMaster() { } // Generate a new master node using the seed. - key, err := hdkeychain.NewMaster(seed) + key, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams) if err != nil { fmt.Println(err) return diff --git a/hdkeychain/extendedkey.go b/hdkeychain/extendedkey.go index e0de677..fb09d7c 100644 --- a/hdkeychain/extendedkey.go +++ b/hdkeychain/extendedkey.go @@ -440,7 +440,7 @@ func (k *ExtendedKey) Zero() { // will derive to an unusable secret key. The ErrUnusable error will be // returned if this should occur, so the caller must check for it and generate a // new seed accordingly. -func NewMaster(seed []byte) (*ExtendedKey, error) { +func NewMaster(seed []byte, net *chaincfg.Params) (*ExtendedKey, error) { // Per [BIP32], the seed must be in range [MinSeedBytes, MaxSeedBytes]. if len(seed) < MinSeedBytes || len(seed) > MaxSeedBytes { return nil, ErrInvalidSeedLen @@ -465,8 +465,8 @@ func NewMaster(seed []byte) (*ExtendedKey, error) { } parentFP := []byte{0x00, 0x00, 0x00, 0x00} - return newExtendedKey(chaincfg.MainNetParams.HDPrivateKeyID[:], secretKey, - chainCode, parentFP, 0, 0, true), nil + return newExtendedKey(net.HDPrivateKeyID[:], secretKey, chainCode, + parentFP, 0, 0, true), nil } // NewKeyFromString returns a new extended key instance from a base58-encoded diff --git a/hdkeychain/extendedkey_test.go b/hdkeychain/extendedkey_test.go index fddef70..95ce51a 100644 --- a/hdkeychain/extendedkey_test.go +++ b/hdkeychain/extendedkey_test.go @@ -33,6 +33,7 @@ func TestBIP0032Vectors(t *testing.T) { path []uint32 wantPub string wantPriv string + net *chaincfg.Params }{ // Test vector 1 { @@ -41,6 +42,7 @@ func TestBIP0032Vectors(t *testing.T) { path: []uint32{}, wantPub: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", wantPriv: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", + net: &chaincfg.MainNetParams, }, { name: "test vector 1 chain m/0H", @@ -48,6 +50,7 @@ func TestBIP0032Vectors(t *testing.T) { path: []uint32{hkStart}, wantPub: "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw", wantPriv: "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7", + net: &chaincfg.MainNetParams, }, { name: "test vector 1 chain m/0H/1", @@ -55,6 +58,7 @@ func TestBIP0032Vectors(t *testing.T) { path: []uint32{hkStart, 1}, wantPub: "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ", wantPriv: "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs", + net: &chaincfg.MainNetParams, }, { name: "test vector 1 chain m/0H/1/2H", @@ -62,6 +66,7 @@ func TestBIP0032Vectors(t *testing.T) { path: []uint32{hkStart, 1, hkStart + 2}, wantPub: "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5", wantPriv: "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM", + net: &chaincfg.MainNetParams, }, { name: "test vector 1 chain m/0H/1/2H/2", @@ -69,6 +74,7 @@ func TestBIP0032Vectors(t *testing.T) { path: []uint32{hkStart, 1, hkStart + 2, 2}, wantPub: "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV", wantPriv: "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334", + net: &chaincfg.MainNetParams, }, { name: "test vector 1 chain m/0H/1/2H/2/1000000000", @@ -76,6 +82,7 @@ func TestBIP0032Vectors(t *testing.T) { path: []uint32{hkStart, 1, hkStart + 2, 2, 1000000000}, wantPub: "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy", wantPriv: "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76", + net: &chaincfg.MainNetParams, }, // Test vector 2 @@ -85,6 +92,7 @@ func TestBIP0032Vectors(t *testing.T) { path: []uint32{}, wantPub: "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB", wantPriv: "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U", + net: &chaincfg.MainNetParams, }, { name: "test vector 2 chain m/0", @@ -92,6 +100,7 @@ func TestBIP0032Vectors(t *testing.T) { path: []uint32{0}, wantPub: "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH", wantPriv: "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt", + net: &chaincfg.MainNetParams, }, { name: "test vector 2 chain m/0/2147483647H", @@ -99,6 +108,7 @@ func TestBIP0032Vectors(t *testing.T) { path: []uint32{0, hkStart + 2147483647}, wantPub: "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a", wantPriv: "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9", + net: &chaincfg.MainNetParams, }, { name: "test vector 2 chain m/0/2147483647H/1", @@ -106,6 +116,7 @@ func TestBIP0032Vectors(t *testing.T) { path: []uint32{0, hkStart + 2147483647, 1}, wantPub: "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon", wantPriv: "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef", + net: &chaincfg.MainNetParams, }, { name: "test vector 2 chain m/0/2147483647H/1/2147483646H", @@ -113,6 +124,7 @@ func TestBIP0032Vectors(t *testing.T) { path: []uint32{0, hkStart + 2147483647, 1, hkStart + 2147483646}, wantPub: "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL", wantPriv: "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc", + net: &chaincfg.MainNetParams, }, { name: "test vector 2 chain m/0/2147483647H/1/2147483646H/2", @@ -120,6 +132,57 @@ func TestBIP0032Vectors(t *testing.T) { path: []uint32{0, hkStart + 2147483647, 1, hkStart + 2147483646, 2}, wantPub: "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt", wantPriv: "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j", + net: &chaincfg.MainNetParams, + }, + + // Test vector 1 - Testnet + { + name: "test vector 1 chain m - testnet", + master: testVec1MasterHex, + path: []uint32{}, + wantPub: "tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp", + wantPriv: "tprv8ZgxMBicQKsPeDgjzdC36fs6bMjGApWDNLR9erAXMs5skhMv36j9MV5ecvfavji5khqjWaWSFhN3YcCUUdiKH6isR4Pwy3U5y5egddBr16m", + net: &chaincfg.TestNet3Params, + }, + { + name: "test vector 1 chain m/0H - testnet", + master: testVec1MasterHex, + path: []uint32{hkStart}, + wantPub: "tpubD8eQVK4Kdxg3gHrF62jGP7dKVCoYiEB8dFSpuTawkL5YxTus5j5pf83vaKnii4bc6v2NVEy81P2gYrJczYne3QNNwMTS53p5uzDyHvnw2jm", + wantPriv: "tprv8bxNLu25VazNnppTCP4fyhyCvBHcYtzE3wr3cwYeL4HA7yf6TLGEUdS4QC1vLT63TkjRssqJe4CvGNEC8DzW5AoPUw56D1Ayg6HY4oy8QZ9", + net: &chaincfg.TestNet3Params, + }, + { + name: "test vector 1 chain m/0H/1 - testnet", + master: testVec1MasterHex, + path: []uint32{hkStart, 1}, + wantPub: "tpubDApXh6cD2fZ7WjtgpHd8yrWyYaneiFuRZa7fVjMkgxsmC1QzoXW8cgx9zQFJ81Jx4deRGfRE7yXA9A3STsxXj4CKEZJHYgpMYikkas9DBTP", + wantPriv: "tprv8e8VYgZxtHsSdGrtvdxYaSrryZGiYviWzGWtDDKTGh5NMXAEB8gYSCLHpFCywNs5uqV7ghRjimALQJkRFZnUrLHpzi2pGkwqLtbubgWuQ8q", + net: &chaincfg.TestNet3Params, + }, + { + name: "test vector 1 chain m/0H/1/2H - testnet", + master: testVec1MasterHex, + path: []uint32{hkStart, 1, hkStart + 2}, + wantPub: "tpubDDRojdS4jYQXNugn4t2WLrZ7mjfAyoVQu7MLk4eurqFCbrc7cHLZX8W5YRS8ZskGR9k9t3PqVv68bVBjAyW4nWM9pTGRddt3GQftg6MVQsm", + wantPriv: "tprv8gjmbDPpbAirVSezBEMuwSu1Ci9EpUJWKokZTYccSZSomNMLytWyLdtDNHRbucNaRJWWHANf9AzEdWVAqahfyRjVMKbNRhBmxAM8EJr7R15", + net: &chaincfg.TestNet3Params, + }, + { + name: "test vector 1 chain m/0H/1/2H/2 - testnet", + master: testVec1MasterHex, + path: []uint32{hkStart, 1, hkStart + 2, 2}, + wantPub: "tpubDFfCa4Z1v25WTPAVm9EbEMiRrYwucPocLbEe12BPBGooxxEUg42vihy1DkRWyftztTsL23snYezF9uXjGGwGW6pQjEpcTpmsH6ajpf4CVPn", + wantPriv: "tprv8iyAReWmmePqZv8hsVZzpx4KHXRyT4chmHdriW95m11R8Tyi3fDLYDM93bq4NGn1V6eCu5cE3zSQ6hPd31F2ApKXkZgTyn1V78pHjkq1V2v", + net: &chaincfg.TestNet3Params, + }, + { + name: "test vector 1 chain m/0H/1/2H/2/1000000000 - testnet", + master: testVec1MasterHex, + path: []uint32{hkStart, 1, hkStart + 2, 2, 1000000000}, + wantPub: "tpubDHNy3kAG39ThyiwwsgoKY4iRenXDRtce8qdCFJZXPMCJg5dsCUHayp84raLTpvyiNA9sXPob5rgqkKvkN8S7MMyXbnEhGJMW64Cf4vFAoaF", + wantPriv: "tprv8kgvuL81tmn36Fv9z38j8f4K5m1HGZRjZY2QxnXDy5PuqbP6a5TzoKWCgTcGHBu66W3TgSbAu2yX6sPza5FkHmy564Sh6gmCPUNeUt4yj2x", + net: &chaincfg.TestNet3Params, }, } @@ -132,7 +195,7 @@ tests: continue } - extKey, err := hdkeychain.NewMaster(masterSeed) + extKey, err := hdkeychain.NewMaster(masterSeed, test.net) if err != nil { t.Errorf("NewMaster #%d (%s): unexpected error when "+ "creating new master key: %v", i, test.name, @@ -585,14 +648,15 @@ func TestNet(t *testing.T) { // the errors are handled properly. func TestErrors(t *testing.T) { // Should get an error when seed has too few bytes. - _, err := hdkeychain.NewMaster(bytes.Repeat([]byte{0x00}, 15)) + net := &chaincfg.MainNetParams + _, err := hdkeychain.NewMaster(bytes.Repeat([]byte{0x00}, 15), net) if err != hdkeychain.ErrInvalidSeedLen { t.Errorf("NewMaster: mismatched error -- got: %v, want: %v", err, hdkeychain.ErrInvalidSeedLen) } // Should get an error when seed has too many bytes. - _, err = hdkeychain.NewMaster(bytes.Repeat([]byte{0x00}, 65)) + _, err = hdkeychain.NewMaster(bytes.Repeat([]byte{0x00}, 65), net) if err != hdkeychain.ErrInvalidSeedLen { t.Errorf("NewMaster: mismatched error -- got: %v, want: %v", err, hdkeychain.ErrInvalidSeedLen) @@ -604,7 +668,7 @@ func TestErrors(t *testing.T) { t.Errorf("GenerateSeed: unexpected error: %v", err) return } - extKey, err := hdkeychain.NewMaster(seed) + extKey, err := hdkeychain.NewMaster(seed, net) if err != nil { t.Errorf("NewMaster: unexpected error: %v", err) return @@ -681,12 +745,14 @@ func TestZero(t *testing.T) { name string master string extKey string + net *chaincfg.Params }{ // Test vector 1 { name: "test vector 1 chain m", master: "000102030405060708090a0b0c0d0e0f", extKey: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", + net: &chaincfg.MainNetParams, }, // Test vector 2 @@ -694,6 +760,7 @@ func TestZero(t *testing.T) { name: "test vector 2 chain m", master: "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542", extKey: "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U", + net: &chaincfg.MainNetParams, }, } @@ -767,7 +834,7 @@ func TestZero(t *testing.T) { i, test.name, err) continue } - key, err := hdkeychain.NewMaster(masterSeed) + key, err := hdkeychain.NewMaster(masterSeed, test.net) if err != nil { t.Errorf("NewMaster #%d (%s): unexpected error when "+ "creating new master key: %v", i, test.name,