commit 692bc148bbff5d7c00964a7f71064f19e274d286
parent c69f812f13aafaf3f11b0d021660194d622c4fd8
Author: ThomasV <thomasv@electrum.org>
Date: Wed, 11 Apr 2018 05:01:34 +0200
lnbase: fix json loading and indentation
Diffstat:
A | lib/lightning.json | | | 801 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | lib/lnbase.py | | | 145 | ++++++++++++++++++++++++++++++++++++++++--------------------------------------- |
2 files changed, 874 insertions(+), 72 deletions(-)
diff --git a/lib/lightning.json b/lib/lightning.json
@@ -0,0 +1,801 @@
+{
+ "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": "4"
+ }
+ }
+ },
+ "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"
+ },
+ "flags": {
+ "position": "108",
+ "length": "2"
+ },
+ "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"
+ }
+ }
+ }
+}
diff --git a/lib/lnbase.py b/lib/lnbase.py
@@ -8,6 +8,7 @@ import json
from collections import OrderedDict
import asyncio
import sys
+import os
import binascii
import hashlib
import hmac
@@ -24,90 +25,90 @@ server_response_timeout = 60
message_types = {}
def handlesingle(x, ma):
- try:
- x = int(x)
- except ValueError:
- x = ma[x]
- try:
- x = int(x)
- except ValueError:
- x = int.from_bytes(x, byteorder="big")
- return x
+ try:
+ x = int(x)
+ except ValueError:
+ x = ma[x]
+ try:
+ x = int(x)
+ except ValueError:
+ x = int.from_bytes(x, byteorder="big")
+ return x
def calcexp(exp, ma):
- exp = str(exp)
- assert "*" not in exp
- return sum(handlesingle(x, ma) for x in exp.split("+"))
+ exp = str(exp)
+ assert "*" not in exp
+ return sum(handlesingle(x, ma) for x in exp.split("+"))
def make_handler(k, v):
- def handler(data):
- nonlocal k, v
- print("msg type", k)
- ma = {}
- pos = 0
- for fieldname in v["payload"]:
- poslenMap = v["payload"][fieldname]
- #print(poslenMap["position"], ma)
- assert pos == calcexp(poslenMap["position"], ma)
- length = poslenMap["length"]
- length = calcexp(length, ma)
- ma[fieldname] = data[pos:pos+length]
- pos += length
- assert pos == len(data), (k, pos, len(data))
- return ma
- return handler
-
-with open("lightning.json") as f:
- structured = json.loads(f.read(), object_pairs_hook=OrderedDict)
+ def handler(data):
+ nonlocal k, v
+ print("msg type", k)
+ ma = {}
+ pos = 0
+ for fieldname in v["payload"]:
+ poslenMap = v["payload"][fieldname]
+ #print(poslenMap["position"], ma)
+ assert pos == calcexp(poslenMap["position"], ma)
+ length = poslenMap["length"]
+ length = calcexp(length, ma)
+ ma[fieldname] = data[pos:pos+length]
+ pos += length
+ assert pos == len(data), (k, pos, len(data))
+ return ma
+ return handler
+
+path = os.path.join(os.path.dirname(__file__), 'lightning.json')
+with open(path) as f:
+ structured = json.loads(f.read(), object_pairs_hook=OrderedDict)
for k in structured:
- v = structured[k]
- if k in ["open_channel","final_incorrect_cltv_expiry", "final_incorrect_htlc_amount"]:
- continue
- if len(v["payload"]) == 0:
- continue
- try:
- num = int(v["type"])
- except ValueError:
- #print("skipping", k)
- continue
- byts = num.to_bytes(byteorder="big",length=2)
- assert byts not in message_types, (byts, message_types[byts].__name__, k)
- names = [x.__name__ for x in message_types.values()]
- assert k + "_handler" not in names, (k, names)
- message_types[byts] = make_handler(k, v)
- message_types[byts].__name__ = k + "_handler"
+ v = structured[k]
+ if k in ["open_channel","final_incorrect_cltv_expiry", "final_incorrect_htlc_amount"]:
+ continue
+ if len(v["payload"]) == 0:
+ continue
+ try:
+ num = int(v["type"])
+ except ValueError:
+ #print("skipping", k)
+ continue
+ byts = num.to_bytes(byteorder="big",length=2)
+ assert byts not in message_types, (byts, message_types[byts].__name__, k)
+ names = [x.__name__ for x in message_types.values()]
+ assert k + "_handler" not in names, (k, names)
+ message_types[byts] = make_handler(k, v)
+ message_types[byts].__name__ = k + "_handler"
assert message_types[b"\x00\x10"].__name__ == "init_handler"
def decode_msg(data):
- typ = data[:2]
- parsed = message_types[typ](data[2:])
- return parsed
-
+ typ = data[:2]
+ parsed = message_types[typ](data[2:])
+ return parsed
def gen_msg(msg_type, **kwargs):
- typ = structured[msg_type]
- data = int(typ["type"]).to_bytes(byteorder="big", length=2)
- lengths = {}
- for k in typ["payload"]:
- poslenMap = typ["payload"][k]
- leng = calcexp(poslenMap["length"], lengths)
- try:
- leng = kwargs[poslenMap["length"]]
- except:
- pass
- try:
- param = kwargs[k]
- except KeyError:
- param = 0
- try:
- param = param.to_bytes(length=leng, byteorder="big")
- except:
- raise Exception("{} does not fit in {} bytes".format(k, leng))
- lengths[k] = len(param)
- data += param
- return data
+ typ = structured[msg_type]
+ data = int(typ["type"]).to_bytes(byteorder="big", length=2)
+ lengths = {}
+ for k in typ["payload"]:
+ poslenMap = typ["payload"][k]
+ leng = calcexp(poslenMap["length"], lengths)
+ try:
+ leng = kwargs[poslenMap["length"]]
+ except:
+ pass
+ try:
+ param = kwargs[k]
+ except KeyError:
+ param = 0
+ try:
+ param = param.to_bytes(length=leng, byteorder="big")
+ except:
+ raise Exception("{} does not fit in {} bytes".format(k, leng))
+ lengths[k] = len(param)
+ data += param
+ return data
###############################