URI: 
       tlightning: do not list python files as resources, use lightning spec generated serialization - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit c69f812f13aafaf3f11b0d021660194d622c4fd8
   DIR parent cbf8d4c78141df88e08e088646d949112248838c
  HTML Author: Janus <ysangkok@gmail.com>
       Date:   Tue, 10 Apr 2018 19:36:49 +0200
       
       lightning: do not list python files as resources, use lightning spec generated serialization
       
       Diffstat:
         M lib/lnbase.py                       |      97 ++++++++++++++++++++++++++++++-
       
       1 file changed, 96 insertions(+), 1 deletion(-)
       ---
   DIR diff --git a/lib/lnbase.py b/lib/lnbase.py
       t@@ -4,6 +4,8 @@
          Derived from https://gist.github.com/AdamISZ/046d05c156aaeb56cc897f85eecb3eb8
        """
        
       +import json
       +from collections import OrderedDict
        import asyncio
        import sys
        import binascii
       t@@ -17,6 +19,99 @@ from electrum.bitcoin import int_to_hex, bfh, rev_hex
        tcp_socket_timeout = 10
        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
       +
       +def calcexp(exp, ma):
       +  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)
       +
       +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"
       +
       +assert message_types[b"\x00\x10"].__name__ == "init_handler"
       +
       +def decode_msg(data):
       +  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
       +
       +###############################
       +
       +
        def decode(string):
            """Return the integer value of the
            bytestring b
       t@@ -198,7 +293,7 @@ async def main_loop(my_privkey, host, port, pubkey, loop):
            rn += 2
        
            # send init
       -    init_msg = encode(16, 2) + encode(0, 2) +encode(0,2)
       +    init_msg = gen_msg("init", gflen=0, lflen=0)
            send_message(writer, init_msg, sk, sn)
            sn += 2