tlnbase: channel establishment flow, avoid using Wallet instance - electrum - Electrum Bitcoin wallet (HTM) git clone https://git.parazyd.org/electrum (DIR) Log (DIR) Files (DIR) Refs (DIR) Submodules --- (DIR) commit 78119f9733c1ec7620b6c0677d71310bb9abb5d6 (DIR) parent 1f5852bd155709f4dfb7e51586dae6150db712aa (HTM) Author: Janus <ysangkok@gmail.com> Date: Thu, 12 Apr 2018 11:01:05 +0200 lnbase: channel establishment flow, avoid using Wallet instance Diffstat: M lib/lnbase.py | 60 ++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 26 deletions(-) --- (DIR) diff --git a/lib/lnbase.py b/lib/lnbase.py t@@ -4,6 +4,7 @@ Derived from https://gist.github.com/AdamISZ/046d05c156aaeb56cc897f85eecb3eb8 """ +import itertools import json from collections import OrderedDict import asyncio t@@ -16,6 +17,7 @@ import hmac import cryptography.hazmat.primitives.ciphers.aead as AEAD from .bitcoin import public_key_from_private_key, ser_to_point, point_to_ser, string_to_number, deserialize_privkey, EC_KEY, rev_hex +from . import bitcoin from .constants import set_testnet, set_simnet from . import constants from .util import PrintError t@@ -213,16 +215,11 @@ def create_ephemeral_key(privkey): return (privkey[:32], pub) def get_unused_public_keys(): - path = os.environ["HOME"] + "/.electrum/" + ("testnet" if constants.net is constants.BitcoinTestnet else "simnet") + "/wallets/default_wallet" - os.stat(path) - WALLET = Wallet(WalletStorage(path)) - for str_address in WALLET.get_unused_addresses(): - pri, redeem_script = WALLET.export_private_key(str_address, None) - - typ, pri, compressed = deserialize_privkey(pri) - pubk = binascii.unhexlify(EC_KEY(pri).get_public_key(True)) - yield pubk - + xprv, xpub = bitcoin.bip32_root(b"testseed", "p2wpkh") + for i in itertools.count(): + childxpub = bitcoin.bip32_public_derivation(xpub, "m/", "m/42/"+str(i)) + _, _, _, _, child_c, child_cK = bitcoin.deserialize_xpub(childxpub) + yield child_cK class Peer(PrintError): t@@ -233,6 +230,7 @@ class Peer(PrintError): self.pubkey = pubkey self.read_buffer = b'' self.ping_time = 0 + self.temporary_channel_id_to_incoming_accept_channel = {} def diagnostic_name(self): return self.host t@@ -314,13 +312,7 @@ class Peer(PrintError): self.send_message(gen_msg('pong', byteslen=l)) def on_accept_channel(self, payload): - # check that it is in my pending requests - # I need to attach a wallet to each request - if ok: - tx = wallet.create_funding_tx() - wallet.sign(tx) - m = gen_msg('funding created', signature) - self.send_message(m) + self.temporary_channel_id_to_incoming_accept_channel[payload["temporary_channel_id"]].set_result(payload) def on_funding_signed(self, payload): sig = payload['signature'] t@@ -331,10 +323,10 @@ class Peer(PrintError): def on_funding_locked(self, payload): pass - def open_channel(self, funding_sat, push_msat): - self.send_message(gen_msg('open_channel', funding_satoshis=funding_sat, push_msat=push_msat)) + #def open_channel(self, funding_sat, push_msat): + # self.send_message(gen_msg('open_channel', funding_satoshis=funding_sat, push_msat=push_msat)) - async def main_loop(self, loop): + async def initialize(self, loop): self.reader, self.writer = await asyncio.open_connection(self.host, self.port, loop=loop) await self.handshake() # read init t@@ -343,11 +335,7 @@ class Peer(PrintError): # send init self.send_message(gen_msg("init", gflen=0, lflen=0)) - pubkeys = get_unused_public_keys() - - msg = gen_msg("open_channel", chain_hash=bytes.fromhex(rev_hex(constants.net.GENESIS)), funding_satoshis=20000, max_accepted_htlcs=5, funding_pubkey=next(pubkeys), revocation_basepoint=next(pubkeys), htlc_basepoint=next(pubkeys), payment_basepoint=next(pubkeys), delayed_payment_basepoint=next(pubkeys), first_per_commitment_point=next(pubkeys)) - self.send_message(msg) - + async def main_loop(self, loop): # loop while True: self.ping_if_required() t@@ -357,6 +345,23 @@ class Peer(PrintError): self.print_error('closing lnbase') self.writer.close() + async def channel_establishment_flow(self): + pubkeys = get_unused_public_keys() + + temp_channel_id = os.urandom(32) + msg = gen_msg("open_channel", temporary_channel_id=temp_channel_id, chain_hash=bytes.fromhex(rev_hex(constants.net.GENESIS)), funding_satoshis=20000, max_accepted_htlcs=5, funding_pubkey=next(pubkeys), revocation_basepoint=next(pubkeys), htlc_basepoint=next(pubkeys), payment_basepoint=next(pubkeys), delayed_payment_basepoint=next(pubkeys), first_per_commitment_point=next(pubkeys)) + self.temporary_channel_id_to_incoming_accept_channel[temp_channel_id] = asyncio.Future() + self.send_message(msg) + accept_channel = await self.temporary_channel_id_to_incoming_accept_channel[temp_channel_id] + del self.temporary_channel_id_to_incoming_accept_channel[temp_channel_id] + + # check that it is in my pending requests + # I need to attach a wallet to each request + if ok: + tx = wallet.create_funding_tx() + wallet.sign(tx) + m = gen_msg('funding created', signature) + self.send_message(m) # replacement for lightningCall class LNWallet(Wallet): t@@ -391,5 +396,8 @@ if __name__ == "__main__": privkey = b"\x21"*32 + b"\x01" peer = Peer(privkey, host, port, pubkey) loop = asyncio.get_event_loop() - loop.run_until_complete(peer.main_loop(loop)) + loop.run_until_complete(peer.initialize(loop)) + async def asynctest(): + await peer.channel_establishment_flow() + loop.run_until_complete(asyncio.gather(asynctest(), peer.main_loop(loop))) loop.close()