bitcoind.py (5183B)
1 import json 2 import logging 3 import os 4 import qrcode 5 import time 6 7 import config 8 from utils import btc_amount_format 9 10 11 class btcd: 12 def __init__(self, node_config): 13 from bitcoinrpc.authproxy import AuthServiceProxy 14 self.config = node_config 15 16 if self.config['tor_bitcoinrpc_host'] is not None: 17 from gateways.tor import session 18 self.session = session 19 self.is_onchain = True 20 21 if self.config['rpc_cookie_file']: 22 if os.path.isfile(self.config['rpc_cookie_file']): 23 rpc_credentials_str = open(self.config['rpc_cookie_file'], "r").read() 24 (username, password) = rpc_credentials_str.split(":") 25 else: 26 raise Exception( 27 "rpc_cookie_file {} not found".format(self.config['rpc_cookie_file']) 28 ) 29 else: 30 username = self.config['username'] 31 password = self.config['password'] 32 33 for i in range(config.connection_attempts): 34 if self.config['tor_bitcoinrpc_host'] is None: 35 self.tor = False 36 connection_str = "http://{}:{}@{}:{}/wallet/{}".format( 37 username, 38 password, 39 self.config['host'], 40 self.config['rpcport'], 41 self.config['wallet'], 42 ) 43 logging.info( 44 "Attempting to connect to Bitcoin node RPC to {}:{} with user {}.".format( 45 self.config['host'], self.config['rpcport'], self.config['username'] 46 ) 47 ) 48 else: 49 self.tor = True 50 logging.info( 51 "Attempting to contact bitcoind rpc tor hidden service: {}:{}".format( 52 self.config['tor_bitcoinrpc_host'], self.config['rpcport'] 53 ) 54 ) 55 56 try: 57 # Normal Connection 58 if self.config['tor_bitcoinrpc_host'] is None: 59 self.rpc = AuthServiceProxy(connection_str) 60 info = self.rpc.getblockchaininfo() 61 # Tor Connection 62 else: 63 info = self.call_tor_bitcoin_rpc("getblockchaininfo", None) 64 65 logging.info(info) 66 logging.info("Successfully contacted bitcoind.") 67 break 68 69 except Exception as e: 70 logging.error(e) 71 if i < 5: 72 time.sleep(2) 73 else: 74 time.sleep(60) 75 logging.info( 76 "Attempting again... {}/{}...".format( 77 i + 1, config.connection_attempts 78 ) 79 ) 80 else: 81 raise Exception( 82 "Could not connect to bitcoind. \ 83 Check your RPC / port tunneling settings and try again." 84 ) 85 86 def call_tor_bitcoin_rpc(self, method, params): 87 url = "{}:{}".format(self.config['tor_bitcoinrpc_host'], config.rpcport) 88 payload = json.dumps({"method": method, "params": params}) 89 headers = {"content-type": "application/json", "cache-control": "no-cache"} 90 response = self.session.request( 91 "POST", 92 url, 93 data=payload, 94 headers=headers, 95 auth=(config.username, config.password), 96 ) 97 return json.loads(response.text) 98 99 def create_qr(self, uuid, address, value): 100 qr_str = "bitcoin:{}?amount={}&label={}".format( 101 address, btc_amount_format(value), uuid 102 ) 103 104 img = qrcode.make(qr_str) 105 img.save("static/qr_codes/{}.png".format(uuid)) 106 return 107 108 def check_payment(self, uuid): 109 if not self.tor: 110 transactions = self.rpc.listtransactions(uuid) 111 else: 112 transactions = self.call_tor_bitcoin_rpc("listtransactions", [uuid])["result"] 113 114 conf_paid = 0 115 unconf_paid = 0 116 for tx in transactions: 117 if tx["confirmations"] >= config.required_confirmations: 118 conf_paid += tx["amount"] 119 else: 120 unconf_paid += tx["amount"] 121 122 return conf_paid, unconf_paid 123 124 def get_address(self, amount, label, expiry): 125 for i in range(config.connection_attempts): 126 try: 127 if not self.tor: 128 address = self.rpc.getnewaddress(label) 129 else: 130 address = self.call_tor_bitcoin_rpc("getnewaddress", [label])["result"] 131 132 return address, None 133 134 except Exception as e: 135 logging.error(e) 136 if i < 5: 137 time.sleep(2) 138 else: 139 time.sleep(60) 140 logging.info( 141 "Attempting again... {}/{}...".format( 142 i + 1, config.connection_attempts 143 ) 144 ) 145 if config.connection_attempts - i == 1: 146 logging.info("Reconnecting...") 147 self.__init__() 148 return None