diff --git a/hdkeychain/extendedkey.go b/hdkeychain/extendedkey.go index 907e16b..48c0421 100644 --- a/hdkeychain/extendedkey.go +++ b/hdkeychain/extendedkey.go @@ -191,6 +191,21 @@ func (k *ExtendedKey) ParentFingerprint() uint32 { return binary.BigEndian.Uint32(k.parentFP) } +// ChainCode returns the chain code part of this extended key. +// +// It is identical for both public and private extended keys. +func (k *ExtendedKey) ChainCode() []byte { + return append([]byte{}, k.chainCode...) +} + +// ChildNum returns the index at which the child extended key was derived. +// +// Extended keys with ChildNum value between 0 and 2^31-1 are normal child +// keys, and those with a value between 2^31 and 2^32-1 are hardened keys. +func (k *ExtendedKey) ChildNum() uint32 { + return k.childNum +} + // Child returns a derived child extended key at the given index. When this // extended key is a private extended key (as determined by the IsPrivate // function), a private extended key will be derived. Otherwise, the derived diff --git a/hdkeychain/extendedkey_test.go b/hdkeychain/extendedkey_test.go index b45f7cf..09c6f05 100644 --- a/hdkeychain/extendedkey_test.go +++ b/hdkeychain/extendedkey_test.go @@ -562,6 +562,8 @@ func TestExtendedKeyAPI(t *testing.T) { extKey string isPrivate bool parentFP uint32 + chainCode []byte + childNum uint32 privKey string privKeyErr error pubKey string @@ -572,6 +574,8 @@ func TestExtendedKeyAPI(t *testing.T) { extKey: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", isPrivate: true, parentFP: 0, + chainCode: []byte{135, 61, 255, 129, 192, 47, 82, 86, 35, 253, 31, 229, 22, 126, 172, 58, 85, 160, 73, 222, 61, 49, 75, 180, 46, 226, 39, 255, 237, 55, 213, 8}, + childNum: 0, privKey: "e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35", pubKey: "0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2", address: "15mKKb2eos1hWa6tisdPwwDC1a5J1y9nma", @@ -581,6 +585,8 @@ func TestExtendedKeyAPI(t *testing.T) { extKey: "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5", isPrivate: false, parentFP: 3203769081, + chainCode: []byte{4, 70, 107, 156, 200, 225, 97, 233, 102, 64, 156, 165, 41, 134, 197, 132, 240, 126, 157, 200, 31, 115, 93, 182, 131, 195, 255, 110, 199, 177, 80, 63}, + childNum: 2147483650, privKeyErr: ErrNotPrivExtKey, pubKey: "0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2", address: "1NjxqbA9aZWnh17q1UW3rB4EPu79wDXj7x", @@ -610,6 +616,20 @@ func TestExtendedKeyAPI(t *testing.T) { continue } + chainCode := key.ChainCode() + if !bytes.Equal(chainCode, test.chainCode) { + t.Errorf("ChainCode #%d (%s): want %v, got %v", i, + test.name, chainCode, test.chainCode) + continue + } + + childNum := key.ChildNum() + if childNum != test.childNum { + t.Errorf("ChildNum #%d (%s): want %d, got %d", i, + test.name, childNum, test.childNum) + continue + } + serializedKey := key.String() if serializedKey != test.extKey { t.Errorf("String #%d (%s): mismatched serialized key "+