Skip to content

Commit af563bb

Browse files
committed
lnd: replicate btcwallet's key derivation exactly
There's this special case in lnd's wallet (btcwallet) where the coin type and account keys are always serialized as a string and encrypted, which actually fixes the key padding issue that makes the difference between DeriveNonStandard and Derive. To replicate lnd's behavior exactly, we need to serialize and de-serialize the extended key at the coin type and account level (depth = 2 or depth = 3). This does not apply to the default account (id = 0) because that is always derived directly.
1 parent d67675e commit af563bb

File tree

1 file changed

+24
-5
lines changed

1 file changed

+24
-5
lines changed

lnd/hdkeychain.go

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,34 @@ const (
2727
func DeriveChildren(key *hdkeychain.ExtendedKey, path []uint32) (
2828
*hdkeychain.ExtendedKey, error) {
2929

30-
var (
31-
currentKey = key
32-
err error
33-
)
30+
var currentKey = key
3431
for _, pathPart := range path {
35-
currentKey, err = currentKey.DeriveNonStandard(pathPart)
32+
derivedKey, err := currentKey.DeriveNonStandard(pathPart)
3633
if err != nil {
3734
return nil, err
3835
}
36+
37+
// There's this special case in lnd's wallet (btcwallet) where
38+
// the coin type and account keys are always serialized as a
39+
// string and encrypted, which actually fixes the key padding
40+
// issue that makes the difference between DeriveNonStandard and
41+
// Derive. To replicate lnd's behavior exactly, we need to
42+
// serialize and de-serialize the extended key at the coin type
43+
// and account level (depth = 2 or depth = 3). This does not
44+
// apply to the default account (id = 0) because that is always
45+
// derived directly.
46+
depth := derivedKey.Depth()
47+
keyID := pathPart - hdkeychain.HardenedKeyStart
48+
if (depth == 3 && keyID != 0) || depth == 2 {
49+
currentKey, err = hdkeychain.NewKeyFromString(
50+
derivedKey.String(),
51+
)
52+
if err != nil {
53+
return nil, err
54+
}
55+
} else {
56+
currentKey = derivedKey
57+
}
3958
}
4059
return currentKey, nil
4160
}

0 commit comments

Comments
 (0)