コード例 #1
0
def wait_to_route(src: LightningRpc, dest: LightningRpc,
                  msatoshi: int) -> None:
    """wait until src knows a route to dest with an amount of msatoshi"""
    found = False
    while not found:
        try:
            src.getroute(node_id=get_id(dest), msatoshi=msatoshi, riskfactor=1)
            found = True
        except RpcError as e:
            assert e.error["message"] == "Could not find a route", e
            time.sleep(2)
コード例 #2
0
def make_many_payments(
    sender: LightningRpc,
    receiver: LightningRpc,
    num_payments: int,
    msatoshi_per_payment: int,
) -> None:
    # in case the receiver is evil, the secret will not be returned and the call
    # to LightningRpc.pay will be stuck, waiting for the secret. therefore we
    # use the lower-level 'sendpay' method which doesn't wait for payment completion

    for i in range(num_payments):
        invoice = receiver.invoice(
            msatoshi=msatoshi_per_payment,
            label=f"label_{time.time()}",  # a unique label is needed
            description="",
        )
        route = sender.getroute(
            node_id=get_id(receiver),
            msatoshi=msatoshi_per_payment,
            riskfactor=1,
        )["route"]

        sender.sendpay(route=route, payment_hash=invoice["payment_hash"])
コード例 #3
0
class LightningNode(object):

    displayName = 'lightning'

    def __init__(self,
                 lightning_dir,
                 lightning_port,
                 btc,
                 executor=None,
                 node_id=0):
        self.bitcoin = btc
        self.executor = executor
        self.daemon = LightningD(lightning_dir,
                                 self.bitcoin,
                                 port=lightning_port)
        socket_path = os.path.join(lightning_dir,
                                   "lightning-rpc").format(node_id)
        self.invoice_count = 0
        self.logger = logging.getLogger(
            'lightning-node({})'.format(lightning_port))

        self.rpc = LightningRpc(socket_path, self.executor)

        orig_call = self.rpc._call

        def rpc_call(method, args):
            self.logger.debug("Calling {} with arguments {}".format(
                method, json.dumps(args, indent=4, sort_keys=True)))
            r = orig_call(method, args)
            self.logger.debug("Call returned {}".format(
                json.dumps(r, indent=4, sort_keys=True)))
            return r

        self.rpc._call = rpc_call
        self.myid = None

    def peers(self):
        return [p['id'] for p in self.rpc.listpeers()['peers']]

    def getinfo(self):
        if not self.info:
            self.info = self.rpc.getinfo()
        return self.info

    def id(self):
        if not self.myid:
            self.myid = self.rpc.getinfo()['id']
        return self.myid

    def openchannel(self, node_id, host, port, satoshis):
        # Make sure we have a connection already
        if node_id not in self.peers():
            raise ValueError("Must connect to node before opening a channel")
        return self.rpc.fundchannel(node_id, satoshis)

    def getaddress(self):
        return self.rpc.newaddr()['address']

    def addfunds(self, bitcoind, satoshis):
        addr = self.getaddress()
        txid = bitcoind.rpc.sendtoaddress(addr, float(satoshis) / 10**8)
        bitcoind.rpc.getrawtransaction(txid)
        while len(self.rpc.listfunds()['outputs']) == 0:
            time.sleep(1)
            bitcoind.rpc.generate(1)

    def ping(self):
        """ Simple liveness test to see if the node is up and running

        Returns true if the node is reachable via RPC, false otherwise.
        """
        try:
            self.rpc.help()
            return True
        except:
            return False

    def check_channel(self, remote, require_both=False):
        """Make sure that we have an active channel with remote

        `require_both` must be False unless the other side supports
        sending a `channel_announcement` and `channel_update` on
        `funding_locked`. This doesn't work for eclair for example.

        """
        remote_id = remote.id()
        self_id = self.id()
        peer = None
        for p in self.rpc.listpeers()['peers']:
            if remote.id() == p['id']:
                peer = p
                break
        if not peer:
            self.logger.debug('Peer {} not found in listpeers'.format(remote))
            return False

        if len(peer['channels']) < 1:
            self.logger.debug(
                'Peer {} has no channel open with us'.format(remote))
            return False

        state = p['channels'][0]['state']
        self.logger.debug("Channel {} -> {} state: {}".format(
            self_id, remote_id, state))

        if state != 'CHANNELD_NORMAL' or not p['connected']:
            self.logger.debug(
                'Channel with peer {} is not in state normal ({}) or peer is not connected ({})'
                .format(remote_id, state, p['connected']))
            return False

        # Make sure that gossipd sees a local channel_update for routing
        scid = p['channels'][0]['short_channel_id']

        channels = self.rpc.listchannels(scid)['channels']

        if not require_both and len(channels) >= 1:
            return channels[0]['active']

        if len(channels) != 2:
            self.logger.debug(
                'Waiting for both channel directions to be announced: 2 != {}'.
                format(len(channels)))
            return False

        return channels[0]['active'] and channels[1]['active']

    def getchannels(self):
        result = []
        for c in self.rpc.listchannels()['channels']:
            result.append((c['source'], c['destination']))
        return set(result)

    def getnodes(self):
        return set([n['nodeid'] for n in self.rpc.listnodes()['nodes']])

    def invoice(self, amount):
        invoice = self.rpc.invoice(amount, "invoice%d" % (self.invoice_count),
                                   "description")
        self.invoice_count += 1
        return invoice['bolt11']

    def send(self, req):
        result = self.rpc.pay(req)
        return result['payment_preimage']

    def connect(self, host, port, node_id):
        return self.rpc.connect(node_id, host, port)

    def info(self):
        r = self.rpc.getinfo()
        return {
            'id': r['id'],
            'blockheight': r['blockheight'],
        }

    def block_sync(self, blockhash):
        time.sleep(1)

    def restart(self):
        self.daemon.stop()
        time.sleep(5)
        self.daemon.start()
        time.sleep(1)

    def stop(self):
        self.daemon.stop()

    def start(self):
        self.daemon.start()

    def check_route(self, node_id, amount):
        try:
            r = self.rpc.getroute(node_id, amount, 1.0)
        except ValueError as e:
            if (str(e).find("Could not find a route") > 0):
                return False
            raise
        return True
コード例 #4
0
ファイル: sendpay.py プロジェクト: willcl-ark/lnproxy
except RpcError:
    raise


# get rpc2 node_id
rpc2_node_id = rpc2.getinfo()["id"]

# rpc1 gets a route to rpc2
# we add 10 satoshi to amount (10 hops max x 1 satoshi fee each)
# we add 60 to cltv (10 hops max, CLTV of 6 each)
amt_msat = inv["msatoshi"] + 10
cltv = 9 + 60

try:
    route = rpc1.getroute(
        node_id=rpc2_node_id, msatoshi=amt_msat, riskfactor=10, cltv=cltv
    )["route"]
except RpcError:
    raise


# rpc1 does a sendpay to rpc2
try:
    send_to_server = rpc1.sendpay(
        route=route,
        payment_hash=inv["payment_hash"],
        description=uuid4().hex,
        msatoshi=amt_msat,
    )
except RpcError:
    raise
コード例 #5
0
def main():
    # Create RPC connection to bitcoin daemon
    bt_cli = bitcoin.rpc.Proxy()
    # Create two instances of the LightningRpc object using two different local c-lightning daemons
    client_node = LightningRpc("/tmp/l1-regtest/regtest/lightning-rpc")
    merchant_node = LightningRpc("/tmp/l2-regtest/regtest/lightning-rpc")
    # start Merchant plugin
    merchant_plugin_path = abspath("Merchant.py")
    response = merchant_node.plugin("start", merchant_plugin_path)
    for plugin in response["plugins"]:
        if plugin["name"] == merchant_plugin_path:
            if plugin["active"] == True:
                break
            else:
                print("Merchant plugin is not loaded")
    print("Merchant plugin initialized")
    # start Client plugin
    client_plugin_path = abspath("Client.py")
    response = client_node.plugin("start", client_plugin_path)
    for plugin in response["plugins"]:
        if plugin["name"] == client_plugin_path:
            if plugin["active"] == True:
                break
            else:
                print("Client plugin is not loaded")
    print("Client plugin initialized")
    # Connect client with merchant node
    # get merchant id, address and port using plugin's RPC method
    merchant_info = merchant_node.connectinfo()
    for i in merchant_info:
        print("Merchant's {} is {}".format(i, merchant_info[i]))
    client_connect_reply = client_node.link(merchant_info["node_id"],
                                            merchant_info["address"],
                                            merchant_info["port"])
    if client_connect_reply["code"] == 0:
        print("Client node is connected to Merchant")
    else:
        print("Client node couldn't connect to Merchant")

    # Fund channel with Merchant, 0.1BTC = 10.000.000 satoshi
    client_channel_reply = client_node.createchannel(merchant_info["node_id"],
                                                     "0.1btc")
    print("Channel was funded")

    print("Current blockchain height is ", bt_cli.getblockcount())

    # Include funding transaction in blockchain
    address = bt_cli.getnewaddress()
    bt_cli.generatetoaddress(6, address)
    print("Current blockchain height is ", bt_cli.getblockcount())

    # Waiting for lightningd synchronize with bitcoind
    route = False
    while not route:
        try:
            route = client_node.getroute(merchant_info["node_id"], 100, 1)
        except Exception as e:
            continue
    print("Route was found")

    # Create invoice
    invoice_label = "invoice#1"
    merchant_invoice = merchant_node.createinvoice(1000000000, invoice_label,
                                                   "test payment to merchant")

    # Pay by invoice
    client_pay_reply = client_node.payinvoice(merchant_invoice["bolt11"])

    # Wait for payment status to become complete
    client_node.waitsendpay(merchant_invoice["payment_hash"])
    print("Client's payment complete")

    # Wait for invoice status to become paid
    merchant_node.waitinvoice(invoice_label)
    print("Merchant's invoice is paid")

    # Close payment channel
    client_node.close(client_channel_reply["channel_id"])

    # Include final transaction in blockchain
    bt_cli.generatetoaddress(6, address)