diff --git a/watchtower/wtclient/interface.go b/watchtower/wtclient/interface.go index b770343ee..df8f376e7 100644 --- a/watchtower/wtclient/interface.go +++ b/watchtower/wtclient/interface.go @@ -5,6 +5,7 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/lightningnetwork/lnd/brontide" + "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/watchtower/wtdb" "github.com/lightningnetwork/lnd/watchtower/wtserver" @@ -77,3 +78,11 @@ func AuthDial(localPriv *btcec.PrivateKey, netAddr *lnwire.NetAddress, return brontide.Dial(localPriv, netAddr, dialer) } + +// SecretKeyRing abstracts the ability to derive HD private keys given a +// description of the derivation path. +type SecretKeyRing interface { + // DerivePrivKey derives the private key from the root seed using a + // key descriptor specifying the key's derivation path. + DerivePrivKey(loc keychain.KeyDescriptor) (*btcec.PrivateKey, error) +} diff --git a/watchtower/wtmock/keyring.go b/watchtower/wtmock/keyring.go new file mode 100644 index 000000000..f18a0fa8e --- /dev/null +++ b/watchtower/wtmock/keyring.go @@ -0,0 +1,44 @@ +package wtmock + +import ( + "sync" + + "github.com/btcsuite/btcd/btcec" + "github.com/lightningnetwork/lnd/keychain" +) + +// SecretKeyRing is a mock, in-memory implementation for deriving private keys. +type SecretKeyRing struct { + mu sync.Mutex + keys map[keychain.KeyLocator]*btcec.PrivateKey +} + +// NewSecretKeyRing creates a new mock SecretKeyRing. +func NewSecretKeyRing() *SecretKeyRing { + return &SecretKeyRing{ + keys: make(map[keychain.KeyLocator]*btcec.PrivateKey), + } +} + +// DerivePrivKey derives the private key for a given key descriptor. If +// this method is called twice with the same argument, it will return the same +// private key. +func (m *SecretKeyRing) DerivePrivKey( + desc keychain.KeyDescriptor) (*btcec.PrivateKey, error) { + + m.mu.Lock() + defer m.mu.Unlock() + + if key, ok := m.keys[desc.KeyLocator]; ok { + return key, nil + } + + privKey, err := btcec.NewPrivateKey(btcec.S256()) + if err != nil { + return nil, err + } + + m.keys[desc.KeyLocator] = privKey + + return privKey, nil +}