BOLT 1: Base Protocol
## Overview This protocol assumes an underlying authenticated and ordered transport mechanism that takes care of framing individual messages. [BOLT #8](08-transport.md) specifies the canonical transport layer used in Lightning, though it can be replaced by any transport that fulfills the above guarantees. The default TCP port depends on the network used. The most common networks are: - Bitcoin
No reviewsSpecification
BOLT #1: Base Protocol
Overview
This protocol assumes an underlying authenticated and ordered transport mechanism that takes care of framing individual messages. BOLT #8 specifies the canonical transport layer used in Lightning, though it can be replaced by any transport that fulfills the above guarantees.
The default TCP port depends on the network used. The most common networks are:
- Bitcoin mainnet with port number 9735 or the corresponding hexadecimal
0x2607; - Bitcoin testnet with port number 19735 (
0x4D17); - Bitcoin signet with port number 39735 (
0x9B37).
The Unicode code point for LIGHTNING <sup>1</sup>, and the port convention try to follow the Bitcoin Core convention.
All data fields are unsigned big-endian unless otherwise specified.
Table of Contents
- Connection Handling and Multiplexing
- Lightning Message Format
- Type-Length-Value Format
- Fundamental Types
- Setup Messages
- Control Messages
- Peer Storage
- Appendix A: BigSize Test Vectors
- Appendix B: Type-Length-Value Test Vectors
- Appendix C: Message Extension
- Appendix D: Signed Integers Test Vectors
- Acknowledgments
- References
- Authors
Connection Handling and Multiplexing
Implementations MUST use a single connection per peer; channel messages (which include a channel ID) are multiplexed over this single connection.
Lightning Message Format
After decryption, all Lightning messages are of the form:
type: a 2-byte big-endian field indicating the type of messagepayload: a variable-length payload that comprises the remainder of the message and that conforms to a format matching thetypeextension: an optional TLV stream
The type field indicates how to interpret the payload field.
The format for each individual type is defined by a specification in this repository.
The type follows the it's ok to be odd rule, so nodes MAY send odd-numbered types without ascertaining that the recipient understands it.
The messages are grouped logically into five groups, ordered by the most significant bit that is set:
- Setup & Control (types
0-31): messages related to connection setup, control, supported features, and error reporting (described below) - Channel (types
32-127): messages used to setup and tear down micropayment channels (described in BOLT #2) - Commitment (types
128-255): messages related to updating the current commitment transaction, which includes adding, revoking, and settling HTLCs as well as updating fees and exchanging signatures (described in BOLT #2) - Routing (types
256-511): messages containing node and channel announcements, as well as any active route exploration (described in BOLT #7) - Custom (types
32768-65535): experimental and application-specific messages
The size of the message is required by the transport layer to fit into a 2-byte unsigned int; therefore, the maximum possible size is 65535 bytes.
A sending node:
- MUST NOT send an evenly-typed message not listed here without prior negotiation.
- MUST NOT send evenly-typed TLV records in the
extensionwithout prior negotiation. - that negotiates an option in this specification:
- MUST include all the fields annotated with that option.
- When defining custom messages:
- SHOULD pick a random
typeto avoid collision with other custom types. - SHOULD pick a
typethat doesn't conflict with other experiments listed in this issue. - SHOULD pick an odd
typeidentifiers when regular nodes should ignore the additional data. - SHOULD pick an even
typeidentifiers when regular nodes should reject the message and close the connection.
- SHOULD pick a random
A receiving node:
- upon receiving a message of odd, unknown type:
- MUST ignore the received message.
- upon receiving a message of even, unknown type:
- MUST close the connection.
- MAY fail the channels.
- upon receiving a known message with insufficient length for the contents:
- MUST close the connection.
- MAY fail the channels.
- upon receiving a message with an
extension:- MAY ignore the
extension. - Otherwise, if the
extensionis invalid:- MUST close the connection.
- MAY fail the channels.
- MAY ignore the
Rationale
By default SHA2 and Bitcoin public keys are both encoded as
big endian, thus it would be unusual to use a different endian for
other fields.
Length is limited to 65535 bytes by the cryptographic wrapping, and messages in the protocol are never more than that length anyway.
The it's ok to be odd rule allows for future optional extensions
without negotiation or special coding in clients. The extension field
similarly allows for future expansion by letting senders include additional
TLV data. Note that an extension field can only be added when the message
payload doesn't already fill the 65535 bytes maximum length.
Implementations may prefer to have message data aligned on an 8-byte boundary (the largest natural alignment requirement of any type here); however, adding a 6-byte padding after the type field was considered wasteful: alignment may be achieved by decrypting the message into a buffer with 6-bytes of pre-padding.
Type-Length-Value Format
Throughout the protocol, a TLV (Type-Length-Value) format is used to allow for the backwards-compatible addition of new fields to existing message types.
A tlv_record represents a single field, encoded in the form:
- [
bigsize:type] - [
bigsize:length] - [
length:value]
A tlv_stream is a series of (possibly zero) tlv_records, represented as the
concatenation of the encoded tlv_records. When used to extend existing
messages, a tlv_stream is typically placed after all currently defined fields.
The type is encoded using the BigSize format. It functions as a
message-specific, 64-bit identifier for the tlv_record determining how the
contents of value should be decoded. type identifiers below 2^16 are
reserved for use in this specification. type identifiers greater than or equal
to 2^16 are available for custom records. Any record not defined in this
specification is considered a custom record. This includes experimental and
application-specific messages.
The length is encoded using the BigSize format signaling the size of
value in bytes.
The value depends entirely on the type, and should be encoded or decoded
according to the message-specific format determined by type.
Requirements
The sending node:
- MUST order
tlv_records in atlv_streamby strictly-increasingtype, hence MUST not produce more than a single TLV record with the sametype - MUST minimally encode
typeandlength. - When defining custom record
typeidentifiers:- SHOULD pick random
typeidentifiers to avoid collision with other custom types. - SHOULD pick odd
typeidentifiers when regular nodes should ignore the additional data. - SHOULD pick even
typeidentifiers when regular nodes should reject the full tlv stream containing the custom record.
- SHOULD pick random
- SHOULD NOT use redundant, variable-length encodings in a
tlv_record.
The receiving node:
- if zero bytes remain before parsing a
type:- MUST stop parsing the
tlv_stream.
- MUST stop parsing the
- if a
typeorlengthis not minimally encoded:- MUST fail to parse the
tlv_stream.
- MUST fail to parse the
- if decoded
types are not strictly-increasing (including situations when two or more occurrences of the sametypeare met):- MUST fail to parse the
tlv_stream.
- MUST fail to parse the
- if
lengthexceeds the number of bytes remaining in the message:- MUST fail to parse the
tlv_stream.
- MUST fail to parse the
- if
typeis known:- MUST decode the next
lengthbytes using the known encoding fortype. - if
lengthis not exactly equal to that required for the known encoding fortype:- MUST fail to parse the
tlv_stream.
- MUST fail to parse the
- if variable-length fields within the known encoding for
typeare not minimal:- MUST fail to parse the
tlv_stream.
- MUST fail to parse the
- MUST decode the next
- otherwise, if
typeis unknown:- if
typeis even:- MUST fail to parse the
tlv_stream.
- MUST fail to parse the
- otherwise, if
typeis odd:- MUST discard the next
lengthbytes.
- MUST discard the next
- if
Rationale
The primary advantage in using TLV is that a reader is able to ignore new fields that it does not understand, since each field carries the exact size of the encoded element. Without TLV, even if a node does not wish to use a particular field, the node is forced to add parsing logic for that field in order to determine the offset of any fields that follow.
The strict monotonicity constraint ensures that all types are unique and can
appear at most once. Fields that map to complex objects, e.g. vectors, maps, or
structs, should do so by defining the encoding such that the object is
serialized within a single tlv_record. The uniqueness constraint, among other
things, enables the following optimizations:
- canonical ordering is defined independent of the encoded
values. - canonical ordering can be known at compile-time, rather than being determined dynamically at the time of encoding.
- verifying canonical ordering requires less state and is less-expensive.
- variable-size fields can reserve their expected size up front, rather than appending elements sequentially and incurring double-and-copy overhead.
The use of a bigsize for type and length permits a space savings for small
types or short values. This potentially leaves more space for application
data over the wire or in an onion payload.
All types must appear in increasing order to create a canonical encoding of
the underlying tlv_records. This is crucial when computing signatures over a
tlv_stream, as it ensures verifiers will be able to recompute the same message
digest as the signer. Note that the canonical ordering over the set of fields
can be enforced even if the verifier does not understand what the fields
contain.
Writers should avoid using redundant, variable-length encodings in a
tlv_record since this results in encoding the length twice and complicates
computing the outer length. As an example, when writing a variable length byte
array, the value should contain only the raw bytes and forgo an additional
internal length since the tlv_record already carries the number of bytes that
follow. On the other hand, if a tlv_record contains multiple, variable-length
elements then this would not be considered redundant, and is needed to allow the
receiver to parse individual elements from value.
Fundamental Types
Various fundamental types are referred to in the message specifications:
byte: an 8-bit bytes8: an 8-bit signed integeru16: a 2 byte unsigned integers16: a 2 byte signed integeru32: a 4 byte unsigned integers32: a 4 byte signed integeru64: an 8 byte unsigned integers64: an 8 byte signed integer
Signed integers use standard big-endian two's complement representation (see test vectors below).
For the final value in TLV records, truncated integers may be used. Leading zeros in truncated integers MUST be omitted:
tu16: a 0 to 2 byte truncated unsigned integertu32: a 0 to 4 byte truncated unsigned integertu64: a 0 to 8 byte truncated unsigned integer
When used to encode amounts, the previous fields MUST comply with the upper bound of 21 million BTC:
- satoshi amounts MUST be at most
0x000775f05a074000 - milli-satoshi amounts MUST be at most
0x1d24b2dfac520000
The following convenience types are also defined:
chain_hash: a 32-byte chain identifier (see BOLT #0)channel_id: a 32-byte channel_id (see BOLT #2)sha256: a 32-byte SHA2-256 hashsignature: a 64-byte bitcoin Elliptic Curve signaturebip340sig: a 64-byte bitcoin Elliptic Curve Schnorr signature as per BIP-340point: a 33-byte Elliptic Curve point (compressed encoding as per SEC 1 standard)short_channel_id: an 8 byte value identifying a channel (see BOLT #7)sciddir_or_pubkey: either 9 or 33 bytes referencing or identifying a node, respectively- if the first byte is 0 or 1, then an 8-byte
short_channel_idfollows for a total of 9 bytes- 0 for the first byte indicates this refers to
node_id_1in thechannel_announcementforshort_channel_id - 1 for the first byte indicates this refers to
node_id_2in thechannel_announcementforshort_channel_id(see BOLT #7
- 0 for the first byte indicates this refers to
- if the first byte is 2 or 3, then the value is a 33-byte
point
- if the first byte is 0 or 1, then an 8-byte
bigsize: a variable-length, unsigned integer similar to Bitcoin's CompactSize encoding, but big-endian. Described in BigSize.utf8: a byte as part of a UTF-8 string. A writer MUST ensure an array of these is a valid UTF-8 string, a reader MAY reject any messages containing an array of these which is not a valid UTF-8 string.
Setup Messages
The init Message
Once authentication is complete, the first message reveals the features supported or required by this node, even if this is a reconnection.
BOLT #9 specifies lists of features. Each feature is generally represented by 2 bits. The least-significant bit is numbered 0, which is even, and the next most significant bit is numbered 1, which is odd. For historical reasons, features are divided into global and local feature bitmasks.
A feature is offered if a peer set it in the init message for the current connection (as either even or odd). A feature is negotiated if either both peers offered it, or the local node offered it as even: it can assume the peer supports it, as it did not disconnect as it would be required to do.
The features f
[Content truncated — view full spec at source]
Discussion (0 threads)
Sign in to start a discussion on this spec.