From 705661a39eee9d858b53a4fdb73c162de3d54eb7 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sat, 17 Feb 2018 15:14:07 -0800 Subject: [PATCH] channeldb: replace raw keys in ChannelConfig with keychain.KeyDescriptor In this commit, we remove references to raw keys from the main ChannelConfig struct and instead replace it with usage of keychain.KeyDescriptor. We do this, as the ChannelConfig as it stands is a near complete static description of a channel. In the future, it will be possible to export these static descriptions as backups. We prefer the KeyDescriptor of a plain PublicKey, as the KeyLocator portion of the struct allows a stateless signer to re-derive the keys as needed when signing. --- channeldb/channel.go | 11 +++++----- channeldb/channel_test.go | 45 ++++++++++++++++++++++++++++----------- channeldb/codec.go | 34 +++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 17 deletions(-) diff --git a/channeldb/channel.go b/channeldb/channel.go index 23469596..0153f3d7 100644 --- a/channeldb/channel.go +++ b/channeldb/channel.go @@ -9,6 +9,7 @@ import ( "sync" "github.com/boltdb/bolt" + "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/shachain" "github.com/roasbeef/btcd/btcec" @@ -170,33 +171,33 @@ type ChannelConfig struct { // MultiSigKey is the key to be used within the 2-of-2 output script // for the owner of this channel config. - MultiSigKey *btcec.PublicKey + MultiSigKey keychain.KeyDescriptor // RevocationBasePoint is the base public key to be used when deriving // revocation keys for the remote node's commitment transaction. This // will be combined along with a per commitment secret to derive a // unique revocation key for each state. - RevocationBasePoint *btcec.PublicKey + RevocationBasePoint keychain.KeyDescriptor // PaymentBasePoint is the base public key to be used when deriving // the key used within the non-delayed pay-to-self output on the // commitment transaction for a node. This will be combined with a // tweak derived from the per-commitment point to ensure unique keys // for each commitment transaction. - PaymentBasePoint *btcec.PublicKey + PaymentBasePoint keychain.KeyDescriptor // DelayBasePoint is the base public key to be used when deriving the // key used within the delayed pay-to-self output on the commitment // transaction for a node. This will be combined with a tweak derived // from the per-commitment point to ensure unique keys for each // commitment transaction. - DelayBasePoint *btcec.PublicKey + DelayBasePoint keychain.KeyDescriptor // HtlcBasePoint is the base public key to be used when deriving the // local HTLC key. The derived key (combined with the tweak derived // from the per-commitment point) is used within the "to self" clause // within any HTLC output scripts. - HtlcBasePoint *btcec.PublicKey + HtlcBasePoint keychain.KeyDescriptor } // ChannelCommitment is a snapshot of the commitment state at a particular diff --git a/channeldb/channel_test.go b/channeldb/channel_test.go index b2643a93..072d24a0 100644 --- a/channeldb/channel_test.go +++ b/channeldb/channel_test.go @@ -11,6 +11,7 @@ import ( "testing" "github.com/davecgh/go-spew/spew" + "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/shachain" "github.com/roasbeef/btcd/btcec" @@ -136,12 +137,22 @@ func createTestChannelState(cdb *DB) (*OpenChannel, error) { MinHTLC: lnwire.MilliSatoshi(rand.Int63()), MaxAcceptedHtlcs: uint16(rand.Int31()), }, - CsvDelay: uint16(rand.Int31()), - MultiSigKey: privKey.PubKey(), - RevocationBasePoint: privKey.PubKey(), - PaymentBasePoint: privKey.PubKey(), - DelayBasePoint: privKey.PubKey(), - HtlcBasePoint: privKey.PubKey(), + CsvDelay: uint16(rand.Int31()), + MultiSigKey: keychain.KeyDescriptor{ + PubKey: privKey.PubKey(), + }, + RevocationBasePoint: keychain.KeyDescriptor{ + PubKey: privKey.PubKey(), + }, + PaymentBasePoint: keychain.KeyDescriptor{ + PubKey: privKey.PubKey(), + }, + DelayBasePoint: keychain.KeyDescriptor{ + PubKey: privKey.PubKey(), + }, + HtlcBasePoint: keychain.KeyDescriptor{ + PubKey: privKey.PubKey(), + }, } remoteCfg := ChannelConfig{ ChannelConstraints: ChannelConstraints{ @@ -151,12 +162,22 @@ func createTestChannelState(cdb *DB) (*OpenChannel, error) { MinHTLC: lnwire.MilliSatoshi(rand.Int63()), MaxAcceptedHtlcs: uint16(rand.Int31()), }, - CsvDelay: uint16(rand.Int31()), - MultiSigKey: privKey.PubKey(), - RevocationBasePoint: privKey.PubKey(), - PaymentBasePoint: privKey.PubKey(), - DelayBasePoint: privKey.PubKey(), - HtlcBasePoint: privKey.PubKey(), + CsvDelay: uint16(rand.Int31()), + MultiSigKey: keychain.KeyDescriptor{ + PubKey: privKey.PubKey(), + }, + RevocationBasePoint: keychain.KeyDescriptor{ + PubKey: privKey.PubKey(), + }, + PaymentBasePoint: keychain.KeyDescriptor{ + PubKey: privKey.PubKey(), + }, + DelayBasePoint: keychain.KeyDescriptor{ + PubKey: privKey.PubKey(), + }, + HtlcBasePoint: keychain.KeyDescriptor{ + PubKey: privKey.PubKey(), + }, } chanID := lnwire.NewShortChanIDFromInt(uint64(rand.Int63())) diff --git a/channeldb/codec.go b/channeldb/codec.go index 5db6dd90..14665e0c 100644 --- a/channeldb/codec.go +++ b/channeldb/codec.go @@ -5,6 +5,7 @@ import ( "fmt" "io" + "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/shachain" "github.com/roasbeef/btcd/btcec" @@ -48,6 +49,22 @@ func readOutpoint(r io.Reader, o *wire.OutPoint) error { // to dynamically expand to accommodate additional data. func writeElement(w io.Writer, element interface{}) error { switch e := element.(type) { + case keychain.KeyDescriptor: + if err := binary.Write(w, byteOrder, e.Family); err != nil { + return err + } + if err := binary.Write(w, byteOrder, e.Index); err != nil { + return err + } + + if e.PubKey != nil { + if err := binary.Write(w, byteOrder, true); err != nil { + } + + return writeElement(w, e.PubKey) + } + + return binary.Write(w, byteOrder, false) case ChannelType: if err := binary.Write(w, byteOrder, e); err != nil { return err @@ -163,6 +180,23 @@ func writeElements(w io.Writer, elements ...interface{}) error { // encoded using the serialization format of the database. func readElement(r io.Reader, element interface{}) error { switch e := element.(type) { + case *keychain.KeyDescriptor: + if err := binary.Read(r, byteOrder, &e.Family); err != nil { + return err + } + if err := binary.Read(r, byteOrder, &e.Index); err != nil { + return err + } + + var hasPubKey bool + if err := binary.Read(r, byteOrder, &hasPubKey); err != nil { + return err + } + + if hasPubKey { + return readElement(r, &e.PubKey) + } + case *ChannelType: if err := binary.Read(r, byteOrder, e); err != nil { return err