From dccef4c8bf28f2c92fa5c82e5f677864fad0a35a Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 26 Apr 2019 17:20:36 -0700 Subject: [PATCH] watchtower/wtdb/codec: import channeldb code for extension --- watchtower/wtdb/codec.go | 143 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 watchtower/wtdb/codec.go diff --git a/watchtower/wtdb/codec.go b/watchtower/wtdb/codec.go new file mode 100644 index 00000000..2fd30196 --- /dev/null +++ b/watchtower/wtdb/codec.go @@ -0,0 +1,143 @@ +package wtdb + +import ( + "io" + + "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/lnwallet" + "github.com/lightningnetwork/lnd/watchtower/blob" + "github.com/lightningnetwork/lnd/watchtower/wtpolicy" +) + +// UnknownElementType is an alias for channeldb.UnknownElementType. +type UnknownElementType = channeldb.UnknownElementType + +// ReadElement deserializes a single element from the provided io.Reader. +func ReadElement(r io.Reader, element interface{}) error { + err := channeldb.ReadElement(r, element) + switch { + + // Known to channeldb codec. + case err == nil: + return nil + + // Fail if error is not UnknownElementType. + case err != nil: + if _, ok := err.(UnknownElementType); !ok { + return err + } + } + + // Process any wtdb-specific extensions to the codec. + switch e := element.(type) { + + case *SessionID: + if _, err := io.ReadFull(r, e[:]); err != nil { + return err + } + + case *BreachHint: + if _, err := io.ReadFull(r, e[:]); err != nil { + return err + } + + case *wtpolicy.Policy: + var ( + blobType uint16 + sweepFeeRate uint64 + ) + err := channeldb.ReadElements(r, + &blobType, + &e.MaxUpdates, + &e.RewardBase, + &e.RewardRate, + &sweepFeeRate, + ) + if err != nil { + return err + } + + e.BlobType = blob.Type(blobType) + e.SweepFeeRate = lnwallet.SatPerKWeight(sweepFeeRate) + + // Type is still unknown to wtdb extensions, fail. + default: + return channeldb.NewUnknownElementType( + "ReadElement", element, + ) + } + + return nil +} + +// WriteElement serializes a single element into the provided io.Writer. +func WriteElement(w io.Writer, element interface{}) error { + err := channeldb.WriteElement(w, element) + switch { + + // Known to channeldb codec. + case err == nil: + return nil + + // Fail if error is not UnknownElementType. + case err != nil: + if _, ok := err.(UnknownElementType); !ok { + return err + } + } + + // Process any wtdb-specific extensions to the codec. + switch e := element.(type) { + + case SessionID: + if _, err := w.Write(e[:]); err != nil { + return err + } + + case BreachHint: + if _, err := w.Write(e[:]); err != nil { + return err + } + + case wtpolicy.Policy: + return channeldb.WriteElements(w, + uint16(e.BlobType), + e.MaxUpdates, + e.RewardBase, + e.RewardRate, + uint64(e.SweepFeeRate), + ) + + // Type is still unknown to wtdb extensions, fail. + default: + return channeldb.NewUnknownElementType( + "WriteElement", element, + ) + } + + return nil +} + +// WriteElements serializes a variadic list of elements into the given +// io.Writer. +func WriteElements(w io.Writer, elements ...interface{}) error { + for _, element := range elements { + if err := WriteElement(w, element); err != nil { + return err + } + } + + return nil +} + +// ReadElements deserializes the provided io.Reader into a variadic list of +// target elements. +func ReadElements(r io.Reader, elements ...interface{}) error { + for _, element := range elements { + if err := ReadElement(r, element); err != nil { + return err + } + } + + return nil +}