예제 #1
0
def init(options, configuration, plugin):
    global rpc, our_nodeid
    plugin.log("feereport init")
    path = join(configuration["lightning-dir"], configuration["rpc-file"])
    rpc = LightningRpc(path)
    info = rpc.getinfo()
    our_nodeid = info["id"]
예제 #2
0
class LightningDaemon(object):
    def __init__(self, daemon_rpc):
        self.rpc = LightningRpc(daemon_rpc)

    def invoice_c_lightning(self, msatoshi, label, description):
        result = self.rpc.invoice(msatoshi,
                                  label,
                                  description,
                                  expiry=INVOICE_EXPIRY)
        log(json.dumps(result, indent=1, sort_keys=True))
        return result

    def get_c_lightning_invoices(self):
        result = self.rpc.listinvoices()
        #log(json.dumps(result, indent=1, sort_keys=True))
        return result

    def delete(self, label, state="paid"):
        result = self.rpc.delinvoice(label, state)
        #        log(json.dumps(result, indent=1, sort_keys=True))
        return result

    def getinfo(self):
        return self.rpc.getinfo()

    def listfunds(self):
        return self.rpc.listfunds()

    def listnodes(self):
        return self.rpc.listnodes()
예제 #3
0
def index(request):
    # Bitcoin RPC Credentials (you need to change these)
    rpc_port = "8332"
    rpc_user = "******"
    rpc_password = "******"

    # LIGHTNING NETWORK

    # Lightning Network Socket file (you might need to change this)
    ln = LightningRpc("/home/pi/.lightning/lightning-rpc")

    try:
        l_info = ln.getinfo()
        l = LightningViewData(True)
        l.block_height = l_info["blockheight"]
        l.version = l_info["version"]
        l.version = l.version.replace("v", "")

        l_peers = ln.listpeers()
        l.peer_count = len(l_peers["peers"])

        l_funds = ln.listfunds()
        l.channel_count = len(l_funds["channels"])
    except:
        l = LightningViewData(False)

# BITCOIN

    b = BitcoinViewData(True)

    try:
        rpc_connection = AuthServiceProxy("http://%s:%[email protected]:%s" %
                                          (rpc_user, rpc_password, rpc_port))
        b_conn_count = rpc_connection.getconnectioncount()
        if b_conn_count > 0:
            b.online = True
    except Exception as e:
        b.running = False

    if b.running == True:
        try:
            b.block_height = rpc_connection.getblockcount()
            b_network_info = rpc_connection.getnetworkinfo()
            b.peer_count = b_network_info["connections"]
            b.version = b_network_info["subversion"]
            b.version = b.version.replace("/", "")
            b.version = b.version.replace("Satoshi:", "")
        except Exception as e:
            b.message = str(e)


# RETURN VIEW DATA

    return render(request, 'dashboard/index.html', {
        'lightning': l,
        'bitcoin': b
    })
예제 #4
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
예제 #5
0
class LightningOperator:

	rpc_interface = None
	__network = None

	def __init__(self, network):

		self.__network = network

		if self.__network == "mainnet":
			self.rpc_interface = LightningRpc(expanduser("~")+"/.mainnet/lightning-rpc")


			self.rpc_interface.connect("02f6725f9c1c40333b67faea92fd211c183050f28df32cac3f9d69685fe9665432@104.198.32.198:9735")
			#self.rpc_interface.connect("030fe6f75d41d7112afee0f6f0e230095d9036abf19c7f88f416cc7b9ab9e9ef3e@203.206.164.188:9735")
			#self.rpc_interface.connect("03abf6f44c355dec0d5aa155bdbdd6e0c8fefe318eff402de65c6eb2e1be55dc3e@52.15.79.245:9735")
			#self.rpc_interface.connect("03cb7983dc247f9f81a0fa2dfa3ce1c255365f7279c8dd143e086ca333df10e278@46.28.204.21:9735")
			#self.rpc_interface.connect("03e50492eab4107a773141bb419e107bda3de3d55652e6e1a41225f06a0bbf2d56@35.172.33.197:9735")

		else:
			self.rpc_interface = LightningRpc(expanduser("~")+"/.lightning/lightning-rpc")

			self.rpc_interface.connect("03236a685d30096b26692dce0cf0fa7c8528bdf61dbf5363a3ef6d5c92733a3016@50.116.3.223:9734")
			#self.rpc_interface.connect("03782bb858e1ec9c0a4a5ac665ed658c97ced02e723eafc3c56137ab4e2e3caebf@52.8.119.71:9736")
			#self.rpc_interface.connect("02ec66fb12dd5d4943d63e7a1a35d063aec015e1c8b89cee6c9f2db3faf0f6687f@3.93.159.131:19735")
			#self.rpc_interface.connect("0218b92d19de937ef740154d20d3a6f37c44e6381ca72b95789295073664cfdd36@5.95.80.47:9735")

		print(type(self.rpc_interface.getinfo()))

		print(self.rpc_interface.listpeers())

	def isMainnet(self):
		return __network == "mainnet"

	def populate_graph(self, graph):

		print("Attempt RPC-call to download nodes and channels from the lightning network")
		nodes = []
		print(self.rpc_interface)
		try:
			while len(nodes) == 0:
				peers = self.rpc_interface.listpeers()["peers"]
				if len(peers) < 1:
					time.sleep(2)
				nodes = self.rpc_interface.listnodes()["nodes"]
		except ValueError as e:
			print("Cannot download nodes from the network, are you connected to a peer?")
			print("RPC error: " + str(e))
			return False

		print("Number of nodes found: {}".format(len(nodes)))

		for node in nodes:
			graph.add_node(node["nodeid"], object=node)

		"""
		Grab the channels
		"""
		if len(graph.nodes) == 0:
			print("Cannot download channels if nodes do not exist. ")
			return False

		try:

			channels = self.rpc_interface.listchannels()["channels"]
			print("Number of retrieved channels: {}".format(len(channels)))
		except ValueError as e:
			print("Cannot download channels from the network, are you connected to a peer?")
			print("RPC error: " + str(e))
			return False

		i = 0
		j = 0
		for channel in channels:

			if (j % 1000) == 0:
				print(j)

			j += 1

			if channel["source"] not in graph.nodes:
				print(channel["source"], "not in list")
				i += 1

			if channel["destination"] not in graph.nodes:
				print(channel["destination"], "not in list")
				i += 1

			graph.add_edge(channel["source"], channel["destination"], **channel)

		print("NOT IN: ", i)
		return True
예제 #6
0
def connect_nodes(n1: LightningRpc, n2: LightningRpc) -> None:
    n1_id = get_id(n1)
    n1_host: str = n1.getinfo()['binding'][0]['address']
    n1_port: int = n1.getinfo()['binding'][0]['port']
    n2.connect(peer_id=n1_id, host=n1_host, port=n1_port)
예제 #7
0
def get_id(l: LightningRpc) -> str:
    return l.getinfo()['id']
예제 #8
0

rpc1 = LightningRpc("/tmp/l1-regtest/regtest/lightning-rpc")
rpc2 = LightningRpc("/tmp/l2-regtest/regtest/lightning-rpc")
rpc3 = LightningRpc("/tmp/l3-regtest/regtest/lightning-rpc")


# rpc3 adds an invoice and returns the decoded invoice
try:
    inv = rpc3.decodepay(rpc3.invoice(10000, uuid4().hex, uuid4().hex)["bolt11"])
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

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

    def peers(self):
        return [p['peerid'] for p in self.rpc.getpeers()['peers']]

    def id(self):
        return self.rpc.getinfo()['id']

    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)
        tx = bitcoind.rpc.getrawtransaction(txid)
        self.rpc.addfunds(tx)

    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):
        """ Make sure that we have an active channel with remote
        """
        remote_id = remote.id()
        self_id = self.id()
        for p in self.rpc.getpeers()['peers']:
            if remote.id() == p['peerid']:
                self.logger.debug("Channel {} -> {} state: {}".format(
                    self_id, remote_id, p['state']))
                return p['state'] == 'CHANNELD_NORMAL'

        self.logger.warning("Channel {} -> {} not found".format(
            self_id, remote_id))
        return False

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

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

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

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

    def connect(self, host, port, node_id):
        return self.rpc.connect(node_id, "{}:{}".format(host, port))

    def info(self):
        r = self.rpc.getinfo()
        return {
            'id': r['id'],
            'blockheight': r['blockheight'],
        }
예제 #10
0
class CLightning(LnNode):
    def __init__(self):
        super().__init__()
        self.lnrpc = ''
        self.rpc_file = '/tmp/lightningrpc'

    def setup(self, ipaddr='127.0.0.1', port=9735, argv=None):
        self.ipaddr = ipaddr
        self.port = port
        if argv is not None:
            self.rpc_file = argv
        self.lnrpc = LightningRpc(self.rpc_file)

    def get_name(self):
        return 'c-lightning'

    '''
    enum channel_state {
        /* In channeld, still waiting for lockin. */
        CHANNELD_AWAITING_LOCKIN = 2,

        /* Normal operating state. */
        CHANNELD_NORMAL,

        /* We are closing, pending HTLC resolution. */
        CHANNELD_SHUTTING_DOWN,

        /* Exchanging signatures on closing tx. */
        CLOSINGD_SIGEXCHANGE,

        /* Waiting for onchain event. */
        CLOSINGD_COMPLETE,

        /* Waiting for unilateral close to hit blockchain. */
        AWAITING_UNILATERAL,

        /* We've seen the funding spent, we're waiting for onchaind. */
        FUNDING_SPEND_SEEN,

        /* On chain */
        ONCHAIN
    };
    '''

    def get_status(self, peer):
        channel_sat = 0
        try:
            result = self.lnrpc.listpeers()
            if ('peers' not in result) or (len(result['peers']) == 0):
                print('(status=none)')
                return LnNode.Status.NONE, 0
            peer_status = ''
            current_ch = None
            for p in result['peers']:
                if p['id'] == peer:
                    for ch in p['channels']:
                        if ch['state'] != 'ONCHAIN':
                            # onchainなものは「済」と判断して無視する
                            current_ch = ch
                            peer_status = ch['state']
                            break
            print('(status=', peer_status + ')')
            if peer_status == 'CHANNELD_NORMAL':
                status = LnNode.Status.NORMAL
                channel_sat = current_ch['msatoshi_to_us']
            elif peer_status == 'CHANNELD_AWAITING_LOCKIN':
                status = LnNode.Status.FUNDING
            elif peer_status == 'CHANNELD_SHUTTING_DOWN' or\
                    peer_status == 'CLOSINGD_SIGEXCHANGE' or\
                    peer_status == 'CLOSINGD_COMPLETE' or\
                    peer_status == 'AWAITING_UNILATERAL' or\
                    peer_status == 'FUNDING_SPEND_SEEN':
                status = LnNode.Status.CLOSING
            else:
                status = LnNode.Status.NONE
        except:
            print('traceback.format_exc():\n%s' % traceback.format_exc())
            os.kill(os.getpid(), signal.SIGKILL)
        return status, channel_sat

    def get_nodeid(self):
        try:
            info = self.lnrpc.getinfo()
            return info['id']
        except:
            print('traceback.format_exc():\n%s' % traceback.format_exc())
            os.kill(os.getpid(), signal.SIGKILL)

    # result[1] = "OK" or "NG"
    def connect(self, node_id, ipaddr, port):
        try:
            res = self.lnrpc.connect(node_id, ipaddr, port)
            print('connect=', res)
            res = '{"result": ["connect","OK","' + node_id + '"]}'
        except RpcError as e:
            print('traceback.format_exc():\n%s' % traceback.format_exc())
            print('fail connect')
            res = '{"result": ["connect","NG","' + node_id + '","' + e.error[
                'message'] + '"]}'
        except:
            print('traceback.format_exc():\n%s' % traceback.format_exc())
            print('fail connect')
            res = '{"result": ["connect","NG","' + node_id + '"]}'
        return res

    # result[1] = "OK" or "NG"
    def disconnect(self, node_id):
        print('disconnect: ' + node_id)
        try:
            res = self.lnrpc.disconnect(node_id, force=True)
            print('disconnect=', res)
            res = '{"result": ["disconnect","OK","' + node_id + '"]}'
        except RpcError as e:
            print('traceback.format_exc():\n%s' % traceback.format_exc())
            print('fail disconnect')
            res = '{"result": ["disconnect","NG","' + node_id + '","' + e.error[
                'message'] + '"]}'
        except:
            print('traceback.format_exc():\n%s' % traceback.format_exc())
            print('fail disconnect')
            res = '{"result": ["disconnect","NG","' + node_id + '"]}'
        return res

    # result[1] = "OK" or "NG"
    def open_channel(self, node_id, amount):
        try:
            res = self.lnrpc.fundchannel(node_id, amount)
            print('open_channel=', res)
            res = '{"result": ["openchannel","OK","' + node_id + '"]}'
        except RpcError as e:
            print('traceback.format_exc():\n%s' % traceback.format_exc())
            print('fail openchannel')
            res = '{"result": ["openchannel","NG","' + node_id + '","' + e.error[
                'message'] + '"]}'
        except:
            print('traceback.format_exc():\n%s' % traceback.format_exc())
            print('fail open_channel')
            res = '{"result": ["openchannel","NG","' + node_id + '"]}'
        return res

    # result[1] = BOLT11 or "NG"
    def get_invoice(self, amount_msat, label=''):
        try:
            res = self.lnrpc.invoice(amount_msat,
                                     "lbl{}".format(random.random()),
                                     "testpayment")
            print('invoice=', res)
            res = '{"result": ["invoice","' + res[
                'bolt11'] + '","' + label + '"]}'
        except RpcError as e:
            print('traceback.format_exc():\n%s' % traceback.format_exc())
            print('fail invoice')
            res = '{"result": ["invoice","NG","' + label + '","' + e.error[
                'message'] + '"]}'
        except:
            print('traceback.format_exc():\n%s' % traceback.format_exc())
            print('fail invoice')
            res = '{"result": ["invoice","NG","' + label + '"]}'
        return res

    # result[1] = "OK" or "NG"
    def pay(self, invoice):
        try:
            res = self.lnrpc.pay(invoice, riskfactor=100)
            print('pay=', res)
            res = '{"result": ["pay","OK","' + invoice + '"]}'
        except RpcError as e:
            print('traceback.format_exc():\n%s' % traceback.format_exc())
            print('fail pay: ' + invoice)
            res = '{"result": ["pay","NG","' + invoice + '","' + e.error[
                'message'] + '"]}'
        except:
            print('traceback.format_exc():\n%s' % traceback.format_exc())
            print('fail pay: ' + invoice)
            res = '{"result": ["pay","NG","' + invoice + '"]}'
        return res

    # result[1] = "OK" or "NG"
    def close_mutual(self, node_id):
        print('close_mutual')
        return self._close(node_id, False)

    # result[1] = "OK" or "NG"
    def close_force(self, node_id):
        print('close_force')
        self.disconnect(node_id)
        return self._close(node_id, True)

    # result[1] = "OK" or "NG"
    def _close(self, node_id, force):
        str_force = 'force' if force else 'mutual'
        try:
            res = self.lnrpc.close(node_id, force=force)
            print('close=', res)
            res = '{"result": ["closechannel","OK","' + node_id + '","' + str_force + '"]}'
        except RpcError as e:
            print('traceback.format_exc():\n%s' % traceback.format_exc())
            print('fail closechannel')
            res = '{"result": ["closechannel","NG","' + node_id + '","' + e.error[
                'message'] + '"]}'
        except:
            print('traceback.format_exc():\n%s' % traceback.format_exc())
            print('fail closechannel')
            res = '{"result": ["closechannel","NG","' + node_id + '","' + str_force + '"]}'
        return res