Пример #1
0
    def add_tx(self, tx):

        if not isinstance(tx, dict):
            return False

        address = tools.tx_owner_address(tx)

        # tools.log('attempt to add tx: ' +str(tx))
        txs_in_pool = self.tx_pool()

        response = Response(True, None)
        if 'type' not in tx or not isinstance(tx['type'], str) \
                or tx['type'] not in BlockchainService.tx_types:
            response.setData('type error')
            response.setFlag(False)
        if tx in txs_in_pool:
            response.setData('no duplicates')
            response.setFlag(False)
        if not BlockchainService.tx_integrity_check(tx).getFlag():
            response.setData('tx: ' + str(tx))
            response.setFlag(False)
        if tx['count'] != self.account.known_tx_count(
                tools.tx_owner_address(tx)):
            response.setData('count error')
            response.setFlag(False)
        if not self.account.is_tx_affordable(address, tx):
            response.setData('fee check error')
            response.setFlag(False)

        if response.getFlag():
            self.tx_pool_add(tx)
            return 'added tx into the pool: ' + str(tx)
        else:
            return 'failed to add tx because: ' + response.getData()
Пример #2
0
    def update_account_with_txs(self,
                                address,
                                account,
                                txs,
                                add_flag=True,
                                only_outgoing=False):
        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

        for tx in txs:
            owner = tools.tx_owner_address(tx)
            if tx['type'] == 'spend':
                if owner == address:
                    account['amount'] = apply(account['amount'], -tx['amount'])
                    account['count'] = apply(account['count'], 1)
                elif tx['to'] == address and not only_outgoing:
                    account['amount'] = apply(account['amount'], tx['amount'])
        return account
Пример #3
0
    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 tx_integrity_check(tx):
        """
        This functions test whether a transaction has basic things right.
        Does it have amount, recipient, RIGHT SIGNATURES and correct address types.
        :param tx:
        :return:
        """
        if not isinstance(tx, dict):
            return Response(False, 'Transaction is not a proper python dict')

        if tx['version'] != custom.version:
            return Response(False, 'belongs to an earlier version')

        if tx['type'] == 'spend':
            if 'to' not in tx or not isinstance(tx['to'], str):
                return Response(
                    False, 'Reward or spend transactions must be addressed')
            if not BlockchainService.tx_signature_check(tx):
                return Response(False, 'Transaction is not properly signed')
            if not tools.is_address_valid(tx['to']):
                return Response(False, 'Address is not valid')
            if tx['to'] == tools.tx_owner_address(tx):
                return Response(False,
                                'You cannot transfer money to same account!')
            if 'amount' not in tx or not isinstance(tx['amount'], int):
                return Response(
                    False,
                    'Transaction amount is not given or not a proper integer')
            if 'count' not in tx or not isinstance(tx['count'], int):
                return Response(False, 'transaction count is missing')

        return Response(True, 'Everything seems fine')
Пример #5
0
    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)
Пример #6
0
def history():
    from halocoin.model.wallet import Wallet
    address = request.values.get('address', None)
    if address is None:
        default_wallet = engine.instance.clientdb.get_default_wallet()
        if default_wallet is not None:
            wallet_name = default_wallet['wallet_name']
            password = default_wallet['password']
            encrypted_wallet_content = engine.instance.clientdb.get_wallet(
                wallet_name)
            wallet = Wallet.from_string(
                tools.decrypt(password, encrypted_wallet_content))
            address = wallet.address
    account = engine.instance.statedb.get_account(wallet.address)
    txs = {"send": [], "recv": []}
    for block_index in reversed(account['tx_blocks']):
        block = engine.instance.blockchain.get_block(block_index)
        for tx in block['txs']:
            if tx['type'] == 'mint':
                continue
            tx['block'] = block_index
            owner = tools.tx_owner_address(tx)
            if owner == address:
                txs['send'].append(tx)
            elif tx['type'] == 'spend' and tx['to'] == address:
                txs['recv'].append(tx)
    return generate_json_response(txs)
Пример #7
0
def mempool():
    purge = request.values.get('purge', None)
    if purge is not None:
        engine.instance.blockchain.tx_pool_pop_all()
    pool = copy.deepcopy(engine.instance.blockchain.tx_pool())
    for i, tx in enumerate(pool):
        pool[i]['from'] = tools.tx_owner_address(tx)

    return generate_json_response(pool)
Пример #8
0
        def update_account_with_txs(address, account, txs):
            for tx in txs:
                owner = tools.tx_owner_address(tx)
                if tx['type'] == 'spend':
                    if owner == address:
                        account['amount'] -= tx['amount']
                    if tx['to'] == address:
                        account['amount'] += tx['amount']

            return account
Пример #9
0
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'])))
Пример #10
0
def history():
    address = request.values.get('address', None)
    if address is None:
        address = engine.instance.db.get('address')
    account = engine.instance.account.get_account(address)
    txs = {"send": [], "recv": [], "mine": []}
    for block_index in reversed(account['tx_blocks']):
        block = engine.instance.db.get(str(block_index))
        for tx in block['txs']:
            tx['block'] = block_index
            owner = tools.tx_owner_address(tx)
            if owner == address:
                txs['send'].append(tx)
            elif tx['type'] == 'spend' and tx['to'] == address:
                txs['recv'].append(tx)
    for block_index in reversed(account['mined_blocks']):
        block = engine.instance.db.get(str(block_index))
        for tx in block['txs']:
            tx['block'] = block_index
            owner = tools.tx_owner_address(tx)
            if owner == address:
                txs['mine'].append(tx)
    return generate_json_response(txs)
Пример #11
0
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'))
Пример #12
0
def block():
    start = int(request.values.get('start', '-1'))
    end = int(request.values.get('end', '-1'))
    length = engine.instance.db.get('length')
    if start == -1 and end == -1:
        end = length
        start = max(end - 20, 0)
    elif start == -1:
        start = max(end - 20, 0)
    elif end == -1:
        end = min(length, start + 20)

    result = {"start": start, "end": end, "blocks": []}
    for i in range(start, end + 1):
        block = engine.instance.db.get(str(i))
        if block is None:
            break
        mint_tx = list(filter(lambda t: t['type'] == 'mint', block['txs']))[0]
        block['miner'] = tools.tx_owner_address(mint_tx)
        result["blocks"].append(block)
    result["blocks"] = list(reversed(result["blocks"]))
    return generate_json_response(result)
Пример #13
0
def print_blocks(blocks):
    table = []
    for block in blocks:
        if block['length'] == 0:
            block['prevHash'] = "N/A"
        block['time'] = datetime.datetime.fromtimestamp(int(
            block['time'])).strftime('%Y-%m-%d %H:%M:%S')
        mint_tx = list(filter(lambda t: t['type'] == 'mint', block['txs']))[0]
        table.append(
            [block['length'],
             tools.tx_owner_address(mint_tx), block['time']])
    print(Colors.WARNING + "Blocks:\n" + Colors.ENDC)
    print(
        tabulate(table,
                 headers=[
                     Colors.HEADER + 'Length' + Colors.ENDC,
                     Colors.HEADER + 'Miner' + Colors.ENDC,
                     Colors.HEADER + 'Time' + Colors.ENDC
                 ],
                 tablefmt='orgtbl'))

    if len(blocks) == 1:
        print(Colors.WARNING + "\nTransactions in the Block:\n" + Colors.ENDC)
        print_txs(blocks[0]['txs'], length=blocks[0]['length'])
Пример #14
0
    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
Пример #15
0
 def number_of_unconfirmed_txs(_address):
     return len(
         list(
             filter(lambda t: _address == tools.tx_owner_address(t),
                    txs_in_pool)))
Пример #16
0
def txs():
    pool = engine.instance.blockchain.tx_pool()
    for i, tx in enumerate(pool):
        pool[i]['from'] = tools.tx_owner_address(tx)
    return generate_json_response(pool)