Menu
BOLT-bolt-09 Final

BOLT-09: Feature Bits

Lightning feature bit assignments. Required and optional features for nodes and channels.

Type Basis of Lightning Technology
Number bolt-09
Status Final
Authors Lightning Network Developers
Original https://github.com/lightning/bolts/blob/master/09-features.md
Requires

BOLT-09: Feature Bit Assignments

BOLT-09 defines the feature bits used in Lightning to negotiate capabilities between nodes. Features enable protocol evolution while maintaining backward compatibility.

Specification Summary

AspectValue
StatusFinal (living document)
LayerProtocol
PurposeCapability negotiation
DependenciesBOLT-01

Feature Bit Semantics

Even/Odd Convention

Bit TypeMeaningIf Unknown
Even (0, 2, 4…)RequiredMust disconnect
Odd (1, 3, 5…)OptionalMay ignore

Feature Pairs

Each feature uses two consecutive bits:

  • Bit N (even): “I require this feature”
  • Bit N+1 (odd): “I understand this feature”
def feature_required(feature_bit: int) -> int:
    """Get required (even) bit for feature."""
    return feature_bit & ~1

def feature_optional(feature_bit: int) -> int:
    """Get optional (odd) bit for feature."""
    return feature_bit | 1

Feature Contexts

Features apply in different contexts:

ContextWhere Used
IInit message (connection)
NNode announcement
CChannel announcement
C-Channel type (not announced)
9Invoice feature bits
BBOLT11 invoice

Assigned Features

Core Protocol Features

BitsNameContextDescription
0/1option_data_loss_protectINSafer channel reestablish
4/5option_upfront_shutdown_scriptINPre-agreed shutdown address
6/7gossip_queriesINGossip query support
8/9var_onion_optinIN9TLV onion payloads
10/11gossip_queries_exINExtended gossip queries
12/13option_static_remotekeyINStatic remote key

Payment Features

BitsNameContextDescription
14/15payment_secretIN9Payment secret required
16/17basic_mppIN9Multi-path payments
18/19option_support_large_channelINWumbo channels (>16M sats)

Channel Features

BitsNameContextDescription
20/21option_anchor_outputsINAnchor outputs
22/23option_anchors_zero_fee_htlc_txINZero-fee anchor HTLCs
24/25option_shutdown_anysegwitINAny SegWit shutdown

Advanced Features

BitsNameContextDescription
26/27option_dual_fundINDual-funded channels
44/45option_scid_aliasINSCID aliases
46/47option_zeroconfINZero-conf channels

Invoice Features

BitsNameContextDescription
8/9var_onion_optinBVariable onion
14/15payment_secretBRequired payment secret
16/17basic_mppBMPP support
48/49payment_metadataBPayment metadata

Feature Negotiation

During Connection

def negotiate_features(local: bytes, remote: bytes) -> bytes:
    """Determine active features for connection."""
    # Check for unknown required features
    for i in range(0, len(remote) * 8, 2):
        if has_bit(remote, i) and not understand_feature(i):
            raise UnknownRequiredFeature(i)

    # Intersection of supported features
    result = bytes(max(len(local), len(remote)))
    for i in range(len(result) * 8):
        if has_bit(local, i) and has_bit(remote, i):
            set_bit(result, i)

    return result

Channel Type Negotiation

def negotiate_channel_type(local_features, remote_features):
    """Determine channel type from features."""
    # Prefer anchors_zero_fee if both support
    if supports(local_features, 22) and supports(remote_features, 22):
        return ChannelType.ANCHORS_ZERO_FEE

    # Fall back to basic anchors
    if supports(local_features, 20) and supports(remote_features, 20):
        return ChannelType.ANCHORS

    # Static remote key
    if supports(local_features, 12) and supports(remote_features, 12):
        return ChannelType.STATIC_REMOTEKEY

    return ChannelType.LEGACY

Feature Dependencies

Some features require others:

FeatureRequires
basic_mpppayment_secret, var_onion_optin
option_anchors_zero_fee_htlc_txoption_anchor_outputs
option_scid_alias(recommended with option_zeroconf)
def validate_features(features: bytes) -> bool:
    """Check feature dependencies."""
    if has_feature(features, 16):  # basic_mpp
        if not has_feature(features, 14):  # payment_secret
            return False
        if not has_feature(features, 8):  # var_onion
            return False
    return True

Implementation

Feature Vector Encoding

def encode_features(features: dict) -> bytes:
    """Encode feature dict to bytes."""
    max_bit = max(features.keys()) if features else 0
    num_bytes = (max_bit + 8) // 8
    result = bytearray(num_bytes)

    for bit, enabled in features.items():
        if enabled:
            byte_idx = bit // 8
            bit_idx = bit % 8
            result[byte_idx] |= (1 << bit_idx)

    return bytes(result)

def decode_features(data: bytes) -> dict:
    """Decode feature bytes to dict."""
    features = {}
    for i in range(len(data) * 8):
        if data[i // 8] & (1 << (i % 8)):
            features[i] = True
    return features

Checking Features

class FeatureVector:
    def __init__(self, data: bytes):
        self.data = data

    def has_feature(self, bit: int) -> bool:
        """Check if feature bit is set."""
        byte_idx = bit // 8
        if byte_idx >= len(self.data):
            return False
        return bool(self.data[byte_idx] & (1 << (bit % 8)))

    def requires(self, feature: int) -> bool:
        """Check if feature is required (even bit)."""
        return self.has_feature(feature & ~1)

    def supports(self, feature: int) -> bool:
        """Check if feature is supported (either bit)."""
        return self.has_feature(feature & ~1) or self.has_feature(feature | 1)

Common Feature Sets

Modern Node (2024+)

MODERN_NODE_FEATURES = {
    1: True,   # data_loss_protect (optional)
    9: True,   # var_onion (optional)
    13: True,  # static_remotekey (optional)
    15: True,  # payment_secret (optional)
    17: True,  # basic_mpp (optional)
    23: True,  # anchors_zero_fee (optional)
    45: True,  # scid_alias (optional)
}

Modern Invoice

INVOICE_FEATURES = {
    9: True,   # var_onion
    15: True,  # payment_secret
    17: True,  # basic_mpp
}
  • BOLT-01 - Feature negotiation in init
  • BOLT-07 - Features in announcements
  • BOLT-11 - Features in invoices

Machine-Readable Summary

{
  "bolt": "09",
  "title": "Feature Bit Assignments",
  "status": "final",
  "key_features": [
    {"bits": [0,1], "name": "data_loss_protect"},
    {"bits": [8,9], "name": "var_onion_optin"},
    {"bits": [12,13], "name": "static_remotekey"},
    {"bits": [14,15], "name": "payment_secret"},
    {"bits": [16,17], "name": "basic_mpp"},
    {"bits": [22,23], "name": "anchors_zero_fee_htlc_tx"}
  ],
  "contexts": ["I", "N", "C", "B", "9"]
}