mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-08-30 07:35:07 +02:00
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:
58
lnwire/channel_type.go
Normal file
58
lnwire/channel_type.go
Normal 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")
|
||||||
|
}
|
28
lnwire/channel_type_test.go
Normal file
28
lnwire/channel_type_test.go
Normal 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)
|
||||||
|
}
|
Reference in New Issue
Block a user