Skip to content

Commit d3e14a4

Browse files
committed
lnd/hdkeychain: add support for xpubs in DeriveKey
If the extendedKey is an xpub, then private key is not generated and the returned WIF will be nil. This enables passing an xpub to "chantools derivekey --rootkey". Added a test for this new feature.
1 parent d93e390 commit d3e14a4

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

cmd/chantools/derivekey_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,24 @@ func TestDeriveKeyXprv(t *testing.T) {
102102
h.assertLogContains("cQcdieZy2d1TAdCsa5MjmHJs2gdHcD7x22nDbhJyVTUa3Ax" +
103103
"5KB3w")
104104
}
105+
106+
func TestDeriveKeyXpub(t *testing.T) {
107+
h := newHarness(t)
108+
109+
// Derive a specific key from xpub.
110+
derive := &deriveKeyCommand{
111+
Path: "m/5/6",
112+
rootKey: &rootKey{
113+
RootKey: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap" +
114+
"9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqse" +
115+
"fD265TMg7usUDFdp6W1EGMcet8",
116+
},
117+
Neuter: true,
118+
}
119+
120+
err := derive.Execute(nil, nil)
121+
require.NoError(t, err)
122+
123+
h.assertLogContains("03dc8655d58bd4fd4326863fe34bd5cdddbefaa3b042571" +
124+
"05eb1ab99aa05e01c2a")
125+
}

lnd/hdkeychain.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ func HardenedKey(key uint32) uint32 {
110110
}
111111

112112
// DeriveKey derives the public key and private key in the WIF format for a
113-
// given key path of the extended key.
113+
// given key path from the extended key. If the extendedKey is an xpub, then
114+
// private key is not generated and the returned WIF will be nil.
114115
func DeriveKey(extendedKey *hdkeychain.ExtendedKey, path string,
115116
params *chaincfg.Params) (*hdkeychain.ExtendedKey, *btcec.PublicKey,
116117
*btcutil.WIF, error) {
@@ -131,6 +132,11 @@ func DeriveKey(extendedKey *hdkeychain.ExtendedKey, path string,
131132
"key: %w", err)
132133
}
133134

135+
// If the extended key is xpub, we can't generate the private key.
136+
if !derivedKey.IsPrivate() {
137+
return derivedKey, pubKey, nil, nil
138+
}
139+
134140
privKey, err := derivedKey.ECPrivKey()
135141
if err != nil {
136142
return nil, nil, nil, fmt.Errorf("could not derive private "+

0 commit comments

Comments
 (0)