2
0
mirror of https://github.com/guggero/chantools synced 2024-11-11 01:10:42 +00:00
chantools/hdkeychain.go
2020-01-04 13:11:11 +01:00

97 lines
2.1 KiB
Go

package chantools
import (
"fmt"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcutil/hdkeychain"
"github.com/lightningnetwork/lnd/keychain"
"strconv"
"strings"
)
const (
hardenedKeyStart = uint32(hdkeychain.HardenedKeyStart)
)
func deriveChildren(key *hdkeychain.ExtendedKey, path []uint32) (
*hdkeychain.ExtendedKey, error) {
var (
currentKey = key
err error
)
for _, pathPart := range path {
currentKey, err = currentKey.Child(pathPart)
if err != nil {
return nil, err
}
}
return currentKey, nil
}
func parsePath(path string) ([]uint32, error) {
path = strings.TrimSpace(path)
if len(path) == 0 {
return nil, fmt.Errorf("path cannot be empty")
}
if !strings.HasPrefix(path, "m/") {
return nil, fmt.Errorf("path must start with m/")
}
parts := strings.Split(path, "/")
indices := make([]uint32, len(parts)-1)
for i := 1; i < len(parts); i++ {
index := uint32(0)
part := parts[i]
if strings.Contains(parts[i], "'") {
index += hardenedKeyStart
part = strings.TrimRight(parts[i], "'")
}
parsed, err := strconv.Atoi(part)
if err != nil {
return nil, fmt.Errorf("could not parse part \"%s\": "+
"%v", part, err)
}
indices[i-1] = index + uint32(parsed)
}
return indices, nil
}
type channelBackupEncryptionRing struct {
extendedKey *hdkeychain.ExtendedKey
chainParams *chaincfg.Params
}
func (r *channelBackupEncryptionRing) DeriveNextKey(_ keychain.KeyFamily) (
keychain.KeyDescriptor, error) {
return keychain.KeyDescriptor{}, nil
}
func (r *channelBackupEncryptionRing) DeriveKey(keyLoc keychain.KeyLocator) (
keychain.KeyDescriptor, error) {
var empty = keychain.KeyDescriptor{}
keyBackup, err := deriveChildren(r.extendedKey, []uint32{
hardenedKeyStart + uint32(keychain.BIP0043Purpose),
hardenedKeyStart + r.chainParams.HDCoinType,
hardenedKeyStart + uint32(keyLoc.Family),
0,
keyLoc.Index,
})
if err != nil {
return empty, err
}
backupPubKey, err := keyBackup.ECPubKey()
if err != nil {
return empty, err
}
return keychain.KeyDescriptor{
KeyLocator: keychain.KeyLocator{
Family: keyLoc.Family,
Index: keyLoc.Index,
},
PubKey: backupPubKey,
}, nil
}