lnwire: introduce new explicit ChannelType TLV record

In this commit, we add a new TLV record that's intended to be used as an
explicit channel commitment type for a new form of funding negotiation,
and later on a dynamic commitment upgrade protocol. As defined, we have
3 channel types: base (the OG), tweakless, and anchors w/ zero fee
HTLCs. We omit the original variant of anchors as it was never truly
deployed from the PoV of lnd.
This commit is contained in:
Olaoluwa Osuntokun
2021-03-03 19:32:14 -08:00
parent 3b026c401c
commit 988d01de0d
2 changed files with 86 additions and 0 deletions

58
lnwire/channel_type.go Normal file
View File

@@ -0,0 +1,58 @@
package lnwire
import (
"io"
"github.com/lightningnetwork/lnd/tlv"
)
const (
// ChannelTypeRecordType is the type of the experimental record used
// to denote which channel type is being negotiated.
ChannelTypeRecordType tlv.Type = 1
)
// ChannelType represents a specific channel type as a set of feature bits that
// comprise it.
type ChannelType RawFeatureVector
// featureBitLen returns the length in bytes of the encoded feature bits.
func (c ChannelType) featureBitLen() uint64 {
fv := RawFeatureVector(c)
return uint64(fv.SerializeSize())
}
// Record returns a TLV record that can be used to encode/decode the channel
// type from a given TLV stream.
func (c *ChannelType) Record() tlv.Record {
return tlv.MakeDynamicRecord(
ChannelTypeRecordType, c, c.featureBitLen, channelTypeEncoder,
channelTypeDecoder,
)
}
// channelTypeEncoder is a custom TLV encoder for the ChannelType record.
func channelTypeEncoder(w io.Writer, val interface{}, buf *[8]byte) error {
if v, ok := val.(*ChannelType); ok {
// Encode the feature bits as a byte slice without its length
// prepended, as that's already taken care of by the TLV record.
fv := RawFeatureVector(*v)
return fv.encode(w, fv.SerializeSize(), 8)
}
return tlv.NewTypeForEncodingErr(val, "lnwire.ChannelType")
}
// channelTypeDecoder is a custom TLV decoder for the ChannelType record.
func channelTypeDecoder(r io.Reader, val interface{}, buf *[8]byte, l uint64) error {
if v, ok := val.(*ChannelType); ok {
fv := NewRawFeatureVector()
if err := fv.decode(r, int(l), 8); err != nil {
return err
}
*v = ChannelType(*fv)
return nil
}
return tlv.NewTypeForEncodingErr(val, "lnwire.ChannelType")
}

View File

@@ -0,0 +1,28 @@
package lnwire
import (
"testing"
"github.com/stretchr/testify/require"
)
// TestChannelTypeEncodeDecode tests that we're able to properly encode and
// decode channel types within TLV streams.
func TestChannelTypeEncodeDecode(t *testing.T) {
t.Parallel()
chanType := ChannelType(*NewRawFeatureVector(
StaticRemoteKeyRequired,
AnchorsZeroFeeHtlcTxRequired,
))
var extraData ExtraOpaqueData
require.NoError(t, extraData.PackRecords(chanType.Record()))
var chanType2 ChannelType
tlvs, err := extraData.ExtractRecords(chanType2.Record())
require.NoError(t, err)
require.Contains(t, tlvs, ChannelTypeRecordType)
require.Equal(t, chanType, chanType2)
}