def __init__(self, cert, config): creds = grpc.ssl_channel_credentials(cert) channel = grpc.secure_channel(config.LND_HOST, creds) self.stub = lnrpc.LightningStub(channel) self.node_address = config.NODE_ADDRESS self.node_port = config.NODE_PORT self.channel_amount = config.CHANNEL_AMOUNT
def new_address(container): channel = get_channel(container) macaroon = codecs.encode(open(_macaroon(container), 'rb').read(), 'hex') stub = lnrpc.LightningStub(channel) request = ln.NewAddressRequest(type=0) response = stub.NewAddress(request, metadata=[('macaroon', macaroon)]) return response.address
def get_stub(): cert = open(os.path.expanduser('./lnd/tls.cert'), 'rb').read() creds = grpc.ssl_channel_credentials(cert) lnurl = "%s:%s"%(os.getenv('LND_IP'), os.getenv('LND_GRPC_PORT')) channel = grpc.secure_channel(lnurl, creds) stub = lnrpc.LightningStub(channel) return stub
def connect(): # Due to updated ECDSA generated tls.cert we need to let gprc know that # we need to use that cipher suite otherwise there will be a handshake # error when we communicate with the lnd rpc server. os.environ["GRPC_SSL_CIPHER_SUITES"] = 'HIGH+ECDSA' with open('/home/lnd/.lnd/tls.cert', 'rb') as f: cert = f.read() with open('/home/lnd/.lnd/data/chain/smartcash/mainnet/invoice.macaroon', 'rb') as f: macaroon_bytes = f.read() macaroon = codecs.encode(macaroon_bytes, 'hex') def metadata_callback(_context, callback): # for more info see grpc docs callback([('macaroon', macaroon)], None) # build ssl credentials using the cert the same as before cert_creds = grpc.ssl_channel_credentials(cert) # now build meta data credentials auth_creds = grpc.metadata_call_credentials(metadata_callback) # combine the cert credentials and the macaroon auth credentials # such that every call is properly encrypted and authenticated combined_creds = grpc.composite_channel_credentials(cert_creds, auth_creds) # finally pass in the combined credentials when creating a channel channel = grpc.secure_channel('localhost:10009', combined_creds) stub = lnrpc.LightningStub(channel) return stub
def __init__(self, config): self.displayName = config['name'] with open(config['tls_cert'], 'rb') as tls_cert_file: cert_credentials = grpc.ssl_channel_credentials( tls_cert_file.read()) if config['admin_macaroon']: with open(config['admin_macaroon'], 'rb') as macaroon_file: macaroon = codecs.encode(macaroon_file.read(), 'hex') macaroon_credentials = self.get_macaroon_credentials( macaroon) credentials = grpc.composite_channel_credentials( cert_credentials, macaroon_credentials) else: credentials = cert_credentials channel = grpc.secure_channel(config["rpc_host"], credentials) # Due to updated ECDSA generated tls.cert we need to let gprc know that # we need to use that cipher suite otherwise there will be a handhsake # error when we communicate with the lnd rpc server. os.environ["GRPC_SSL_CIPHER_SUITES"] = 'HIGH+ECDSA' logger.info( f'CONNECTING TO {config["name"]}: {config["rpc_host"]}') self.client = lnrpc.LightningStub(channel) self.identity_pubkey = self.getinfo().identity_pubkey
def main(): if not BOT_TOKEN: sys.stderr.write("Please specify BOT_TOKEN environment variable\n") return 1 # Open database global sessionmaker logger.info("Opening database {}".format(DB_PATH)) sessionmaker = db.open_database(DB_PATH) session = sessionmaker() logger.info("Counting {} users and {} transactions".format( db.count_users(session), db.count_transactions(session))) session.close() # Connect to lightning gRPC global stub logger.info("Reading TLS certificate {}".format(CERT_PATH)) cert = open(CERT_PATH, 'rb').read() creds = grpc.ssl_channel_credentials(cert) logger.info("Connecting to lnd at {}".format(LND_GRPC)) channel = grpc.secure_channel(LND_GRPC, creds) stub = lnrpc.LightningStub(channel) # Do a test call info = stub.GetInfo(ln.GetInfoRequest(), timeout=GRPC_TIMEOUT) logger.info(info) logger.info("Connected to lnd".format(info.alias)) if not info.testnet and TESTNET: logger.critical("lnd is running on mainnet, quitting") sys.exit(1) if not info.synced_to_chain: logger.critical("lnd is not synced") sys.exit(1) if not info.chains == ["bitcoin"]: logger.critical("Only bitcoin is supported at this time") sys.exit(1) # Create the telegram bot global updater updater = Updater(token=BOT_TOKEN) updater.dispatcher.add_handler(CommandHandler('start', command_start)) updater.dispatcher.add_handler(CommandHandler('balance', command_balance)) updater.dispatcher.add_handler( CommandHandler('invoice', command_invoice, pass_args=True)) updater.dispatcher.add_handler( CommandHandler('pay', command_pay, pass_args=True)) updater.dispatcher.add_handler(CommandHandler('help', help_handler)) updater.dispatcher.add_handler(MessageHandler(Filters.photo, photo_handler)) updater.dispatcher.add_handler(MessageHandler(Filters.text, text_handler)) updater.start_polling() # Payments listener in a new thread import thread thread.start_new_thread(payments_listener_thread, ()) logger.info("Bot started") # Wait until telegram poller stops or ^C updater.idle() return 0
def main(): # Due to updated ECDSA generated tls.cert we need to let gprc know that # we need to use that cipher suite otherwise there will be a handshake # error when we communicate with the lnd rpc server. os.environ["GRPC_SSL_CIPHER_SUITES"] = 'HIGH+ECDSA' with open('/home/lnd/.lnd/tls.cert', 'rb') as f: cert = f.read() with open('/home/lnd/.lnd/data/chain/smartcash/mainnet/invoice.macaroon', 'rb') as f: macaroon_bytes = f.read() macaroon = codecs.encode(macaroon_bytes, 'hex') def metadata_callback(context, callback): # for more info see grpc docs callback([('macaroon', macaroon)], None) # build ssl credentials using the cert the same as before cert_creds = grpc.ssl_channel_credentials(cert) # now build meta data credentials auth_creds = grpc.metadata_call_credentials(metadata_callback) # combine the cert credentials and the macaroon auth credentials # such that every call is properly encrypted and authenticated combined_creds = grpc.composite_channel_credentials(cert_creds, auth_creds) # finally pass in the combined credentials when creating a channel channel = grpc.secure_channel('localhost:10009', combined_creds) stub = lnrpc.LightningStub(channel) invoice = stub.AddInvoice(ln.Invoice(memo="Donation for Mempool")) print("Content-Type: application/json; charset=UTF-8") print("") print('{"r_hash":"%s","payment_request":"%s","add_index":%d}' % (binascii.hexlify(invoice.r_hash),invoice.payment_request,invoice.add_index))
def get_info(container): channel = get_channel(container) macaroon = codecs.encode(open(_macaroon(container), 'rb').read(), 'hex') stub = lnrpc.LightningStub(channel) request = ln.GetInfoRequest() response = stub.GetInfo(request, metadata=[('macaroon', macaroon)]) return response
def index(request): """ Build the home page of this demo app. :param request: :return: HTTP response providing the home page of this demo app. """ # Due to updated ECDSA generated tls.cert we need to let gprc know that # we need to use that cipher suite otherwise there will be a handhsake # error when we communicate with the lnd rpc server. os.environ["GRPC_SSL_CIPHER_SUITES"] = 'HIGH+ECDSA' # Lnd cert is at ~/.lnd/tls.cert on Linux and # ~/Library/Application Support/Lnd/tls.cert on Mac cert = open(os.path.expanduser('~/.lnd/tls.cert'), 'rb').read() creds = grpc.ssl_channel_credentials(cert) channel = grpc.secure_channel('localhost:10009', creds) stub = lnrpc.LightningStub(channel) # Retrieve and display the wallet balance #response = stub.WalletBalance(ln.WalletBalanceRequest()) m_request = ln.Invoice(value=100, ) response = stub.AddInvoice(m_request) # Build context for rendering QR codes. context = dict( #invoice_id='lntb100u1pdukkecpp505wuvr8a9jujgh80a9nkl60kns0866y73f9ekr8rw5ff0xmmu4nqdqqcqzysxwtzpe8c9pufk5v7z7794247amqh43g43w43elfeea2lpdhj84jjm57desvjp443rvhcfl7x6y5vn0wu77wt2q6h2279dw7kcn6mu6gpuj4uw6', invoice_id=response.payment_request, ) # Render the index page. return render(request, 'qr_code_demo/index.html', context=context)
def __init__(self): os.environ['GRPC_SSL_CIPHER_SUITES'] = 'HIGH+ECDSA' combined_credentials = self.get_credentials(LND_DIR) channel_options = [ ('grpc.max_message_length', MESSAGE_SIZE_MB), ('grpc.max_receive_message_length', MESSAGE_SIZE_MB) ] grpc_channel = grpc.secure_channel(SERVER, combined_credentials, channel_options) self.stub = lnrpc.LightningStub(grpc_channel) self.graph = None
def index(): try: rpc_connect = AuthServiceProxy("http://{}:{}@{}:{}".format(rpc_user,rpc_password,allowed_ip,rpc_port)) current_block_height = rpc_connect.getblockcount() onchain_peers = rpc_connect.getconnectioncount() onchain_balance = rpc_connect.getbalance() bitcoin_version = (rpc_connect.getnetworkinfo()['subversion'])[1:-1].replace("Satoshi:","") sync_prog = str(round(rpc_connect.getblockchaininfo()['verificationprogress']*100, 2)) + "%" chain_type = rpc_connect.getblockchaininfo()['chain'] if onchain_balance > 0 and chain_type == "main": onchain_balance = u"â‚¿ " + str(onchain_balance) elif onchain_balance == 0: onchain_balance = u"â‚¿ " + str(0) elif onchain_balance > 0 and chain_type == "test": onchain_balance = u"tâ‚¿ " + str(onchain_balance) else: onchain_balance = u"tâ‚¿ " + str(0) if chain_type == "test": chaintype_ln = "testnet" else: chaintype_ln = "mainnet" except: current_block_height = onchain_peers = onchain_balance = bitcoin_version = sync_prog = chain_type = "Offline!" try: os.environ["GRPC_SSL_CIPHER_SUITES"] = 'HIGH+ECDSA' with open(os.path.expanduser(lnd_dir_location + 'data/chain/bitcoin/{}/admin.macaroon'.format(chaintype_ln)), 'rb') as f: macaroon_bytes = f.read() macaroon = codecs.encode(macaroon_bytes, 'hex') cert = open(os.path.expanduser(lnd_dir_location + 'tls.cert'), 'rb').read() creds = grpc.ssl_channel_credentials(cert) channel = grpc.secure_channel('localhost:10009', creds) stub = lnrpc.LightningStub(channel) response = stub.GetInfo(ln.GetInfoRequest(), metadata=[('macaroon', macaroon)]) satbalance = stub.ChannelBalance(ln.ChannelBalanceRequest(), metadata=[('macaroon', macaroon)]) lightning_channels_act = response.num_active_channels lightning_peers = response.num_peers offchain_balance = u"ÅŸ " + str(format(satbalance.balance,',')) lightning_version = response.version[:5] alias = response.alias except: lightning_channels_act = lightning_peers = offchain_balance = lightning_version = alias = "Offline!" return render_template('index.html', current_block_height=current_block_height, onchain_peers=onchain_peers, onchain_balance=onchain_balance, bitcoin_version=bitcoin_version, sync_prog=sync_prog, chain_type=chain_type, lightning_channels_act=lightning_channels_act, lightning_peers=lightning_peers, offchain_balance=offchain_balance, lightning_version=lightning_version, alias=alias)
def get_lightning_stub(): os.environ['GRPC_SSL_CIPHER_SUITES'] = 'HIGH+ECDSA' cert = open(LND_DIR + 'tls.cert', 'rb').read() ssl_creds = grpc.ssl_channel_credentials(cert) auth_creds = grpc.metadata_call_credentials(metadata_callback) combined_creds = grpc.composite_channel_credentials(ssl_creds, auth_creds) channel = grpc.secure_channel('localhost:10009', combined_creds) stub = lnrpc.LightningStub(channel) return stub
def connect(source_container, dest_container): dest_info = get_info(dest_container) channel = get_channel(source_container) macaroon = codecs.encode( open(_macaroon(source_container), 'rb').read(), 'hex') stub = lnrpc.LightningStub(channel) addr = ln.LightningAddress( pubkey=dest_info.identity_pubkey, host=dest_container, ) request = ln.ConnectPeerRequest(addr=addr) stub.ConnectPeer(request, metadata=[('macaroon', macaroon)])
def start(self): super().start() self.wait_for_log('RPC server listening on') self.unlocker_stub = lnrpc_grpc.WalletUnlockerStub(self.make_channel()) seed = self.unlocker_stub.GenSeed(lnrpc.GenSeedRequest()) self.unlocker_stub.InitWallet( lnrpc.InitWalletRequest( wallet_password=b"password", recovery_window=0, cipher_seed_mnemonic=seed.cipher_seed_mnemonic)) self.wait_for_log('Done catching up block hashes') time.sleep(5) # need to remake the channel, otherwise the Lightning gRPC service might not be there yet self.stub = lnrpc_grpc.LightningStub(self.make_channel()) logging.info('LND started (pid: {})'.format(self.proc.pid))
def __init__(self, cert, config): cert_creds = grpc.ssl_channel_credentials(cert) auth_creds = grpc.metadata_call_credentials(metadata_callback) creds = grpc.composite_channel_credentials(cert_creds, auth_creds) channel = grpc.secure_channel(config.LND_HOST, creds) self.stub = lnrpc.LightningStub(channel) self.DEFAULT_PRICE = config.DEFAULT_PRICE self.DEFAULT_EXPIRY = config.DEFAULT_EXPIRY try: request = ln.GetInfoRequest() response = self.stub.GetInfo(request) logging.info(response) except grpc.RpcError as e: logging.error(e)
def main(): # Due to updated ECDSA generated tls.cert we need to let gprc know that # we need to use that cipher suite otherwise there will be a handshake # error when we communicate with the lnd rpc server. os.environ["GRPC_SSL_CIPHER_SUITES"] = 'HIGH+ECDSA' with open('/home/lnd/.lnd/tls.cert', 'rb') as f: cert = f.read() with open('/home/lnd/.lnd/data/chain/bitcoin/mainnet/invoice.macaroon', 'rb') as f: macaroon_bytes = f.read() macaroon = codecs.encode(macaroon_bytes, 'hex') def metadata_callback(context, callback): # for more info see grpc docs callback([('macaroon', macaroon)], None) # build ssl credentials using the cert the same as before cert_creds = grpc.ssl_channel_credentials(cert) # now build meta data credentials auth_creds = grpc.metadata_call_credentials(metadata_callback) # combine the cert credentials and the macaroon auth credentials # such that every call is properly encrypted and authenticated combined_creds = grpc.composite_channel_credentials(cert_creds, auth_creds) # finally pass in the combined credentials when creating a channel channel = grpc.secure_channel('localhost:10009', combined_creds) stub = lnrpc.LightningStub(channel) uri = os.environ.get("REQUEST_URI") match = re.search("[?&]r_hash=([0-9a-f]+)(&.*)?$", uri) if not match: raise ("No Index") rhash = match.group(1) settled = False timeout = time.time() + 60 # 1 minute timeout while not settled and time.time() < timeout: invoice = stub.LookupInvoice(ln.PaymentHash(r_hash_str=rhash)) if invoice.settled: settled = True break time.sleep(1) print("Content-Type: application/json; charset=UTF-8") print("") print('{"settled":%s}' % ("true" if settled else "false"))
def __init__(self, lnddatadir): os.environ["GRPC_SSL_CIPHER_SUITES"] = 'HIGH+ECDSA' cert = open(os.path.join(lnddatadir, 'tls.cert'), 'rb').read() certCredentials = grpc.ssl_channel_credentials(cert) authCredentials = grpc.metadata_call_credentials(self.metadataCallback) combinedCredentials = grpc.composite_channel_credentials( certCredentials, authCredentials) self.channel = grpc.secure_channel('localhost:10009', combinedCredentials) self.stub = lnrpc.LightningStub(self.channel) self.invoicesstub = invoicesrpc.InvoicesStub(self.channel) self.macaroon = codecs.encode( open( os.path.join(lnddatadir, 'data/chain/bitcoin/mainnet/admin.macaroon'), 'rb').read(), 'hex')
def init_node(): def metadata_callback(context, callback): callback([('macaroon', b64decode(LND_MACAROON).hex())], None) # build ssl credentials using the cert the same as before cert_creds = grpc.ssl_channel_credentials(b64decode(LND_TLS_CERT)) # now build meta data credentials auth_creds = grpc.metadata_call_credentials(metadata_callback) # combine the cert credentials and the macaroon auth credentials # such that every call is properly encrypted and authenticated combined_creds = grpc.composite_channel_credentials(cert_creds, auth_creds) # finally pass in the combined credentials when creating a channel channel = grpc.secure_channel(LND_GRPC_URL, combined_creds) return lnrpc.LightningStub(channel)
def startServerConnection(serverConfigDict): tls_cert_path = serverConfigDict["tls_cert_path"] macaroon_path = serverConfigDict["macaroon_path"] ip_port_adr = serverConfigDict["ip_port_adr"] # print("Opening secure channel to server") cert = open(os.path.expanduser(tls_cert_path), 'rb').read() creds = grpc.ssl_channel_credentials(cert) with open(os.path.expanduser(macaroon_path), 'rb') as f: macaroon_bytes = f.read() macaroon = codecs.encode(macaroon_bytes, 'hex') channel = grpc.secure_channel(ip_port_adr, creds) stub = lnrpc.LightningStub(channel) return [stub, macaroon]
def __init__(self, cert, config): creds = grpc.ssl_channel_credentials(cert) channel = grpc.secure_channel(config.LND_HOST, creds) self.stub = lnrpc.LightningStub(channel) self.DEFAULT_PRICE = config.DEFAULT_PRICE self.DEFAULT_EXPIRY = config.DEFAULT_EXPIRY try: request = ln.GetInfoRequest() response = self.stub.GetInfo(request) logging.info(response) except grpc.RpcError as e: logging.error(e) self.broadcast = Broadcaster._instance self.invoiceThread = threading.Thread(target = self.subscribe_invoices) self.invoiceThread.daemon = True LndWrapper._instance = self
def get_stub(node_url: str, macaroon: str, cert: str): def metadata_callback(context, callback): # for more info see grpc docs callback([('macaroon', macaroon)], None) # build ssl credentials using the cert the same as before cert_creds = grpc.ssl_channel_credentials(b64decode(cert)) # now build meta data credentials auth_creds = grpc.metadata_call_credentials(metadata_callback) # combine the cert credentials and the macaroon auth credentials # such that every call is properly encrypted and authenticated combined_creds = grpc.composite_channel_credentials(cert_creds, auth_creds) # finally pass in the combined credentials when creating a channel channel = grpc.secure_channel(node_url, combined_creds) return lnrpc.LightningStub(channel)
def get_lightning_stub(): os.environ['GRPC_SSL_CIPHER_SUITES'] = 'HIGH+ECDSA' cert = open(LND_DIR + 'tls.cert', 'rb').read() ssl_creds = grpc.ssl_channel_credentials(cert) auth_creds = grpc.metadata_call_credentials(metadata_callback) combined_creds = grpc.composite_channel_credentials(ssl_creds, auth_creds) #channel = grpc.secure_channel('localhost:10009', combined_creds) channel = grpc.secure_channel(grpc_url, combined_creds, options=[('grpc.max_send_message_length', 50 * 1024 * 1024), ('grpc.max_receive_message_length', 50 * 1024 * 1024)]) stub = lnrpc.LightningStub(channel) return stub
def open_channel(source_container, dest_container, amount): """Open a channel between the 2 specified containers.""" # source_info = get_info(source_container) dest_info = get_info(dest_container) try: connect(source_container, dest_container) except Exception: # TODO: Catch more specific error pass channel = get_channel(source_container) macaroon = codecs.encode( open(_macaroon(source_container), 'rb').read(), 'hex') stub = lnrpc.LightningStub(channel) request = ln.OpenChannelRequest( node_pubkey_string=dest_info.identity_pubkey, local_funding_amount=amount, spend_unconfirmed=True, ) stub.OpenChannelSync(request, metadata=[('macaroon', macaroon)])
class LNDRPC: cert = open(os.path.expanduser('~/.lnd/tls.cert')).read() creds = grpc.ssl_channel_credentials(cert) channel = grpc.secure_channel('localhost:10009', creds) stub = lnrpc.LightningStub(channel) def __init__(self): pass def get_balances(self): return self.stub.WalletBalance( ln.WalletBalanceRequest(witness_only=True)) def describe_graph(self): return self.stub.DescribeGraph(ln.ChannelGraphRequest()) def connect_peer(self, pubkey, host): addr = ln.LightningAddress(pubkey=pubkey, host=host) request = ln.ConnectPeerRequest(addr=addr) try: response = self.stub.ConnectPeer(request) return True except grpc._channel._Rendezvous as e: print "Error connecting to " + pubkey + ' ' + str(e) return False def open_channel(self, pubkey, local_funding_amount): pubkey_bytes = codecs.decode(pubkey, 'hex') request = ln.OpenChannelRequest( node_pubkey=pubkey_bytes, node_pubkey_string=pubkey, local_funding_amount=local_funding_amount) try: response = self.stub.OpenChannel(request) #TODO: return success when OpenChannel finishes except grpc._channel._Rendezvous as e: print "Error opening channel with " + pubkey + ' ' + str(e)
def connect(): config = getConfig() with open(config['readonlymacaroonpath'], 'rb') as f: macaroon_bytes = f.read() macaroon = codecs.encode(macaroon_bytes, 'hex') os.environ["GRPC_SSL_CIPHER_SUITES"] = 'HIGH+ECDSA' cert = open(config['tlscertpath'], 'rb').read() creds = grpc.ssl_channel_credentials(cert) channel = grpc.secure_channel( config['lndrpchost'] + ':' + config['lndrpcport'], creds) stub = lnrpc.LightningStub(channel) # Simple test to query WalletBalance (There is probably a better test) if stub.WalletBalance(ln.WalletBalanceRequest(), metadata=[('macaroon', macaroon)]): logger.info( f'Connection to LND on {config["lndrpchost"]}:{config["lndrpcport"]} successful' ) return stub, macaroon
def __init__(self, rpc_port): self.port = rpc_port cred = grpc.ssl_channel_credentials(open('tls.cert', 'rb').read()) channel = grpc.secure_channel('localhost:{}'.format(rpc_port), cred) self.stub = lnrpc_grpc.LightningStub(channel)
import rpc_pb2 as ln, rpc_pb2_grpc as lnrpc import grpc from flask import Flask from flask_cors import CORS # Change this to the port your lightning node is running on: default 10009 LND_PORT = "10009" # Change this to the path to your tls.cert, but keep /home/<user> format, not ~ PATH_TO_TLS_CERT = '/home/valentine/.lnd/tls.cert' SERVER_PUBKEY = "03a2102f6978b9e5c6a2dd39697f95b36a7992a60ca65e0316dcd517108e8da171" SERVER_HOST = "52.53.90.150:9735" cert = open(PATH_TO_TLS_CERT).read() creds = grpc.ssl_channel_credentials(cert) channel = grpc.secure_channel('localhost:' + LND_PORT, creds) stub = lnrpc.LightningStub(channel) # Add server as peer. listpeers_req = ln.ListPeersRequest() listpeers_res = stub.ListPeers(listpeers_req) already_peers = False for peer in listpeers_res.peers: if peer.pub_key == SERVER_PUBKEY: already_peers = True if not already_peers: ln_addr = ln.LightningAddress(pubkey=SERVER_PUBKEY, host=SERVER_HOST) req = ln.ConnectPeerRequest(addr=ln_addr) res = stub.ConnectPeer(req) app = Flask(__name__) CORS(app)
def peerpage(): try: rpc_connect = AuthServiceProxy("http://{}:{}@{}:{}".format(rpc_user,rpc_password,allowed_ip,rpc_port)) chain_type = rpc_connect.getblockchaininfo()['chain'] if chain_type == "test": chaintype_ln = "testnet" else: chaintype_ln = "mainnet" os.environ["GRPC_SSL_CIPHER_SUITES"] = 'HIGH+ECDSA' with open(os.path.expanduser(lnd_dir_location + 'data/chain/bitcoin/{}/admin.macaroon'.format(chaintype_ln)), 'rb') as f: macaroon_bytes = f.read() macaroon = codecs.encode(macaroon_bytes, 'hex') cert = open(os.path.expanduser(lnd_dir_location + 'tls.cert'), 'rb').read() creds = grpc.ssl_channel_credentials(cert) channel = grpc.secure_channel('localhost:10009', creds) stub = lnrpc.LightningStub(channel) pbks = stub.ListChannels(ln.ListChannelsRequest(), metadata=[('macaroon', macaroon)]) pubkey_list = [str(i.remote_pubkey) for i in pbks.channels] response = stub.ListPeers(ln.ListPeersRequest(), metadata=[('macaroon', macaroon)]) show_current_peers = response.peers show_current_peers_list = [] for peer in show_current_peers: if peer.pub_key in pubkey_list: show_current_peers_list.append((str(peer.pub_key), True)) else: show_current_peers_list.append((str(peer.pub_key), False)) conn = True length_of = len(show_current_peers_list) except: show_current_peers_list = ["Offline!"] length_of = 0 conn = False pubkey_list = ["Offline!"] if conn == True: if request.method == 'POST': if request.form['action'] == "connectbutton": if len(request.form['text']) > 10: response_uri = str(request.form['text']) result = response_uri.strip() def connect(host, port, node_id): addr = ln.LightningAddress(pubkey=node_id, host="{}:{}".format(host, port)) req = ln.ConnectPeerRequest(addr=addr, perm=True) stub.ConnectPeer(ln.ConnectPeerRequest(addr=addr,perm=False), metadata=[('macaroon',macaroon)]) try: nodeid, lnhost, lnport = result[:66], result[67:-5], result[-4:] connect(lnhost,lnport,nodeid) show_current_peers_list.append((nodeid, False)) length_of = len(show_current_peers_list) result = "Successfully connected!" return render_template('peerpage.html', len=len(show_current_peers_list), show_current_peers=show_current_peers_list, length_of=length_of, result="SuccessCon", conn=conn) except: return render_template('peerpage.html', len=len(show_current_peers_list), show_current_peers=show_current_peers_list, length_of=length_of, result="FalseCon", conn=conn) else: return render_template('peerpage.html', len=len(show_current_peers_list), show_current_peers=show_current_peers_list, length_of=length_of, result="FalseCon", conn=conn) else: if len(request.form['text']) > 10: response_uri = str(request.form['text']) result = response_uri.strip() def disconnect(pubkey): req = ln.DisconnectPeerRequest(pub_key=pubkey) stub.DisconnectPeer(ln.DisconnectPeerRequest(pub_key=pubkey), metadata=[('macaroon',macaroon)]) try: disconnect(result) del show_current_peers_list[-1] length_of = len(show_current_peers_list) return render_template('peerpage.html', len=len(show_current_peers_list), show_current_peers=show_current_peers_list, length_of=length_of, result="SuccessDis", conn=conn) except: return render_template('peerpage.html', len=len(show_current_peers_list), show_current_peers=show_current_peers_list, length_of=length_of, result="FalseDis", conn=conn) else: return render_template('peerpage.html', len=len(show_current_peers_list), show_current_peers=show_current_peers_list, length_of=length_of, result="FalseDis", conn=conn) return render_template('peerpage.html', len=len(show_current_peers_list), length_of=length_of, show_current_peers=show_current_peers_list, conn=conn)
def main(): # sets up grpc connection to lnd channel = get_secure_channel() # note that the 'admin' macaroon already has the required # permissions for the walletkit request, so we don't need # that third macaroon. macaroon, signer_macaroon = get_macaroons(["admin", "signer"]) # the main stub allows access to the default rpc commands: stub = lnrpc.LightningStub(channel) # the signer stub allows us to access the rpc for signing # transactions on our coins: stub_signer = signrpc.SignerStub(channel) # we also need a stub for the walletkit rpc to extract # public keys for addresses holding coins: stub_walletkit = walletrpc.WalletKitStub(channel) # Here we start the process to sign a custom tx. # 1. List unspent coins, get most recent ones (just an example). # 2. Get the pubkeys of those addresses. # 3. Get the next unused address in the wallet as destination. # 4. Build a transaction, (in future: optionally taking extra # inputs and outputs from elsewhere). # 5. Use signOutputRaw rpc to sign the new transaction. # 6. Use the walletkit PublishTransaction to publish. # Just an example of retrieving basic info, not necessary: # Retrieve and display the wallet balance response = stub.WalletBalance(ln.WalletBalanceRequest(), metadata=[('macaroon', macaroon)]) print("Current on-chain wallet balance: ", response.total_balance) inputs = get_our_coins(stub, macaroon) + get_other_coins() for inp in inputs: # Attach auxiliary data needed to the inputs, for signing. # Get the public key of an address inp["pubkey"] = stub_walletkit.KeyForAddress( walletkit.KeyForAddressRequest(addr_in=inp["utxo"].address), metadata=[('macaroon', macaroon)]).raw_key_bytes # this data (known as scriptCode in BIP143 parlance) # is the pubkeyhash script for this p2wpkh, as is needed # to construct the signature hash. # **NOTE** This code currently works with bech32 only. # TODO update to allow p2sh-p2wpkh in wallet coins, also. inp["script"] = btc.pubkey_to_p2pkh_script(inp["pubkey"]) # We need an output address for the transaction, this is taken from the # standard wallet 'new address' request (type 0 is bech32 p2wpkh): request = ln.NewAddressRequest(type=0, ) response = stub.NewAddress(request, metadata=[('macaroon', macaroon)]) output_address = response.address print("Generated new address: ", output_address) # Build the raw unsigned transaction tx_ins = [] output_amt = 0 for inp in inputs: tx_ins.append(inp["utxo"].outpoint.txid_str + ":" + str(inp["utxo"].outpoint.output_index)) output_amt += inp["utxo"].amount_sat fee_est = estimate_tx_fee(2, 1, "p2wpkh", 6, stub, macaroon) output = {"address": output_address, "value": output_amt - fee_est} tx_unsigned = btc.mktx(tx_ins, [output], version=2) print(btc.deserialize(tx_unsigned)) # use SignOutputRaw to sign each input (currently, they are all ours). raw_sigs = {} for i, inp in enumerate(inputs): # KeyDescriptors must contain at least one of the pubkey and the HD path, # here we use the latter: kd = signer.KeyDescriptor(raw_key_bytes=inp["pubkey"]) # specify the utxo information for this input into a TxOut: sdout = signer.TxOut(value=inp["utxo"].amount_sat, pk_script=unhexlify(inp["utxo"].pk_script)) # we must pass a list of SignDescriptors; we could batch all into # one grpc call if we preferred. The witnessscript field is # constructed above as the "script" field in the input dict. sds = [ signer.SignDescriptor(key_desc=kd, input_index=i, output=sdout, witness_script=inp["script"], sighash=1) ] req = signer.SignReq(raw_tx_bytes=unhexlify(tx_unsigned), sign_descs=sds) # here we make the actual signing request to lnd over grpc: response = stub_signer.SignOutputRaw(req, metadata=[('macaroon', signer_macaroon)]) # note that btcwallet's sign function does not return the sighash byte, # it must be added manually: raw_sigs[i] = response.raw_sigs[0] + sighash_all_bytes # insert the signatures into the relevant inputs in the deserialized tx tx_unsigned_deser = btc.deserialize(tx_unsigned) for i in range(len(inputs)): tx_unsigned_deser["ins"][i]["txinwitness"] = [ btc.safe_hexlify(raw_sigs[i]), btc.safe_hexlify(inputs[i]["pubkey"]) ] print("Signed transaction: \n", tx_unsigned_deser) hextx = btc.serialize(tx_unsigned_deser) print("Serialized: ", hextx) print("You can broadcast this externally e.g. via Bitcoin Core")
def getStub(url): channel = grpc.secure_channel(url, creds) return lnrpc.LightningStub(channel)