Skip to content

Commit

Permalink
Merge pull request #179 from starius/xpub-derive
Browse files Browse the repository at this point in the history
derivekey: support xpubs in addition to xprvs
  • Loading branch information
guggero authored Jan 12, 2025
2 parents b352ed9 + 6e4a076 commit 74b748e
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 2 deletions.
2 changes: 1 addition & 1 deletion cmd/chantools/derivekey.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func deriveKey(extendedKey *hdkeychain.ExtendedKey, path string,
}

privKey, xPriv := na, na
if !neuter {
if !neuter && wif != nil {
privKey, xPriv = wif.String(), child.String()
}

Expand Down
61 changes: 61 additions & 0 deletions cmd/chantools/derivekey_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,64 @@ func TestDeriveKeySeedBip39(t *testing.T) {

h.assertLogContains(keyContentBIP39)
}

func TestDeriveKeyXprv(t *testing.T) {
h := newHarness(t)

// Derive a specific key from xprv.
derive := &deriveKeyCommand{
Path: testPath,
rootKey: &rootKey{
RootKey: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nR" +
"k4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejM" +
"RNNU3TGtRBeJgk33yuGBxrMPHi",
},
}

err := derive.Execute(nil, nil)
require.NoError(t, err)

h.assertLogContains("cQcdieZy2d1TAdCsa5MjmHJs2gdHcD7x22nDbhJyVTUa3Ax" +
"5KB3w")
}

func TestDeriveKeyXpub(t *testing.T) {
h := newHarness(t)

// Derive a specific key from xpub.
derive := &deriveKeyCommand{
Path: "m/5/6",
rootKey: &rootKey{
RootKey: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap" +
"9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqse" +
"fD265TMg7usUDFdp6W1EGMcet8",
},
Neuter: true,
}

err := derive.Execute(nil, nil)
require.NoError(t, err)

h.assertLogContains("03dc8655d58bd4fd4326863fe34bd5cdddbefaa3b042571" +
"05eb1ab99aa05e01c2a")
}

func TestDeriveKeyXpubNoNeuter(t *testing.T) {
h := newHarness(t)

// Derive a specific key from xpub.
derive := &deriveKeyCommand{
Path: "m/5/6",
rootKey: &rootKey{
RootKey: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap" +
"9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqse" +
"fD265TMg7usUDFdp6W1EGMcet8",
},
}

err := derive.Execute(nil, nil)
require.NoError(t, err)

h.assertLogContains("03dc8655d58bd4fd4326863fe34bd5cdddbefaa3b042571" +
"05eb1ab99aa05e01c2a")
}
8 changes: 7 additions & 1 deletion lnd/hdkeychain.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ func HardenedKey(key uint32) uint32 {
}

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

// If the extended key is xpub, we can't generate the private key.
if !derivedKey.IsPrivate() {
return derivedKey, pubKey, nil, nil
}

privKey, err := derivedKey.ECPrivKey()
if err != nil {
return nil, nil, nil, fmt.Errorf("could not derive private "+
Expand Down

0 comments on commit 74b748e

Please sign in to comment.