def configure_droplet(id, servers=None): # presumably id was just popped from droplets_to_configure if servers is None: servers = get_servers() account = Account(droplet_to_uid[id]) logging.info('Configuring %s for %s' % (id, account.uid)) droplet = servers[id] logging.info('Got server %s' % repr(droplet)) ip = droplet['main_ip'] password = droplet['default_password'] droplet_ips[id] = ip # ssh try: print('root', password, ip) _, stdout, stderr = ssh(ip, 'root', password, create_install_command(account.name.get(), account.client.get(), account.branch.get(), gen_loc(account.dcid.get()))) except Exception as e: print(e) logging.error('could not configure server %s due to %s' % (id, repr(e))) return print(stdout.read(), stderr.read()) account.add_msg('Started compilation script on server %s -- can take hours as it also bootstraps the blockchain.' % id) logging.info('Configuring server %s' % id) account.compile_ts.set(int(time.time())) droplets_to_configure.remove(id) currently_compiling.add(id)
def process_tx_initial(tx_obj: Tx): found_relevant_address = False for out in tx_obj.txs_out: address = out.bitcoin_address() if address in all_addresses: found_relevant_address = True break if not found_relevant_address: logging.info('Found irrelevant tx %s' % hash_to_hex(tx_obj.hash())) return tx_hash = tx_obj.hash() txid = hash_to_hex(tx_hash).decode() if tx_hash in known_txs: return known_txs.add(tx_hash) txs[tx_hash] = tx_obj.as_hex() for out in tx_obj.txs_out: address = out.bitcoin_address() if address in all_addresses and address is not None: unprocessed_txs.add(tx_hash) uid = addr_to_uid[address] account = Account(uid) account.txs.add(tx_hash) account.unconf_minutes.incr(calc_node_minutes(satoshi_amount=out.coin_value, exchange_rate=exchange_rate.get())) account.add_msg('Found tx for %.08f, %s' % (out.coin_value / COIN, txid)) nodes_recently_updated.append(account.uid)
def process_next_creation(): if len(nodes_recently_updated) == 0: return next_uid = nodes_recently_updated.popleft() logging.info("Processing uid: %s" % next_uid) account = Account(next_uid) if not account.node_created.get(): if account.unconf_minutes.get() < MIN_TIME: account.add_msg('Node creation failed! A minimum of %d minutes need to be purchased at a time. You need %d more minutes.' % (MIN_TIME, MIN_TIME - account.unconf_minutes.get())) return if account.destroyed.get(): account.add_msg('Node creation failed as it has already been destroyed, please use a new account and contact [email protected] to get your coins back.') return account.add_msg('Creating server now. ETA 10-20 minutes.') dcid = random.choice([1, 5, 7]) # NJ, LA, Amsterdam try: res = requests.post("https://api.vultr.com/v1/server/create?api_key=%s" % vultr_api_key.get(), data={"DCID": dcid, "VPSPLANID": 87, "OSID": 192, "SSHKEYID": ssh_management_key.get(), "label": str(account.uid), "enable_private_network": 'yes', 'enable_ipv6 string': 'yes'}) except Exception as e: nodes_recently_updated.prepend(next_uid) logging.error('Attempted to create server / Exception: %s' % repr(e)) if res.status_code == 200: # accepted response = res.json() subid = response['SUBID'] logging.info(response) account.creation_ts.set(int(time.time())) account.droplet_id.set(subid) account.node_created.set(True) account.dcid.set(dcid) droplets_to_configure.add(subid, account.creation_ts.get()) droplet_to_uid[subid] = account.uid active_servers.add(subid) account.add_msg('Server created successfully! Server ID %s' % (account.droplet_id.get(),)) account.tweet_creation() node_creation_issues.set(False) else: logging.error('Server creation failed! Status %d' % res.status_code) if res.status_code == 412 and res.content == NODE_CREATION_LIMIT_MSG: node_creation_issues.set(True) logging.error(res.content) nodes_recently_updated.append(next_uid) account.add_msg('Server creation failed... will keep retrying') return 'CREATION_FAILED' # import pdb; pdb.set_trace() else: logging.warning('Account already has a node created.') print(account.node_created.get())
def check_compiling_node(id): account = Account(droplet_to_uid[id]) ip = droplet_ips[id].decode() s = socket.socket() try: s.connect((ip, 8333)) # VEEERRRRY simple except: # can't connect, check we're not way out in terms of time if int(time.time()) - account.compile_ts.get() > 60 * 180: # 60 min account.add_msg('Possible compile issue (taking >180 minutes). Restarting.') droplets_to_configure.add(id, 0) currently_compiling.remove(id) return s.close() account.add_msg('Node detected! Check at https://getaddr.bitnodes.io/nodes/%s-%d/' % (ip, 8333)) account.email_node_up(ip) logging.info('Detected node %s' % id) currently_compiling.remove(id) nodes_currently_syncing.add(id)
def check_server_for_expiration(id): account = Account(droplet_to_uid[id]) now = int(time.time()) creation_ts = account.creation_ts.get() paid_minutes = account.total_minutes.get() if (now) < (creation_ts + 6 * 60 * 60): # created in within the last 6 hours should be ignored to allow for unconf servers not being destroyed return if now > (creation_ts + paid_minutes * 60): # then destroy logging.warning('Destroying node %s' % id) res = requests.post("https://api.vultr.com/v1/server/destroy?api_key=%s" % vultr_api_key.get(), data={"SUBID": int(id)}) if res.status_code == 200: account.destroy() account.add_msg('Node lifetime consumed in total, node destroyed.') else: logging.error('Could not destroy server! %s' % id) account.add_msg('Attempted to destroy node (unpaid into future) but I failed :(') if account.destroyed.get(): active_servers.remove(id)
def check_unprocessed(top_height): for tx_hash in unprocessed_txs.members(): txid = hash_to_hex(tx_hash).decode() tx = Tx.tx_from_hex(txs[tx_hash].decode()) tx_blockchain = get_tx(txid) logging.info('Checking %s' % txid) if tx_blockchain.block_height == -1: continue if top_height - tx_blockchain.block_height + 1 >= REQUIRED_CONFIRMATIONS: # off by one error - if tx in top block that is 1 conf unprocessed_txs.remove(tx_hash) for out in tx.txs_out: address = out.bitcoin_address() if address not in all_addresses: continue account = Account(addr_to_uid[address]) satoshis = out.coin_value satoshis = int(satoshis / (1 + account.tip.get())) # scale for tip account.total_coins.incr(satoshis) node_minutes_d = calc_node_minutes(satoshis, exchange_rate=exchange_rate.get()) account.total_minutes.incr(node_minutes_d) total_nodeminutes.incr(node_minutes_d) nodes_recently_updated.append(account.uid) account.add_msg('Detected payment via txid: %s' % (txid,)) account.add_msg('Increased total paid by %.8f to %.8f (considering tip of %d %%)' % (satoshis / COIN, account.total_coins.get() / COIN, account.tip.get() * 100)) account.add_msg('Increased node life by %d minutes; expiring around %s' % (node_minutes_d, account.get_expiry().isoformat()))
time.sleep(10) # only do this at most once per block continue logging.info('Latest block: %s' % best_block_hash) for tx_hash in unprocessed_txs.members(): txid = hash_to_hex(tx_hash).decode() tx = Tx.tx_from_hex(txs[tx_hash].decode()) tx_blockchain = get_tx(txid) logging.info('Checking %s' % txid) if tx_blockchain.block_height == -1: continue if top_height - tx_blockchain.block_height + 1 >= REQUIRED_CONFIRMATIONS: # off by one error - if tx in top block that is 1 conf unprocessed_txs.remove(tx_hash) for out in tx.txs_out: address = out.bitcoin_address() if address not in all_addresses: continue account = Account(addr_to_uid[address]) satoshis = out.coin_value satoshis = int(satoshis / (1 + account.tip.get())) # scale for tip account.total_coins.incr(satoshis) node_minutes_d = calc_node_minutes(satoshis, exchange_rate=exchange_rate.get()) account.total_minutes.incr(node_minutes_d) total_nodeminutes.incr(node_minutes_d) nodes_recently_updated.append(account.uid) account.add_msg('Detected payment via txid: %s' % (txid,)) account.add_msg('Increased total paid by %.8f to %.8f (considering tip of %d %%)' % (satoshis / COIN, account.total_coins.get() / COIN, account.tip.get() * 100)) account.add_msg('Increased node life by %d minutes; expiring around %s' % (node_minutes_d, account.get_expiry().isoformat())) last_block_checked.set(best_block_hash) logging.info('Checked: %s' % best_block_hash)
if args.reconfigure_all_nodes: for id in active_servers: droplets_to_configure.add(id, 0) if args.restart_all_nodes: for id in active_servers: servers_to_restart.append(id) if args.show_last_n_msgs != 0: n = args.show_last_n_msgs for msg in all_msgs[:n]: print(msg) if args.msg_user_uid != '' and args.msg_content != '': account = Account(process_uid(args.msg_user_uid)) account.add_msg(args.msg_content) # if args.set_uid_total_minutes_to_zero != '': # account = Account(process_uid(args.set_uid_total_minutes_to_zero)) # if args.server_owner != '': account = Account(droplet_to_uid[args.server_owner]) print(account.pretty_string()) if args.twitter_consumer_key != '': twitter_consumer_key.set(args.twitter_consumer_key) if args.twitter_consumer_secret != '': twitter_consumer_secret.set(args.twitter_consumer_secret)
def handle(method, **params): response = {} real_uid = params['uid'] uid = process_uid(params['uid']) # not user chosen any longer account = Account(uid) fieldMap = { 'emailNotify': account.email_notify, 'email': account.email, 'name': account.name, 'client': account.client, 'tip': account.tip, 'branch': account.branch, } if method == 'getPaymentDetails': client = params['client'] months = max(0, int(params['months'])) tip = account.tip.get() amount = actually_charge(months, tip, exchange_rate.get()) # note: this URI cannot contain spaces as some wallets cannot read it. response['uri'] = "bitcoin:%s?amount=%.8f&label=nodeup.xk.io_sponsored_node_funding_address" % (account.address, amount) response['status'] = 'Payment received.' if account.unconf_minutes.get() > 0 else 'Waiting for payment...' elif method == '': pass elif method == 'saveField': field = params['field'] value = params['value'] if field == 'name' and len(value) > 140: value = value[:140] fieldMap[field].set(value) elif method == 'loadField': field = params['field'] response['field'] = field response['value'] = fieldMap[field].get() elif method == 'getMsgs': if 'n' in params: n = params['n'] else: n = 10 response['msgs'] = account.get_msgs(n) elif method == 'getStats': response['nodeMinutes'] = int(total_nodeminutes.get()) response['totalMinutesPaid'] = account.total_minutes.get() response['totalCoinsPaid'] = account.total_coins.get() response['exchangeRate'] = exchange_rate.get() response['activeNodes'] = len(active_servers) response['nodeCreationIssues'] = node_creation_issues.get() elif method == 'recompile': if account.node_created.get(): droplets_to_configure.add(account.droplet_id.get(), 0) account.add_msg('Queued node for recompilation.') response['recompile_queued'] = True else: response['recompile_queued'] = False elif method == 'sendNodeDetails': account.email_user('Node Details', NODE_DETAILS_EMAIL.format(uid=real_uid), force=True) return response