From 38c3c9c24a101d77ba7adc8f4e436fa93b577b7c Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Wed, 22 Jun 2022 11:10:28 +0000 Subject: [PATCH] Format code with yapf This commit fixes the style issues introduced in ed81e22 according to the output from yapf. Details: https://deepsource.io/gh/Frigyes06/ProtoPool/transform/e87d9223-6323-4333-9303-a770ff0b3ca1/ --- _main.py | 14 ++-- accountancy.py | 38 +++++++---- client.py | 4 +- log_module.py | 3 +- mining.py | 40 ++++++++---- params.py | 9 +-- restapi.py | 51 ++++++++++----- server.py | 104 ++++++++++++++++++++---------- sqlite_handler.py | 24 ++++--- stratum.py | 68 ++++++++++++++------ wallet_json_rpc.py | 157 ++++++++++++++++++++++++++++++++++++++------- 11 files changed, 375 insertions(+), 137 deletions(-) diff --git a/_main.py b/_main.py index b0f19c0..27d6269 100644 --- a/_main.py +++ b/_main.py @@ -9,6 +9,7 @@ from params import version from log_module import logger + #TODO # - rounding errors in balance calculation, example: from_account=1084190 # - wallet connection crashes sometimes after mining-submit @@ -17,6 +18,7 @@ class WalletNotFoundError(Exception): pass + def wallet_notify_watchdog(): if client.last_miner_notify_flag is False: try: @@ -25,10 +27,14 @@ def wallet_notify_watchdog(): logger.error("WALLET notify watchdog error: " + str(e)) pass client.last_miner_notify_flag = False - threading.Timer(client.last_miner_notify_timeout, wallet_notify_watchdog, []).start() + threading.Timer(client.last_miner_notify_timeout, wallet_notify_watchdog, + []).start() + -print("Starting MicroCoin mining pool by vegtamas. Pool version: " + str(version)) -logger.info("Starting MicroCoin mining pool by vegtamas. Pool version: " + str(version)) +print("Starting MicroCoin mining pool by vegtamas. Pool version: " + + str(version)) +logger.info("Starting MicroCoin mining pool by vegtamas. Pool version: " + + str(version)) while True: print("Waiting for wallet sync") @@ -43,7 +49,7 @@ def wallet_notify_watchdog(): thread_client = threading.Thread(target=client.client_handler) thread_client.start() -if(wallet_json_rpc.wallet_ok): +if (wallet_json_rpc.wallet_ok): server.start_diff_servers() #thread_mining_notify = threading.Thread(target=server.send_mining_notify_to_all) diff --git a/accountancy.py b/accountancy.py index 4aef776..3699494 100644 --- a/accountancy.py +++ b/accountancy.py @@ -11,6 +11,7 @@ account_fees = {} current_block = 0 + class Payment_batch(): """ Payment batch class: @@ -39,7 +40,7 @@ def new_block_accountancy(): if not sqlite_handler.db.is_block_in_db_already(current_block): calc_shares() - calc_share_rates(current_block, current_block*5) + calc_share_rates(current_block, current_block * 5) def calc_shares(): @@ -67,16 +68,20 @@ def calc_share_rates(last_block, from_account): mining.shares_of_current_block = 0 new_payment_batch.add_payment(pool_account, 0) - new_payment_batch_text = "New payment batch: block: " + str(new_payment_batch.block) + ", from account: " + str( - new_payment_batch.from_account) + '\n' + new_payment_batch_text = "New payment batch: block: " + str( + new_payment_batch.block) + ", from account: " + str( + new_payment_batch.from_account) + '\n' for payment in new_payment_batch.payments: - text = "To: " + str(payment) + ", " + str(new_payment_batch.payments[payment]) + '\n' + text = "To: " + str(payment) + ", " + str( + new_payment_batch.payments[payment]) + '\n' new_payment_batch_text = new_payment_batch_text + text new_payment_batch_text += '\n' for payment in new_payment_batch.payments: try: - sqlite_handler.db.add_payment_to_DB(last_block, from_account, payment, new_payment_batch.payments[payment]) + sqlite_handler.db.add_payment_to_DB( + last_block, from_account, payment, + new_payment_batch.payments[payment]) except Exception as e: logger.error("SQlite error at calc_share_rates: " + str(e)) print("SQlite error") @@ -95,20 +100,25 @@ def set_amounts(block): if payment[3] == pool_account: continue if payment[3] not in account_fees: - account_fees[payment[3]] = pool_fee # if there was a restart after account goes offline, there is no fee data + account_fees[payment[ + 3]] = pool_fee # if there was a restart after account goes offline, there is no fee data from_account = payment[2] to_account = payment[3] - amount = round((payment[8] * block_reward * (1 - (account_fees[payment[3]] / 100)) - payment_fee - payment_fee_to_pool), payment_prec) + amount = round((payment[8] * block_reward * + (1 - (account_fees[payment[3]] / 100)) - payment_fee - + payment_fee_to_pool), payment_prec) if amount > payment_fee: - sqlite_handler.db.set_amount_for_payment(payment[1], payment[2], payment[3], amount) + sqlite_handler.db.set_amount_for_payment(payment[1], payment[2], + payment[3], amount) spent += amount + payment_fee else: sqlite_handler.db.remove_payment_from_DB(from_account, to_account) amount = round(block_reward - spent - payment_fee, payment_prec) if amount > payment_fee: - sqlite_handler.db.set_amount_for_payment(block, from_account, pool_account, amount) + sqlite_handler.db.set_amount_for_payment(block, from_account, + pool_account, amount) else: sqlite_handler.db.remove_payment_from_DB(from_account, pool_account) @@ -135,8 +145,10 @@ def payment_processor(): if retval: sqlite_handler.db.set_block_to_acked_by_wallet(block[1]) set_amounts(block[1]) - elif block[1] < current_block - orphan_age_limit: # check if the block is orphan - sqlite_handler.db.set_block_to_orphan(block[1]) # set to orphan in db + elif block[ + 1] < current_block - orphan_age_limit: # check if the block is orphan + sqlite_handler.db.set_block_to_orphan( + block[1]) # set to orphan in db print("Block %d marked as orphan" % block[1]) result = sqlite_handler.db.get_unconfirmed_blocks() @@ -165,7 +177,7 @@ def payment_processor(): try: wallet_json_rpc.send_payment(row[2], row[3], row[4], row[1]) except wallet_json_rpc.WalletPubKeyError: - if row[1] < current_block - orphan_age_limit: # block is orphan + if row[1] < current_block - orphan_age_limit: # block is orphan sqlite_handler.db.set_block_to_orphan(row[1]) except wallet_json_rpc.WalletCommError: return False @@ -173,7 +185,7 @@ def payment_processor(): # TODO handle invalid target account. But if it's validated on auth, then no need for that. logger.info("Invalid target account: " + str(row[3])) except wallet_json_rpc.WalletInvalidOperationError: - pass # TODO it's probably a balance issue which occurs rarely. Sometimes payouts fails and rewards are sent twice for an account and there is no money left for the rest. + pass # TODO it's probably a balance issue which occurs rarely. Sometimes payouts fails and rewards are sent twice for an account and there is no money left for the rest. else: sqlite_handler.db.set_payment_to_paid(row[1], row[2], row[3]) diff --git a/client.py b/client.py index 1eac517..f0dfff8 100644 --- a/client.py +++ b/client.py @@ -71,7 +71,9 @@ def client_handler(): last_miner_notify_flag = True if "result" in msg and "pow" in msg["result"]: - print("NEW BLOCK FOUND!! YEEEE NEW BLOCK FOUND!! YEEEE NEW BLOCK FOUND!! YEEEE NEW BLOCK FOUND!! YEEEE NEW BLOCK FOUND!! YEEEE") + print( + "NEW BLOCK FOUND!! YEEEE NEW BLOCK FOUND!! YEEEE NEW BLOCK FOUND!! YEEEE NEW BLOCK FOUND!! YEEEE NEW BLOCK FOUND!! YEEEE" + ) accountancy.new_block_accountancy() diff --git a/log_module.py b/log_module.py index 2fc5f6b..16ea378 100644 --- a/log_module.py +++ b/log_module.py @@ -1,7 +1,8 @@ import logging logger = logging.getLogger("protopool") -hdlr = logging.handlers.TimedRotatingFileHandler('./protopool.log', when='midnight') +hdlr = logging.handlers.TimedRotatingFileHandler('./protopool.log', + when='midnight') formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') hdlr.setFormatter(formatter) logger.addHandler(hdlr) diff --git a/mining.py b/mining.py index c9c4aa7..64b4197 100644 --- a/mining.py +++ b/mining.py @@ -5,16 +5,19 @@ shares_of_current_block = 0 -miners = {} # "account": number_of_shares -shares = {} # dict of pplns_shares objects, every account has an element + pool has one +miners = {} # "account": number_of_shares +shares = { +} # dict of pplns_shares objects, every account has an element + pool has one # TODO miner object for every miner/account, # collect every miner related function to that # TODO future feature: collect shares worker-by-worker for detailed stat -hr_shares = {} # shares log for hashrate calculation for each account; example = {"1111":{"1":[timestamp1, timestamp2, timestamp3, ...], "32":[timestamp1, timestamp2, timestamp3, ..]}} -hr_avrg_shares = 30 # number of shares to calculated average hashrate +hr_shares = { +} # shares log for hashrate calculation for each account; example = {"1111":{"1":[timestamp1, timestamp2, timestamp3, ...], "32":[timestamp1, timestamp2, timestamp3, ..]}} +hr_avrg_shares = 30 # number of shares to calculated average hashrate + +share_timeout = 240 # shares older than this will be deleted -share_timeout = 240 # shares older than this will be deleted class miner_conn(): """Miner connection class. Stores a miner with all of it's details""" @@ -24,19 +27,25 @@ def __init__(self, connection, address): self.addr = address self.timestamps = {} self.account = "" + def set_account(self, account): self.account = account + def add_share(self, timestamp, difficulty): self.timestamps[timestamp] = difficulty + miner_conns = [] + def print_stat(): """Prints pool statistics every minute""" global shares_of_current_block, miner_conns - print("Number of connected miners: " + str(len(miner_conns)) + " Running threads: " + str(threading.active_count())) + print("Number of connected miners: " + str(len(miner_conns)) + + " Running threads: " + str(threading.active_count())) threading.Timer(60, print_stat).start() + def add_share_for_hr_calc(account, difficulty): """Adds shares to global list of hr_shares for hashrate calculation""" global hr_shares @@ -59,6 +68,7 @@ def add_share_for_hr_calc(account, difficulty): hr_shares[account][difficulty].append(time.time()) + def get_hr(account): """ Get hashrate for an account. @@ -70,19 +80,21 @@ def get_hr(account): global hr_shares - account = str(account) # using account as str + account = str(account) # using account as str if account not in hr_shares: return 0 diffs = [] - for diff in server.get_server_diffs(): # using diffs as str + for diff in server.get_server_diffs(): # using diffs as str diffs.append(str(diff)) - hrs = [] # hashrate for every difficulty, then sum them for account hashrate + hrs = [ + ] # hashrate for every difficulty, then sum them for account hashrate for diff in diffs: - if len(hr_shares[account][diff]) < 2: # can't calculate from 0 or 1 shares + if len(hr_shares[account] + [diff]) < 2: # can't calculate from 0 or 1 shares continue # delete old shares @@ -93,13 +105,15 @@ def get_hr(account): new_timestamps.append(ts) hr_shares[account][diff] = new_timestamps - if len(hr_shares[account][diff]) < 2: # can't calculate from 0 or 1 shares + if len(hr_shares[account] + [diff]) < 2: # can't calculate from 0 or 1 shares continue # get average share time last_share = hr_shares[account][diff][-1] first_share = hr_shares[account][diff][0] - avrg_time = (last_share - first_share) / (len(hr_shares[account][diff]) - 1) + avrg_time = (last_share - + first_share) / (len(hr_shares[account][diff]) - 1) new_hr = float(diff) * 2**32 / avrg_time hrs.append(new_hr) @@ -108,6 +122,7 @@ def get_hr(account): sum_hr += hr return sum_hr + def get_pool_hr(): """Gets pool hashrate by adding up individual hashrates""" global hr_shares @@ -118,6 +133,7 @@ def get_pool_hr(): return pool_hr + def No_miners(): """Returns the number of active miner connections""" return len(miner_conns) diff --git a/params.py b/params.py index e5ef205..bd3d617 100644 --- a/params.py +++ b/params.py @@ -7,11 +7,12 @@ version = 2.0 # user config -payment_fee_to_pool = config_data["payment_fee_to_pool"] # this fee will be sent to pool address in order to prevent tx errors occured by rounding +payment_fee_to_pool = config_data[ + "payment_fee_to_pool"] # this fee will be sent to pool address in order to prevent tx errors occured by rounding pool_fee = config_data["pool_fee"] pool_account = config_data["pool_account"] payment_fee = config_data["payment_fee"] -pplns_interval = config_data["pplns_interval"] # in secs +pplns_interval = config_data["pplns_interval"] # in secs wallet_jsonrpc_ip = config_data["wallet_jsonrpc_ip"] wallet_jsonrpc_port = config_data["wallet_jsonrpc_port"] @@ -21,6 +22,6 @@ main_db_file = config_data["main_db_file"] # other configs -orphan_age_limit = 20 # after how many blocks should the pool mark a block as orphan +orphan_age_limit = 20 # after how many blocks should the pool mark a block as orphan payment_prec = 4 -maturation_time = 10 # in blocks +maturation_time = 10 # in blocks diff --git a/restapi.py b/restapi.py index 487fc2f..651728c 100644 --- a/restapi.py +++ b/restapi.py @@ -48,48 +48,69 @@ def transfer_account_handler(new_pubkey): last_account_transferred_block = current_block return acc_number + @app.route('/pool_data', methods=['GET']) def get_pool_data(): network_height = wallet_json_rpc.get_current_block() pool_data = { "current_block": str(network_height), - "net_hashrate": str(wallet_json_rpc.get_net_hashrate(network_height)) + " Gh", + "net_hashrate": + str(wallet_json_rpc.get_net_hashrate(network_height)) + " Gh", "algorithm": "Pascal", "poolhash": str(round(mining.get_pool_hr() / 10**9, 2)) + " Gh", - "nethash": 0, - "workers": str(mining.No_miners()), - "fee": str(pool_fee) + "%", - "period": "Every block" + "nethash": 0, + "workers": str(mining.No_miners()), + "fee": str(pool_fee) + "%", + "period": "Every block" } return jsonify({'pool_data': pool_data}) + @app.route('/miner_data/', methods=['GET']) def get_miner_data(account): miner_data = { "account": str(account), "hashrate": str(round(mining.get_hr(account) / 10**9, 3)) + " Gh", - "1hour": 0, - "24hours": 0, - "average_mined": 0, - "payments": sqlite_handler.db.get_account_payments(account) + "1hour": 0, + "24hours": 0, + "average_mined": 0, + "payments": sqlite_handler.db.get_account_payments(account) } return jsonify({'miner_data': miner_data}) + @app.route('/get_account', methods=['POST']) def get_account(): pubkey = request.get_json(force=True)['pubkey'] try: acc_number = transfer_account_handler(pubkey) except wallet_json_rpc.WalletCommError: - return jsonify({'result': 'An error occured on the pool side. Please try again. If you see this message multiple times please report it to the team on Discord or Telegram. Thank you!'}) + return jsonify({ + 'result': + 'An error occured on the pool side. Please try again. If you see this message multiple times please report it to the team on Discord or Telegram. Thank you!' + }) except BePatientError: - return jsonify({'result': 'An account was already sent to someone in this block. Please try again in a few minutes. If you see this message multiple times please report it to the team on Discord or Telegram. Thank you!'}) + return jsonify({ + 'result': + 'An account was already sent to someone in this block. Please try again in a few minutes. If you see this message multiple times please report it to the team on Discord or Telegram. Thank you!' + }) except wallet_json_rpc.NoEmptyAccountError: - return jsonify({'result': 'No free account is left on the pool. Please try again in a few minutes. If you see this message multiple times please report it to the team on Discord or Telegram. Thank you!'}) + return jsonify({ + 'result': + 'No free account is left on the pool. Please try again in a few minutes. If you see this message multiple times please report it to the team on Discord or Telegram. Thank you!' + }) except wallet_json_rpc.InputParameterError: - return jsonify({'result': 'Wrong public key! You can export your public key from the wallet. It has to start with "3G". If you see this message multiple times please report it to the team on Discord or Telegram. Thank you!'}) + return jsonify({ + 'result': + 'Wrong public key! You can export your public key from the wallet. It has to start with "3G". If you see this message multiple times please report it to the team on Discord or Telegram. Thank you!' + }) + + return jsonify({ + 'result': + 'Account ' + str(acc_number) + + ' was successfully sent to your public key. You will see it in the next block in appr. 5 minutes.' + }) - return jsonify({'result': 'Account ' + str(acc_number) + ' was successfully sent to your public key. You will see it in the next block in appr. 5 minutes.'}) def start_restapi(): - app.run(debug=False, port = 3000) + app.run(debug=False, port=3000) diff --git a/server.py b/server.py index aeeb436..5cbac1f 100644 --- a/server.py +++ b/server.py @@ -11,37 +11,49 @@ import accountancy host = '' -diffs = [1,32] -diff_ports = [3333,3334] +diffs = [1, 32] +diff_ports = [3333, 3334] max_conn = 200 + def get_server_diffs(): return diffs + def send_mining_notify_to_all(): for miner in mining.miner_conns[:]: - thread = threading.Thread(target=stratum.send_mining_notify,args=(miner, 'null')) + thread = threading.Thread(target=stratum.send_mining_notify, + args=(miner, 'null')) thread.start() + def calc_block_pow(part1, payload, part3, timestamp, nonce): - part1_raw = binascii.unhexlify(part1) - payload_raw = binascii.unhexlify(payload) - part3_raw = binascii.unhexlify(part3) - - new_timestamp = timestamp[6:] + timestamp[4:6] + timestamp[2:4] + timestamp[0:2] - new_timestamp_raw = binascii.unhexlify(new_timestamp) - new_nonce= nonce[6:] + nonce[4:6] + nonce[2:4] + nonce[0:2] - new_nonce_raw = binascii.unhexlify(new_nonce) - to_hash = part1_raw + payload_raw + part3_raw + new_timestamp_raw + new_nonce_raw - d = hashlib.sha256(to_hash) - d2 = hashlib.sha256() - d2.update(d.digest()) - return int(d2.hexdigest(),16) + part1_raw = binascii.unhexlify(part1) + payload_raw = binascii.unhexlify(payload) + part3_raw = binascii.unhexlify(part3) + + new_timestamp = timestamp[6:] + timestamp[4:6] + timestamp[ + 2:4] + timestamp[0:2] + new_timestamp_raw = binascii.unhexlify(new_timestamp) + new_nonce = nonce[6:] + nonce[4:6] + nonce[2:4] + nonce[0:2] + new_nonce_raw = binascii.unhexlify(new_nonce) + to_hash = part1_raw + payload_raw + part3_raw + new_timestamp_raw + new_nonce_raw + d = hashlib.sha256(to_hash) + d2 = hashlib.sha256() + d2.update(d.digest()) + return int(d2.hexdigest(), 16) + def get_block_pow(payload, timestamp, nonce): - pow1 = calc_block_pow(client.last_miner_notify[1]["params"][0]["part1"], payload, client.last_miner_notify[1]["params"][0]["part3"], timestamp, nonce) + pow1 = calc_block_pow(client.last_miner_notify[1]["params"][0]["part1"], + payload, + client.last_miner_notify[1]["params"][0]["part3"], + timestamp, nonce) if client.last_miner_notify_buf_full: - pow2 = calc_block_pow(client.last_miner_notify[0]["params"][0]["part1"], payload, client.last_miner_notify[0]["params"][0]["part3"], timestamp, nonce) + pow2 = calc_block_pow( + client.last_miner_notify[0]["params"][0]["part1"], payload, + client.last_miner_notify[0]["params"][0]["part3"], timestamp, + nonce) else: return pow1 @@ -49,16 +61,19 @@ def get_block_pow(payload, timestamp, nonce): return pow2 return pow1 + def calc_diff_from_target(target): maximum_target = 0x00000000FFFF0000000000000000000000000000000000000000000000000000 difficulty = maximum_target / target return difficulty + def close_miner_conn(miner): if miner in mining.miner_conns: mining.miner_conns.remove(miner) miner.conn.close() + def connection_handler(conn, addr, difficulty): account = 0 extranonce = 0 @@ -71,7 +86,8 @@ def connection_handler(conn, addr, difficulty): try: buf = new_miner.conn.recv(4096) except: - print("Miner disconnected from " + new_miner.addr[0] + ':' + str(new_miner.addr[1])) + print("Miner disconnected from " + new_miner.addr[0] + ':' + + str(new_miner.addr[1])) try: close_miner_conn(new_miner) except: @@ -96,7 +112,8 @@ def connection_handler(conn, addr, difficulty): if "method" not in msg: continue if msg["method"] == "mining.subscribe": - extranonce = stratum.send_subscribe_ack(new_miner, msg["id"]) + extranonce = stratum.send_subscribe_ack( + new_miner, msg["id"]) stratum.send_difficulty(new_miner, difficulty, msg["id"]) stratum.send_mining_notify(new_miner, msg["id"]) @@ -105,44 +122,57 @@ def connection_handler(conn, addr, difficulty): #TODO check if account is a valid account number! account = int(((msg["params"][0]).split('-'))[0]) try: - accountancy.account_fees[account] = int(msg["params"][1]) + accountancy.account_fees[account] = int( + msg["params"][1]) except: - accountancy.account_fees[account] = accountancy.pool_fee - if accountancy.account_fees[account] < accountancy.pool_fee or accountancy.account_fees[account] > 100: - accountancy.account_fees[account] = accountancy.pool_fee + accountancy.account_fees[ + account] = accountancy.pool_fee + if accountancy.account_fees[ + account] < accountancy.pool_fee or accountancy.account_fees[ + account] > 100: + accountancy.account_fees[ + account] = accountancy.pool_fee except: print("Wrong account name") stratum.send_auth_error(new_miner, msg["id"]) new_miner.conn.close() - break #TODO send error msg + break #TODO send error msg new_miner.set_account(account) mining.miner_conns.append(new_miner) if account not in mining.miners: mining.shares[account] = new_miner - mining.miners[account] = 0 #set shares to 0 for that account - stratum.send_auth_ack(new_miner,msg["id"]) + mining.miners[ + account] = 0 #set shares to 0 for that account + stratum.send_auth_ack(new_miner, msg["id"]) elif msg["method"] == "mining.submit": payload = extranonce + msg["params"][2] - if last_payload == payload and last_timestamp == msg["params"][3] and last_nonce == msg["params"][4]: + if last_payload == payload and last_timestamp == msg[ + "params"][3] and last_nonce == msg["params"][4]: stratum.send_submit_error(new_miner, msg["id"]) #print("Share rejected because of duplication from: " + new_miner.addr[0]) else: - block_pow = get_block_pow(payload, msg["params"][3], msg["params"][4]) - target_pow = int(client.last_miner_notify[client.last_miner_notify_cnt]["params"][0]["target_pow"], 16) + block_pow = get_block_pow(payload, msg["params"][3], + msg["params"][4]) + target_pow = int( + client.last_miner_notify[ + client.last_miner_notify_cnt]["params"][0] + ["target_pow"], 16) #print(calc_diff_from_target(block_pow)) if calc_diff_from_target(block_pow) >= difficulty: stratum.send_submit_ack(new_miner, msg["id"]) timestamp = time.time() - mining.shares[account].add_share(timestamp, difficulty) + mining.shares[account].add_share( + timestamp, difficulty) mining.add_share_for_hr_calc(account, difficulty) #print("Share accepted from: " + new_miner.addr[0]) else: stratum.send_submit_error(new_miner, msg["id"]) #print("Share rejected from: " + new_miner.addr[0]) if block_pow <= target_pow: - print("Block found with this share from: " + new_miner.addr[0]) + print("Block found with this share from: " + + new_miner.addr[0]) client.mining_submit_handler(msg, extranonce) last_payload = payload last_timestamp = msg["params"][3] @@ -152,19 +182,23 @@ def connection_handler(conn, addr, difficulty): else: close_miner_conn(new_miner) + def server_handler(diff, diff_port): server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - server.bind((host,diff_port)) + server.bind((host, diff_port)) server.listen(max_conn) print("Server started, diff: " + str(diff) + ", port: " + str(diff_port)) while True: conn, addr = server.accept() print("Miner connected from: " + addr[0] + ':' + str(addr[1])) - thread = threading.Thread(target=connection_handler, args=(conn,addr,diff)) + thread = threading.Thread(target=connection_handler, + args=(conn, addr, diff)) thread.start() + def start_diff_servers(): global diffs, diff_ports for i in range(len(diffs)): - thread_server = threading.Thread(target=server_handler, args=(diffs[i],diff_ports[i])) + thread_server = threading.Thread(target=server_handler, + args=(diffs[i], diff_ports[i])) thread_server.start() diff --git a/sqlite_handler.py b/sqlite_handler.py index 00e35a8..9d4414a 100644 --- a/sqlite_handler.py +++ b/sqlite_handler.py @@ -4,7 +4,9 @@ from params import main_db_file + class Database: + def __init__(self, db_file): sql_create_payments_table = """ CREATE TABLE IF NOT EXISTS payments ( timestamp INTEGER NOT NULL, @@ -40,9 +42,11 @@ def wait_and_lock_busy(self): def unlock_busy(self): self.busy = False - def add_payment_to_DB(self, reward_block, from_account, to_account, share_rate): + def add_payment_to_DB(self, reward_block, from_account, to_account, + share_rate): sql = "INSERT INTO payments (timestamp, reward_block, from_account, to_account, amount, paid, acked_by_wallet, confirmed, share_rate, orphan) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" - payment = (int(time.time()), reward_block, from_account, to_account, 0, 0, 0, 0, share_rate, 0) + payment = (int(time.time()), reward_block, from_account, to_account, 0, + 0, 0, 0, share_rate, 0) self.wait_and_lock_busy() @@ -55,7 +59,8 @@ def add_payment_to_DB(self, reward_block, from_account, to_account, share_rate): self.unlock_busy() - def set_amount_for_payment(self, reward_block, from_account, to_account, new_amount): + def set_amount_for_payment(self, reward_block, from_account, to_account, + new_amount): sql = "UPDATE payments SET amount = ? WHERE reward_block = ? AND from_account = ? AND to_account = ?" payment = (new_amount, reward_block, from_account, to_account) @@ -91,7 +96,7 @@ def set_block_to_acked_by_wallet(self, reward_block): self.wait_and_lock_busy() c = self.conn.cursor() - c.execute(sql, (reward_block,)) + c.execute(sql, (reward_block, )) try: self.conn.commit() except sqlite3.DatabaseError: @@ -105,7 +110,7 @@ def set_block_confirmed(self, reward_block): self.wait_and_lock_busy() c = self.conn.cursor() - c.execute(sql, (reward_block,)) + c.execute(sql, (reward_block, )) try: self.conn.commit() except sqlite3.DatabaseError: @@ -119,7 +124,7 @@ def set_block_to_orphan(self, block): self.wait_and_lock_busy() c = self.conn.cursor() - c.execute(sql, (block,)) + c.execute(sql, (block, )) try: self.conn.commit() except sqlite3.DatabaseError: @@ -158,7 +163,7 @@ def remove_payment_from_DB(self, from_account, to_account): def get_payments_of_block(self, block): sql = "SELECT * FROM payments WHERE reward_block = ?" - payment = (block,) + payment = (block, ) self.wait_and_lock_busy() @@ -212,7 +217,7 @@ def get_unpaid_payments(self): def get_account_payments(self, account): sql = "SELECT timestamp, reward_block, from_account, amount, paid, orphan FROM payments WHERE to_account = ? ORDER BY reward_block DESC LIMIT 100" - params = (account,) + params = (account, ) self.wait_and_lock_busy() @@ -230,7 +235,7 @@ def is_block_in_db_already(self, block): self.wait_and_lock_busy() c = self.conn.cursor() - c.execute(sql, (block,)) + c.execute(sql, (block, )) result = c.fetchall() @@ -238,4 +243,5 @@ def is_block_in_db_already(self, block): return bool(len(result)) + db = Database(main_db_file) diff --git a/stratum.py b/stratum.py index feac6f7..cda9a22 100644 --- a/stratum.py +++ b/stratum.py @@ -8,15 +8,18 @@ unique_miner_id_cnt = 1 needed_extranonce_size = 26 + def send_tcp_msg(miner, msg): try: #print("Sending to " + addr[0] + ':' + str(addr[1]) + ': ' + msg) miner.conn.sendall(msg.encode()) except Exception as e: - logger.error("Sending failed to " + miner.addr[0] + ':' + str(miner.addr[1]) + " error: " + str(e)) + logger.error("Sending failed to " + miner.addr[0] + ':' + + str(miner.addr[1]) + " error: " + str(e)) print("Sending failed to " + miner.addr[0] + ':' + str(miner.addr[1])) server.close_miner_conn(miner) + def send_stratum_msg(miner, id, method, params): if id == 'null': @@ -37,7 +40,8 @@ def send_stratum_msg(miner, id, method, params): msg = msg + params[8] msg = msg + ']}\n' - send_tcp_msg(miner,msg) + send_tcp_msg(miner, msg) + def send_subscribe_ack(miner, id): global extranonce2_size, unique_miner_id_cnt, needed_extranonce_size @@ -48,53 +52,77 @@ def send_subscribe_ack(miner, id): char = val_str[i] hex_text = hex_text + str(hex(int(char) + 48)[2:]) - extranonce = client.last_miner_notify[client.last_miner_notify_cnt]["params"][0]["payload_start"] + hex_text + extranonce = client.last_miner_notify[ + client.last_miner_notify_cnt]["params"][0]["payload_start"] + hex_text - add_zeros = needed_extranonce_size - int(len(extranonce)/2) + add_zeros = needed_extranonce_size - int(len(extranonce) / 2) for i in range(add_zeros): extranonce = extranonce + '30' unique_miner_id_cnt += 1 - msg = '{"id":' + str(id) + ', "error": null, "result": [[["mining.notify", "00000000000000000000000000000000"]],"' + extranonce + '",' + str(extranonce2_size) + ']}\n' + msg = '{"id":' + str( + id + ) + ', "error": null, "result": [[["mining.notify", "00000000000000000000000000000000"]],"' + extranonce + '",' + str( + extranonce2_size) + ']}\n' send_tcp_msg(miner, msg) return extranonce + def send_difficulty(miner, difficulty, id): - msg = '{"id":' + str(id) + ', "method": "mining.set_difficulty", "params": [' + str(difficulty) + ']}\n' + msg = '{"id":' + str( + id) + ', "method": "mining.set_difficulty", "params": [' + str( + difficulty) + ']}\n' send_tcp_msg(miner, msg) -def send_auth_ack(miner,id): + +def send_auth_ack(miner, id): msg = '{"id":' + str(id) + ', "result": true, "error": null}\n' - send_tcp_msg(miner,msg) + send_tcp_msg(miner, msg) + def send_auth_error(miner, id): - error = '{"id":' + str(id) + ', "result": null, "error": [20, "Wrong username!", null]}' - msg = '{"id":' + str(id) + ', "result": null, "error":' + str(error) + '}\n' + error = '{"id":' + str( + id) + ', "result": null, "error": [20, "Wrong username!", null]}' + msg = '{"id":' + str(id) + ', "result": null, "error":' + str( + error) + '}\n' send_tcp_msg(miner, msg) -def send_submit_ack(miner,id): + +def send_submit_ack(miner, id): msg = '{"id":' + str(id) + ',"result":true,"error":null}\n' - send_tcp_msg(miner,msg) + send_tcp_msg(miner, msg) -def send_submit_error(miner,id): + +def send_submit_error(miner, id): msg = '{"id":' + str(id) + ',"result":false,"error":null}\n' - send_tcp_msg(miner,msg) + send_tcp_msg(miner, msg) + def send_extranonce_subscribe_ack(miner, id): msg = '{"id":' + str(id) + ', "error": null, "result": true}\n' - send_tcp_msg(miner,msg) + send_tcp_msg(miner, msg) + def send_mining_notify(miner, id): global job_id params = [] params.append(str(hex(job_id)[2:])) - params.append("0000000000000000000000000000000000000000000000000000000000000000") - params.append(client.last_miner_notify[client.last_miner_notify_cnt]["params"][0]["part1"]) - params.append(client.last_miner_notify[client.last_miner_notify_cnt]["params"][0]["part3"]) + params.append( + "0000000000000000000000000000000000000000000000000000000000000000") + params.append(client.last_miner_notify[client.last_miner_notify_cnt] + ["params"][0]["part1"]) + params.append(client.last_miner_notify[client.last_miner_notify_cnt] + ["params"][0]["part3"]) params.append([]) params.append("00000000") - params.append(str(hex(client.last_miner_notify[client.last_miner_notify_cnt]["params"][0]["target"])[2:])) - params.append(str(hex(client.last_miner_notify[client.last_miner_notify_cnt]["params"][0]["timestamp"])[2:])) + params.append( + str( + hex(client.last_miner_notify[client.last_miner_notify_cnt] + ["params"][0]["target"])[2:])) + params.append( + str( + hex(client.last_miner_notify[client.last_miner_notify_cnt] + ["params"][0]["timestamp"])[2:])) params.append('true') send_stratum_msg(miner, id, 'mining.notify', params) diff --git a/wallet_json_rpc.py b/wallet_json_rpc.py index 9b21b83..4b8d4c2 100644 --- a/wallet_json_rpc.py +++ b/wallet_json_rpc.py @@ -44,7 +44,14 @@ class InputParameterError(Exception): def get_block_reward(block): - msg = {"jsonrpc": "2.0", "method": "getblock", "params": {"block": block}, "id": 123} + msg = { + "jsonrpc": "2.0", + "method": "getblock", + "params": { + "block": block + }, + "id": 123 + } try: response_raw = requests.post(wallet_jsonrpc_ip_port, json=msg) except: @@ -57,8 +64,16 @@ def get_block_reward(block): return response["result"]["reward"] + response["result"]["fee"] + def is_block_matured(block): - msg = {"jsonrpc": "2.0", "method": "getblock", "params": {"block": block}, "id": 123} + msg = { + "jsonrpc": "2.0", + "method": "getblock", + "params": { + "block": block + }, + "id": 123 + } try: response_raw = requests.post(wallet_jsonrpc_ip_port, json=msg) except: @@ -72,10 +87,18 @@ def is_block_matured(block): return bool(response["result"]["maturation"] >= maturation_time) + def check_block_pubkey(block): global pool_public_key - msg = {"jsonrpc": "2.0", "method": "getblock", "params": {"block": block}, "id": 123} + msg = { + "jsonrpc": "2.0", + "method": "getblock", + "params": { + "block": block + }, + "id": 123 + } try: response_raw = requests.post(wallet_jsonrpc_ip_port, json=msg) except: @@ -90,8 +113,16 @@ def check_block_pubkey(block): return bool(enc_pubkey == pool_public_key) + def get_last_block(): - msg = {"jsonrpc": "2.0", "method": "getblockcount", "params": {"last": 1}, "id": 123} + msg = { + "jsonrpc": "2.0", + "method": "getblockcount", + "params": { + "last": 1 + }, + "id": 123 + } try: response_raw = requests.post(wallet_jsonrpc_ip_port, json=msg) except: @@ -101,6 +132,7 @@ def get_last_block(): last_block = response["result"] return last_block + def get_last_account(): data = {"jsonrpc": "2.0", "method": "getwalletaccountscount", "id": 123} try: @@ -110,12 +142,23 @@ def get_last_account(): response = json.loads(response_raw.text) - msg = {"jsonrpc":"2.0","method":"getwalletaccounts","params":{"start":response["result"]-5},"id":123} + msg = { + "jsonrpc": "2.0", + "method": "getwalletaccounts", + "params": { + "start": response["result"] - 5 + }, + "id": 123 + } response_raw = requests.post(wallet_jsonrpc_ip_port, json=msg) response = json.loads(response_raw.text) - wallet = {"account": response["result"][0]["account"], "balance":response["result"][0]["balance"]} + wallet = { + "account": response["result"][0]["account"], + "balance": response["result"][0]["balance"] + } return wallet + def get_a_zero_balance_account_number(): msg = {"jsonrpc": "2.0", "method": "getwalletaccounts", "id": 123} try: @@ -130,8 +173,16 @@ def get_a_zero_balance_account_number(): raise NoEmptyAccountError + def unlock_wallet(): - msg = {"jsonrpc": "2.0", "method": "unlock", "params": {"pwd": wallet_password}, "id": 123} + msg = { + "jsonrpc": "2.0", + "method": "unlock", + "params": { + "pwd": wallet_password + }, + "id": 123 + } try: response_raw = requests.post(wallet_jsonrpc_ip_port, json=msg) except: @@ -141,6 +192,7 @@ def unlock_wallet(): if response["result"] is False: print("Wallet can't be unlocked.") + def lock_wallet(): msg = {"jsonrpc": "2.0", "method": "lock", "id": 123} try: @@ -149,12 +201,26 @@ def lock_wallet(): print(e) raise WalletCommError + def send_payment(from_account, to_account, amount, block): if wallet_ok is False: raise WalletNotReadyError payload = "pool share, block: " + str(block) payload = payload.encode('utf-8') - msg = {"jsonrpc":"2.0","method":"sendto","params":{"sender":from_account,"target":to_account,"amount":amount,"fee":accountancy.payment_fee,"payload":payload.hex(),"payload_method":"none","pwd":wallet_password},"id":123} + msg = { + "jsonrpc": "2.0", + "method": "sendto", + "params": { + "sender": from_account, + "target": to_account, + "amount": amount, + "fee": accountancy.payment_fee, + "payload": payload.hex(), + "payload_method": "none", + "pwd": wallet_password + }, + "id": 123 + } try: response_raw = requests.post(wallet_jsonrpc_ip_port, json=msg) except: @@ -165,29 +231,38 @@ def send_payment(from_account, to_account, amount, block): logger.info("PAYMENT to wallet: " + json.dumps(msg)) logger.info("PAYMENT from wallet: " + response_raw.text) if "result" in response: - logger.info("Payment sent from: " + str(from_account) + " to: " + str(to_account) + ", amount: " + str(amount)) + logger.info("Payment sent from: " + str(from_account) + " to: " + + str(to_account) + ", amount: " + str(amount)) else: if response["error"]["code"] == 1004: - print("Payment ERROR from: " + str(from_account) + " to: " + str(to_account) + ", amount: " + str( - amount) + " " + response["error"]["message"]) + print("Payment ERROR from: " + str(from_account) + " to: " + + str(to_account) + ", amount: " + str(amount) + " " + + response["error"]["message"]) raise WalletInvalidOperationError - if response["error"]["code"] == 1005: # invalid public key -> orphan + if response["error"]["code"] == 1005: # invalid public key -> orphan raise WalletPubKeyError if response["error"]["code"] == 1002: raise WalletInvalidTargetAccountError raise Exception + def wallet_has_nodes(): global wallet_ok try: - data = {"jsonrpc": "2.0", "method": "nodestatus", "params": {}, "id": 123} + data = { + "jsonrpc": "2.0", + "method": "nodestatus", + "params": {}, + "id": 123 + } try: response_raw = requests.post(wallet_jsonrpc_ip_port, json=data) except: raise WalletCommError response = json.loads(response_raw.text) - if response["result"]["ready"] is False and response["result"]["ready_s"] == "Alone in the world...": + if response["result"]["ready"] is False and response["result"][ + "ready_s"] == "Alone in the world...": wallet_ok = False return False wallet_ok = True @@ -197,17 +272,21 @@ def wallet_has_nodes(): wallet_ok = False return False + def wait_for_wallet_start(): global wallet_ok try: while True: - data = {"jsonrpc": "2.0", "method": "nodestatus", "params": {}, "id": 123} + data = { + "jsonrpc": "2.0", + "method": "nodestatus", + "params": {}, + "id": 123 + } response_raw = requests.post(wallet_jsonrpc_ip_port, json=data) response = json.loads(response_raw.text) - if ( - "status_s" in response["result"] and - response["result"]["status_s"] == "Running" - ): + if ("status_s" in response["result"] + and response["result"]["status_s"] == "Running"): wallet_ok = True return True return False @@ -217,6 +296,7 @@ def wait_for_wallet_start(): wallet_ok = False return False + def get_public_key(): global pool_public_key, wallet_ok try: @@ -235,8 +315,16 @@ def get_public_key(): wallet_ok = False return False + def get_account_balance(account): - data = {"jsonrpc": "2.0", "method": "getaccount", "params":{"account":account}, "id": 123} + data = { + "jsonrpc": "2.0", + "method": "getaccount", + "params": { + "account": account + }, + "id": 123 + } try: response_raw = requests.post(wallet_jsonrpc_ip_port, json=data) @@ -246,6 +334,7 @@ def get_account_balance(account): response = json.loads(response_raw.text) return response["result"]["balance"] + def get_current_block(): data = {"jsonrpc": "2.0", "method": "getblockcount", "id": 123} @@ -259,8 +348,16 @@ def get_current_block(): print(current_block) return current_block + def get_net_hashrate(current_block): - data = {"jsonrpc": "2.0", "method": "getblock", "params":{"block":current_block-1}, "id": 123} + data = { + "jsonrpc": "2.0", + "method": "getblock", + "params": { + "block": current_block - 1 + }, + "id": 123 + } try: response_raw = requests.post(wallet_jsonrpc_ip_port, json=data) @@ -271,12 +368,26 @@ def get_net_hashrate(current_block): nethash_khs = response["result"]["hashratekhs"] - nethash_ghs = round((nethash_khs/1000000), 2) # divides by 1000000 to get MHs, and rounds to 2 decimals + nethash_ghs = round( + (nethash_khs / 1000000), + 2) # divides by 1000000 to get MHs, and rounds to 2 decimals return nethash_ghs + def change_key(new_pubkey, acc_number): - data = {"jsonrpc":"2.0","method":"changekey","params":{"account":acc_number,"new_b58_pubkey": new_pubkey,"fee":0,"payload":"","payload_method":"none"},"id":123} + data = { + "jsonrpc": "2.0", + "method": "changekey", + "params": { + "account": acc_number, + "new_b58_pubkey": new_pubkey, + "fee": 0, + "payload": "", + "payload_method": "none" + }, + "id": 123 + } try: response_raw = requests.post(wallet_jsonrpc_ip_port, json=data) except: