def on_block_height_changed(prev_block_height, curr_block_height): log('On block height changed: {0} -> {1}'.format(prev_block_height, curr_block_height)) # !!!! NOTE: 确保这个过程不会中断,否则有可能会漏掉玩家转入的币 unspent_data_dict = model.collect_unspent_data() bet_list = model.construct_bets(unspent_data_dict) # 1. 将当前块未花费的数据保存起来 save_raw_unspent_data_to_json(unspent_data_dict, curr_block_height) # 2. 将每一个地址的 unspent 数据存入数据库 save_unspent_data_to_database(bet_list) # 3. 尝试资金汇集 try_collect_all_balance(bet_list, curr_block_height) # 4. 尝试结算下注 closing_block_set = try_closing_bets(curr_block_height) # 5. 尝试支付赢家奖金 paied_block_set = try_pay_winers(curr_block_height) # 算出哪一些下注块的信息需要更新 need_update_view_block_set = closing_block_set | paied_block_set # 尝试更新网页 try_update_view(need_update_view_block_set)
def get_account_name_by_address(_address): command = 'getaccount {0}'.format(_address) result = do_command(command) if result == -1: log('Get account name by address faild: {0}'.format(_address)) return -1 return result
def create_abet(_join_txid, _bet_address, _bet_amount): bet = Bet() join_txid = _join_txid join_block_hash, join_block_height, join_block_timestamp = api.get_block_hash_height_time_by_txid( join_txid) bet_block_height = get_bet_block_height_by_join_block_height( join_block_height) bet_address = _bet_address bet_amount = _bet_amount bet_nonce_last_digit = addresses2number[bet_address] payment_address = api.get_payment_address(join_txid, bet_address) if payment_address in addresses: log('Fatal error , payment address is bet address! {}'.format( payment_address)) sys.exit() bet.join_txid = join_txid bet.join_block_height = int(join_block_height) bet.join_block_hash = join_block_hash bet.join_block_timestamp = int(join_block_timestamp) bet.bet_block_height = int(bet_block_height) bet.bet_address = bet_address bet.bet_amount = bet_amount bet.bet_nonce_last_digit = int(bet_nonce_last_digit) bet.payment_address = payment_address return bet
def get_balance_by_address(_address): unspent_list = get_unspent_list_by_address(_address) if unspent_list == -1: log('get balance by address faild: {}'.format(_address)) return -1 balance = 0 for unspent in unspent_list: amount = unspent['amount'] balance += amount return balance
def get_block_hash_height_time_by_txid(_txid): command = 'getrawtransaction {0} 1'.format(_txid) result = do_command(command) if result == -1: log('get block hash and hgith and time faild: {0}', _txid) return -1, -1, -1 json_obj = json.loads(result) block_hash = json_obj['blockhash'] block_height = json_obj['height'] block_time = json_obj['blocktime'] return block_hash, block_height, block_time
def send_all_balance_to_address(from_address, to_address, comment=''): account_balance = get_balance_by_address(from_address) if account_balance == -1: log('FAILD! Get Balance Faild!, cant payout!') return -1 if account_balance == 0: # print('No Balance in address {0}'.format(from_address)) return -1 address_list = [to_address] amount_list = [account_balance] log('Send all balance from {} -> {}'.format(from_address, to_address)) return send_to_many(from_address, address_list, amount_list, None, comment)
def construct_bets(unspent_data_dict): try: bet_list = [] for address in unspent_data_dict: unspent_list = unspent_data_dict[address] bet_address = address for unspent in unspent_list: join_txid = unspent['txid'] bet_amount = unspent['amount'] abet = create_abet(join_txid, bet_address, bet_amount) bet_list.append(abet) return bet_list except Exception as _e: log('!!!!! Construct bets faild! ' + str(_e)) sys.exit()
def make_sure_network_updated(): same_count = 0 last_height = api.get_curr_blockchain_height() time.sleep(1) while True: curr_height = api.get_curr_blockchain_height() if curr_height == last_height and curr_height != 0: same_count += 1 else: last_height = curr_height same_count = 0 if same_count >= 10: log('Blockchain update OK!') break log('Sync Block {}'.format(curr_height)) time.sleep(1)
def main_game_loop(): print(' Game Start '.center(50, '=')) last_block_height = api.get_curr_blockchain_height() print('Now Block {0}'.format(last_block_height)) while True: if last_block_height == -1: last_block_height = api.get_curr_blockchain_height() else: curr_block_height = api.get_curr_blockchain_height() if curr_block_height == -1: log('Get current blockchain height faild!') else: if curr_block_height != last_block_height: prev_block_height = last_block_height last_block_height = curr_block_height on_block_height_changed(prev_block_height, curr_block_height) time.sleep(1)
def get_payment_address(unspent_txid, unspent_address): command = 'getrawtransaction {0} 1'.format(unspent_txid) result = do_command(command) if result == -1: log('get payment address faild, get rawtrasaction by unspent_txid faild!' ) return -1 json_obj = json.loads(result) vout_array = json_obj['vout'] vout_count = len(vout_array) if vout_count == 1: # 没有找零地址,从vin中获取输入地址 receive_address = vout_array[0]['scriptPubKey']['addresses'][0] if receive_address != unspent_address: log('Fatal Error: receive address is not equal unspent address \njson:{0}' .format(result)) return -1 # detect input address from vin txid vin_array = json_obj['vin'] vin_txid = vin_array[0]['txid'] vin_vout = vin_array[0]['vout'] command = 'getrawtransaction {0} 1'.format(vin_txid) result = do_command(command) if result == -1: log('get payment address faild, get rawtransaction by vin_txid faild! vin_txid: {0} vin_vout:{1}' .format(vin_txid, vin_vout)) return -1 json_obj = json.loads(result) vout = json_obj['vout'][vin_vout] payment_address = vout['scriptPubKey']['addresses'][0] return payment_address elif vout_count == 2: # 有找零地址,直接使用找零地址 for vout in vout_array: vout_address = vout['scriptPubKey']['addresses'][0] if vout_address != unspent_address: return vout_address log('Fatal error , unknow error!') return -1 else: log("F**k, i can't detect the payment address!") return -1
def get_account_address(account_name): """ Get geekcash address by account name, if the account no address, create new one. """ command = 'getaddressesbyaccount {0}'.format(account_name) result = do_command(command) if result == -1: log('Fatal error: get addresses by account faild!') return -1 json_obj = json.loads(result) address_count = len(json_obj) if address_count == 0: log('no account address: {0}, to create new one!'.format(account_name)) command = 'getaccountaddress {0}'.format(account_name) result = do_command(command) if result == -1: log('Fatal error, create new address faild: {0}'.format( account_name)) return -1 else: return result else: return json_obj[0]
def send_to_many(from_address, address_list, amount_list, change_address, comment=''): """ from_address: which address to payout address_list: which addresses you want to pay ['address1','address2','address3'] amount_list: the item length is match to address_list, the amount you want to pay for each address change_address: basically , the change_address is the address of from_account, make sure account has just one address, that's very clear comment: comment is the comment of command, whatever Note: receiver pay the fee! """ address_count = len(address_list) amount_count = len(amount_list) if address_count != amount_count: print("Address Count and Amount count is not match!") return -1 account_name = get_account_name_by_address(from_address) if account_name == -1: log('send to many get account name faild: {0}'.format(from_address)) return -1 account_balance = get_balance_by_address(from_address) if account_balance == -1: print("Get Balance Faild!, can't payout!") return -1 total_payout = 0.0 for x in range(0, amount_count): total_payout += amount_list[x] total_change = account_balance - total_payout total_change = round(total_change, 8) if total_change < 0: print( "Balance not enough, can't payout! balance:{0},payout:{1}".format( account_balance, total_payout)) return -1 payout_str = '' address_str = '' # combine receivers for x in range(0, address_count): address = address_list[x] amount = amount_list[x] payout_str += '\\"{0}\\":{1},'.format(address, amount) address_str += '\\"{0}\\",'.format(address) print('Payout {0} {1}'.format(address, amount)) print('Change {0} {1}'.format(change_address, total_change)) # combine change if total_change > 0 and change_address is not None: payout_str += '\\"{0}\\":{1},'.format(change_address, total_change) address_str += '\\"{0}\\",'.format(change_address) payout_str = '"{' + payout_str[:-1] + '}"' address_str = '"[' + address_str[:-1] + ']"' command = 'sendmany "{0}" {1} 0 false "{2}" {3}'.format( account_name, payout_str, comment, address_str) return do_command(command)