Ejemplo n.º 1
0
    def __next__(self):
        tx = self.transaction_pool_obj.get_pending_transaction()

        if not tx:
            raise StopIteration

        if not tx.validate():
            return False

        addr_from_state = self.state.get_address(address=tx.addr_from)
        addr_from_pk_state = addr_from_state

        addr_from_pk = Transaction.get_slave(tx)
        if addr_from_pk:
            addr_from_pk_state = self.state.get_address(address=addr_from_pk)

        is_valid_state = tx.validate_extended(addr_from_state=addr_from_state,
                                              addr_from_pk_state=addr_from_pk_state)

        is_valid_pool_state = tx.validate_transaction_pool(self.transaction_pool_obj.transaction_pool)

        if not (is_valid_state and is_valid_pool_state):
            logger.info('>>>TX %s failed state_validate', tx.txhash)
            return False

        logger.info('A TXN has been Processed %s', bin2hstr(tx.txhash))
        self.transaction_pool_obj.add_tx_to_pool(tx)
        self.transaction_pool_obj.append_addr_ots_hash(tx)
        self.broadcast_tx(tx)

        return True
Ejemplo n.º 2
0
    def __next__(self):
        if not self.transaction_pool_obj.pending_tx_pool:
            raise StopIteration

        if len(self.transaction_pool_obj.transaction_pool) >= config.dev.transaction_pool_size:
            raise StopIteration

        tx = self.transaction_pool_obj.pending_tx_pool.pop(0)
        tx = tx[0]

        if not tx.validate():
            return False

        addr_from_state = self.state.get_address(address=tx.txfrom)
        addr_from_pk_state = addr_from_state

        addr_from_pk = Transaction.get_slave(tx)
        if addr_from_pk:
            addr_from_pk_state = self.state.get_address(address=addr_from_pk)

        is_valid_state = tx.validate_extended(addr_from_state=addr_from_state,
                                              addr_from_pk_state=addr_from_pk_state,
                                              transaction_pool=self.transaction_pool_obj.transaction_pool)

        is_valid_pool_state = tx.validate_transaction_pool(self.transaction_pool_obj.transaction_pool)

        if not (is_valid_state and is_valid_pool_state):
            logger.info('>>>TX %s failed state_validate', tx.txhash)
            return False

        logger.info('A TXN has been Processed %s', bin2hstr(tx.txhash))
        self.transaction_pool_obj.add_tx_to_pool(tx)
        self.broadcast_tx(tx)

        return True
Ejemplo n.º 3
0
    def validate_block(self, block, address_txn) -> bool:
        len_transactions = len(block.transactions)

        if len_transactions < 1:
            return False

        coinbase_tx = Transaction.from_pbdata(block.transactions[0])

        if not isinstance(coinbase_tx, CoinBase):
            return False

        if not coinbase_tx.validate_extended():
            return False

        if not PoWValidator().validate_mining_nonce(self.state,
                                                    block.blockheader):
            return False

        coinbase_tx.apply_on_state(address_txn)

        # TODO: check block reward must be equal to coinbase amount

        for tx_idx in range(1, len_transactions):
            tx = Transaction.from_pbdata(block.transactions[tx_idx])

            if isinstance(tx, CoinBase):
                return False

            if not tx.validate(
            ):  # TODO: Move this validation, before adding txn to pool
                return False

            addr_from_pk_state = address_txn[tx.addr_from]
            addr_from_pk = Transaction.get_slave(tx)
            if addr_from_pk:
                addr_from_pk_state = address_txn[addr_from_pk]

            if not tx.validate_extended(address_txn[tx.addr_from],
                                        addr_from_pk_state):
                return False

            expected_nonce = addr_from_pk_state.nonce + 1

            if tx.nonce != expected_nonce:
                logger.warning('nonce incorrect, invalid tx')
                logger.warning('subtype: %s', tx.type)
                logger.warning('%s actual: %s expected: %s', tx.addr_from,
                               tx.nonce, expected_nonce)
                return False

            if addr_from_pk_state.ots_key_reuse(tx.ots_key):
                logger.warning('pubkey reuse detected: invalid tx %s',
                               tx.txhash)
                logger.warning('subtype: %s', tx.type)
                return False

            tx.apply_on_state(address_txn)

        return True
Ejemplo n.º 4
0
    def create_block(self,
                     last_block,
                     mining_nonce,
                     tx_pool: TransactionPool,
                     miner_address) -> Optional[Block]:
        # TODO: Persistence will move to rocksdb
        # FIXME: Difference between this and create block?????????????

        dummy_block = Block.create(block_number=last_block.block_number + 1,
                                   prevblock_headerhash=last_block.headerhash,
                                   transactions=[],
                                   miner_address=miner_address)
        dummy_block.set_nonces(mining_nonce, 0)

        t_pool2 = tx_pool.transactions

        addresses_set = set()
        for tx_set in t_pool2:
            tx = tx_set[1]
            tx.set_effected_address(addresses_set)

        addresses_state = dict()
        for address in addresses_set:
            addresses_state[address] = self.state.get_address(address)

        block_size = dummy_block.size
        block_size_limit = self.state.get_block_size_limit(last_block)

        transactions = []
        for tx_set in t_pool2:
            tx = tx_set[1]
            # Skip Transactions for later, which doesn't fit into block
            if block_size + tx.size + config.dev.tx_extra_overhead > block_size_limit:
                continue

            addr_from_pk_state = addresses_state[tx.addr_from]
            addr_from_pk = Transaction.get_slave(tx)
            if addr_from_pk:
                addr_from_pk_state = addresses_state[addr_from_pk]

            if not tx.validate_extended(addresses_state[tx.addr_from], addr_from_pk_state):
                logger.warning('Txn validation failed for tx in tx_pool')
                tx_pool.remove_tx_from_pool(tx)
                continue

            tx.apply_on_state(addresses_state)

            tx._data.nonce = addr_from_pk_state.nonce
            block_size += tx.size + config.dev.tx_extra_overhead
            transactions.append(tx)

        block = Block.create(block_number=last_block.block_number + 1,
                             prevblock_headerhash=last_block.headerhash,
                             transactions=transactions,
                             miner_address=miner_address)

        return block
Ejemplo n.º 5
0
    def apply_state_changes(self, address_txn) -> bool:
        coinbase_tx = Transaction.from_pbdata(self.transactions[0])

        if not coinbase_tx.validate_extended():
            logger.warning('Coinbase transaction failed')
            return False

        coinbase_tx.apply_state_changes(address_txn)

        len_transactions = len(self.transactions)
        for tx_idx in range(1, len_transactions):
            tx = Transaction.from_pbdata(self.transactions[tx_idx])

            if isinstance(tx, CoinBase):
                logger.warning('Found another coinbase transaction')
                return False

            if not tx.validate():
                return False

            addr_from_pk_state = address_txn[tx.addr_from]
            addr_from_pk = Transaction.get_slave(tx)
            if addr_from_pk:
                addr_from_pk_state = address_txn[addr_from_pk]

            if not tx.validate_extended(address_txn[tx.addr_from],
                                        addr_from_pk_state):
                return False

            expected_nonce = addr_from_pk_state.nonce + 1

            if tx.nonce != expected_nonce:
                logger.warning('nonce incorrect, invalid tx')
                logger.warning('subtype: %s', tx.type)
                logger.warning('%s actual: %s expected: %s', tx.addr_from,
                               tx.nonce, expected_nonce)
                return False

            if addr_from_pk_state.ots_key_reuse(tx.ots_key):
                logger.warning('pubkey reuse detected: invalid tx %s',
                               bin2hstr(tx.txhash))
                logger.warning('subtype: %s', tx.type)
                return False

            tx.apply_state_changes(address_txn)

        return True
    def __next__(self):
        if not self.transaction_pool_obj.pending_tx_pool:
            raise StopIteration

        if len(self.transaction_pool_obj.transaction_pool
               ) >= config.dev.transaction_pool_size:
            raise StopIteration

        tx = self.transaction_pool_obj.pending_tx_pool.pop(0)
        tx = tx[0]

        if not tx.validate():
            return False

        addr_from_state = self.state.get_address(address=tx.addr_from)
        addr_from_pk_state = addr_from_state

        addr_from_pk = Transaction.get_slave(tx)
        if addr_from_pk:
            addr_from_pk_state = self.state.get_address(address=addr_from_pk)

        is_valid_state = tx.validate_extended(
            addr_from_state=addr_from_state,
            addr_from_pk_state=addr_from_pk_state)

        is_valid_pool_state = tx.validate_transaction_pool(
            self.transaction_pool_obj.transaction_pool)

        if not (is_valid_state and is_valid_pool_state):
            logger.info('>>>TX %s failed state_validate', tx.txhash)
            return False

        for old_tx in self.transaction_pool_obj.transaction_pool:
            if old_tx.txhash == tx.txhash:
                return True

        logger.info('A TXN has been Processed %s', bin2hstr(tx.txhash))
        self.transaction_pool_obj.add_tx_to_pool(tx)
        self.broadcast_tx(tx)

        return True
Ejemplo n.º 7
0
    def validate_block(self, block, address_txn) -> bool:
        len_transactions = len(block.transactions)

        if len_transactions < 1:
            return False

        coinbase_tx = Transaction.from_pbdata(block.transactions[0])
        coinbase_tx.validate()

        if not self.validate_mining_nonce(block):
            return False

        if coinbase_tx.subtype != qrl_pb2.Transaction.COINBASE:
            return False

        if not coinbase_tx.validate():
            return False

        coinbase_tx.apply_on_state(address_txn)

        addr_from_pk_state = address_txn[coinbase_tx.txto]
        addr_from_pk = Transaction.get_slave(coinbase_tx)
        if addr_from_pk:
            addr_from_pk_state = address_txn[addr_from_pk]

        if not coinbase_tx.validate_extended(address_txn[coinbase_tx.txto],
                                             addr_from_pk_state,
                                             []):
            return False

        # TODO: check block reward must be equal to coinbase amount

        for tx_idx in range(1, len_transactions):
            tx = Transaction.from_pbdata(block.transactions[tx_idx])

            if tx.subtype == qrl_pb2.Transaction.COINBASE:
                return False

            if not tx.validate():  # TODO: Move this validation, before adding txn to pool
                return False

            addr_from_pk_state = address_txn[tx.txfrom]
            addr_from_pk = Transaction.get_slave(tx)
            if addr_from_pk:
                addr_from_pk_state = address_txn[addr_from_pk]

            if not tx.validate_extended(address_txn[tx.txfrom], addr_from_pk_state, []):
                return False

            expected_nonce = address_txn[tx.txfrom].nonce + 1

            if tx.nonce != expected_nonce:
                logger.warning('nonce incorrect, invalid tx')
                logger.warning('subtype: %s', tx.subtype)
                logger.warning('%s actual: %s expected: %s', tx.txfrom, tx.nonce, expected_nonce)
                return False

            if tx.ots_key_reuse(address_txn[tx.txfrom], tx.ots_key):
                logger.warning('pubkey reuse detected: invalid tx %s', tx.txhash)
                logger.warning('subtype: %s', tx.subtype)
                return False

            tx.apply_on_state(address_txn)

        return True
Ejemplo n.º 8
0
    def create_block(self, last_block, mining_nonce, tx_pool, signing_xmss,
                     master_address) -> Optional[Block]:
        # TODO: Persistence will move to rocksdb
        # FIXME: Difference between this and create block?????????????

        # FIXME: Break encapsulation
        if not self._dummy_xmss:
            self._dummy_xmss = XMSS.from_height(signing_xmss.height)

        dummy_block = Block.create(block_number=last_block.block_number + 1,
                                   prevblock_headerhash=last_block.headerhash,
                                   transactions=[],
                                   signing_xmss=self._dummy_xmss,
                                   master_address=master_address,
                                   nonce=0)
        dummy_block.set_mining_nonce(mining_nonce)

        t_pool2 = copy.deepcopy(tx_pool.transaction_pool)
        del tx_pool.transaction_pool[:]
        ######

        # recreate the transaction pool as in the tx_hash_list, ordered by txhash..
        total_txn = len(t_pool2)
        txnum = 0
        addresses_set = set()
        while txnum < total_txn:
            tx = t_pool2[txnum]
            tx.set_effected_address(addresses_set)
            txnum += 1

        addresses_state = dict()
        for address in addresses_set:
            addresses_state[address] = self.state.get_address(address)

        block_size = dummy_block.size
        block_size_limit = self.state.get_block_size_limit(last_block)
        txnum = 0
        while txnum < total_txn:
            tx = t_pool2[txnum]
            # Skip Transactions for later, which doesn't fit into block
            if block_size + tx.size + config.dev.tx_extra_overhead > block_size_limit:
                txnum += 1
                continue

            addr_from_pk_state = addresses_state[tx.addr_from]
            addr_from_pk = Transaction.get_slave(tx)
            if addr_from_pk:
                addr_from_pk_state = addresses_state[addr_from_pk]

            if addr_from_pk_state.ots_key_reuse(tx.ots_key):
                del t_pool2[txnum]
                total_txn -= 1
                continue

            if isinstance(tx, TransferTransaction):
                if addresses_state[
                        tx.addr_from].balance < tx.total_amount + tx.fee:
                    logger.warning('%s %s exceeds balance, invalid tx', tx,
                                   tx.addr_from)
                    logger.warning('type: %s', tx.type)
                    logger.warning(
                        'Buffer State Balance: %s  Transfer Amount %s',
                        addresses_state[tx.addr_from].balance, tx.total_amount)
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

            if isinstance(tx, MessageTransaction):
                if addresses_state[tx.addr_from].balance < tx.fee:
                    logger.warning('%s %s exceeds balance, invalid message tx',
                                   tx, tx.addr_from)
                    logger.warning('type: %s', tx.type)
                    logger.warning('Buffer State Balance: %s  Free %s',
                                   addresses_state[tx.addr_from].balance,
                                   tx.fee)
                    total_txn -= 1
                    continue

            if isinstance(tx, TokenTransaction):
                if addresses_state[tx.addr_from].balance < tx.fee:
                    logger.warning('%s %s exceeds balance, invalid tx', tx,
                                   tx.addr_from)
                    logger.warning('type: %s', tx.type)
                    logger.warning('Buffer State Balance: %s  Fee %s',
                                   addresses_state[tx.addr_from].balance,
                                   tx.fee)
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

            if isinstance(tx, TransferTokenTransaction):
                if addresses_state[tx.addr_from].balance < tx.fee:
                    logger.warning('%s %s exceeds balance, invalid tx', tx,
                                   tx.addr_from)
                    logger.warning('type: %s', tx.type)
                    logger.warning(
                        'Buffer State Balance: %s  Transfer Amount %s',
                        addresses_state[tx.addr_from].balance, tx.fee)
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

                if bin2hstr(tx.token_txhash).encode() not in addresses_state[
                        tx.addr_from].tokens:
                    logger.warning(
                        '%s doesnt own any token with token_txnhash %s',
                        tx.addr_from,
                        bin2hstr(tx.token_txhash).encode())
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

                if addresses_state[tx.addr_from].tokens[bin2hstr(
                        tx.token_txhash).encode()] < tx.total_amount:
                    logger.warning(
                        'Token Transfer amount exceeds available token')
                    logger.warning('Token Txhash %s',
                                   bin2hstr(tx.token_txhash).encode())
                    logger.warning(
                        'Available Token Amount %s',
                        addresses_state[tx.addr_from].tokens[bin2hstr(
                            tx.token_txhash).encode()])
                    logger.warning('Transaction Amount %s', tx.total_amount)
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

            if isinstance(tx, LatticePublicKey):
                if addresses_state[tx.addr_from].balance < tx.fee:
                    logger.warning(
                        'Lattice TXN %s %s exceeds balance, invalid tx', tx,
                        tx.addr_from)
                    logger.warning('type: %s', tx.type)
                    logger.warning(
                        'Buffer State Balance: %s  Transfer Amount %s',
                        addresses_state[tx.addr_from].balance, tx.fee)
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

            if isinstance(tx, SlaveTransaction):
                if addresses_state[tx.addr_from].balance < tx.fee:
                    logger.warning(
                        'Slave TXN %s %s exceeds balance, invalid tx', tx,
                        tx.addr_from)
                    logger.warning('type: %s', tx.type)
                    logger.warning(
                        'Buffer State Balance: %s  Transfer Amount %s',
                        addresses_state[tx.addr_from].balance, tx.fee)
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

            tx.apply_on_state(addresses_state)

            tx_pool.add_tx_to_pool(tx)
            tx._data.nonce = addresses_state[tx.addr_from].nonce
            txnum += 1
            block_size += tx.size + config.dev.tx_extra_overhead

        coinbase_nonce = self.state.get_address(signing_xmss.address).nonce
        if signing_xmss.address in addresses_state:
            coinbase_nonce = addresses_state[signing_xmss.address].nonce + 1

        block = Block.create(block_number=last_block.block_number + 1,
                             prevblock_headerhash=last_block.headerhash,
                             transactions=t_pool2,
                             signing_xmss=signing_xmss,
                             master_address=master_address,
                             nonce=coinbase_nonce)

        return block
Ejemplo n.º 9
0
Archivo: Miner.py Proyecto: fanff/QRL
    def create_block(self, last_block, mining_nonce, tx_pool, signing_xmss, master_address) -> Optional[Block]:
        # TODO: Persistence will move to rocksdb
        # FIXME: Difference between this and create block?????????????

        # FIXME: Break encapsulation
        dummy_block = Block.create(mining_nonce=mining_nonce,
                                   block_number=last_block.block_number + 1,
                                   prevblock_headerhash=last_block.headerhash,
                                   transactions=[],
                                   signing_xmss=signing_xmss,
                                   master_address=master_address,
                                   nonce=0)
        dummy_block.set_mining_nonce(mining_nonce)
        signing_xmss.set_index(signing_xmss.get_index() - 1)

        t_pool2 = copy.deepcopy(tx_pool.transaction_pool)
        del tx_pool.transaction_pool[:]
        ######

        # recreate the transaction pool as in the tx_hash_list, ordered by txhash..
        total_txn = len(t_pool2)
        txnum = 0
        addresses_set = set()
        while txnum < total_txn:
            tx = t_pool2[txnum]
            tx.set_effected_address(addresses_set)
            txnum += 1

        addresses_state = dict()
        for address in addresses_set:
            addresses_state[address] = self.state.get_address(address)

        block_size = dummy_block.size
        block_size_limit = self.state.get_block_size_limit(last_block)
        txnum = 0
        while txnum < total_txn:
            tx = t_pool2[txnum]
            # Skip Transactions for later, which doesn't fit into block
            if block_size + tx.size + config.dev.tx_extra_overhead > block_size_limit:
                txnum += 1
                continue

            addr_from_pk_state = addresses_state[tx.txfrom]
            addr_from_pk = Transaction.get_slave(tx)
            if addr_from_pk:
                addr_from_pk_state = addresses_state[addr_from_pk]

            if tx.ots_key_reuse(addr_from_pk_state, tx.ots_key):
                del t_pool2[txnum]
                total_txn -= 1
                continue

            if tx.subtype == qrl_pb2.Transaction.TRANSFER:
                if addresses_state[tx.txfrom].balance < tx.amount + tx.fee:
                    logger.warning('%s %s exceeds balance, invalid tx', tx, tx.txfrom)
                    logger.warning('subtype: %s', tx.subtype)
                    logger.warning('Buffer State Balance: %s  Transfer Amount %s', addresses_state[tx.txfrom].balance,
                                   tx.amount)
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

            if tx.subtype == qrl_pb2.Transaction.MESSAGE:
                if addresses_state[tx.txfrom].balance < tx.fee:
                    logger.warning('%s %s exceeds balance, invalid message tx', tx, tx.txfrom)
                    logger.warning('subtype: %s', tx.subtype)
                    logger.warning('Buffer State Balance: %s  Free %s', addresses_state[tx.txfrom].balance, tx.fee)
                    total_txn -= 1
                    continue

            if tx.subtype == qrl_pb2.Transaction.TOKEN:
                if addresses_state[tx.txfrom].balance < tx.fee:
                    logger.warning('%s %s exceeds balance, invalid tx', tx, tx.txfrom)
                    logger.warning('subtype: %s', tx.subtype)
                    logger.warning('Buffer State Balance: %s  Fee %s',
                                   addresses_state[tx.txfrom].balance,
                                   tx.fee)
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

            if tx.subtype == qrl_pb2.Transaction.TRANSFERTOKEN:
                if addresses_state[tx.txfrom].balance < tx.fee:
                    logger.warning('%s %s exceeds balance, invalid tx', tx, tx.txfrom)
                    logger.warning('subtype: %s', tx.subtype)
                    logger.warning('Buffer State Balance: %s  Transfer Amount %s',
                                   addresses_state[tx.txfrom].balance,
                                   tx.fee)
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

                if bin2hstr(tx.token_txhash).encode() not in addresses_state[tx.txfrom].tokens:
                    logger.warning('%s doesnt own any token with token_txnhash %s', tx.txfrom,
                                   bin2hstr(tx.token_txhash).encode())
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

                if addresses_state[tx.txfrom].tokens[bin2hstr(tx.token_txhash).encode()] < tx.amount:
                    logger.warning('Token Transfer amount exceeds available token')
                    logger.warning('Token Txhash %s', bin2hstr(tx.token_txhash).encode())
                    logger.warning('Available Token Amount %s',
                                   addresses_state[tx.txfrom].tokens[bin2hstr(tx.token_txhash).encode()])
                    logger.warning('Transaction Amount %s', tx.amount)
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

            if tx.subtype == qrl_pb2.Transaction.LATTICE:
                if addresses_state[tx.txfrom].balance < tx.fee:
                    logger.warning('Lattice TXN %s %s exceeds balance, invalid tx', tx, tx.txfrom)
                    logger.warning('subtype: %s', tx.subtype)
                    logger.warning('Buffer State Balance: %s  Transfer Amount %s',
                                   addresses_state[tx.txfrom].balance,
                                   tx.fee)
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

            if tx.subtype == qrl_pb2.Transaction.SLAVE:
                if addresses_state[tx.txfrom].balance < tx.fee:
                    logger.warning('Slave TXN %s %s exceeds balance, invalid tx', tx, tx.txfrom)
                    logger.warning('subtype: %s', tx.subtype)
                    logger.warning('Buffer State Balance: %s  Transfer Amount %s',
                                   addresses_state[tx.txfrom].balance,
                                   tx.fee)
                    del t_pool2[txnum]
                    total_txn -= 1
                    continue

            tx.apply_on_state(addresses_state)

            tx_pool.add_tx_to_pool(tx)
            tx._data.nonce = addresses_state[tx.txfrom].nonce
            txnum += 1
            block_size += tx.size + config.dev.tx_extra_overhead

        coinbase_nonce = self.state.get_address(signing_xmss.get_address()).nonce
        if signing_xmss.get_address() in addresses_state:
            coinbase_nonce = addresses_state[signing_xmss.get_address()].nonce + 1

        block = Block.create(mining_nonce=mining_nonce,
                             block_number=last_block.block_number + 1,
                             prevblock_headerhash=last_block.headerhash,
                             transactions=t_pool2,
                             signing_xmss=signing_xmss,
                             master_address=master_address,
                             nonce=coinbase_nonce)

        return block