mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-08-27 14:11:04 +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