Browse Source

lnmsg: rewrite LN msg encoding/decoding

master
SomberNight 6 years ago
parent
commit
4c10a830f3
No known key found for this signature in database
GPG Key ID: B33B5F232C6271E9
  1. 4
      electrum/channel_db.py
  2. 903
      electrum/lightning.json
  3. 5
      electrum/lnchannel.py
  4. 343
      electrum/lnmsg.py
  5. 14
      electrum/lnpeer.py
  6. 5
      electrum/lnwire/README.md
  7. 53
      electrum/lnwire/onion_wire.csv
  8. 210
      electrum/lnwire/peer_wire.csv

4
electrum/channel_db.py

@ -321,11 +321,12 @@ class ChannelDB(SqlDB):
return ret return ret
# note: currently channel announcements are trusted by default (trusted=True); # note: currently channel announcements are trusted by default (trusted=True);
# they are not verified. Verifying them would make the gossip sync # they are not SPV-verified. Verifying them would make the gossip sync
# even slower; especially as servers will start throttling us. # even slower; especially as servers will start throttling us.
# It would probably put significant strain on servers if all clients # It would probably put significant strain on servers if all clients
# verified the complete gossip. # verified the complete gossip.
def add_channel_announcement(self, msg_payloads, *, trusted=True): def add_channel_announcement(self, msg_payloads, *, trusted=True):
# note: signatures have already been verified.
if type(msg_payloads) is dict: if type(msg_payloads) is dict:
msg_payloads = [msg_payloads] msg_payloads = [msg_payloads]
added = 0 added = 0
@ -499,6 +500,7 @@ class ChannelDB(SqlDB):
raise Exception(f'failed verifying channel update for {short_channel_id}') raise Exception(f'failed verifying channel update for {short_channel_id}')
def add_node_announcement(self, msg_payloads): def add_node_announcement(self, msg_payloads):
# note: signatures have already been verified.
if type(msg_payloads) is dict: if type(msg_payloads) is dict:
msg_payloads = [msg_payloads] msg_payloads = [msg_payloads]
new_nodes = {} new_nodes = {}

903
electrum/lightning.json

@ -1,903 +0,0 @@
{
"init": {
"type": "16",
"payload": {
"gflen": {
"position": "0",
"length": "2"
},
"globalfeatures": {
"position": "2",
"length": "gflen"
},
"lflen": {
"position": "2+gflen",
"length": "2"
},
"localfeatures": {
"position": "4+gflen",
"length": "lflen"
}
}
},
"error": {
"type": "17",
"payload": {
"channel_id": {
"position": "0",
"length": "32"
},
"len": {
"position": "32",
"length": "2"
},
"data": {
"position": "34",
"length": "len"
}
}
},
"ping": {
"type": "18",
"payload": {
"num_pong_bytes": {
"position": "0",
"length": "2"
},
"byteslen": {
"position": "2",
"length": "2"
},
"ignored": {
"position": "4",
"length": "byteslen"
}
}
},
"pong": {
"type": "19",
"payload": {
"byteslen": {
"position": "0",
"length": "2"
},
"ignored": {
"position": "2",
"length": "byteslen"
}
}
},
"open_channel": {
"type": "32",
"payload": {
"chain_hash": {
"position": "0",
"length": "32"
},
"temporary_channel_id": {
"position": "32",
"length": "32"
},
"funding_satoshis": {
"position": "64",
"length": "8"
},
"push_msat": {
"position": "72",
"length": "8"
},
"dust_limit_satoshis": {
"position": "80",
"length": "8"
},
"max_htlc_value_in_flight_msat": {
"position": "88",
"length": "8"
},
"channel_reserve_satoshis": {
"position": "96",
"length": "8"
},
"htlc_minimum_msat": {
"position": "104",
"length": "8"
},
"feerate_per_kw": {
"position": "112",
"length": "4"
},
"to_self_delay": {
"position": "116",
"length": "2"
},
"max_accepted_htlcs": {
"position": "118",
"length": "2"
},
"funding_pubkey": {
"position": "120",
"length": "33"
},
"revocation_basepoint": {
"position": "153",
"length": "33"
},
"payment_basepoint": {
"position": "186",
"length": "33"
},
"delayed_payment_basepoint": {
"position": "219",
"length": "33"
},
"htlc_basepoint": {
"position": "252",
"length": "33"
},
"first_per_commitment_point": {
"position": "285",
"length": "33"
},
"channel_flags": {
"position": "318",
"length": "1"
},
"shutdown_len": {
"position": "319",
"length": "2",
"feature": "option_upfront_shutdown_script"
},
"shutdown_scriptpubkey": {
"position": "321",
"length": "shutdown_len",
"feature": "option_upfront_shutdown_script"
}
}
},
"accept_channel": {
"type": "33",
"payload": {
"temporary_channel_id": {
"position": "0",
"length": "32"
},
"dust_limit_satoshis": {
"position": "32",
"length": "8"
},
"max_htlc_value_in_flight_msat": {
"position": "40",
"length": "8"
},
"channel_reserve_satoshis": {
"position": "48",
"length": "8"
},
"htlc_minimum_msat": {
"position": "56",
"length": "8"
},
"minimum_depth": {
"position": "64",
"length": "4"
},
"to_self_delay": {
"position": "68",
"length": "2"
},
"max_accepted_htlcs": {
"position": "70",
"length": "2"
},
"funding_pubkey": {
"position": "72",
"length": "33"
},
"revocation_basepoint": {
"position": "105",
"length": "33"
},
"payment_basepoint": {
"position": "138",
"length": "33"
},
"delayed_payment_basepoint": {
"position": "171",
"length": "33"
},
"htlc_basepoint": {
"position": "204",
"length": "33"
},
"first_per_commitment_point": {
"position": "237",
"length": "33"
},
"shutdown_len": {
"position": "270",
"length": "2",
"feature": "option_upfront_shutdown_script"
},
"shutdown_scriptpubkey": {
"position": "272",
"length": "shutdown_len",
"feature": "option_upfront_shutdown_script"
}
}
},
"funding_created": {
"type": "34",
"payload": {
"temporary_channel_id": {
"position": "0",
"length": "32"
},
"funding_txid": {
"position": "32",
"length": "32"
},
"funding_output_index": {
"position": "64",
"length": "2"
},
"signature": {
"position": "66",
"length": "64"
}
}
},
"funding_signed": {
"type": "35",
"payload": {
"channel_id": {
"position": "0",
"length": "32"
},
"signature": {
"position": "32",
"length": "64"
}
}
},
"funding_locked": {
"type": "36",
"payload": {
"channel_id": {
"position": "0",
"length": "32"
},
"next_per_commitment_point": {
"position": "32",
"length": "33"
}
}
},
"shutdown": {
"type": "38",
"payload": {
"channel_id": {
"position": "0",
"length": "32"
},
"len": {
"position": "32",
"length": "2"
},
"scriptpubkey": {
"position": "34",
"length": "len"
}
}
},
"closing_signed": {
"type": "39",
"payload": {
"channel_id": {
"position": "0",
"length": "32"
},
"fee_satoshis": {
"position": "32",
"length": "8"
},
"signature": {
"position": "40",
"length": "64"
}
}
},
"update_add_htlc": {
"type": "128",
"payload": {
"channel_id": {
"position": "0",
"length": "32"
},
"id": {
"position": "32",
"length": "8"
},
"amount_msat": {
"position": "40",
"length": "8"
},
"payment_hash": {
"position": "48",
"length": "32"
},
"cltv_expiry": {
"position": "80",
"length": "4"
},
"onion_routing_packet": {
"position": "84",
"length": "1366"
}
}
},
"update_fulfill_htlc": {
"type": "130",
"payload": {
"channel_id": {
"position": "0",
"length": "32"
},
"id": {
"position": "32",
"length": "8"
},
"payment_preimage": {
"position": "40",
"length": "32"
}
}
},
"update_fail_htlc": {
"type": "131",
"payload": {
"channel_id": {
"position": "0",
"length": "32"
},
"id": {
"position": "32",
"length": "8"
},
"len": {
"position": "40",
"length": "2"
},
"reason": {
"position": "42",
"length": "len"
}
}
},
"update_fail_malformed_htlc": {
"type": "135",
"payload": {
"channel_id": {
"position": "0",
"length": "32"
},
"id": {
"position": "32",
"length": "8"
},
"sha256_of_onion": {
"position": "40",
"length": "32"
},
"failure_code": {
"position": "72",
"length": "2"
}
}
},
"commitment_signed": {
"type": "132",
"payload": {
"channel_id": {
"position": "0",
"length": "32"
},
"signature": {
"position": "32",
"length": "64"
},
"num_htlcs": {
"position": "96",
"length": "2"
},
"htlc_signature": {
"position": "98",
"length": "num_htlcs*64"
}
}
},
"revoke_and_ack": {
"type": "133",
"payload": {
"channel_id": {
"position": "0",
"length": "32"
},
"per_commitment_secret": {
"position": "32",
"length": "32"
},
"next_per_commitment_point": {
"position": "64",
"length": "33"
}
}
},
"update_fee": {
"type": "134",
"payload": {
"channel_id": {
"position": "0",
"length": "32"
},
"feerate_per_kw": {
"position": "32",
"length": "4"
}
}
},
"channel_reestablish": {
"type": "136",
"payload": {
"channel_id": {
"position": "0",
"length": "32"
},
"next_local_commitment_number": {
"position": "32",
"length": "8"
},
"next_remote_revocation_number": {
"position": "40",
"length": "8"
},
"your_last_per_commitment_secret": {
"position": "48",
"length": "32",
"feature": "option_data_loss_protect"
},
"my_current_per_commitment_point": {
"position": "80",
"length": "33",
"feature": "option_data_loss_protect"
}
}
},
"invalid_realm": {
"type": "PERM|1",
"payload": {}
},
"temporary_node_failure": {
"type": "NODE|2",
"payload": {}
},
"permanent_node_failure": {
"type": "PERM|NODE|2",
"payload": {}
},
"required_node_feature_missing": {
"type": "PERM|NODE|3",
"payload": {}
},
"invalid_onion_version": {
"type": "BADONION|PERM|4",
"payload": {
"sha256_of_onion": {
"position": "0",
"length": "32"
}
}
},
"invalid_onion_hmac": {
"type": "BADONION|PERM|5",
"payload": {
"sha256_of_onion": {
"position": "0",
"length": "32"
}
}
},
"invalid_onion_key": {
"type": "BADONION|PERM|6",
"payload": {
"sha256_of_onion": {
"position": "0",
"length": "32"
}
}
},
"temporary_channel_failure": {
"type": "UPDATE|7",
"payload": {
"len": {
"position": "0",
"length": "2"
},
"channel_update": {
"position": "2",
"length": "len"
}
}
},
"permanent_channel_failure": {
"type": "PERM|8",
"payload": {}
},
"required_channel_feature_missing": {
"type": "PERM|9",
"payload": {}
},
"unknown_next_peer": {
"type": "PERM|10",
"payload": {}
},
"amount_below_minimum": {
"type": "UPDATE|11",
"payload": {
"htlc_msat": {
"position": "0",
"length": "8"
},
"len": {
"position": "8",
"length": "2"
},
"channel_update": {
"position": "10",
"length": "len"
}
}
},
"fee_insufficient": {
"type": "UPDATE|12",
"payload": {
"htlc_msat": {
"position": "0",
"length": "8"
},
"len": {
"position": "8",
"length": "2"
},
"channel_update": {
"position": "10",
"length": "len"
}
}
},
"incorrect_cltv_expiry": {
"type": "UPDATE|13",
"payload": {
"cltv_expiry": {
"position": "0",
"length": "4"
},
"len": {
"position": "4",
"length": "2"
},
"channel_update": {
"position": "6",
"length": "len"
}
}
},
"expiry_too_soon": {
"type": "UPDATE|14",
"payload": {
"len": {
"position": "0",
"length": "2"
},
"channel_update": {
"position": "2",
"length": "len"
}
}
},
"unknown_payment_hash": {
"type": "PERM|15",
"payload": {}
},
"incorrect_payment_amount": {
"type": "PERM|16",
"payload": {}
},
"final_expiry_too_soon": {
"type": "17",
"payload": {}
},
"final_incorrect_cltv_expiry": {
"type": "18",
"payload": {
"cltv_expiry": {
"position": "0",
"length": "4"
}
}
},
"final_incorrect_htlc_amount": {
"type": "19",
"payload": {
"incoming_htlc_amt": {
"position": "0",
"length": "8"
}
}
},
"channel_disabled": {
"type": "UPDATE|20",
"payload": {}
},
"expiry_too_far": {
"type": "21",
"payload": {}
},
"announcement_signatures": {
"type": "259",
"payload": {
"channel_id": {
"position": "0",
"length": "32"
},
"short_channel_id": {
"position": "32",
"length": "8"
},
"node_signature": {
"position": "40",
"length": "64"
},
"bitcoin_signature": {
"position": "104",
"length": "64"
}
}
},
"channel_announcement": {
"type": "256",
"payload": {
"node_signature_1": {
"position": "0",
"length": "64"
},
"node_signature_2": {
"position": "64",
"length": "64"
},
"bitcoin_signature_1": {
"position": "128",
"length": "64"
},
"bitcoin_signature_2": {
"position": "192",
"length": "64"
},
"len": {
"position": "256",
"length": "2"
},
"features": {
"position": "258",
"length": "len"
},
"chain_hash": {
"position": "258+len",
"length": "32"
},
"short_channel_id": {
"position": "290+len",
"length": "8"
},
"node_id_1": {
"position": "298+len",
"length": "33"
},
"node_id_2": {
"position": "331+len",
"length": "33"
},
"bitcoin_key_1": {
"position": "364+len",
"length": "33"
},
"bitcoin_key_2": {
"position": "397+len",
"length": "33"
}
}
},
"node_announcement": {
"type": "257",
"payload": {
"signature": {
"position": "0",
"length": "64"
},
"flen": {
"position": "64",
"length": "2"
},
"features": {
"position": "66",
"length": "flen"
},
"timestamp": {
"position": "66+flen",
"length": "4"
},
"node_id": {
"position": "70+flen",
"length": "33"
},
"rgb_color": {
"position": "103+flen",
"length": "3"
},
"alias": {
"position": "106+flen",
"length": "32"
},
"addrlen": {
"position": "138+flen",
"length": "2"
},
"addresses": {
"position": "140+flen",
"length": "addrlen"
}
}
},
"channel_update": {
"type": "258",
"payload": {
"signature": {
"position": "0",
"length": "64"
},
"chain_hash": {
"position": "64",
"length": "32"
},
"short_channel_id": {
"position": "96",
"length": "8"
},
"timestamp": {
"position": "104",
"length": "4"
},
"message_flags": {
"position": "108",
"length": "1"
},
"channel_flags": {
"position": "109",
"length": "1"
},
"cltv_expiry_delta": {
"position": "110",
"length": "2"
},
"htlc_minimum_msat": {
"position": "112",
"length": "8"
},
"fee_base_msat": {
"position": "120",
"length": "4"
},
"fee_proportional_millionths": {
"position": "124",
"length": "4"
},
"htlc_maximum_msat": {
"position": "128",
"length": "8",
"feature": "option_channel_htlc_max"
}
}
},
"query_short_channel_ids": {
"type": "261",
"payload": {
"chain_hash": {
"position": "0",
"length": "32"
},
"len": {
"position": "32",
"length": "2"
},
"encoded_short_ids": {
"position": "34",
"length": "len"
}
}
},
"reply_short_channel_ids_end": {
"type": "262",
"payload": {
"chain_hash": {
"position": "0",
"length": "32"
},
"complete": {
"position": "32",
"length": "1"
}
}
},
"query_channel_range": {
"type": "263",
"payload": {
"chain_hash": {
"position": "0",
"length": "32"
},
"first_blocknum": {
"position": "32",
"length": "4"
},
"number_of_blocks": {
"position": "36",
"length": "4"
}
}
},
"reply_channel_range": {
"type": "264",
"payload": {
"chain_hash": {
"position": "0",
"length": "32"
},
"first_blocknum": {
"position": "32",
"length": "4"
},
"number_of_blocks": {
"position": "36",
"length": "4"
},
"complete": {
"position": "40",
"length": "1"
},
"len": {
"position": "41",
"length": "2"
},
"encoded_short_ids": {
"position": "43",
"length": "len"
}
}
},
"gossip_timestamp_filter": {
"type": "265",
"payload": {
"chain_hash": {
"position": "0",
"length": "32"
},
"first_timestamp": {
"position": "32",
"length": "4"
},
"timestamp_range": {
"position": "36",
"length": "4"
}
}
}
}

5
electrum/lnchannel.py

@ -249,7 +249,8 @@ class Channel(Logger):
node_ids = sorted_node_ids node_ids = sorted_node_ids
bitcoin_keys.reverse() bitcoin_keys.reverse()
chan_ann = encode_msg("channel_announcement", chan_ann = encode_msg(
"channel_announcement",
len=0, len=0,
features=b'', features=b'',
chain_hash=constants.net.rev_genesis_bytes(), chain_hash=constants.net.rev_genesis_bytes(),
@ -257,7 +258,7 @@ class Channel(Logger):
node_id_1=node_ids[0], node_id_1=node_ids[0],
node_id_2=node_ids[1], node_id_2=node_ids[1],
bitcoin_key_1=bitcoin_keys[0], bitcoin_key_1=bitcoin_keys[0],
bitcoin_key_2=bitcoin_keys[1] bitcoin_key_2=bitcoin_keys[1],
) )
self._chan_ann_without_sigs = chan_ann self._chan_ann_without_sigs = chan_ann

343
electrum/lnmsg.py

@ -1,152 +1,225 @@
import json
import os import os
from typing import Callable, Tuple import csv
from collections import OrderedDict import io
from typing import Callable, Tuple, Any, Dict, List, Sequence, Union
def _eval_length_term(x, ma: dict) -> int:
"""
Evaluate a term of the simple language used class MalformedMsg(Exception):
to specify lightning message field lengths. pass
If `x` is an integer, it is returned as is,
otherwise it is treated as a variable and class UnknownMsgFieldType(MalformedMsg):
looked up in `ma`. pass
If the value in `ma` was no integer, it is
assumed big-endian bytes and decoded. class UnexpectedEndOfStream(MalformedMsg):
pass
Returns evaluated result as int
"""
try: def _assert_can_read_at_least_n_bytes(fd: io.BytesIO, n: int) -> None:
x = int(x) cur_pos = fd.tell()
except ValueError: end_pos = fd.seek(0, io.SEEK_END)
x = ma[x] fd.seek(cur_pos)
try: if end_pos - cur_pos < n:
x = int(x) raise UnexpectedEndOfStream(f"cur_pos={cur_pos}. end_pos={end_pos}. wants to read: {n}")
except ValueError:
x = int.from_bytes(x, byteorder='big')
return x # TODO return int when it makes sense
def _read_field(*, fd: io.BytesIO, field_type: str, count: int) -> bytes:
def _eval_exp_with_ctx(exp, ctx: dict) -> int: if not fd: raise Exception()
""" assert isinstance(count, int) and count >= 0, f"{count!r} must be non-neg int"
Evaluate simple mathematical expression given if count == 0:
in `exp` with context (variables assigned) return b""
from the dict `ctx`. type_len = None
if field_type == 'byte':
Returns evaluated result as int type_len = 1
""" elif field_type == 'u16':
exp = str(exp) type_len = 2
if "*" in exp: elif field_type == 'u32':
assert "+" not in exp type_len = 4
result = 1 elif field_type == 'u64':
for term in exp.split("*"): type_len = 8
result *= _eval_length_term(term, ctx) # TODO tu16/tu32/tu64
return result elif field_type == 'chain_hash':
return sum(_eval_length_term(x, ctx) for x in exp.split("+")) type_len = 32
elif field_type == 'channel_id':
def _make_handler(msg_name: str, v: dict) -> Callable[[bytes], Tuple[str, dict]]: type_len = 32
""" elif field_type == 'sha256':
Generate a message handler function (taking bytes) type_len = 32
for message type `msg_name` with specification `v` elif field_type == 'signature':
type_len = 64
Check lib/lightning.json, `msg_name` could be 'init', elif field_type == 'point':
and `v` could be type_len = 33
elif field_type == 'short_channel_id':
{ type: 16, payload: { 'gflen': ..., ... }, ... } type_len = 8
if type_len is None:
Returns function taking bytes raise UnknownMsgFieldType(f"unexpected field type: {field_type!r}")
""" total_len = count * type_len
def handler(data: bytes) -> Tuple[str, dict]: _assert_can_read_at_least_n_bytes(fd, total_len)
ma = {} # map of field name -> field data; after parsing msg return fd.read(total_len)
pos = 0
for fieldname in v["payload"]:
poslenMap = v["payload"][fieldname] def _write_field(*, fd: io.BytesIO, field_type: str, count: int,
if "feature" in poslenMap and pos == len(data): value: Union[bytes, int]) -> None:
continue if not fd: raise Exception()
#assert pos == _eval_exp_with_ctx(poslenMap["position"], ma) # this assert is expensive... assert isinstance(count, int) and count >= 0, f"{count!r} must be non-neg int"
length = poslenMap["length"] if count == 0:
length = _eval_exp_with_ctx(length, ma) return
ma[fieldname] = data[pos:pos+length] type_len = None
pos += length if field_type == 'byte':
# BOLT-01: "MUST ignore any additional data within a message beyond the length that it expects for that type." type_len = 1
assert pos <= len(data), (msg_name, pos, len(data)) elif field_type == 'u16':
return msg_name, ma type_len = 2
return handler elif field_type == 'u32':
type_len = 4
elif field_type == 'u64':
type_len = 8
# TODO tu16/tu32/tu64
elif field_type == 'chain_hash':
type_len = 32
elif field_type == 'channel_id':
type_len = 32
elif field_type == 'sha256':
type_len = 32
elif field_type == 'signature':
type_len = 64
elif field_type == 'point':
type_len = 33
elif field_type == 'short_channel_id':
type_len = 8
if type_len is None:
raise UnknownMsgFieldType(f"unexpected fundamental type: {field_type!r}")
total_len = count * type_len
if isinstance(value, int) and (count == 1 or field_type == 'byte'):
value = int.to_bytes(value, length=total_len, byteorder="big", signed=False)
if not isinstance(value, (bytes, bytearray)):
raise Exception(f"can only write bytes into fd. got: {value!r}")
if total_len != len(value):
raise Exception(f"unexpected field size. expected: {total_len}, got {len(value)}")
nbytes_written = fd.write(value)
if nbytes_written != len(value):
raise Exception(f"tried to write {len(value)} bytes, but only wrote {nbytes_written}!?")
class LNSerializer: class LNSerializer:
def __init__(self): def __init__(self):
message_types = {} self.msg_scheme_from_type = {} # type: Dict[bytes, List[Sequence[str]]]
path = os.path.join(os.path.dirname(__file__), 'lightning.json') self.msg_type_from_name = {} # type: Dict[str, bytes]
with open(path) as f: path = os.path.join(os.path.dirname(__file__), "lnwire", "peer_wire.csv")
structured = json.loads(f.read(), object_pairs_hook=OrderedDict) with open(path, newline='') as f:
csvreader = csv.reader(f)
for msg_name in structured: for row in csvreader:
v = structured[msg_name] #print(f">>> {row!r}")
# these message types are skipped since their types collide if row[0] == "msgtype":
# (for example with pong, which also uses type=19) msg_type_name = row[1]
# we don't need them yet msg_type_int = int(row[2])
if msg_name in ["final_incorrect_cltv_expiry", "final_incorrect_htlc_amount"]: msg_type_bytes = msg_type_int.to_bytes(2, 'big')
continue assert msg_type_bytes not in self.msg_scheme_from_type, f"type collision? for {msg_type_name}"
if len(v["payload"]) == 0: assert msg_type_name not in self.msg_type_from_name, f"type collision? for {msg_type_name}"
continue row[2] = msg_type_int
try: self.msg_scheme_from_type[msg_type_bytes] = [tuple(row)]
num = int(v["type"]) self.msg_type_from_name[msg_type_name] = msg_type_bytes
except ValueError: elif row[0] == "msgdata":
#print("skipping", k) assert msg_type_name == row[1]
continue self.msg_scheme_from_type[msg_type_bytes].append(tuple(row))
byts = num.to_bytes(2, 'big') else:
assert byts not in message_types, (byts, message_types[byts].__name__, msg_name) pass # TODO
names = [x.__name__ for x in message_types.values()]
assert msg_name + "_handler" not in names, (msg_name, names) def encode_msg(self, msg_type: str, **kwargs) -> bytes:
message_types[byts] = _make_handler(msg_name, v)
message_types[byts].__name__ = msg_name + "_handler"
assert message_types[b"\x00\x10"].__name__ == "init_handler"
self.structured = structured
self.message_types = message_types
def encode_msg(self, msg_type : str, **kwargs) -> bytes:
""" """
Encode kwargs into a Lightning message (bytes) Encode kwargs into a Lightning message (bytes)
of the type given in the msg_type string of the type given in the msg_type string
""" """
typ = self.structured[msg_type] #print(f">>> encode_msg. msg_type={msg_type}, payload={kwargs!r}")
data = int(typ["type"]).to_bytes(2, 'big') msg_type_bytes = self.msg_type_from_name[msg_type]
lengths = {} scheme = self.msg_scheme_from_type[msg_type_bytes]
for k in typ["payload"]: with io.BytesIO() as fd:
poslenMap = typ["payload"][k] fd.write(msg_type_bytes)
if k not in kwargs and "feature" in poslenMap: for row in scheme:
continue if row[0] == "msgtype":
param = kwargs.get(k, 0) pass
leng = _eval_exp_with_ctx(poslenMap["length"], lengths) elif row[0] == "msgdata":
try: field_name = row[2]
clone = dict(lengths) field_type = row[3]
clone.update(kwargs) field_count_str = row[4]
leng = _eval_exp_with_ctx(poslenMap["length"], clone) #print(f">>> encode_msg. msgdata. field_name={field_name!r}. field_type={field_type!r}. field_count_str={field_count_str!r}")
except KeyError: if field_count_str == "":
pass field_count = 1
try: else:
if not isinstance(param, bytes): try:
assert isinstance(param, int), "field {} is neither bytes or int".format(k) field_count = int(field_count_str)
param = param.to_bytes(leng, 'big') except ValueError:
except ValueError: field_count = kwargs[field_count_str]
raise Exception("{} does not fit in {} bytes".format(k, leng)) if isinstance(field_count, (bytes, bytearray)):
lengths[k] = len(param) field_count = int.from_bytes(field_count, byteorder="big")
if lengths[k] != leng: assert isinstance(field_count, int)
raise Exception("field {} is {} bytes long, should be {} bytes long".format(k, lengths[k], leng)) try:
data += param field_value = kwargs[field_name]
return data except KeyError:
if len(row) > 5:
def decode_msg(self, data : bytes) -> Tuple[str, dict]: break # optional feature field not present
else:
field_value = 0 # default mandatory fields to zero
#print(f">>> encode_msg. writing field: {field_name}. value={field_value!r}. field_type={field_type!r}. count={field_count!r}")
try:
_write_field(fd=fd,
field_type=field_type,
count=field_count,
value=field_value)
#print(f">>> encode_msg. so far: {fd.getvalue().hex()}")
except UnknownMsgFieldType as e:
pass # TODO
else:
pass # TODO
return fd.getvalue()
def decode_msg(self, data: bytes) -> Tuple[str, dict]:
""" """
Decode Lightning message by reading the first Decode Lightning message by reading the first
two bytes to determine message type. two bytes to determine message type.
Returns message type string and parsed message contents dict Returns message type string and parsed message contents dict
""" """
typ = data[:2] #print(f"decode_msg >>> {data.hex()}")
k, parsed = self.message_types[typ](data[2:]) assert len(data) >= 2
return k, parsed msg_type_bytes = data[:2]
msg_type_int = int.from_bytes(msg_type_bytes, byteorder="big", signed=False)
scheme = self.msg_scheme_from_type[msg_type_bytes]
assert scheme[0][2] == msg_type_int
msg_type_name = scheme[0][1]
parsed = {}
with io.BytesIO(data[2:]) as fd:
for row in scheme:
#print(f"row: {row!r}")
if row[0] == "msgtype":
pass
elif row[0] == "msgdata":
field_name = row[2]
field_type = row[3]
field_count_str = row[4]
if field_count_str == "":
field_count = 1
else:
try:
field_count = int(field_count_str)
except ValueError:
field_count = int.from_bytes(parsed[field_count_str], byteorder="big")
#print(f">> count={field_count}. parsed={parsed}")
try:
parsed[field_name] = _read_field(fd=fd,
field_type=field_type,
count=field_count)
except UnknownMsgFieldType as e:
pass # TODO
except UnexpectedEndOfStream as e:
if len(row) > 5:
break # optional feature field not present
else:
raise
else:
pass # TODO
return msg_type_name, parsed
_inst = LNSerializer() _inst = LNSerializer()
encode_msg = _inst.encode_msg encode_msg = _inst.encode_msg

14
electrum/lnpeer.py

@ -131,7 +131,7 @@ class Peer(Logger):
async def initialize(self): async def initialize(self):
if isinstance(self.transport, LNTransport): if isinstance(self.transport, LNTransport):
await self.transport.handshake() await self.transport.handshake()
self.send_message("init", gflen=0, lflen=2, localfeatures=self.localfeatures) self.send_message("init", gflen=0, flen=2, features=self.localfeatures)
self._sent_init = True self._sent_init = True
self.maybe_set_initialized() self.maybe_set_initialized()
@ -201,7 +201,7 @@ class Peer(Logger):
return return
# if they required some even flag we don't have, they will close themselves # if they required some even flag we don't have, they will close themselves
# but if we require an even flag they don't have, we close # but if we require an even flag they don't have, we close
their_localfeatures = int.from_bytes(payload['localfeatures'], byteorder="big") their_localfeatures = int.from_bytes(payload['features'], byteorder="big") # TODO feature bit unification
try: try:
self.localfeatures = ln_compare_features(self.localfeatures, their_localfeatures) self.localfeatures = ln_compare_features(self.localfeatures, their_localfeatures)
except IncompatibleLightningFeatures as e: except IncompatibleLightningFeatures as e:
@ -760,16 +760,16 @@ class Peer(Logger):
self.send_message( self.send_message(
"channel_reestablish", "channel_reestablish",
channel_id=chan_id, channel_id=chan_id,
next_local_commitment_number=next_local_ctn, next_commitment_number=next_local_ctn,
next_remote_revocation_number=oldest_unrevoked_remote_ctn, next_revocation_number=oldest_unrevoked_remote_ctn,
your_last_per_commitment_secret=last_rev_secret, your_last_per_commitment_secret=last_rev_secret,
my_current_per_commitment_point=latest_point) my_current_per_commitment_point=latest_point)
self.logger.info(f'channel_reestablish ({chan.get_id_for_log()}): sent channel_reestablish with ' self.logger.info(f'channel_reestablish ({chan.get_id_for_log()}): sent channel_reestablish with '
f'(next_local_ctn={next_local_ctn}, ' f'(next_local_ctn={next_local_ctn}, '
f'oldest_unrevoked_remote_ctn={oldest_unrevoked_remote_ctn})') f'oldest_unrevoked_remote_ctn={oldest_unrevoked_remote_ctn})')
msg = await self.wait_for_message('channel_reestablish', chan_id) msg = await self.wait_for_message('channel_reestablish', chan_id)
their_next_local_ctn = int.from_bytes(msg["next_local_commitment_number"], 'big') their_next_local_ctn = int.from_bytes(msg["next_commitment_number"], 'big')
their_oldest_unrevoked_remote_ctn = int.from_bytes(msg["next_remote_revocation_number"], 'big') their_oldest_unrevoked_remote_ctn = int.from_bytes(msg["next_revocation_number"], 'big')
their_local_pcp = msg.get("my_current_per_commitment_point") their_local_pcp = msg.get("my_current_per_commitment_point")
their_claim_of_our_last_per_commitment_secret = msg.get("your_last_per_commitment_secret") their_claim_of_our_last_per_commitment_secret = msg.get("your_last_per_commitment_secret")
self.logger.info(f'channel_reestablish ({chan.get_id_for_log()}): received channel_reestablish with ' self.logger.info(f'channel_reestablish ({chan.get_id_for_log()}): received channel_reestablish with '
@ -818,7 +818,7 @@ class Peer(Logger):
if oldest_unrevoked_local_ctn != their_oldest_unrevoked_remote_ctn: if oldest_unrevoked_local_ctn != their_oldest_unrevoked_remote_ctn:
if oldest_unrevoked_local_ctn - 1 == their_oldest_unrevoked_remote_ctn: if oldest_unrevoked_local_ctn - 1 == their_oldest_unrevoked_remote_ctn:
# A node: # A node:
# if next_remote_revocation_number is equal to the commitment number of the last revoke_and_ack # if next_revocation_number is equal to the commitment number of the last revoke_and_ack
# the receiving node sent, AND the receiving node hasn't already received a closing_signed: # the receiving node sent, AND the receiving node hasn't already received a closing_signed:
# MUST re-send the revoke_and_ack. # MUST re-send the revoke_and_ack.
last_secret, last_point = chan.get_secret_and_point(LOCAL, oldest_unrevoked_local_ctn - 1) last_secret, last_point = chan.get_secret_and_point(LOCAL, oldest_unrevoked_local_ctn - 1)

5
electrum/lnwire/README.md

@ -0,0 +1,5 @@
These files are generated from the BOLT repository:
```
$ python3 tools/extract-formats.py 01-*.md 02-*.md 07-*.md > peer_wire.csv
$ python3 tools/extract-formats.py 04-*.md > onion_wire.csv
```

53
electrum/lnwire/onion_wire.csv

@ -0,0 +1,53 @@
tlvtype,tlv_payload,amt_to_forward,2
tlvdata,tlv_payload,amt_to_forward,amt_to_forward,tu64,
tlvtype,tlv_payload,outgoing_cltv_value,4
tlvdata,tlv_payload,outgoing_cltv_value,outgoing_cltv_value,tu32,
tlvtype,tlv_payload,short_channel_id,6
tlvdata,tlv_payload,short_channel_id,short_channel_id,short_channel_id,
tlvtype,tlv_payload,payment_data,8
tlvdata,tlv_payload,payment_data,payment_secret,byte,32
tlvdata,tlv_payload,payment_data,total_msat,tu64,
msgtype,invalid_realm,PERM|1
msgtype,temporary_node_failure,NODE|2
msgtype,permanent_node_failure,PERM|NODE|2
msgtype,required_node_feature_missing,PERM|NODE|3
msgtype,invalid_onion_version,BADONION|PERM|4
msgdata,invalid_onion_version,sha256_of_onion,sha256,
msgtype,invalid_onion_hmac,BADONION|PERM|5
msgdata,invalid_onion_hmac,sha256_of_onion,sha256,
msgtype,invalid_onion_key,BADONION|PERM|6
msgdata,invalid_onion_key,sha256_of_onion,sha256,
msgtype,temporary_channel_failure,UPDATE|7
msgdata,temporary_channel_failure,len,u16,
msgdata,temporary_channel_failure,channel_update,byte,len
msgtype,permanent_channel_failure,PERM|8
msgtype,required_channel_feature_missing,PERM|9
msgtype,unknown_next_peer,PERM|10
msgtype,amount_below_minimum,UPDATE|11
msgdata,amount_below_minimum,htlc_msat,u64,
msgdata,amount_below_minimum,len,u16,
msgdata,amount_below_minimum,channel_update,byte,len
msgtype,fee_insufficient,UPDATE|12
msgdata,fee_insufficient,htlc_msat,u64,
msgdata,fee_insufficient,len,u16,
msgdata,fee_insufficient,channel_update,byte,len
msgtype,incorrect_cltv_expiry,UPDATE|13
msgdata,incorrect_cltv_expiry,cltv_expiry,u32,
msgdata,incorrect_cltv_expiry,len,u16,
msgdata,incorrect_cltv_expiry,channel_update,byte,len
msgtype,expiry_too_soon,UPDATE|14
msgdata,expiry_too_soon,len,u16,
msgdata,expiry_too_soon,channel_update,byte,len
msgtype,incorrect_or_unknown_payment_details,PERM|15
msgdata,incorrect_or_unknown_payment_details,htlc_msat,u64,
msgdata,incorrect_or_unknown_payment_details,height,u32,
msgtype,final_incorrect_cltv_expiry,18
msgdata,final_incorrect_cltv_expiry,cltv_expiry,u32,
msgtype,final_incorrect_htlc_amount,19
msgdata,final_incorrect_htlc_amount,incoming_htlc_amt,u64,
msgtype,channel_disabled,UPDATE|20
msgtype,expiry_too_far,21
msgtype,invalid_onion_payload,PERM|22
msgdata,invalid_onion_payload,type,varint,
msgdata,invalid_onion_payload,offset,u16,
msgtype,mpp_timeout,23
1 tlvtype,tlv_payload,amt_to_forward,2
2 tlvdata,tlv_payload,amt_to_forward,amt_to_forward,tu64,
3 tlvtype,tlv_payload,outgoing_cltv_value,4
4 tlvdata,tlv_payload,outgoing_cltv_value,outgoing_cltv_value,tu32,
5 tlvtype,tlv_payload,short_channel_id,6
6 tlvdata,tlv_payload,short_channel_id,short_channel_id,short_channel_id,
7 tlvtype,tlv_payload,payment_data,8
8 tlvdata,tlv_payload,payment_data,payment_secret,byte,32
9 tlvdata,tlv_payload,payment_data,total_msat,tu64,
10 msgtype,invalid_realm,PERM|1
11 msgtype,temporary_node_failure,NODE|2
12 msgtype,permanent_node_failure,PERM|NODE|2
13 msgtype,required_node_feature_missing,PERM|NODE|3
14 msgtype,invalid_onion_version,BADONION|PERM|4
15 msgdata,invalid_onion_version,sha256_of_onion,sha256,
16 msgtype,invalid_onion_hmac,BADONION|PERM|5
17 msgdata,invalid_onion_hmac,sha256_of_onion,sha256,
18 msgtype,invalid_onion_key,BADONION|PERM|6
19 msgdata,invalid_onion_key,sha256_of_onion,sha256,
20 msgtype,temporary_channel_failure,UPDATE|7
21 msgdata,temporary_channel_failure,len,u16,
22 msgdata,temporary_channel_failure,channel_update,byte,len
23 msgtype,permanent_channel_failure,PERM|8
24 msgtype,required_channel_feature_missing,PERM|9
25 msgtype,unknown_next_peer,PERM|10
26 msgtype,amount_below_minimum,UPDATE|11
27 msgdata,amount_below_minimum,htlc_msat,u64,
28 msgdata,amount_below_minimum,len,u16,
29 msgdata,amount_below_minimum,channel_update,byte,len
30 msgtype,fee_insufficient,UPDATE|12
31 msgdata,fee_insufficient,htlc_msat,u64,
32 msgdata,fee_insufficient,len,u16,
33 msgdata,fee_insufficient,channel_update,byte,len
34 msgtype,incorrect_cltv_expiry,UPDATE|13
35 msgdata,incorrect_cltv_expiry,cltv_expiry,u32,
36 msgdata,incorrect_cltv_expiry,len,u16,
37 msgdata,incorrect_cltv_expiry,channel_update,byte,len
38 msgtype,expiry_too_soon,UPDATE|14
39 msgdata,expiry_too_soon,len,u16,
40 msgdata,expiry_too_soon,channel_update,byte,len
41 msgtype,incorrect_or_unknown_payment_details,PERM|15
42 msgdata,incorrect_or_unknown_payment_details,htlc_msat,u64,
43 msgdata,incorrect_or_unknown_payment_details,height,u32,
44 msgtype,final_incorrect_cltv_expiry,18
45 msgdata,final_incorrect_cltv_expiry,cltv_expiry,u32,
46 msgtype,final_incorrect_htlc_amount,19
47 msgdata,final_incorrect_htlc_amount,incoming_htlc_amt,u64,
48 msgtype,channel_disabled,UPDATE|20
49 msgtype,expiry_too_far,21
50 msgtype,invalid_onion_payload,PERM|22
51 msgdata,invalid_onion_payload,type,varint,
52 msgdata,invalid_onion_payload,offset,u16,
53 msgtype,mpp_timeout,23

210
electrum/lnwire/peer_wire.csv

@ -0,0 +1,210 @@
msgtype,init,16
msgdata,init,gflen,u16,
msgdata,init,globalfeatures,byte,gflen
msgdata,init,flen,u16,
msgdata,init,features,byte,flen
msgdata,init,tlvs,init_tlvs,
tlvtype,init_tlvs,networks,1
tlvdata,init_tlvs,networks,chains,chain_hash,...
msgtype,error,17
msgdata,error,channel_id,channel_id,
msgdata,error,len,u16,
msgdata,error,data,byte,len
msgtype,ping,18
msgdata,ping,num_pong_bytes,u16,
msgdata,ping,byteslen,u16,
msgdata,ping,ignored,byte,byteslen
msgtype,pong,19
msgdata,pong,byteslen,u16,
msgdata,pong,ignored,byte,byteslen
tlvtype,n1,tlv1,1
tlvdata,n1,tlv1,amount_msat,tu64,
tlvtype,n1,tlv2,2
tlvdata,n1,tlv2,scid,short_channel_id,
tlvtype,n1,tlv3,3
tlvdata,n1,tlv3,node_id,point,
tlvdata,n1,tlv3,amount_msat_1,u64,
tlvdata,n1,tlv3,amount_msat_2,u64,
tlvtype,n1,tlv4,254
tlvdata,n1,tlv4,cltv_delta,u16,
tlvtype,n2,tlv1,0
tlvdata,n2,tlv1,amount_msat,tu64,
tlvtype,n2,tlv2,11
tlvdata,n2,tlv2,cltv_expiry,tu32,
msgtype,open_channel,32
msgdata,open_channel,chain_hash,chain_hash,
msgdata,open_channel,temporary_channel_id,byte,32
msgdata,open_channel,funding_satoshis,u64,
msgdata,open_channel,push_msat,u64,
msgdata,open_channel,dust_limit_satoshis,u64,
msgdata,open_channel,max_htlc_value_in_flight_msat,u64,
msgdata,open_channel,channel_reserve_satoshis,u64,
msgdata,open_channel,htlc_minimum_msat,u64,
msgdata,open_channel,feerate_per_kw,u32,
msgdata,open_channel,to_self_delay,u16,
msgdata,open_channel,max_accepted_htlcs,u16,
msgdata,open_channel,funding_pubkey,point,
msgdata,open_channel,revocation_basepoint,point,
msgdata,open_channel,payment_basepoint,point,
msgdata,open_channel,delayed_payment_basepoint,point,
msgdata,open_channel,htlc_basepoint,point,
msgdata,open_channel,first_per_commitment_point,point,
msgdata,open_channel,channel_flags,byte,
msgdata,open_channel,shutdown_len,u16,,option_upfront_shutdown_script
msgdata,open_channel,shutdown_scriptpubkey,byte,shutdown_len,option_upfront_shutdown_script
msgtype,accept_channel,33
msgdata,accept_channel,temporary_channel_id,byte,32
msgdata,accept_channel,dust_limit_satoshis,u64,
msgdata,accept_channel,max_htlc_value_in_flight_msat,u64,
msgdata,accept_channel,channel_reserve_satoshis,u64,
msgdata,accept_channel,htlc_minimum_msat,u64,
msgdata,accept_channel,minimum_depth,u32,
msgdata,accept_channel,to_self_delay,u16,
msgdata,accept_channel,max_accepted_htlcs,u16,
msgdata,accept_channel,funding_pubkey,point,
msgdata,accept_channel,revocation_basepoint,point,
msgdata,accept_channel,payment_basepoint,point,
msgdata,accept_channel,delayed_payment_basepoint,point,
msgdata,accept_channel,htlc_basepoint,point,
msgdata,accept_channel,first_per_commitment_point,point,
msgdata,accept_channel,shutdown_len,u16,,option_upfront_shutdown_script
msgdata,accept_channel,shutdown_scriptpubkey,byte,shutdown_len,option_upfront_shutdown_script
msgtype,funding_created,34
msgdata,funding_created,temporary_channel_id,byte,32
msgdata,funding_created,funding_txid,sha256,
msgdata,funding_created,funding_output_index,u16,
msgdata,funding_created,signature,signature,
msgtype,funding_signed,35
msgdata,funding_signed,channel_id,channel_id,
msgdata,funding_signed,signature,signature,
msgtype,funding_locked,36
msgdata,funding_locked,channel_id,channel_id,
msgdata,funding_locked,next_per_commitment_point,point,
msgtype,shutdown,38
msgdata,shutdown,channel_id,channel_id,
msgdata,shutdown,len,u16,
msgdata,shutdown,scriptpubkey,byte,len
msgtype,closing_signed,39
msgdata,closing_signed,channel_id,channel_id,
msgdata,closing_signed,fee_satoshis,u64,
msgdata,closing_signed,signature,signature,
msgtype,update_add_htlc,128
msgdata,update_add_htlc,channel_id,channel_id,
msgdata,update_add_htlc,id,u64,
msgdata,update_add_htlc,amount_msat,u64,
msgdata,update_add_htlc,payment_hash,sha256,
msgdata,update_add_htlc,cltv_expiry,u32,
msgdata,update_add_htlc,onion_routing_packet,byte,1366
msgtype,update_fulfill_htlc,130
msgdata,update_fulfill_htlc,channel_id,channel_id,
msgdata,update_fulfill_htlc,id,u64,
msgdata,update_fulfill_htlc,payment_preimage,byte,32
msgtype,update_fail_htlc,131
msgdata,update_fail_htlc,channel_id,channel_id,
msgdata,update_fail_htlc,id,u64,
msgdata,update_fail_htlc,len,u16,
msgdata,update_fail_htlc,reason,byte,len
msgtype,update_fail_malformed_htlc,135
msgdata,update_fail_malformed_htlc,channel_id,channel_id,
msgdata,update_fail_malformed_htlc,id,u64,
msgdata,update_fail_malformed_htlc,sha256_of_onion,sha256,
msgdata,update_fail_malformed_htlc,failure_code,u16,
msgtype,commitment_signed,132
msgdata,commitment_signed,channel_id,channel_id,
msgdata,commitment_signed,signature,signature,
msgdata,commitment_signed,num_htlcs,u16,
msgdata,commitment_signed,htlc_signature,signature,num_htlcs
msgtype,revoke_and_ack,133
msgdata,revoke_and_ack,channel_id,channel_id,
msgdata,revoke_and_ack,per_commitment_secret,byte,32
msgdata,revoke_and_ack,next_per_commitment_point,point,
msgtype,update_fee,134
msgdata,update_fee,channel_id,channel_id,
msgdata,update_fee,feerate_per_kw,u32,
msgtype,channel_reestablish,136
msgdata,channel_reestablish,channel_id,channel_id,
msgdata,channel_reestablish,next_commitment_number,u64,
msgdata,channel_reestablish,next_revocation_number,u64,
msgdata,channel_reestablish,your_last_per_commitment_secret,byte,32,option_data_loss_protect,option_static_remotekey
msgdata,channel_reestablish,my_current_per_commitment_point,point,,option_data_loss_protect,option_static_remotekey
msgtype,announcement_signatures,259
msgdata,announcement_signatures,channel_id,channel_id,
msgdata,announcement_signatures,short_channel_id,short_channel_id,
msgdata,announcement_signatures,node_signature,signature,
msgdata,announcement_signatures,bitcoin_signature,signature,
msgtype,channel_announcement,256
msgdata,channel_announcement,node_signature_1,signature,
msgdata,channel_announcement,node_signature_2,signature,
msgdata,channel_announcement,bitcoin_signature_1,signature,
msgdata,channel_announcement,bitcoin_signature_2,signature,
msgdata,channel_announcement,len,u16,
msgdata,channel_announcement,features,byte,len
msgdata,channel_announcement,chain_hash,chain_hash,
msgdata,channel_announcement,short_channel_id,short_channel_id,
msgdata,channel_announcement,node_id_1,point,
msgdata,channel_announcement,node_id_2,point,
msgdata,channel_announcement,bitcoin_key_1,point,
msgdata,channel_announcement,bitcoin_key_2,point,
msgtype,node_announcement,257
msgdata,node_announcement,signature,signature,
msgdata,node_announcement,flen,u16,
msgdata,node_announcement,features,byte,flen
msgdata,node_announcement,timestamp,u32,
msgdata,node_announcement,node_id,point,
msgdata,node_announcement,rgb_color,byte,3
msgdata,node_announcement,alias,byte,32
msgdata,node_announcement,addrlen,u16,
msgdata,node_announcement,addresses,byte,addrlen
msgtype,channel_update,258
msgdata,channel_update,signature,signature,
msgdata,channel_update,chain_hash,chain_hash,
msgdata,channel_update,short_channel_id,short_channel_id,
msgdata,channel_update,timestamp,u32,
msgdata,channel_update,message_flags,byte,
msgdata,channel_update,channel_flags,byte,
msgdata,channel_update,cltv_expiry_delta,u16,
msgdata,channel_update,htlc_minimum_msat,u64,
msgdata,channel_update,fee_base_msat,u32,
msgdata,channel_update,fee_proportional_millionths,u32,
msgdata,channel_update,htlc_maximum_msat,u64,,option_channel_htlc_max
msgtype,query_short_channel_ids,261,gossip_queries
msgdata,query_short_channel_ids,chain_hash,chain_hash,
msgdata,query_short_channel_ids,len,u16,
msgdata,query_short_channel_ids,encoded_short_ids,byte,len
msgdata,query_short_channel_ids,tlvs,query_short_channel_ids_tlvs,
tlvtype,query_short_channel_ids_tlvs,query_flags,1
tlvdata,query_short_channel_ids_tlvs,query_flags,encoding_type,u8,
tlvdata,query_short_channel_ids_tlvs,query_flags,encoded_query_flags,byte,...
msgtype,reply_short_channel_ids_end,262,gossip_queries
msgdata,reply_short_channel_ids_end,chain_hash,chain_hash,
msgdata,reply_short_channel_ids_end,complete,byte,
msgtype,query_channel_range,263,gossip_queries
msgdata,query_channel_range,chain_hash,chain_hash,
msgdata,query_channel_range,first_blocknum,u32,
msgdata,query_channel_range,number_of_blocks,u32,
msgdata,query_channel_range,tlvs,query_channel_range_tlvs,
tlvtype,query_channel_range_tlvs,query_option,1
tlvdata,query_channel_range_tlvs,query_option,query_option_flags,varint,
msgtype,reply_channel_range,264,gossip_queries
msgdata,reply_channel_range,chain_hash,chain_hash,
msgdata,reply_channel_range,first_blocknum,u32,
msgdata,reply_channel_range,number_of_blocks,u32,
msgdata,reply_channel_range,complete,byte,
msgdata,reply_channel_range,len,u16,
msgdata,reply_channel_range,encoded_short_ids,byte,len
msgdata,reply_channel_range,tlvs,reply_channel_range_tlvs,
tlvtype,reply_channel_range_tlvs,timestamps_tlv,1
tlvdata,reply_channel_range_tlvs,timestamps_tlv,encoding_type,u8,
tlvdata,reply_channel_range_tlvs,timestamps_tlv,encoded_timestamps,byte,...
tlvtype,reply_channel_range_tlvs,checksums_tlv,3
tlvdata,reply_channel_range_tlvs,checksums_tlv,checksums,channel_update_checksums,...
subtype,channel_update_timestamps
subtypedata,channel_update_timestamps,timestamp_node_id_1,u32,
subtypedata,channel_update_timestamps,timestamp_node_id_2,u32,
subtype,channel_update_checksums
subtypedata,channel_update_checksums,checksum_node_id_1,u32,
subtypedata,channel_update_checksums,checksum_node_id_2,u32,
msgtype,gossip_timestamp_filter,265,gossip_queries
msgdata,gossip_timestamp_filter,chain_hash,chain_hash,
msgdata,gossip_timestamp_filter,first_timestamp,u32,
msgdata,gossip_timestamp_filter,timestamp_range,u32,
1 msgtype,init,16
2 msgdata,init,gflen,u16,
3 msgdata,init,globalfeatures,byte,gflen
4 msgdata,init,flen,u16,
5 msgdata,init,features,byte,flen
6 msgdata,init,tlvs,init_tlvs,
7 tlvtype,init_tlvs,networks,1
8 tlvdata,init_tlvs,networks,chains,chain_hash,...
9 msgtype,error,17
10 msgdata,error,channel_id,channel_id,
11 msgdata,error,len,u16,
12 msgdata,error,data,byte,len
13 msgtype,ping,18
14 msgdata,ping,num_pong_bytes,u16,
15 msgdata,ping,byteslen,u16,
16 msgdata,ping,ignored,byte,byteslen
17 msgtype,pong,19
18 msgdata,pong,byteslen,u16,
19 msgdata,pong,ignored,byte,byteslen
20 tlvtype,n1,tlv1,1
21 tlvdata,n1,tlv1,amount_msat,tu64,
22 tlvtype,n1,tlv2,2
23 tlvdata,n1,tlv2,scid,short_channel_id,
24 tlvtype,n1,tlv3,3
25 tlvdata,n1,tlv3,node_id,point,
26 tlvdata,n1,tlv3,amount_msat_1,u64,
27 tlvdata,n1,tlv3,amount_msat_2,u64,
28 tlvtype,n1,tlv4,254
29 tlvdata,n1,tlv4,cltv_delta,u16,
30 tlvtype,n2,tlv1,0
31 tlvdata,n2,tlv1,amount_msat,tu64,
32 tlvtype,n2,tlv2,11
33 tlvdata,n2,tlv2,cltv_expiry,tu32,
34 msgtype,open_channel,32
35 msgdata,open_channel,chain_hash,chain_hash,
36 msgdata,open_channel,temporary_channel_id,byte,32
37 msgdata,open_channel,funding_satoshis,u64,
38 msgdata,open_channel,push_msat,u64,
39 msgdata,open_channel,dust_limit_satoshis,u64,
40 msgdata,open_channel,max_htlc_value_in_flight_msat,u64,
41 msgdata,open_channel,channel_reserve_satoshis,u64,
42 msgdata,open_channel,htlc_minimum_msat,u64,
43 msgdata,open_channel,feerate_per_kw,u32,
44 msgdata,open_channel,to_self_delay,u16,
45 msgdata,open_channel,max_accepted_htlcs,u16,
46 msgdata,open_channel,funding_pubkey,point,
47 msgdata,open_channel,revocation_basepoint,point,
48 msgdata,open_channel,payment_basepoint,point,
49 msgdata,open_channel,delayed_payment_basepoint,point,
50 msgdata,open_channel,htlc_basepoint,point,
51 msgdata,open_channel,first_per_commitment_point,point,
52 msgdata,open_channel,channel_flags,byte,
53 msgdata,open_channel,shutdown_len,u16,,option_upfront_shutdown_script
54 msgdata,open_channel,shutdown_scriptpubkey,byte,shutdown_len,option_upfront_shutdown_script
55 msgtype,accept_channel,33
56 msgdata,accept_channel,temporary_channel_id,byte,32
57 msgdata,accept_channel,dust_limit_satoshis,u64,
58 msgdata,accept_channel,max_htlc_value_in_flight_msat,u64,
59 msgdata,accept_channel,channel_reserve_satoshis,u64,
60 msgdata,accept_channel,htlc_minimum_msat,u64,
61 msgdata,accept_channel,minimum_depth,u32,
62 msgdata,accept_channel,to_self_delay,u16,
63 msgdata,accept_channel,max_accepted_htlcs,u16,
64 msgdata,accept_channel,funding_pubkey,point,
65 msgdata,accept_channel,revocation_basepoint,point,
66 msgdata,accept_channel,payment_basepoint,point,
67 msgdata,accept_channel,delayed_payment_basepoint,point,
68 msgdata,accept_channel,htlc_basepoint,point,
69 msgdata,accept_channel,first_per_commitment_point,point,
70 msgdata,accept_channel,shutdown_len,u16,,option_upfront_shutdown_script
71 msgdata,accept_channel,shutdown_scriptpubkey,byte,shutdown_len,option_upfront_shutdown_script
72 msgtype,funding_created,34
73 msgdata,funding_created,temporary_channel_id,byte,32
74 msgdata,funding_created,funding_txid,sha256,
75 msgdata,funding_created,funding_output_index,u16,
76 msgdata,funding_created,signature,signature,
77 msgtype,funding_signed,35
78 msgdata,funding_signed,channel_id,channel_id,
79 msgdata,funding_signed,signature,signature,
80 msgtype,funding_locked,36
81 msgdata,funding_locked,channel_id,channel_id,
82 msgdata,funding_locked,next_per_commitment_point,point,
83 msgtype,shutdown,38
84 msgdata,shutdown,channel_id,channel_id,
85 msgdata,shutdown,len,u16,
86 msgdata,shutdown,scriptpubkey,byte,len
87 msgtype,closing_signed,39
88 msgdata,closing_signed,channel_id,channel_id,
89 msgdata,closing_signed,fee_satoshis,u64,
90 msgdata,closing_signed,signature,signature,
91 msgtype,update_add_htlc,128
92 msgdata,update_add_htlc,channel_id,channel_id,
93 msgdata,update_add_htlc,id,u64,
94 msgdata,update_add_htlc,amount_msat,u64,
95 msgdata,update_add_htlc,payment_hash,sha256,
96 msgdata,update_add_htlc,cltv_expiry,u32,
97 msgdata,update_add_htlc,onion_routing_packet,byte,1366
98 msgtype,update_fulfill_htlc,130
99 msgdata,update_fulfill_htlc,channel_id,channel_id,
100 msgdata,update_fulfill_htlc,id,u64,
101 msgdata,update_fulfill_htlc,payment_preimage,byte,32
102 msgtype,update_fail_htlc,131
103 msgdata,update_fail_htlc,channel_id,channel_id,
104 msgdata,update_fail_htlc,id,u64,
105 msgdata,update_fail_htlc,len,u16,
106 msgdata,update_fail_htlc,reason,byte,len
107 msgtype,update_fail_malformed_htlc,135
108 msgdata,update_fail_malformed_htlc,channel_id,channel_id,
109 msgdata,update_fail_malformed_htlc,id,u64,
110 msgdata,update_fail_malformed_htlc,sha256_of_onion,sha256,
111 msgdata,update_fail_malformed_htlc,failure_code,u16,
112 msgtype,commitment_signed,132
113 msgdata,commitment_signed,channel_id,channel_id,
114 msgdata,commitment_signed,signature,signature,
115 msgdata,commitment_signed,num_htlcs,u16,
116 msgdata,commitment_signed,htlc_signature,signature,num_htlcs
117 msgtype,revoke_and_ack,133
118 msgdata,revoke_and_ack,channel_id,channel_id,
119 msgdata,revoke_and_ack,per_commitment_secret,byte,32
120 msgdata,revoke_and_ack,next_per_commitment_point,point,
121 msgtype,update_fee,134
122 msgdata,update_fee,channel_id,channel_id,
123 msgdata,update_fee,feerate_per_kw,u32,
124 msgtype,channel_reestablish,136
125 msgdata,channel_reestablish,channel_id,channel_id,
126 msgdata,channel_reestablish,next_commitment_number,u64,
127 msgdata,channel_reestablish,next_revocation_number,u64,
128 msgdata,channel_reestablish,your_last_per_commitment_secret,byte,32,option_data_loss_protect,option_static_remotekey
129 msgdata,channel_reestablish,my_current_per_commitment_point,point,,option_data_loss_protect,option_static_remotekey
130 msgtype,announcement_signatures,259
131 msgdata,announcement_signatures,channel_id,channel_id,
132 msgdata,announcement_signatures,short_channel_id,short_channel_id,
133 msgdata,announcement_signatures,node_signature,signature,
134 msgdata,announcement_signatures,bitcoin_signature,signature,
135 msgtype,channel_announcement,256
136 msgdata,channel_announcement,node_signature_1,signature,
137 msgdata,channel_announcement,node_signature_2,signature,
138 msgdata,channel_announcement,bitcoin_signature_1,signature,
139 msgdata,channel_announcement,bitcoin_signature_2,signature,
140 msgdata,channel_announcement,len,u16,
141 msgdata,channel_announcement,features,byte,len
142 msgdata,channel_announcement,chain_hash,chain_hash,
143 msgdata,channel_announcement,short_channel_id,short_channel_id,
144 msgdata,channel_announcement,node_id_1,point,
145 msgdata,channel_announcement,node_id_2,point,
146 msgdata,channel_announcement,bitcoin_key_1,point,
147 msgdata,channel_announcement,bitcoin_key_2,point,
148 msgtype,node_announcement,257
149 msgdata,node_announcement,signature,signature,
150 msgdata,node_announcement,flen,u16,
151 msgdata,node_announcement,features,byte,flen
152 msgdata,node_announcement,timestamp,u32,
153 msgdata,node_announcement,node_id,point,
154 msgdata,node_announcement,rgb_color,byte,3
155 msgdata,node_announcement,alias,byte,32
156 msgdata,node_announcement,addrlen,u16,
157 msgdata,node_announcement,addresses,byte,addrlen
158 msgtype,channel_update,258
159 msgdata,channel_update,signature,signature,
160 msgdata,channel_update,chain_hash,chain_hash,
161 msgdata,channel_update,short_channel_id,short_channel_id,
162 msgdata,channel_update,timestamp,u32,
163 msgdata,channel_update,message_flags,byte,
164 msgdata,channel_update,channel_flags,byte,
165 msgdata,channel_update,cltv_expiry_delta,u16,
166 msgdata,channel_update,htlc_minimum_msat,u64,
167 msgdata,channel_update,fee_base_msat,u32,
168 msgdata,channel_update,fee_proportional_millionths,u32,
169 msgdata,channel_update,htlc_maximum_msat,u64,,option_channel_htlc_max
170 msgtype,query_short_channel_ids,261,gossip_queries
171 msgdata,query_short_channel_ids,chain_hash,chain_hash,
172 msgdata,query_short_channel_ids,len,u16,
173 msgdata,query_short_channel_ids,encoded_short_ids,byte,len
174 msgdata,query_short_channel_ids,tlvs,query_short_channel_ids_tlvs,
175 tlvtype,query_short_channel_ids_tlvs,query_flags,1
176 tlvdata,query_short_channel_ids_tlvs,query_flags,encoding_type,u8,
177 tlvdata,query_short_channel_ids_tlvs,query_flags,encoded_query_flags,byte,...
178 msgtype,reply_short_channel_ids_end,262,gossip_queries
179 msgdata,reply_short_channel_ids_end,chain_hash,chain_hash,
180 msgdata,reply_short_channel_ids_end,complete,byte,
181 msgtype,query_channel_range,263,gossip_queries
182 msgdata,query_channel_range,chain_hash,chain_hash,
183 msgdata,query_channel_range,first_blocknum,u32,
184 msgdata,query_channel_range,number_of_blocks,u32,
185 msgdata,query_channel_range,tlvs,query_channel_range_tlvs,
186 tlvtype,query_channel_range_tlvs,query_option,1
187 tlvdata,query_channel_range_tlvs,query_option,query_option_flags,varint,
188 msgtype,reply_channel_range,264,gossip_queries
189 msgdata,reply_channel_range,chain_hash,chain_hash,
190 msgdata,reply_channel_range,first_blocknum,u32,
191 msgdata,reply_channel_range,number_of_blocks,u32,
192 msgdata,reply_channel_range,complete,byte,
193 msgdata,reply_channel_range,len,u16,
194 msgdata,reply_channel_range,encoded_short_ids,byte,len
195 msgdata,reply_channel_range,tlvs,reply_channel_range_tlvs,
196 tlvtype,reply_channel_range_tlvs,timestamps_tlv,1
197 tlvdata,reply_channel_range_tlvs,timestamps_tlv,encoding_type,u8,
198 tlvdata,reply_channel_range_tlvs,timestamps_tlv,encoded_timestamps,byte,...
199 tlvtype,reply_channel_range_tlvs,checksums_tlv,3
200 tlvdata,reply_channel_range_tlvs,checksums_tlv,checksums,channel_update_checksums,...
201 subtype,channel_update_timestamps
202 subtypedata,channel_update_timestamps,timestamp_node_id_1,u32,
203 subtypedata,channel_update_timestamps,timestamp_node_id_2,u32,
204 subtype,channel_update_checksums
205 subtypedata,channel_update_checksums,checksum_node_id_1,u32,
206 subtypedata,channel_update_checksums,checksum_node_id_2,u32,
207 msgtype,gossip_timestamp_filter,265,gossip_queries
208 msgdata,gossip_timestamp_filter,chain_hash,chain_hash,
209 msgdata,gossip_timestamp_filter,first_timestamp,u32,
210 msgdata,gossip_timestamp_filter,timestamp_range,u32,
Loading…
Cancel
Save