def update_database_with_tx(self, tx, block_length, count_pool=False): send_address = tools.tx_owner_address(tx) send_account = self.get_account(send_address) if tx['type'] == 'mint': send_account['amount'] += tools.block_reward(block_length) self.update_account(send_address, send_account) elif tx['type'] == 'spend': if tx['count'] != self.known_tx_count(send_address, count_pool=count_pool): return False recv_address = tx['to'] recv_account = self.get_account(recv_address) send_account['amount'] -= tx['amount'] send_account['count'] += 1 send_account['tx_blocks'].append(block_length) recv_account['amount'] += tx['amount'] recv_account['tx_blocks'].append(block_length) if (recv_account['amount'] < 0) or (send_account['amount'] < 0): return False self.update_account(send_address, send_account) self.update_account(recv_address, recv_account) else: return False return True
def rollback_block(self, block): # TODO: 0.007-12c changes """ A block rollback means removing the block from chain. A block is defined by its transactions. Here we rollback every object in database to the version that existed before this block. Blocks must be removed one by one. :param block: Block to be removed :return: Success of removal """ current_length = self.db.get('length') if block['length'] != current_length: # Block is not at the top the chain return False for tx in block['txs']: tx_owner_address = tools.tx_owner_address(tx) owner_account = self.get_account(tx_owner_address) if tx['type'] == 'mint': owner_account['amount'] -= tools.block_reward(block['length']) self.db.put(tx_owner_address, owner_account) elif tx['type'] == 'spend': owner_account['amount'] += tx['amount'] owner_account['count'] -= 1 owner_account['tx_blocks'].remove(block['length']) receiver_account = self.db.get(tx['to']) receiver_account['amount'] -= tx['amount'] receiver_account['tx_blocks'].remove(block['length']) self.db.put(tx_owner_address, owner_account) self.db.put(tx['to'], receiver_account)
def print_txs(txs, length=-1): table = [] for tx in txs: tx['from'] = tools.tx_owner_address(tx) if tx['type'] == 'mint': tx['to'] = 'N/A' tx['amount'] = tools.block_reward(length) tx['message'] = '' table.append( [tx['type'], tx['from'], tx['to'], tx['amount'], tx['message']]) print( tabulate(table, headers=[ Colors.HEADER + 'Type' + Colors.ENDC, Colors.HEADER + 'From' + Colors.ENDC, Colors.HEADER + 'To' + Colors.ENDC, Colors.HEADER + 'Amount' + Colors.ENDC, Colors.HEADER + 'Message' + Colors.ENDC ], tablefmt='orgtbl'))
def print_history(history): if history is None: print("Could not receive history") elif isinstance(history, str): print(history) else: for tx in history['send']: print("In Block {} {} => {} for amount {}".format( tx['block'], Colors.HEADER + tools.tx_owner_address(tx) + Colors.ENDC, Colors.WARNING + tx['to'] + Colors.ENDC, tx['amount'])) for tx in history['recv']: print("In Block {} {} => {} for amount {}".format( tx['block'], Colors.WARNING + tools.tx_owner_address(tx) + Colors.ENDC, Colors.HEADER + tx['to'] + Colors.ENDC, tx['amount'])) for tx in history['mine']: print("In Block {} {} mined amount {}".format( tx['block'], Colors.HEADER + tools.tx_owner_address(tx) + Colors.ENDC, tools.block_reward(tx['block'])))
def update_accounts_with_block(self, block, add_flag=True, simulate=False): """ :param block: :param add_flag: Is block being added or removed :param simulate: Do not actually update the accounts, return any irregularity :return: """ def apply(a, b): if isinstance(a, int): if add_flag: a += b else: a -= b elif isinstance(a, list): if add_flag: a.append(b) else: a.remove(b) return a def get_acc(address): if not simulate: account = self.get_account(address) else: if address not in account_sandbox: account = self.get_account(address) account_sandbox[address] = account account = account_sandbox[address] return account def update_acc(address, account): if not simulate: self.update_account(address, account) else: account_sandbox[address] = account return True flag = True account_sandbox = {} for tx in block['txs']: send_address = tools.tx_owner_address(tx) send_account = get_acc(send_address) if tx['type'] == 'mint': send_account['amount'] = apply( send_account['amount'], tools.block_reward(block['length'])) send_account['mined_blocks'] = apply( send_account['mined_blocks'], block['length']) elif tx['type'] == 'spend': recv_address = tx['to'] recv_account = get_acc(recv_address) send_account['amount'] = apply(send_account['amount'], -tx['amount']) send_account['count'] = apply(send_account['count'], 1) send_account['tx_blocks'] = apply(send_account['tx_blocks'], block['length']) recv_account['amount'] = apply(recv_account['amount'], tx['amount']) recv_account['tx_blocks'] = apply(recv_account['tx_blocks'], block['length']) flag &= (recv_account['amount'] >= 0) flag &= (send_account['amount'] >= 0) if not flag: return False else: update_acc(send_address, send_account) if tx['type'] == 'spend': update_acc(recv_address, recv_account) return flag