2017-02-16 13:31:19 +01:00
|
|
|
package lnwire
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/binary"
|
2019-11-08 14:29:16 +01:00
|
|
|
"errors"
|
2017-02-16 13:31:19 +01:00
|
|
|
"io"
|
|
|
|
)
|
|
|
|
|
2019-11-08 14:29:16 +01:00
|
|
|
var (
|
|
|
|
// ErrFeaturePairExists signals an error in feature vector construction
|
|
|
|
// where the opposing bit in a feature pair has already been set.
|
|
|
|
ErrFeaturePairExists = errors.New("feature pair exists")
|
|
|
|
)
|
|
|
|
|
2017-10-11 20:25:37 +02:00
|
|
|
// FeatureBit represents a feature that can be enabled in either a local or
|
|
|
|
// global feature vector at a specific bit position. Feature bits follow the
|
|
|
|
// "it's OK to be odd" rule, where features at even bit positions must be known
|
|
|
|
// to a node receiving them from a peer while odd bits do not. In accordance,
|
|
|
|
// feature bits are usually assigned in pairs, first being assigned an odd bit
|
|
|
|
// position which may later be changed to the preceding even position once
|
|
|
|
// knowledge of the feature becomes required on the network.
|
|
|
|
type FeatureBit uint16
|
2017-02-16 13:31:19 +01:00
|
|
|
|
|
|
|
const (
|
2018-04-17 03:44:25 +02:00
|
|
|
// DataLossProtectRequired is a feature bit that indicates that a peer
|
|
|
|
// *requires* the other party know about the data-loss-protect optional
|
|
|
|
// feature. If the remote peer does not know of such a feature, then
|
|
|
|
// the sending peer SHOLUD disconnect them. The data-loss-protect
|
|
|
|
// feature allows a peer that's lost partial data to recover their
|
|
|
|
// settled funds of the latest commitment state.
|
|
|
|
DataLossProtectRequired FeatureBit = 0
|
|
|
|
|
|
|
|
// DataLossProtectOptional is an optional feature bit that indicates
|
|
|
|
// that the sending peer knows of this new feature and can activate it
|
|
|
|
// it. The data-loss-protect feature allows a peer that's lost partial
|
|
|
|
// data to recover their settled funds of the latest commitment state.
|
|
|
|
DataLossProtectOptional FeatureBit = 1
|
|
|
|
|
2017-11-17 22:26:39 +01:00
|
|
|
// InitialRoutingSync is a local feature bit meaning that the receiving
|
|
|
|
// node should send a complete dump of routing information when a new
|
|
|
|
// connection is established.
|
2017-10-11 20:25:37 +02:00
|
|
|
InitialRoutingSync FeatureBit = 3
|
2017-02-16 13:31:19 +01:00
|
|
|
|
2019-12-03 10:38:21 +01:00
|
|
|
// UpfrontShutdownScriptRequired is a feature bit which indicates that a
|
|
|
|
// peer *requires* that the remote peer accept an upfront shutdown script to
|
|
|
|
// which payout is enforced on cooperative closes.
|
|
|
|
UpfrontShutdownScriptRequired FeatureBit = 4
|
|
|
|
|
|
|
|
// UpfrontShutdownScriptOptional is an optional feature bit which indicates
|
|
|
|
// that the peer will accept an upfront shutdown script to which payout is
|
|
|
|
// enforced on cooperative closes.
|
|
|
|
UpfrontShutdownScriptOptional FeatureBit = 5
|
|
|
|
|
2018-04-17 03:44:51 +02:00
|
|
|
// GossipQueriesRequired is a feature bit that indicates that the
|
|
|
|
// receiving peer MUST know of the set of features that allows nodes to
|
|
|
|
// more efficiently query the network view of peers on the network for
|
|
|
|
// reconciliation purposes.
|
|
|
|
GossipQueriesRequired FeatureBit = 6
|
|
|
|
|
|
|
|
// GossipQueriesOptional is an optional feature bit that signals that
|
|
|
|
// the setting peer knows of the set of features that allows more
|
|
|
|
// efficient network view reconciliation.
|
|
|
|
GossipQueriesOptional FeatureBit = 7
|
|
|
|
|
2019-07-31 06:53:02 +02:00
|
|
|
// TLVOnionPayloadRequired is a feature bit that indicates a node is
|
|
|
|
// able to decode the new TLV information included in the onion packet.
|
|
|
|
TLVOnionPayloadRequired FeatureBit = 8
|
|
|
|
|
2020-11-25 22:12:29 +01:00
|
|
|
// TLVOnionPayloadOptional is an optional feature bit that indicates a
|
2019-07-31 06:53:02 +02:00
|
|
|
// node is able to decode the new TLV information included in the onion
|
|
|
|
// packet.
|
|
|
|
TLVOnionPayloadOptional FeatureBit = 9
|
|
|
|
|
2019-08-01 04:57:52 +02:00
|
|
|
// StaticRemoteKeyRequired is a required feature bit that signals that
|
|
|
|
// within one's commitment transaction, the key used for the remote
|
|
|
|
// party's non-delay output should not be tweaked.
|
2019-10-02 12:33:22 +02:00
|
|
|
StaticRemoteKeyRequired FeatureBit = 12
|
2019-08-01 04:57:52 +02:00
|
|
|
|
|
|
|
// StaticRemoteKeyOptional is an optional feature bit that signals that
|
|
|
|
// within one's commitment transaction, the key used for the remote
|
|
|
|
// party's non-delay output should not be tweaked.
|
2019-10-02 12:33:22 +02:00
|
|
|
StaticRemoteKeyOptional FeatureBit = 13
|
2019-08-01 04:57:52 +02:00
|
|
|
|
2019-12-16 22:06:15 +01:00
|
|
|
// PaymentAddrRequired is a required feature bit that signals that a
|
|
|
|
// node requires payment addresses, which are used to mitigate probing
|
|
|
|
// attacks on the receiver of a payment.
|
|
|
|
PaymentAddrRequired FeatureBit = 14
|
|
|
|
|
|
|
|
// PaymentAddrOptional is an optional feature bit that signals that a
|
|
|
|
// node supports payment addresses, which are used to mitigate probing
|
|
|
|
// attacks on the receiver of a payment.
|
|
|
|
PaymentAddrOptional FeatureBit = 15
|
|
|
|
|
2021-06-17 14:21:48 +02:00
|
|
|
// MPPRequired is a required feature bit that signals that the receiver
|
2019-12-16 22:06:15 +01:00
|
|
|
// of a payment requires settlement of an invoice with more than one
|
|
|
|
// HTLC.
|
|
|
|
MPPRequired FeatureBit = 16
|
|
|
|
|
|
|
|
// MPPOptional is an optional feature bit that signals that the receiver
|
|
|
|
// of a payment supports settlement of an invoice with more than one
|
|
|
|
// HTLC.
|
|
|
|
MPPOptional FeatureBit = 17
|
|
|
|
|
2020-07-02 06:02:25 +02:00
|
|
|
// WumboChannelsRequired is a required feature bit that signals that a
|
|
|
|
// node is willing to accept channels larger than 2^24 satoshis.
|
2020-07-20 08:36:39 +02:00
|
|
|
WumboChannelsRequired FeatureBit = 18
|
2020-07-02 06:02:25 +02:00
|
|
|
|
2020-07-20 08:36:39 +02:00
|
|
|
// WumboChannelsOptional is an optional feature bit that signals that a
|
2020-07-02 06:02:25 +02:00
|
|
|
// node is willing to accept channels larger than 2^24 satoshis.
|
2020-07-20 08:36:39 +02:00
|
|
|
WumboChannelsOptional FeatureBit = 19
|
2020-07-02 06:02:25 +02:00
|
|
|
|
2020-03-06 16:11:48 +01:00
|
|
|
// AnchorsRequired is a required feature bit that signals that the node
|
|
|
|
// requires channels to be made using commitments having anchor
|
|
|
|
// outputs.
|
2020-08-21 13:38:36 +02:00
|
|
|
AnchorsRequired FeatureBit = 20
|
2020-03-06 16:11:48 +01:00
|
|
|
|
2020-11-25 22:12:29 +01:00
|
|
|
// AnchorsOptional is an optional feature bit that signals that the
|
2020-03-06 16:11:48 +01:00
|
|
|
// node supports channels to be made using commitments having anchor
|
|
|
|
// outputs.
|
2020-08-21 13:38:36 +02:00
|
|
|
AnchorsOptional FeatureBit = 21
|
2020-03-06 16:11:48 +01:00
|
|
|
|
2020-12-07 14:12:45 +01:00
|
|
|
// AnchorsZeroFeeHtlcTxRequired is a required feature bit that signals
|
|
|
|
// that the node requires channels having zero-fee second-level HTLC
|
|
|
|
// transactions, which also imply anchor commitments.
|
|
|
|
AnchorsZeroFeeHtlcTxRequired FeatureBit = 22
|
|
|
|
|
2021-06-17 14:21:48 +02:00
|
|
|
// AnchorsZeroFeeHtlcTxOptional is an optional feature bit that signals
|
2020-12-07 14:12:45 +01:00
|
|
|
// that the node supports channels having zero-fee second-level HTLC
|
|
|
|
// transactions, which also imply anchor commitments.
|
|
|
|
AnchorsZeroFeeHtlcTxOptional FeatureBit = 23
|
|
|
|
|
2022-06-10 20:14:54 +02:00
|
|
|
// ShutdownAnySegwitRequired is an required feature bit that signals
|
|
|
|
// that the sender is able to properly handle/parse segwit witness
|
|
|
|
// programs up to version 16. This enables utilization of Taproot
|
|
|
|
// addresses for cooperative closure addresses.
|
|
|
|
ShutdownAnySegwitRequired FeatureBit = 26
|
|
|
|
|
|
|
|
// ShutdownAnySegwitOptional is an optional feature bit that signals
|
|
|
|
// that the sender is able to properly handle/parse segwit witness
|
|
|
|
// programs up to version 16. This enables utilization of Taproot
|
|
|
|
// addresses for cooperative closure addresses.
|
|
|
|
ShutdownAnySegwitOptional FeatureBit = 27
|
|
|
|
|
2021-03-25 03:48:08 +01:00
|
|
|
// AMPRequired is a required feature bit that signals that the receiver
|
|
|
|
// of a payment supports accepts spontaneous payments, i.e.
|
|
|
|
// sender-generated preimages according to BOLT XX.
|
|
|
|
AMPRequired FeatureBit = 30
|
|
|
|
|
|
|
|
// AMPOptional is an optional feature bit that signals that the receiver
|
|
|
|
// of a payment supports accepts spontaneous payments, i.e.
|
|
|
|
// sender-generated preimages according to BOLT XX.
|
|
|
|
AMPOptional FeatureBit = 31
|
|
|
|
|
2021-03-04 04:39:12 +01:00
|
|
|
// ExplicitChannelTypeRequired is a required bit that denotes that a
|
|
|
|
// connection established with this node is to use explicit channel
|
|
|
|
// commitment types for negotiation instead of the existing implicit
|
|
|
|
// negotiation methods. With this bit, there is no longer a "default"
|
|
|
|
// implicit channel commitment type, allowing a connection to
|
|
|
|
// open/maintain types of several channels over its lifetime.
|
2021-10-20 02:39:57 +02:00
|
|
|
ExplicitChannelTypeRequired = 44
|
2021-03-04 04:39:12 +01:00
|
|
|
|
|
|
|
// ExplicitChannelTypeOptional is an optional bit that denotes that a
|
|
|
|
// connection established with this node is to use explicit channel
|
|
|
|
// commitment types for negotiation instead of the existing implicit
|
|
|
|
// negotiation methods. With this bit, there is no longer a "default"
|
|
|
|
// implicit channel commitment type, allowing a connection to
|
|
|
|
// TODO: Decide on actual feature bit value.
|
2021-10-20 02:39:57 +02:00
|
|
|
ExplicitChannelTypeOptional = 45
|
2021-03-04 04:39:12 +01:00
|
|
|
|
2022-04-04 21:16:13 +02:00
|
|
|
// ScidAliasRequired is a required feature bit that signals that the
|
|
|
|
// node requires understanding of ShortChannelID aliases in the TLV
|
|
|
|
// segment of the funding_locked message.
|
|
|
|
ScidAliasRequired FeatureBit = 46
|
|
|
|
|
|
|
|
// ScidAliasOptional is an optional feature bit that signals that the
|
|
|
|
// node understands ShortChannelID aliases in the TLV segment of the
|
|
|
|
// funding_locked message.
|
|
|
|
ScidAliasOptional FeatureBit = 47
|
|
|
|
|
2021-10-04 09:33:12 +02:00
|
|
|
// PaymentMetadataRequired is a required bit that denotes that if an
|
|
|
|
// invoice contains metadata, it must be passed along with the payment
|
|
|
|
// htlc(s).
|
|
|
|
PaymentMetadataRequired = 48
|
|
|
|
|
|
|
|
// PaymentMetadataOptional is an optional bit that denotes that if an
|
|
|
|
// invoice contains metadata, it may be passed along with the payment
|
|
|
|
// htlc(s).
|
|
|
|
PaymentMetadataOptional = 49
|
|
|
|
|
2022-04-04 21:16:13 +02:00
|
|
|
// ZeroConfRequired is a required feature bit that signals that the
|
|
|
|
// node requires understanding of the zero-conf channel_type.
|
|
|
|
ZeroConfRequired FeatureBit = 50
|
|
|
|
|
|
|
|
// ZeroConfOptional is an optional feature bit that signals that the
|
|
|
|
// node understands the zero-conf channel type.
|
|
|
|
ZeroConfOptional FeatureBit = 51
|
|
|
|
|
2022-04-14 13:54:57 +02:00
|
|
|
// KeysendRequired is a required bit that indicates that the node is
|
|
|
|
// able and willing to accept keysend payments.
|
|
|
|
KeysendRequired = 54
|
|
|
|
|
|
|
|
// KeysendOptional is an optional bit that indicates that the node is
|
|
|
|
// able and willing to accept keysend payments.
|
|
|
|
KeysendOptional = 55
|
|
|
|
|
2022-04-04 21:16:13 +02:00
|
|
|
// ScriptEnforcedLeaseOptional is an optional feature bit that signals
|
2021-07-14 00:20:46 +02:00
|
|
|
// that the node requires channels having zero-fee second-level HTLC
|
|
|
|
// transactions, which also imply anchor commitments, along with an
|
|
|
|
// additional CLTV constraint of a channel lease's expiration height
|
|
|
|
// applied to all outputs that pay directly to the channel initiator.
|
|
|
|
//
|
|
|
|
// TODO: Decide on actual feature bit value.
|
|
|
|
ScriptEnforcedLeaseRequired FeatureBit = 2022
|
|
|
|
|
2022-04-14 13:54:57 +02:00
|
|
|
// ScriptEnforcedLeaseOptional is an optional feature bit that signals
|
2021-07-14 00:20:46 +02:00
|
|
|
// that the node requires channels having zero-fee second-level HTLC
|
|
|
|
// transactions, which also imply anchor commitments, along with an
|
|
|
|
// additional CLTV constraint of a channel lease's expiration height
|
|
|
|
// applied to all outputs that pay directly to the channel initiator.
|
|
|
|
//
|
|
|
|
// TODO: Decide on actual feature bit value.
|
|
|
|
ScriptEnforcedLeaseOptional FeatureBit = 2023
|
|
|
|
|
2017-02-16 13:31:19 +01:00
|
|
|
// maxAllowedSize is a maximum allowed size of feature vector.
|
2017-03-16 20:11:53 +01:00
|
|
|
//
|
2017-02-16 13:31:19 +01:00
|
|
|
// NOTE: Within the protocol, the maximum allowed message size is 65535
|
2019-02-06 13:02:10 +01:00
|
|
|
// bytes for all messages. Accounting for the overhead within the feature
|
|
|
|
// message to signal the type of message, that leaves us with 65533 bytes
|
|
|
|
// for the init message itself. Next, we reserve 4 bytes to encode the
|
|
|
|
// lengths of both the local and global feature vectors, so 65529 bytes
|
2020-11-25 22:12:29 +01:00
|
|
|
// for the local and global features. Knocking off one byte for the sake
|
2019-02-06 13:02:10 +01:00
|
|
|
// of the calculation, that leads us to 32764 bytes for each feature
|
|
|
|
// vector, or 131056 different features.
|
|
|
|
maxAllowedSize = 32764
|
2017-02-16 13:31:19 +01:00
|
|
|
)
|
|
|
|
|
2019-12-10 22:09:36 +01:00
|
|
|
// IsRequired returns true if the feature bit is even, and false otherwise.
|
|
|
|
func (b FeatureBit) IsRequired() bool {
|
|
|
|
return b&0x01 == 0x00
|
|
|
|
}
|
|
|
|
|
2019-11-08 14:28:47 +01:00
|
|
|
// Features is a mapping of known feature bits to a descriptive name. All known
|
|
|
|
// feature bits must be assigned a name in this mapping, and feature bit pairs
|
|
|
|
// must be assigned together for correct behavior.
|
|
|
|
var Features = map[FeatureBit]string{
|
2019-12-03 10:38:21 +01:00
|
|
|
DataLossProtectRequired: "data-loss-protect",
|
|
|
|
DataLossProtectOptional: "data-loss-protect",
|
|
|
|
InitialRoutingSync: "initial-routing-sync",
|
|
|
|
UpfrontShutdownScriptRequired: "upfront-shutdown-script",
|
|
|
|
UpfrontShutdownScriptOptional: "upfront-shutdown-script",
|
|
|
|
GossipQueriesRequired: "gossip-queries",
|
|
|
|
GossipQueriesOptional: "gossip-queries",
|
|
|
|
TLVOnionPayloadRequired: "tlv-onion",
|
|
|
|
TLVOnionPayloadOptional: "tlv-onion",
|
|
|
|
StaticRemoteKeyOptional: "static-remote-key",
|
|
|
|
StaticRemoteKeyRequired: "static-remote-key",
|
2019-12-19 08:58:11 +01:00
|
|
|
PaymentAddrOptional: "payment-addr",
|
|
|
|
PaymentAddrRequired: "payment-addr",
|
|
|
|
MPPOptional: "multi-path-payments",
|
|
|
|
MPPRequired: "multi-path-payments",
|
2020-03-06 16:11:48 +01:00
|
|
|
AnchorsRequired: "anchor-commitments",
|
|
|
|
AnchorsOptional: "anchor-commitments",
|
2020-12-07 14:12:45 +01:00
|
|
|
AnchorsZeroFeeHtlcTxRequired: "anchors-zero-fee-htlc-tx",
|
|
|
|
AnchorsZeroFeeHtlcTxOptional: "anchors-zero-fee-htlc-tx",
|
2020-07-02 06:02:25 +02:00
|
|
|
WumboChannelsRequired: "wumbo-channels",
|
|
|
|
WumboChannelsOptional: "wumbo-channels",
|
2021-03-25 03:48:08 +01:00
|
|
|
AMPRequired: "amp",
|
|
|
|
AMPOptional: "amp",
|
2021-10-04 09:33:12 +02:00
|
|
|
PaymentMetadataOptional: "payment-metadata",
|
|
|
|
PaymentMetadataRequired: "payment-metadata",
|
2021-03-04 04:39:12 +01:00
|
|
|
ExplicitChannelTypeOptional: "explicit-commitment-type",
|
|
|
|
ExplicitChannelTypeRequired: "explicit-commitment-type",
|
2022-04-14 13:54:57 +02:00
|
|
|
KeysendOptional: "keysend",
|
|
|
|
KeysendRequired: "keysend",
|
2021-07-14 00:20:46 +02:00
|
|
|
ScriptEnforcedLeaseRequired: "script-enforced-lease",
|
|
|
|
ScriptEnforcedLeaseOptional: "script-enforced-lease",
|
2022-04-04 21:16:13 +02:00
|
|
|
ScidAliasRequired: "scid-alias",
|
|
|
|
ScidAliasOptional: "scid-alias",
|
|
|
|
ZeroConfRequired: "zero-conf",
|
|
|
|
ZeroConfOptional: "zero-conf",
|
2022-06-10 20:14:54 +02:00
|
|
|
ShutdownAnySegwitRequired: "shutdown-any-segwit",
|
|
|
|
ShutdownAnySegwitOptional: "shutdown-any-segwit",
|
2019-11-08 14:28:47 +01:00
|
|
|
}
|
|
|
|
|
2017-11-17 22:26:39 +01:00
|
|
|
// RawFeatureVector represents a set of feature bits as defined in BOLT-09. A
|
|
|
|
// RawFeatureVector itself just stores a set of bit flags but can be used to
|
2017-10-11 20:25:37 +02:00
|
|
|
// construct a FeatureVector which binds meaning to each bit. Feature vectors
|
2017-11-17 22:26:39 +01:00
|
|
|
// can be serialized and deserialized to/from a byte representation that is
|
2017-10-11 20:25:37 +02:00
|
|
|
// transmitted in Lightning network messages.
|
|
|
|
type RawFeatureVector struct {
|
2021-07-13 02:41:50 +02:00
|
|
|
features map[FeatureBit]struct{}
|
2017-02-16 13:31:19 +01:00
|
|
|
}
|
|
|
|
|
2017-10-11 20:25:37 +02:00
|
|
|
// NewRawFeatureVector creates a feature vector with all of the feature bits
|
|
|
|
// given as arguments enabled.
|
|
|
|
func NewRawFeatureVector(bits ...FeatureBit) *RawFeatureVector {
|
2021-07-13 02:41:50 +02:00
|
|
|
fv := &RawFeatureVector{features: make(map[FeatureBit]struct{})}
|
2017-10-11 20:25:37 +02:00
|
|
|
for _, bit := range bits {
|
|
|
|
fv.Set(bit)
|
2017-02-17 15:28:11 +01:00
|
|
|
}
|
2017-10-11 20:25:37 +02:00
|
|
|
return fv
|
|
|
|
}
|
2017-02-17 15:28:11 +01:00
|
|
|
|
2021-07-13 02:41:50 +02:00
|
|
|
// IsEmpty returns whether the feature vector contains any feature bits.
|
|
|
|
func (fv RawFeatureVector) IsEmpty() bool {
|
|
|
|
return len(fv.features) == 0
|
|
|
|
}
|
|
|
|
|
|
|
|
// OnlyContains determines whether only the specified feature bits are found.
|
|
|
|
func (fv RawFeatureVector) OnlyContains(bits ...FeatureBit) bool {
|
|
|
|
if len(bits) != len(fv.features) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for _, bit := range bits {
|
|
|
|
if !fv.IsSet(bit) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// Equals determines whether two features vectors contain exactly the same
|
|
|
|
// features.
|
|
|
|
func (fv RawFeatureVector) Equals(other *RawFeatureVector) bool {
|
|
|
|
if len(fv.features) != len(other.features) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for bit := range fv.features {
|
|
|
|
if _, ok := other.features[bit]; !ok {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2019-11-08 14:31:47 +01:00
|
|
|
// Merges sets all feature bits in other on the receiver's feature vector.
|
|
|
|
func (fv *RawFeatureVector) Merge(other *RawFeatureVector) error {
|
|
|
|
for bit := range other.features {
|
|
|
|
err := fv.SafeSet(bit)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-11-08 14:29:16 +01:00
|
|
|
// Clone makes a copy of a feature vector.
|
|
|
|
func (fv *RawFeatureVector) Clone() *RawFeatureVector {
|
|
|
|
newFeatures := NewRawFeatureVector()
|
|
|
|
for bit := range fv.features {
|
|
|
|
newFeatures.Set(bit)
|
|
|
|
}
|
|
|
|
return newFeatures
|
|
|
|
}
|
|
|
|
|
2017-10-11 20:25:37 +02:00
|
|
|
// IsSet returns whether a particular feature bit is enabled in the vector.
|
|
|
|
func (fv *RawFeatureVector) IsSet(feature FeatureBit) bool {
|
2021-07-13 02:41:50 +02:00
|
|
|
_, ok := fv.features[feature]
|
|
|
|
return ok
|
2017-02-16 13:31:19 +01:00
|
|
|
}
|
|
|
|
|
2017-10-11 20:25:37 +02:00
|
|
|
// Set marks a feature as enabled in the vector.
|
|
|
|
func (fv *RawFeatureVector) Set(feature FeatureBit) {
|
2021-07-13 02:41:50 +02:00
|
|
|
fv.features[feature] = struct{}{}
|
2017-10-11 20:25:37 +02:00
|
|
|
}
|
2017-02-16 13:31:19 +01:00
|
|
|
|
2019-11-08 14:29:16 +01:00
|
|
|
// SafeSet sets the chosen feature bit in the feature vector, but returns an
|
|
|
|
// error if the opposing feature bit is already set. This ensures both that we
|
|
|
|
// are creating properly structured feature vectors, and in some cases, that
|
|
|
|
// peers are sending properly encoded ones, i.e. it can't be both optional and
|
|
|
|
// required.
|
|
|
|
func (fv *RawFeatureVector) SafeSet(feature FeatureBit) error {
|
|
|
|
if _, ok := fv.features[feature^1]; ok {
|
|
|
|
return ErrFeaturePairExists
|
|
|
|
}
|
|
|
|
|
|
|
|
fv.Set(feature)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-10-11 20:25:37 +02:00
|
|
|
// Unset marks a feature as disabled in the vector.
|
|
|
|
func (fv *RawFeatureVector) Unset(feature FeatureBit) {
|
|
|
|
delete(fv.features, feature)
|
2017-02-16 13:31:19 +01:00
|
|
|
}
|
|
|
|
|
2017-10-11 20:25:37 +02:00
|
|
|
// SerializeSize returns the number of bytes needed to represent feature vector
|
|
|
|
// in byte format.
|
|
|
|
func (fv *RawFeatureVector) SerializeSize() int {
|
2019-08-26 21:54:04 +02:00
|
|
|
// We calculate byte-length via the largest bit index.
|
|
|
|
return fv.serializeSize(8)
|
|
|
|
}
|
|
|
|
|
|
|
|
// SerializeSize32 returns the number of bytes needed to represent feature
|
|
|
|
// vector in base32 format.
|
|
|
|
func (fv *RawFeatureVector) SerializeSize32() int {
|
|
|
|
// We calculate base32-length via the largest bit index.
|
|
|
|
return fv.serializeSize(5)
|
|
|
|
}
|
|
|
|
|
|
|
|
// serializeSize returns the number of bytes required to encode the feature
|
|
|
|
// vector using at most width bits per encoded byte.
|
|
|
|
func (fv *RawFeatureVector) serializeSize(width int) int {
|
2017-10-11 20:25:37 +02:00
|
|
|
// Find the largest feature bit index
|
2017-09-15 19:04:46 +02:00
|
|
|
max := -1
|
2017-10-11 20:25:37 +02:00
|
|
|
for feature := range fv.features {
|
|
|
|
index := int(feature)
|
2017-09-15 19:04:46 +02:00
|
|
|
if index > max {
|
|
|
|
max = index
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if max == -1 {
|
|
|
|
return 0
|
|
|
|
}
|
2017-10-11 20:25:37 +02:00
|
|
|
|
2019-08-26 21:54:04 +02:00
|
|
|
return max/width + 1
|
2017-02-16 13:31:19 +01:00
|
|
|
}
|
|
|
|
|
2017-10-11 20:25:37 +02:00
|
|
|
// Encode writes the feature vector in byte representation. Every feature
|
|
|
|
// encoded as a bit, and the bit vector is serialized using the least number of
|
|
|
|
// bytes. Since the bit vector length is variable, the first two bytes of the
|
|
|
|
// serialization represent the length.
|
|
|
|
func (fv *RawFeatureVector) Encode(w io.Writer) error {
|
|
|
|
// Write length of feature vector.
|
|
|
|
var l [2]byte
|
|
|
|
length := fv.SerializeSize()
|
|
|
|
binary.BigEndian.PutUint16(l[:], uint16(length))
|
|
|
|
if _, err := w.Write(l[:]); err != nil {
|
|
|
|
return err
|
2017-02-16 13:31:19 +01:00
|
|
|
}
|
|
|
|
|
2019-08-26 22:07:21 +02:00
|
|
|
return fv.encode(w, length, 8)
|
|
|
|
}
|
|
|
|
|
2019-11-22 11:23:35 +01:00
|
|
|
// EncodeBase256 writes the feature vector in base256 representation. Every
|
|
|
|
// feature is encoded as a bit, and the bit vector is serialized using the least
|
|
|
|
// number of bytes.
|
|
|
|
func (fv *RawFeatureVector) EncodeBase256(w io.Writer) error {
|
|
|
|
length := fv.SerializeSize()
|
|
|
|
return fv.encode(w, length, 8)
|
|
|
|
}
|
|
|
|
|
2019-08-26 22:07:21 +02:00
|
|
|
// EncodeBase32 writes the feature vector in base32 representation. Every feature
|
2019-11-22 11:23:35 +01:00
|
|
|
// is encoded as a bit, and the bit vector is serialized using the least number of
|
2019-08-26 22:07:21 +02:00
|
|
|
// bytes.
|
|
|
|
func (fv *RawFeatureVector) EncodeBase32(w io.Writer) error {
|
|
|
|
length := fv.SerializeSize32()
|
|
|
|
return fv.encode(w, length, 5)
|
|
|
|
}
|
|
|
|
|
|
|
|
// encode writes the feature vector
|
|
|
|
func (fv *RawFeatureVector) encode(w io.Writer, length, width int) error {
|
2017-10-11 20:25:37 +02:00
|
|
|
// Generate the data and write it.
|
|
|
|
data := make([]byte, length)
|
|
|
|
for feature := range fv.features {
|
2019-08-26 22:07:21 +02:00
|
|
|
byteIndex := int(feature) / width
|
|
|
|
bitIndex := int(feature) % width
|
|
|
|
data[length-byteIndex-1] |= 1 << uint(bitIndex)
|
2017-02-16 13:31:19 +01:00
|
|
|
}
|
|
|
|
|
2017-10-11 20:25:37 +02:00
|
|
|
_, err := w.Write(data)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decode reads the feature vector from its byte representation. Every feature
|
2019-11-22 11:23:35 +01:00
|
|
|
// is encoded as a bit, and the bit vector is serialized using the least number
|
|
|
|
// of bytes. Since the bit vector length is variable, the first two bytes of the
|
2017-10-11 20:25:37 +02:00
|
|
|
// serialization represent the length.
|
|
|
|
func (fv *RawFeatureVector) Decode(r io.Reader) error {
|
2017-02-16 13:31:19 +01:00
|
|
|
// Read the length of the feature vector.
|
|
|
|
var l [2]byte
|
2017-04-20 01:07:11 +02:00
|
|
|
if _, err := io.ReadFull(r, l[:]); err != nil {
|
2017-10-11 20:25:37 +02:00
|
|
|
return err
|
2017-02-16 13:31:19 +01:00
|
|
|
}
|
|
|
|
length := binary.BigEndian.Uint16(l[:])
|
|
|
|
|
2019-08-26 22:07:21 +02:00
|
|
|
return fv.decode(r, int(length), 8)
|
|
|
|
}
|
|
|
|
|
2019-11-22 11:23:35 +01:00
|
|
|
// DecodeBase256 reads the feature vector from its base256 representation. Every
|
|
|
|
// feature encoded as a bit, and the bit vector is serialized using the least
|
|
|
|
// number of bytes.
|
|
|
|
func (fv *RawFeatureVector) DecodeBase256(r io.Reader, length int) error {
|
|
|
|
return fv.decode(r, length, 8)
|
|
|
|
}
|
|
|
|
|
2019-08-26 22:07:21 +02:00
|
|
|
// DecodeBase32 reads the feature vector from its base32 representation. Every
|
|
|
|
// feature encoded as a bit, and the bit vector is serialized using the least
|
|
|
|
// number of bytes.
|
|
|
|
func (fv *RawFeatureVector) DecodeBase32(r io.Reader, length int) error {
|
|
|
|
return fv.decode(r, length, 5)
|
|
|
|
}
|
|
|
|
|
|
|
|
// decode reads a feature vector from the next length bytes of the io.Reader,
|
|
|
|
// assuming each byte has width feature bits encoded per byte.
|
|
|
|
func (fv *RawFeatureVector) decode(r io.Reader, length, width int) error {
|
2017-02-16 13:31:19 +01:00
|
|
|
// Read the feature vector data.
|
|
|
|
data := make([]byte, length)
|
2017-10-11 20:25:37 +02:00
|
|
|
if _, err := io.ReadFull(r, data); err != nil {
|
|
|
|
return err
|
2017-02-16 13:31:19 +01:00
|
|
|
}
|
|
|
|
|
2017-10-11 20:25:37 +02:00
|
|
|
// Set feature bits from parsed data.
|
2019-08-26 22:07:21 +02:00
|
|
|
bitsNumber := len(data) * width
|
2017-10-11 20:25:37 +02:00
|
|
|
for i := 0; i < bitsNumber; i++ {
|
2019-08-26 22:07:21 +02:00
|
|
|
byteIndex := int(i / width)
|
|
|
|
bitIndex := uint(i % width)
|
2017-10-11 20:25:37 +02:00
|
|
|
if (data[length-byteIndex-1]>>bitIndex)&1 == 1 {
|
|
|
|
fv.Set(FeatureBit(i))
|
2017-02-16 13:31:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-11 20:25:37 +02:00
|
|
|
return nil
|
2017-02-16 13:31:19 +01:00
|
|
|
}
|
|
|
|
|
2017-10-11 20:25:37 +02:00
|
|
|
// FeatureVector represents a set of enabled features. The set stores
|
|
|
|
// information on enabled flags and metadata about the feature names. A feature
|
|
|
|
// vector is serializable to a compact byte representation that is included in
|
|
|
|
// Lightning network messages.
|
|
|
|
type FeatureVector struct {
|
|
|
|
*RawFeatureVector
|
|
|
|
featureNames map[FeatureBit]string
|
2017-02-16 13:31:19 +01:00
|
|
|
}
|
|
|
|
|
2017-11-17 22:26:39 +01:00
|
|
|
// NewFeatureVector constructs a new FeatureVector from a raw feature vector
|
|
|
|
// and mapping of feature definitions. If the feature vector argument is nil, a
|
|
|
|
// new one will be constructed with no enabled features.
|
2017-10-11 20:25:37 +02:00
|
|
|
func NewFeatureVector(featureVector *RawFeatureVector,
|
|
|
|
featureNames map[FeatureBit]string) *FeatureVector {
|
2017-02-16 13:31:19 +01:00
|
|
|
|
2017-10-11 20:37:54 +02:00
|
|
|
if featureVector == nil {
|
|
|
|
featureVector = NewRawFeatureVector()
|
|
|
|
}
|
2017-10-11 20:25:37 +02:00
|
|
|
return &FeatureVector{
|
|
|
|
RawFeatureVector: featureVector,
|
|
|
|
featureNames: featureNames,
|
2017-02-16 13:31:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-19 08:52:44 +01:00
|
|
|
// EmptyFeatureVector returns a feature vector with no bits set.
|
|
|
|
func EmptyFeatureVector() *FeatureVector {
|
|
|
|
return NewFeatureVector(nil, Features)
|
|
|
|
}
|
|
|
|
|
2017-10-11 20:25:37 +02:00
|
|
|
// HasFeature returns whether a particular feature is included in the set. The
|
|
|
|
// feature can be seen as set either if the bit is set directly OR the queried
|
|
|
|
// bit has the same meaning as its corresponding even/odd bit, which is set
|
|
|
|
// instead. The second case is because feature bits are generally assigned in
|
|
|
|
// pairs where both the even and odd position represent the same feature.
|
|
|
|
func (fv *FeatureVector) HasFeature(feature FeatureBit) bool {
|
|
|
|
return fv.IsSet(feature) ||
|
|
|
|
(fv.isFeatureBitPair(feature) && fv.IsSet(feature^1))
|
|
|
|
}
|
2017-02-17 15:28:11 +01:00
|
|
|
|
2020-11-25 04:54:35 +01:00
|
|
|
// RequiresFeature returns true if the referenced feature vector *requires*
|
|
|
|
// that the given required bit be set. This method can be used with both
|
|
|
|
// optional and required feature bits as a parameter.
|
|
|
|
func (fv *FeatureVector) RequiresFeature(feature FeatureBit) bool {
|
|
|
|
// If we weren't passed a required feature bit, then we'll flip the
|
|
|
|
// lowest bit to query for the required version of the feature. This
|
|
|
|
// lets callers pass in both the optional and required bits.
|
|
|
|
if !feature.IsRequired() {
|
|
|
|
feature ^= 1
|
|
|
|
}
|
|
|
|
|
|
|
|
return fv.IsSet(feature)
|
|
|
|
}
|
|
|
|
|
2017-11-17 22:26:39 +01:00
|
|
|
// UnknownRequiredFeatures returns a list of feature bits set in the vector
|
|
|
|
// that are unknown and in an even bit position. Feature bits with an even
|
|
|
|
// index must be known to a node receiving the feature vector in a message.
|
2017-10-11 20:25:37 +02:00
|
|
|
func (fv *FeatureVector) UnknownRequiredFeatures() []FeatureBit {
|
|
|
|
var unknown []FeatureBit
|
|
|
|
for feature := range fv.features {
|
|
|
|
if feature%2 == 0 && !fv.IsKnown(feature) {
|
|
|
|
unknown = append(unknown, feature)
|
2017-02-17 15:28:11 +01:00
|
|
|
}
|
|
|
|
}
|
2017-10-11 20:25:37 +02:00
|
|
|
return unknown
|
2017-02-17 15:28:11 +01:00
|
|
|
}
|
|
|
|
|
2017-10-11 20:25:37 +02:00
|
|
|
// Name returns a string identifier for the feature represented by this bit. If
|
|
|
|
// the bit does not represent a known feature, this returns a string indicating
|
2020-11-25 22:12:29 +01:00
|
|
|
// as such.
|
2017-10-11 20:25:37 +02:00
|
|
|
func (fv *FeatureVector) Name(bit FeatureBit) string {
|
|
|
|
name, known := fv.featureNames[bit]
|
|
|
|
if !known {
|
2019-12-10 22:08:59 +01:00
|
|
|
return "unknown"
|
2017-10-11 20:25:37 +02:00
|
|
|
}
|
2019-12-10 22:08:59 +01:00
|
|
|
return name
|
2017-02-16 13:31:19 +01:00
|
|
|
}
|
|
|
|
|
2017-10-11 20:25:37 +02:00
|
|
|
// IsKnown returns whether this feature bit represents a known feature.
|
|
|
|
func (fv *FeatureVector) IsKnown(bit FeatureBit) bool {
|
|
|
|
_, known := fv.featureNames[bit]
|
|
|
|
return known
|
2017-02-16 13:31:19 +01:00
|
|
|
}
|
|
|
|
|
2017-10-11 20:25:37 +02:00
|
|
|
// isFeatureBitPair returns whether this feature bit and its corresponding
|
|
|
|
// even/odd bit both represent the same feature. This may often be the case as
|
|
|
|
// bits are generally assigned in pairs, first being assigned an odd bit
|
|
|
|
// position then being promoted to an even bit position once the network is
|
|
|
|
// ready.
|
|
|
|
func (fv *FeatureVector) isFeatureBitPair(bit FeatureBit) bool {
|
|
|
|
name1, known1 := fv.featureNames[bit]
|
|
|
|
name2, known2 := fv.featureNames[bit^1]
|
|
|
|
return known1 && known2 && name1 == name2
|
2017-02-16 13:31:19 +01:00
|
|
|
}
|
2019-11-22 11:24:28 +01:00
|
|
|
|
2019-12-10 22:09:36 +01:00
|
|
|
// Features returns the set of raw features contained in the feature vector.
|
|
|
|
func (fv *FeatureVector) Features() map[FeatureBit]struct{} {
|
|
|
|
fs := make(map[FeatureBit]struct{}, len(fv.RawFeatureVector.features))
|
|
|
|
for b := range fv.RawFeatureVector.features {
|
|
|
|
fs[b] = struct{}{}
|
|
|
|
}
|
|
|
|
return fs
|
|
|
|
}
|
|
|
|
|
2019-11-22 11:24:28 +01:00
|
|
|
// Clone copies a feature vector, carrying over its feature bits. The feature
|
|
|
|
// names are not copied.
|
|
|
|
func (fv *FeatureVector) Clone() *FeatureVector {
|
|
|
|
features := fv.RawFeatureVector.Clone()
|
|
|
|
return NewFeatureVector(features, fv.featureNames)
|
|
|
|
}
|