def test_txpool_3907_block_4098_4099(self, m_is_full_transaction_pool,
                                         m_config):
        """
        TxPool = [3907, 4095-4100, 4200]
        Block = [4098, 4099]
        TxPool Afterwards = [3907, 4095, 4100, 4200]
        """
        # Ensure that a "large OTS index" is 4096
        m_config.dev.max_ots_tracking_index = 4096

        m_block = Mock(autospec=Block)
        m_block.transactions = [CoinBase(), self.tx_4098, self.tx_4099]

        self.txpool.add_tx_to_pool(self.tx_3907, 5)

        self.txpool.remove_tx_in_block_from_pool(m_block)
        txs_in_txpool = [
            t[1].transaction for t in self.txpool.transaction_pool
        ]

        # 3907 should also be in the Pool since it is exempt from the counter
        self.assertEqual(len(self.txpool.transaction_pool), 4)
        self.assertNotIn(self.tx_4097, txs_in_txpool)
        self.assertNotIn(self.tx_4098, txs_in_txpool)
        self.assertNotIn(self.tx_4099, txs_in_txpool)

        self.assertIn(self.tx_3907, txs_in_txpool)
        self.assertIn(self.tx_4095, txs_in_txpool)
        self.assertIn(self.tx_4100, txs_in_txpool)
        self.assertIn(self.tx_4200, txs_in_txpool)
Example #2
0
    def test_revert_coinbase_txn(self, m_logger):
        """
        Alice earned some coins. Undo this.
        """
        tx = CoinBase.create(config.dev, self.amount, self.alice.address, self.mock_blockheader.block_number)
        addresses_state = {
            config.dev.coinbase_address: OptimizedAddressState.get_default(config.dev.coinbase_address),
            self.alice.address: OptimizedAddressState.get_default(self.alice.address),
        }
        addresses_state[config.dev.coinbase_address].pbdata.balance = 1000000

        state_container = StateContainer(addresses_state=addresses_state,
                                         tokens=Indexer(b'token', None),
                                         slaves=Indexer(b'slave', None),
                                         lattice_pk=Indexer(b'lattice_pk', None),
                                         multi_sig_spend_txs=dict(),
                                         votes_stats=dict(),
                                         block_number=self.mock_blockheader.block_number,
                                         total_coin_supply=100,
                                         current_dev_config=config.dev,
                                         write_access=True,
                                         my_db=self.state._db,
                                         batch=None)
        tx.apply(self.state, state_container)
        tx.revert(self.state, state_container)

        self.assertEqual(1000000, addresses_state[config.dev.coinbase_address].balance)

        storage_key = state_container.paginated_tx_hash.generate_key(config.dev.coinbase_address, 1)
        self.assertEqual([], state_container.paginated_tx_hash.key_value[storage_key])
        self.assertEqual(0, addresses_state[self.alice.address].balance)

        storage_key = state_container.paginated_tx_hash.generate_key(config.dev.coinbase_address, 1)
        self.assertEqual([], state_container.paginated_tx_hash.key_value[storage_key])
Example #3
0
    def test_txpool_4095_4096_4097_otherppl_block_4098_4099(self, m_is_full_transaction_pool, m_config):
        """
        TxPool = [4096-4100, 4200, 4095-4097_otherppl]
        Block = [4200]
        TxPool Afterwards = [4095, 4095-4097_otherppl]
        """
        # Ensure that a "large OTS index" is 4096
        m_config.dev.max_ots_tracking_index = 4096

        m_block = Mock(autospec=Block)
        m_block.transactions = [CoinBase(), self.tx_4200]

        tx_other_4095 = make_tx(name='Mock TX 4095', txhash=b'h4095_other', ots_key=4095, PK='otherppl')
        tx_other_4096 = make_tx(name='Mock TX 4096', txhash=b'h4096_other', ots_key=4096, PK='otherppl')
        tx_other_4097 = make_tx(name='Mock TX 4097', txhash=b'h4097_other', ots_key=4097, PK='otherppl')

        self.txpool.add_tx_to_pool(tx_other_4095, 5)
        self.txpool.add_tx_to_pool(tx_other_4096, 5)
        self.txpool.add_tx_to_pool(tx_other_4097, 5)

        self.txpool.remove_tx_in_block_from_pool(m_block)
        txs_in_txpool = [t[1].transaction for t in self.txpool.transaction_pool]

        self.assertEqual(len(self.txpool.transaction_pool), 4)
        self.assertIn(self.tx_4095, txs_in_txpool)
        self.assertIn(tx_other_4095, txs_in_txpool)
        self.assertIn(tx_other_4096, txs_in_txpool)
        self.assertIn(tx_other_4097, txs_in_txpool)
Example #4
0
    def test_update_pending_tx_pool_rejects_coinbase_txs(self, m_is_full_pending_transaction_pool, m_logger):
        tx1 = CoinBase()
        ip = '127.0.0.1'
        m_is_full_pending_transaction_pool.return_value = False

        result = self.txpool.update_pending_tx_pool(tx1, ip)
        self.assertFalse(result)
    def test_block_4098_4099(self, m_is_full_transaction_pool, m_config):
        """
        TxPool = [4095-4100, 4200]
        Block = [4098, 4099]
        TxPool Afterwards = [4095, 4100, 4200]
        """
        # Ensure that a "large OTS index" is 4096
        m_config.dev.max_ots_tracking_index = 4096

        m_block = Mock(autospec=Block)
        m_block.transactions = [CoinBase(), self.tx_4098, self.tx_4099]

        self.txpool.remove_tx_in_block_from_pool(m_block)
        txs_in_txpool = [
            t[1].transaction for t in self.txpool.transaction_pool
        ]

        self.assertEqual(len(self.txpool.transaction_pool), 3)
        self.assertNotIn(self.tx_4097, txs_in_txpool)
        self.assertNotIn(self.tx_4098, txs_in_txpool)
        self.assertNotIn(self.tx_4099, txs_in_txpool)

        self.assertIn(self.tx_4095, txs_in_txpool)
        self.assertIn(self.tx_4100, txs_in_txpool)
        self.assertIn(self.tx_4200, txs_in_txpool)
Example #6
0
    def test_revert_state_changes(self, m_logger):
        """
        Alice earned some coins. Undo this.
        """
        tx = CoinBase.create(self.amount, self.alice.address, self.mock_blockheader.block_number)
        addresses_state = {
            config.dev.coinbase_address: Mock(autospec=AddressState, name='CoinBase AddressState',
                                              transaction_hashes=[tx.txhash], balance=1000000 - self.amount),
            self.alice.address: Mock(autospec=AddressState, name='alice AddressState', transaction_hashes=[tx.txhash],
                                     balance=self.amount),
        }
        unused_chain_manager_mock = Mock(autospec=ChainManager, name='unused ChainManager')

        tx.revert_state_changes(addresses_state, unused_chain_manager_mock)

        self.assertEqual(1000000, addresses_state[config.dev.coinbase_address].balance)
        self.assertEqual([], addresses_state[config.dev.coinbase_address].transaction_hashes)
        self.assertEqual(0, addresses_state[self.alice.address].balance)
        self.assertEqual([], addresses_state[self.alice.address].transaction_hashes)

        # A blank addresses_state doesn't get modified at all (but in practice, every node should have an AddressState
        # for the CoinBase addr
        addresses_state_empty = {}
        tx.revert_state_changes(addresses_state_empty, unused_chain_manager_mock)
        self.assertEqual({}, addresses_state_empty)
Example #7
0
 def test_affected_address(self, m_logger):
     # This transaction can only involve 2 addresses.
     affected_addresses = set()
     tx = CoinBase.create(config.dev, self.amount, self.alice.address,
                          self.mock_blockheader.block_number)
     tx.set_affected_address(affected_addresses)
     self.assertEqual(2, len(affected_addresses))
Example #8
0
    def test_add_tx_from_block_to_pool(self, m_add_tx_to_pool, m_from_pbdata, m_logger):
        m_block = Mock(autospec=Block, block_number=5, headerhash=b'test block header')
        m_block.transactions = [CoinBase(), make_tx(), make_tx()]

        self.txpool.add_tx_from_block_to_pool(m_block, 5)

        self.assertEqual(m_add_tx_to_pool.call_count, 2)  # 2 because the function ignores the Coinbase tx

        # If there is a problem adding to the tx_pool, the logger should be invoked.
        m_add_tx_to_pool.return_value = False
        self.txpool.add_tx_from_block_to_pool(m_block, 5)
        m_logger.warning.assert_called()
Example #9
0
    def test_from_txdict(self, m_logger):
        amount = self.mock_blockheader.block_reward + self.mock_blockheader.fee_reward
        tx = CoinBase.create(amount, self.alice.address, self.mock_blockheader.block_number)
        self.assertIsInstance(tx, CoinBase)

        # Test that common Transaction components were copied over.
        self.assertEqual(self.mock_blockheader.block_number + 1, tx.nonce)
        self.assertEqual('010300a1da274e68c88b0ccf448e0b1916fa789b01eb2ed4e9ad565ce264c9390782a9c61ac02f',
                         bin2hstr(tx.addr_to))

        self.assertEqual('222460cc57ab8683b46f1831fe6cf1832c7e3134baf74d33bfaf91741e19cba2', bin2hstr(tx.txhash))
        self.assertEqual(tx.amount, 90)
Example #10
0
    def test_validate_custom(self, m_logger):
        """
        CoinBase _validate_custom() only checks if fee == 0
        """
        tx = CoinBase.create(self.amount, self.alice.address, self.mock_blockheader.block_number)
        tx._data.fee = 1
        result = tx._validate_custom()
        self.assertFalse(result)

        tx._data.fee = 0
        result = tx._validate_custom()
        self.assertTrue(result)
Example #11
0
    def test_get_mini_transactions_by_address(self, mock_get_tx_metadata,
                                              mock_get_optimized_address_state,
                                              mock_get_paginated_data):
        """
        QRLNode.get_transactions_by_address() returns all the changes in balance caused by a transaction.
        """
        get_tx_metadata = GetTXMetadata()

        xmss = get_alice_xmss()
        xmss2 = get_random_xmss()
        addr_state = OptimizedAddressState.get_default(xmss.address)
        addr_state.pbdata.balance = 100
        addr_state.pbdata.transaction_hash_count = 3
        mock_get_optimized_address_state.return_value = addr_state

        tx1 = CoinBase.create(config.dev, 100, xmss.address, 5)
        get_tx_metadata.register_tx_metadata(tx1, 1)

        tx2 = TransferTransaction.create(addrs_to=[xmss2.address],
                                         amounts=[10],
                                         message_data=None,
                                         fee=1,
                                         xmss_pk=xmss.pk)
        tx2.sign(xmss)
        get_tx_metadata.register_tx_metadata(tx2, 1)

        tx3 = TransferTransaction.create(addrs_to=[xmss.address],
                                         amounts=[100],
                                         message_data=None,
                                         fee=1,
                                         xmss_pk=xmss2.pk)
        tx3.sign(xmss)
        get_tx_metadata.register_tx_metadata(tx3, 2)

        mock_get_paginated_data.return_value = [
            tx1.txhash, tx2.txhash, tx3.txhash
        ]
        mock_get_tx_metadata.side_effect = get_tx_metadata.get_tx_metadata
        response = self.qrlnode.get_mini_transactions_by_address(
            alice.address, 3, 1)
        result, balance = response.mini_transactions, response.balance
        self.assertEqual(len(result), 3)

        self.assertEqual(result[0].amount, 100)
        self.assertEqual(result[0].out, False)

        self.assertEqual(result[1].amount, 11)
        self.assertEqual(result[1].out, True)

        self.assertEqual(result[2].amount, 100)
        self.assertEqual(result[2].out, False)

        self.assertEqual(balance, 100)
Example #12
0
    def test_extra_coinbase_tx(self, m_TransferTransaction_validate,
                               m_TransferTransaction_validate_extended,
                               m_TransferTransaction_apply_state_changes,
                               m_CoinBase_apply_state_changes):
        address_states = self.generate_address_states(
            self.alice_addrstate_attrs, {}, self.slave_addrstate_attrs)

        coinbase_extra = CoinBase.create(500, self.alice.address, 5)
        self.block_attrs["transactions"] = [self.tx1, coinbase_extra, self.tx2]

        block = Block.create(**self.block_attrs)
        result = block.apply_state_changes(address_states)
        self.assertFalse(result)
    def test_remove_tx_in_block_from_pool(self):
        m_block = Mock(autospec=Block)
        tx1 = make_tx(name='Mock TX 1', ots_key=1, PK=b'pk')
        tx2 = make_tx(name='Mock TX 2', ots_key=2, PK=b'pk')
        m_block.transactions = [CoinBase(), tx1, tx2]

        # To remove the tx from the pool we have to add it first!
        self.txpool.add_tx_to_pool(tx1, 5)
        self.txpool.add_tx_to_pool(tx2, 5)
        self.assertEqual(len(self.txpool.transaction_pool), 2)

        self.txpool.remove_tx_in_block_from_pool(m_block)
        self.assertEqual(len(self.txpool.transaction_pool), 0)
Example #14
0
    def create(dev_config: DevConfig, block_number: int,
               prev_headerhash: bytes, prev_timestamp: int, transactions: list,
               miner_address: bytes, seed_height: Optional[int],
               seed_hash: Optional[bytes]):

        block = Block()

        # Process transactions
        hashedtransactions = []
        fee_reward = 0

        for tx in transactions:
            fee_reward += tx.fee

        # Prepare coinbase tx
        total_reward_amount = BlockHeader.block_reward_calc(
            block_number, dev_config) + fee_reward
        coinbase_tx = CoinBase.create(dev_config, total_reward_amount,
                                      miner_address, block_number)
        hashedtransactions.append(coinbase_tx.txhash)
        Block._copy_tx_pbdata_into_block(
            block, coinbase_tx)  # copy memory rather than sym link

        for tx in transactions:
            hashedtransactions.append(tx.txhash)
            Block._copy_tx_pbdata_into_block(
                block, tx)  # copy memory rather than sym link

        txs_hash = merkle_tx_hash(
            hashedtransactions)  # FIXME: Find a better name, type changes

        tmp_blockheader = BlockHeader.create(dev_config=dev_config,
                                             blocknumber=block_number,
                                             prev_headerhash=prev_headerhash,
                                             prev_timestamp=prev_timestamp,
                                             hashedtransactions=txs_hash,
                                             fee_reward=fee_reward,
                                             seed_height=seed_height,
                                             seed_hash=seed_hash)

        block.blockheader = tmp_blockheader

        block._data.header.MergeFrom(tmp_blockheader.pbdata)

        block.set_nonces(dev_config, 0, 0)

        return block
Example #15
0
    def test_get_transactions_by_address(self):
        """
        QRLNode.get_transactions_by_address() returns all the changes in balance caused by a transaction.
        """
        mock_get_tx_metadata = GetTXMetadata()

        xmss = get_alice_xmss()
        xmss2 = get_random_xmss()
        addr_state = AddressState.get_default(xmss.address)
        addr_state.pbdata.balance = 100

        tx1 = CoinBase.create(100, xmss.address, 5)
        mock_get_tx_metadata.register_tx_metadata(tx1, 5)
        addr_state.transaction_hashes.append(tx1.txhash)

        tx2 = TransferTransaction.create(addrs_to=[xmss2.address],
                                         amounts=[10],
                                         fee=1,
                                         xmss_pk=xmss.pk)
        tx2.sign(xmss)
        mock_get_tx_metadata.register_tx_metadata(tx2, 99)
        addr_state.transaction_hashes.append(tx2.txhash)

        tx3 = TransferTransaction.create(addrs_to=[xmss.address],
                                         amounts=[100],
                                         fee=1,
                                         xmss_pk=xmss2.pk)
        tx3.sign(xmss)
        mock_get_tx_metadata.register_tx_metadata(tx3, 101)
        addr_state.transaction_hashes.append(tx3.txhash)

        self.db_state.get_address_state.return_value = addr_state
        self.db_state.get_tx_metadata = mock_get_tx_metadata.get_tx_metadata
        result, balance = self.qrlnode.get_transactions_by_address(
            alice.address)
        self.assertEqual(len(result), 3)

        self.assertEqual(result[0].amount, 100)
        self.assertEqual(result[0].out, False)

        self.assertEqual(result[1].amount, 11)
        self.assertEqual(result[1].out, True)

        self.assertEqual(result[2].amount, 100)
        self.assertEqual(result[2].out, False)

        self.assertEqual(balance, 189)
Example #16
0
    def test_extra_coinbase_tx(self,
                               m_TransferTransaction_validate,
                               m_TransferTransaction_validate_extended,
                               m_TransferTransaction_apply_state_changes,
                               m_CoinBase_apply_state_changes):
        get_optimized_address_state = MockFunction()
        get_optimized_address_state.put(self.coinbase_addrstate_attrs.address, self.coinbase_addrstate_attrs)
        get_optimized_address_state.put(self.bob_addrstate_attrs.address, self.bob_addrstate_attrs)
        get_optimized_address_state.put(self.alice_addrstate_attrs.address, self.alice_addrstate_attrs)
        get_optimized_address_state.put(self.slave_addrstate_attrs.address, self.slave_addrstate_attrs)

        coinbase_extra = CoinBase.create(config.dev, 500, self.alice.address, 5)
        self.block_attrs["transactions"] = [self.tx1, coinbase_extra, self.tx2]

        block = Block.create(**self.block_attrs)
        result = self.chain_manager._apply_state_changes(block, None)
        self.assertFalse(result)
Example #17
0
    def test_validate_extended(self, m_logger):
        """
        CoinBase validate_extended() checks for
        1. valid coinbase address (the coinbase address must be config.dev.coinbase_address)
        2. valid addr_to
        then calls _validate_custom()
        """
        tx = CoinBase.create(config.dev, self.amount, self.alice.address,
                             self.mock_blockheader.block_number)
        tx._data.master_addr = self.alice.address

        addresses_state = {
            config.dev.coinbase_address:
            OptimizedAddressState.get_default(config.dev.coinbase_address),
            self.alice.address:
            OptimizedAddressState.get_default(self.alice.address),
        }
        addresses_state[config.dev.coinbase_address].pbdata.balance = 1000000

        state_container = StateContainer(
            addresses_state=addresses_state,
            tokens=Indexer(b'token', None),
            slaves=Indexer(b'slave', None),
            lattice_pk=Indexer(b'lattice_pk', None),
            multi_sig_spend_txs=dict(),
            votes_stats=dict(),
            block_number=self.mock_blockheader.block_number,
            total_coin_supply=100,
            current_dev_config=config.dev,
            write_access=True,
            my_db=self.state._db,
            batch=None)

        result = tx._validate_extended(state_container)
        self.assertFalse(result)

        tx._data.master_addr = config.dev.coinbase_address
        with patch('qrl.core.txs.CoinBase.CoinBase.addr_to',
                   new_callable=PropertyMock) as m_addr_to:
            m_addr_to.return_value = b'Fake Address'
            result = tx._validate_extended(state_container)
            self.assertFalse(result)

        result = tx._validate_extended(state_container)
        self.assertTrue(result)
Example #18
0
    def test_block_1000(self, m_is_full_transaction_pool, m_config):
        """
        TxPool = [4095-4100, 4200]
        Block = [1000]
        TxPool Afterwards = [4095-4100, 4200]
        """
        # Ensure that a "large OTS index" is 4096
        m_config.dev.max_ots_tracking_index = 4096

        tx_1000 = make_tx(name='Mock TX 1000', txhash=b'h1000', ots_key=1000)
        m_block = Mock(autospec=Block)
        m_block.transactions = [CoinBase(), tx_1000]
        self.assertEqual(7, len(self.txpool.transaction_pool))

        self.txpool.remove_tx_in_block_from_pool(m_block)

        txs_in_txpool = [t[1].transaction for t in self.txpool.transaction_pool]
        self.assertEqual(7, len(txs_in_txpool))
Example #19
0
    def block_params(self, msg_hash: bytes, block):
        if msg_hash not in self.requested_hash:
            return False

        params = self.requested_hash[msg_hash].params
        coinbase_tx = CoinBase.from_pbdata(block.transactions[0])
        if coinbase_tx.addr_from != params.stake_selector:
            return False

        if block.block_number != params.block_number:
            return False

        if block.prev_headerhash != params.prev_headerhash:
            return False

        if block.reveal_hash != params.reveal_hash:
            return False

        return True
Example #20
0
    def create(block_number: int, prev_headerhash: bytes, prev_timestamp: int,
               transactions: list, miner_address: bytes):

        block = Block()

        # Process transactions
        hashedtransactions = []
        fee_reward = 0

        for tx in transactions:
            fee_reward += tx.fee

        # Prepare coinbase tx
        total_reward_amount = BlockHeader.block_reward_calc(
            block_number) + fee_reward
        coinbase_tx = CoinBase.create(total_reward_amount, miner_address,
                                      block_number)
        hashedtransactions.append(coinbase_tx.txhash)
        block._data.transactions.extend([coinbase_tx.pbdata
                                         ])  # copy memory rather than sym link

        for tx in transactions:
            hashedtransactions.append(tx.txhash)
            block._data.transactions.extend(
                [tx.pbdata])  # copy memory rather than sym link

        txs_hash = merkle_tx_hash(
            hashedtransactions)  # FIXME: Find a better name, type changes

        tmp_blockheader = BlockHeader.create(blocknumber=block_number,
                                             prev_headerhash=prev_headerhash,
                                             prev_timestamp=prev_timestamp,
                                             hashedtransactions=txs_hash,
                                             fee_reward=fee_reward)

        block.blockheader = tmp_blockheader

        block._data.header.MergeFrom(tmp_blockheader.pbdata)

        block.set_nonces(0, 0)

        return block
Example #21
0
    def test_validate_extended(self, m_logger):
        """
        CoinBase validate_extended() checks for
        1. valid coinbase address (the coinbase address must be config.dev.coinbase_address)
        2. valid addr_to
        then calls _validate_custom()
        """
        tx = CoinBase.create(self.amount, self.alice.address, self.mock_blockheader.block_number)
        tx._data.master_addr = self.alice.address

        result = tx.validate_extended(self.mock_blockheader.block_number)
        self.assertFalse(result)

        tx._data.master_addr = config.dev.coinbase_address
        with patch('qrl.core.txs.CoinBase.CoinBase.addr_to', new_callable=PropertyMock) as m_addr_to:
            m_addr_to.return_value = b'Fake Address'
            result = tx.validate_extended(self.mock_blockheader.block_number)
            self.assertFalse(result)

        result = tx.validate_extended(self.mock_blockheader.block_number)
        self.assertTrue(result)
Example #22
0
    def test_apply_state_changes(self, m_logger):
        """
        Alice earned some coins.
        """
        addresses_state = {
            config.dev.coinbase_address: Mock(autospec=AddressState, name='CoinBase AddressState',
                                              transaction_hashes=[], balance=1000000),
            self.alice.address: Mock(autospec=AddressState, name='alice AddressState', transaction_hashes=[],
                                     balance=0),
        }
        tx = CoinBase.create(self.amount, self.alice.address, self.mock_blockheader.block_number)

        tx.apply_state_changes(addresses_state)

        self.assertEqual(1000000 - tx.amount, addresses_state[config.dev.coinbase_address].balance)
        self.assertEqual([tx.txhash], addresses_state[config.dev.coinbase_address].transaction_hashes)
        self.assertEqual(tx.amount, addresses_state[self.alice.address].balance)
        self.assertEqual([tx.txhash], addresses_state[self.alice.address].transaction_hashes)

        # A blank addresses_state doesn't get modified at all (but in practice, every node should have an AddressState
        # for the CoinBase addr
        addresses_state_empty = {}
        tx.apply_state_changes(addresses_state_empty)
        self.assertEqual({}, addresses_state_empty)
Example #23
0
 def test_to_json(self, m_logger):
     amount = self.mock_blockheader.block_reward + self.mock_blockheader.fee_reward
     tx = CoinBase.create(amount, self.alice.address, self.mock_blockheader.block_number)
     txjson = tx.to_json()
     self.assertEqual(json.loads(test_json_CoinBase), json.loads(txjson))
Example #24
0
 def test_create(self, m_logger):
     tx = CoinBase.create(self.amount, self.alice.address, self.mock_blockheader.block_number)
     self.assertIsInstance(tx, CoinBase)