vib14

script.py

Aug 16th, 2018
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.46 KB | None | 0 0
  1. import os
  2. import sys
  3. import subprocess
  4. import parser
  5. import shutil
  6. import time
  7. import json
  8.  
  9. DEV_PATH = "/home/ubuntu/lightning_routing/dev"
  10. RPC_PORT_OFFSET = 10000
  11. PEER_PORT_OFFSET = 5000
  12. REST_PORT_OFFSET = 8000
  13.  
  14.  
  15. # start bitcoin daemon and directories
  16. def initial_setup(num_nodes):
  17.     # start bitcoin daemon
  18.     btcd = subprocess.Popen(["btcd", "--txindex", "--simnet","--rpcuser=kek", "--rpcpass=kek"])
  19.  
  20.     # create separate directories
  21.     for i in range(num_nodes):
  22.         if not os.path.exists(os.path.join(DEV_PATH, str(i))):
  23.             os.makedirs(os.path.join(DEV_PATH, str(i)))
  24.  
  25.  
  26.  
  27.  
  28. # delete derectories and kill all running processes
  29. def teardown(num_nodes):
  30.     for i in range(num_nodes):
  31.         shutil.rmtree(os.path.join(DEV_PATH, str(i)))
  32.  
  33.     # kill lnd, btcd
  34.     os.system("killall -9 btcd")
  35.     os.system("killall -9 lnd")
  36.  
  37.  
  38.  
  39. # set up the lnd daemons for every port
  40. def setup_lnd_daemons(num_nodes):
  41.     for i in range(num_nodes):
  42.         rpcport = RPC_PORT_OFFSET + i
  43.         listenport = PEER_PORT_OFFSET + i
  44.         restport= REST_PORT_OFFSET + i
  45.         working_dir = os.path.join(DEV_PATH, str(i))
  46.  
  47.         print rpcport, listenport
  48.  
  49.         subprocess.Popen(["lnd", "--rpclisten=localhost:" + str(rpcport),\
  50.             "--listen=localhost:" + str(listenport),\
  51.             "--restlisten=localhost:" + str(restport),\
  52.             "--datadir=data", "--logdir=log",\
  53.             "--debuglevel=info", "--bitcoin.simnet", "--bitcoin.active", \
  54.             "--bitcoin.node=btcd", "--btcd.rpcuser=kek", "--btcd.rpcpass=kek", \
  55.             "--noencryptwallet"], cwd=working_dir)
  56.  
  57.  
  58.  
  59. # set up the wallets for every client
  60. def setup_wallets(num_nodes):
  61.     for i in range(num_nodes):
  62.         rpcport = RPC_PORT_OFFSET + i
  63.         working_dir = os.path.join(DEV_PATH, str(i))
  64.  
  65.         p = subprocess.call(["lncli", "--rpcserver=localhost:" + str(rpcport), \
  66.                 "--macaroonpath=data/admin.macaroon", "create"], cwd=working_dir)
  67.  
  68.         if p != 0:
  69.             print "Error setting up wallet for node", i
  70.  
  71.  
  72.  
  73. # generate bitcoin addresses for each of the nodes
  74. def generate_btc_addresses(num_nodes):
  75.     address_list = []
  76.     for i in range(num_nodes):
  77.         rpcport = RPC_PORT_OFFSET + i
  78.         print rpcport
  79.         working_dir = os.path.join(DEV_PATH, str(i))
  80.  
  81.         addr_output = subprocess.check_output(["lncli", "--rpcserver=localhost:" + str(rpcport), \
  82.                         "--macaroonpath=data/admin.macaroon", "newaddress",\
  83.                         "np2wkh"], cwd=working_dir)
  84.  
  85.         json_output = json.loads(addr_output)
  86.         address = json_output["address"].strip('\"')
  87.         address_list.append(address)
  88.     return address_list
  89.  
  90.  
  91.  
  92. # find the public key for all of the lnd nodes
  93. # used to setup peer to peer network and to open channels
  94. def find_pub_keys(num_nodes):
  95.     pub_key_list = []
  96.     for i in range(num_nodes):
  97.         rpcport = RPC_PORT_OFFSET + i
  98.         print rpcport
  99.         working_dir = os.path.join(DEV_PATH, str(i))
  100.  
  101.         info_output = subprocess.check_output(["lncli", "--rpcserver=localhost:" + str(rpcport), \
  102.                         "--macaroonpath=data/admin.macaroon", "getinfo"],\
  103.                         cwd=working_dir)
  104.  
  105.         json_output = json.loads(info_output)
  106.         pub_key_list.append(json_output["identity_pubkey"].strip('\"'))
  107.     return pub_key_list
  108.  
  109.  
  110.  
  111. # set up peer to peer network for all nodes as per the adjacency matrix
  112. # only one direction needs to be set up, so we set it up for src < dest
  113. def setup_peer_to_peer_network(adj_matrix, pub_key_list):
  114.     for i, adj_nodes in adj_matrix.iteritems():
  115.         for j in adj_nodes:
  116.             if i < j:
  117.                 peer_port = PEER_PORT_OFFSET + j
  118.                 peer_pub_key = pub_key_list[j]
  119.  
  120.                 my_rpcport = RPC_PORT_OFFSET + i
  121.                 working_dir = os.path.join(DEV_PATH, str(i))
  122.                
  123.                 p = subprocess.call(["lncli", "--rpcserver=localhost:" + str(my_rpcport), \
  124.                     "--macaroonpath=data/admin.macaroon", "connect",\
  125.                     peer_pub_key + "@localhost:" + str(peer_port)], cwd=working_dir)
  126.                 if p != 0:
  127.                     print "Error in setting up link from ", i, " to ", j
  128.  
  129.  
  130.             peer_rpcport = RPC_PORT_OFFSET + j
  131.             peer_working_dir = os.path.join(DEV_PATH, str(j))
  132.  
  133.            
  134.             peer_op = subprocess.check_output(["lncli", "--rpcserver=localhost:" + str(peer_rpcport), \
  135.                 "--macaroonpath=data/admin.macaroon", "listpeers"], cwd=peer_working_dir)
  136.             print "list of channels", peer_op
  137.  
  138.  
  139.  
  140. # set up lightning network for all nodes as per the adjacency matrix
  141. # only one direction needs to be set up, so we set it up for src < dest
  142. # for every channel to become valid, we need to also generate 6 blocks each
  143. def setup_lightning_network(adj_matrix, pub_key_list, credit_amt_dict):
  144.     for i, adj_nodes in adj_matrix.iteritems():
  145.         for j in adj_nodes:
  146.             if i < j:
  147.                 credit = int(credit_amt_dict[(i, j)])
  148.                 peer_pub_key = pub_key_list[j]
  149.  
  150.                 my_rpcport = RPC_PORT_OFFSET + i
  151.                 working_dir = os.path.join(DEV_PATH, str(i))
  152.  
  153.                 wallet_bal = subprocess.check_output(["lncli", "--rpcserver=localhost:" + str(my_rpcport), \
  154.                     "--macaroonpath=data/admin.macaroon", "walletbalance"], cwd=working_dir)
  155.                 print "wallet balance for ", i, " is ", wallet_bal
  156.                 print " initiating channel from ", i, " to ", j, " with bal ", credit
  157.                
  158.                 # create a balanced channel so push half the amount to the other side
  159.                 p = subprocess.Popen(["lncli", "--rpcserver=localhost:" + str(my_rpcport), \
  160.                     "--macaroonpath=data/admin.macaroon", "openchannel",\
  161.                     "--node_key=" + peer_pub_key, "--local_amt=" + str(credit)], cwd=working_dir)
  162.                     #"--push_amt=" + str(credit/2)], cwd=working_dir)
  163.                 time.sleep(5)
  164.                 print p
  165.                 #if p != 0:
  166.                     #print "Error initiating channel from ", i, " to ", j
  167.  
  168.  
  169.  
  170.                 # generate 6 blocks
  171.                 p = subprocess.call(["btcctl", "--simnet", "--rpcuser=kek",\
  172.                         "--rpcpass=kek", "generate",  "10"])
  173.                 time.sleep(5)
  174.                 if p != 0:
  175.                     print "Error in generating blocks for channel confirmation from ", i, " to ", j
  176.  
  177.                 channel_op = subprocess.check_output(["lncli", "--rpcserver=localhost:" + str(my_rpcport), \
  178.                     "--macaroonpath=data/admin.macaroon", "pendingchannels"], cwd=working_dir)
  179.                 print "list of channels", channel_op
  180.  
  181.  
  182.  
  183. # fund the bitcoin addresses by turning on and off the btcd client
  184. # with each of them being the miner in turn
  185. def fund_btc_addresses(btc_address_list):
  186.  
  187.     os.system("killall -9 btcd")
  188.    
  189.     for i, address in enumerate(btc_address_list):
  190.         # kill current bitcoin client and restart with current address
  191.         # receiving mining rewards
  192.         os.system("killall -9 btcd")
  193.  
  194.         btcd = subprocess.Popen(["btcd", "--txindex", "--simnet","--rpcuser=kek", "--rpcpass=kek",\
  195.                 "--miningaddr=" + address])
  196.  
  197.         time.sleep(5)
  198.        
  199.         # generate enough blocks for funds
  200.         # TODO: edit this to make sure channel creation doesn't fail
  201.         p = subprocess.call(["btcctl", "--simnet", "--rpcuser=kek",\
  202.                 "--rpcpass=kek", "generate",  "400"])
  203.         if p != 0:
  204.             print "error mining blocks for address", address
  205.  
  206.         time.sleep(5)
  207.  
  208.     # make sure wallets are funded
  209.     for i, address in enumerate(btc_address_list):
  210.  
  211.         my_rpcport = RPC_PORT_OFFSET + i
  212.         working_dir = os.path.join(DEV_PATH, str(i))
  213.  
  214.  
  215.         wallet_bal = subprocess.check_output(["lncli", "--rpcserver=localhost:" + str(my_rpcport), \
  216.             "--macaroonpath=data/admin.macaroon", "walletbalance"], cwd=working_dir)
  217.         print "wallet balance for ", i, " is ", wallet_bal
  218.  
  219.  
  220.  
  221. # execute each transaction and decide if it was a success or a failure
  222. def execute_transactions(transaction_list):
  223.     success_num = 0.0
  224.     success_vol = 0.0
  225.     total_vol = 0.0
  226.     total_num = 0.0
  227.  
  228.     for src_dest, txn_size in transaction_list.iteritems():
  229.  
  230.         total_vol += txn_size
  231.         total_num += 1
  232.  
  233.         src = src_dest[0]
  234.         dst = src_dest[1]
  235.  
  236.         # generate invoice for payment
  237.         dst_rpcport = RPC_PORT_OFFSET + dst
  238.         dst_dir = os.path.join(DEV_PATH, str(dst))
  239.         invoice_output = subprocess.check_output(["lncli", "--rpcserver=localhost:" + str(dst_rpcport), \
  240.                         "--macaroonpath=data/admin.macaroon", "addinvoice", \
  241.                         "--amt=" + str(int(txn_size))], cwd=dst_dir)
  242.  
  243.         # parse the output to the get the encoded invoice
  244.         json_output = json.loads(invoice_output)
  245.         encoded_invoice = json_output["pay_req"].strip('\"')
  246.  
  247.         # now make a payment to that invoice
  248.         src_rpcport = RPC_PORT_OFFSET + src
  249.         src_dir = os.path.join(DEV_PATH, str(src))
  250.         payment_output = subprocess.check_output(["lncli", "--rpcserver=localhost:" + str(src_rpcport), \
  251.                         "--macaroonpath=data/admin.macaroon", "sendpayment", \
  252.                         "--pay_req=" + encoded_invoice], cwd=src_dir)
  253.  
  254.  
  255.         channel_info_output = subprocess.check_output(["lncli", "--rpcserver=localhost:" + str(src_rpcport), \
  256.                         "--macaroonpath=data/admin.macaroon", "listchannels"], cwd=src_dir)
  257.  
  258.         print channel_info_output
  259.  
  260.  
  261.  
  262.         # TODO: need to parse payment output to infer success/failure
  263.         print payment_output
  264.  
  265. def main():
  266.  
  267.     # parse topology to get number of nodes and edge links
  268.     adj_dict = {0: set([1]), 1: set([0])} #parser.parse_graph(sys.argv[1])
  269.     num_nodes = len(adj_dict)
  270.  
  271.     # read the credit amounts per link
  272.     credit_amt_dict = {(0,1): 20000} # parser.parse_credits(sys.argv[1] + "_CREDIT_LINKS")
  273.  
  274.     # parse the transactions
  275.     '''txn_srcdest_list, txn_size_list = parser.parse_transactions(sys.argv[2])
  276.    transactions = dict(zip(txn_srcdest_list, txn_size_list))'''
  277.  
  278.     try:
  279.         initial_setup(num_nodes)
  280.  
  281.         # create per node directories, run lnd in each of them
  282.         setup_lnd_daemons(num_nodes)
  283.         time.sleep(10)
  284.  
  285.         # setup wallets per node - not needed because they are unlocked by default
  286.         #setup_wallets(num_nodes)
  287.  
  288.         # generate bitcoin_addresses for the nodes
  289.         btc_address_list = generate_btc_addresses(num_nodes)
  290.         print "btc address list is", btc_address_list
  291.  
  292.         # fund each one of them according to necessary credit
  293.         # repeatedly turn on and off btcd which one mining
  294.         fund_btc_addresses(btc_address_list)
  295.  
  296.         # find public key for every node by parsing output
  297.         pub_key_list = find_pub_keys(num_nodes)
  298.         print(pub_key_list)
  299.  
  300.         # set up the underlying P2P network
  301.         setup_peer_to_peer_network(adj_dict, pub_key_list)
  302.  
  303.         time.sleep(10)
  304.  
  305.         # setup lighting network
  306.         # with the right capacities
  307.         setup_lightning_network(adj_dict, pub_key_list, credit_amt_dict)
  308.  
  309.         # execute transactions
  310.         '''execute_transactions(transactions)'''
  311.  
  312.     finally:
  313.         # close everything
  314.         teardown(num_nodes)
  315.         ()
  316.  
  317.  
  318. main()
Add Comment
Please, Sign In to add comment