Beispiel #1
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])
    def setUp(self):
        with set_qrl_dir('no_data'):
            self.state = State()

        self.alice = get_alice_xmss()
        self.bob = get_bob_xmss()

        alice_address_state = OptimizedAddressState.get_default(self.alice.address)
        alice_address_state.pbdata.balance = 100
        self.addresses_state = {
            self.alice.address: alice_address_state,
            self.bob.address: OptimizedAddressState.get_default(self.bob.address)
        }

        self.params = {
            "symbol": b'QRL',
            "name": b'Quantum Resistant Ledger',
            "owner": self.alice.address,
            "decimals": 15,
            "initial_balances": [],
            "fee": 1,
            "xmss_pk": self.alice.pk
        }

        self.unused_chain_manager_mock = Mock(autospec=ChainManager, name='unused ChainManager')
    def setUp(self):
        with set_qrl_dir('no_data'):
            self.state = State()

        self.alice = get_alice_xmss()
        self.bob = get_bob_xmss()

        alice_address_state = OptimizedAddressState.get_default(
            self.alice.address)
        alice_address_state.pbdata.balance = 100
        self.addresses_state = {
            self.alice.address: alice_address_state,
            self.bob.address:
            OptimizedAddressState.get_default(self.bob.address)
        }

        self.params = {
            "token_txhash": b'I declare the TEST token',
            "addrs_to": [self.bob.address],
            "amounts": [100],
            "fee": 1,
            "xmss_pk": self.alice.pk
        }

        self.unused_chain_manager_mock = Mock(autospec=ChainManager,
                                              name='unused ChainManager')
    def _validate_custom(self):
        for amount in self.amounts:
            if amount == 0:
                logger.warning('Amount cannot be 0 - %s', self.amounts)
                logger.warning('TransferTokenTransaction')
                return False

        if self.fee < 0:
            logger.info('TransferTokenTransaction [%s] Invalid Fee = %d',
                        bin2hstr(self.txhash), self.fee)
            return False

        if len(self.addrs_to) != len(self.amounts):
            logger.warning(
                '[TransferTokenTransaction] Mismatch number of addresses to & amounts'
            )
            logger.warning('>> Length of addresses_to %s', len(self.addrs_to))
            logger.warning('>> Length of amounts %s', len(self.amounts))
            return False

        if not OptimizedAddressState.address_is_valid(self.addr_from):
            logger.warning(
                '[TransferTokenTransaction] Invalid address addr_from: %s',
                bin2hstr(self.addr_from))
            return False

        for addr_to in self.addrs_to:
            if not OptimizedAddressState.address_is_valid(addr_to):
                logger.warning(
                    '[TransferTokenTransaction] Invalid address addr_to: %s',
                    bin2hstr(addr_to))
                return False

        return True
Beispiel #5
0
    def test_apply_multi_sig_create_txn2(self):
        """
        Features Tested
        - Multi Sig Create txn with duplicate signatories

        Expectation
        - It should result into custom validation error throwing ValueError exception
        :return:
        """
        addresses_state = {
            self.alice.address:
            OptimizedAddressState.get_default(self.alice.address),
            self.bob.address:
            OptimizedAddressState.get_default(self.bob.address),
            self.random.address:
            OptimizedAddressState.get_default(self.random.address),
            self.random_signer.address:
            OptimizedAddressState.get_default(self.random_signer.address),
        }
        addresses_state[self.random_signer.address].pbdata.balance = 200
        modified_signatories = list(self.signatories)
        modified_weights = list(self.weights)

        # Appending bob as signatory second time
        modified_signatories.append(self.bob.address)
        modified_weights.append(2)

        tx = None
        with self.assertRaises(ValueError):
            tx = MultiSigCreate.create(modified_signatories, modified_weights,
                                       self.threshold, 1,
                                       self.random_signer.pk)
        self.assertIsNone(tx)
Beispiel #6
0
    def test_apply(self):
        multi_sig_address = MultiSigAddressState.generate_multi_sig_address(
            b'')
        multi_sig_address_state = MultiSigAddressState.create(
            creation_tx_hash=b'',
            balance=100,
            signatories=[self.alice.address, self.bob.address],
            weights=[4, 6],
            threshold=5,
            transaction_hash_count=0)
        alice_address_state = OptimizedAddressState.get_default(
            self.alice.address)
        alice_address_state.pbdata.balance = 5
        bob_address_state = OptimizedAddressState.get_default(self.bob.address)
        addresses_state = {
            self.alice.address: alice_address_state,
            self.bob.address: bob_address_state,
            multi_sig_address: multi_sig_address_state,
        }

        tx = MultiSigSpend.create(multi_sig_address=multi_sig_address,
                                  addrs_to=[self.bob.address],
                                  amounts=[100],
                                  expiry_block_number=15000,
                                  fee=5,
                                  xmss_pk=self.alice.pk)
        tx.sign(self.alice)

        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=1,
                                         total_coin_supply=100,
                                         current_dev_config=config.dev,
                                         write_access=True,
                                         my_db=self.state._db,
                                         batch=None)

        self.assertFalse(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, tx.ots_key))

        tx.apply(self.state, state_container)

        self.assertTrue(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, tx.ots_key))
        self.assertIn(tx.txhash, state_container.votes_stats)
        vote_stats = state_container.votes_stats[tx.txhash]
        self.assertEqual(vote_stats.shared_key, tx.txhash)
        self.assertEqual(vote_stats.total_weight, 0)
        self.assertEqual(vote_stats.signatories,
                         multi_sig_address_state.signatories)
Beispiel #7
0
    def test_validate_all(self):
        """
        TODO: Check by signing txn from a non signatory address
        """
        multi_sig_address = MultiSigAddressState.generate_multi_sig_address(
            b'')
        tx = MultiSigSpend.create(multi_sig_address=multi_sig_address,
                                  addrs_to=[self.bob.address],
                                  amounts=[100],
                                  expiry_block_number=15000,
                                  fee=5,
                                  xmss_pk=self.random.pk,
                                  master_addr=self.alice.address)
        tx.sign(self.random)
        tx._data.nonce = 1
        alice_address_state = OptimizedAddressState.get_default(
            address=self.alice.address)
        alice_address_state.pbdata.balance = 5
        random_address_state = OptimizedAddressState.get_default(
            address=self.random.address)
        multi_sig_address_state = MultiSigAddressState.create(
            creation_tx_hash=b'',
            balance=100,
            signatories=[self.alice.address, self.bob.address],
            weights=[4, 6],
            threshold=5,
            transaction_hash_count=0)
        addresses_state = {
            self.alice.address: alice_address_state,
            self.random.address: random_address_state,
            multi_sig_address: multi_sig_address_state,
        }
        slaves = Indexer(b'slave', None)
        slaves.data[(self.alice.address,
                     self.random.pk)] = SlaveMetadata(access_type=0)

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

        result = tx.validate_all(state_container)
        self.assertTrue(result)

        tx._data.nonce = 2
        result = tx.validate_all(state_container)
        self.assertFalse(result)  # False as nonce is invalid
Beispiel #8
0
    def test_revert_transfer_txn(self, m_logger):
        """
        Alice has sent 100 coins to Bob, using 1 as Transaction fee. Now we need to undo this.
        """
        self.tx.sign(self.alice)
        ots_key = self.alice.ots_index - 1

        addresses_state = {
            self.alice.address:
            OptimizedAddressState.get_default(self.alice.address),
            self.bob.address:
            OptimizedAddressState.get_default(self.bob.address)
        }
        addresses_state[self.alice.address].pbdata.balance = 200
        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=1,
                                         total_coin_supply=100,
                                         current_dev_config=config.dev,
                                         write_access=True,
                                         my_db=self.state._db,
                                         batch=None)
        state_container.paginated_bitfield.set_ots_key(addresses_state,
                                                       self.alice.address,
                                                       ots_key)
        state_container.paginated_bitfield.put_addresses_bitfield(None)

        self.assertTrue(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, ots_key))
        self.tx.apply(self.state, state_container)
        self.tx.revert(self.state, state_container)
        self.assertFalse(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, ots_key))
        self.assertEqual(0, addresses_state[self.alice.address].nonce)

        self.assertEqual(200, addresses_state[self.alice.address].balance)
        self.assertEqual(0, addresses_state[self.bob.address].balance)

        storage_key = state_container.paginated_tx_hash.generate_key(
            self.alice.address, 1)
        self.assertEqual(
            [], state_container.paginated_tx_hash.key_value[storage_key])

        storage_key = state_container.paginated_tx_hash.generate_key(
            self.bob.address, 1)
        self.assertEqual(
            [], state_container.paginated_tx_hash.key_value[storage_key])
Beispiel #9
0
    def test_get_optimized_address_state2(self):
        alice_xmss = get_alice_xmss()

        alice_address = alice_xmss.address
        address_state = OptimizedAddressState.get_optimized_address_state(self.state, alice_address)
        addresses_state = {
            alice_address: address_state
        }
        self.assertTrue(isinstance(address_state.address, bytes))
        OptimizedAddressState.put_optimized_addresses_state(self.state, addresses_state)
        address_state = OptimizedAddressState.get_optimized_address_state(self.state, alice_address)
        self.assertTrue(isinstance(address_state.address, bytes))
Beispiel #10
0
    def _validate_custom(self):
        if len(self.signatories) == 0:
            logger.warning("[MultiSigCreate] No Signatories found")
            return False

        for weight in self.weights:
            if weight == 0:
                logger.warning('Weight cannot be 0 - %s', weight)
                logger.warning('Invalid MultiSigCreate Transaction')
                return False

        if self.fee < 0:
            logger.warning('MultiSigCreate [%s] Invalid Fee = %d',
                           bin2hstr(self.txhash), self.fee)
            return False

        if self.total_weight < self.threshold:
            logger.warning(
                '[MultiSigCreate] Validation failed for %s because: Insufficient weight',
                bin2hstr(self.txhash))
            logger.warning('Total weight: %s, Threshold: %s',
                           self.total_weight, self.threshold)
            return False

        if len(set(self.signatories)) != len(self.signatories):
            logger.warning(
                '[MultiSigCreate] Signatories list include duplicate signatories'
            )
            return False

        if len(self.signatories) != len(self.weights):
            logger.warning(
                '[MultiSigCreate] Mismatch number of signatories & weights')
            logger.warning('>> Length of signatories %s',
                           len(self.signatories))
            logger.warning('>> Length of weights %s', len(self.weights))
            return False

        if not OptimizedAddressState.address_is_valid(self.addr_from):
            logger.warning('[MultiSigCreate] Invalid address addr_from: %s',
                           bin2hstr(self.addr_from))
            return False

        for signatory in self.signatories:
            if not OptimizedAddressState.address_is_valid(signatory):
                logger.warning('[MultiSigCreate] Invalid address addr_to: %s',
                               bin2hstr(signatory))
                return False

        return True
Beispiel #11
0
    def test_revert_state_changes_for_PK_master_slave_XMSS(self, m_logger):
        addresses_state = {
            self.alice.address:
            OptimizedAddressState.get_default(self.alice.address),
            self.slave.address:
            OptimizedAddressState.get_default(self.slave.address)
        }
        addresses_state[self.alice.address].pbdata.balance = 101
        addresses_state[self.slave.address].pbdata.nonce = 1

        tx = TransferTransaction.create(addrs_to=[self.bob.address],
                                        amounts=[100],
                                        message_data=None,
                                        fee=1,
                                        xmss_pk=self.slave.pk,
                                        master_addr=self.alice.address)
        tx.sign(self.slave)
        ots_key = self.slave.ots_index - 1
        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=1,
                                         total_coin_supply=100,
                                         current_dev_config=config.dev,
                                         write_access=True,
                                         my_db=self.state._db,
                                         batch=None)
        state_container.paginated_bitfield.set_ots_key(addresses_state,
                                                       self.slave.address,
                                                       ots_key)
        state_container.paginated_bitfield.put_addresses_bitfield(None)

        self.assertTrue(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.slave.address, ots_key))
        self.assertFalse(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, self.alice.ots_index))
        tx._apply_state_changes_for_PK(state_container)
        tx._revert_state_changes_for_PK(state_container)
        self.assertFalse(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.slave.address, ots_key))
        self.assertFalse(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, self.alice.ots_index))
Beispiel #12
0
    def test_apply_state_changes_for_PK_master_slave_XMSS(self, m_logger):
        """
        If the TX was signed by a slave XMSS, the slave XMSS's AddressState should be updated (not the master's).
        :return:
        """
        tx = TransferTransaction.create(addrs_to=[self.bob.address],
                                        amounts=[100],
                                        message_data=None,
                                        fee=1,
                                        xmss_pk=self.slave.pk,
                                        master_addr=self.alice.address)
        addresses_state = {
            self.alice.address:
            OptimizedAddressState.get_default(self.alice.address),
            self.slave.address:
            OptimizedAddressState.get_default(self.slave.address)
        }
        tx.sign(self.slave)
        ots_key = self.slave.ots_index - 1
        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=1,
                                         total_coin_supply=100,
                                         current_dev_config=config.dev,
                                         write_access=True,
                                         my_db=self.state._db,
                                         batch=None)

        self.assertFalse(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.slave.address, ots_key))
        self.assertFalse(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, self.alice.ots_index))
        tx._apply_state_changes_for_PK(state_container)
        self.assertTrue(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.slave.address, ots_key))
        self.assertFalse(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, self.alice.ots_index))

        self.assertEqual(1, addresses_state[self.slave.address].nonce)
        self.assertEqual(0, addresses_state[self.alice.address].nonce)
Beispiel #13
0
    def test_revert_transfer_txn_tx_sends_to_self(self, m_logger):
        """
        Alice sent coins to herself, but she still lost the Transaction fee. Undo this.
        """
        addresses_state = {
            self.alice.address:
            OptimizedAddressState.get_default(self.alice.address),
            self.bob.address:
            OptimizedAddressState.get_default(self.bob.address)
        }
        addresses_state[self.alice.address].pbdata.balance = 200

        tx = TransferTransaction.create(addrs_to=[self.alice.address],
                                        amounts=[100],
                                        message_data=None,
                                        fee=1,
                                        xmss_pk=self.alice.pk)
        tx.sign(self.alice)
        ots_key = self.alice.ots_index - 1
        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=1,
                                         total_coin_supply=100,
                                         current_dev_config=config.dev,
                                         write_access=True,
                                         my_db=self.state._db,
                                         batch=None)
        state_container.paginated_bitfield.set_ots_key(addresses_state,
                                                       self.alice.address,
                                                       ots_key)
        state_container.paginated_bitfield.put_addresses_bitfield(None)

        self.assertTrue(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, ots_key))
        tx.apply(self.state, state_container)
        tx.revert(self.state, state_container)
        self.assertFalse(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, ots_key))

        self.assertEqual(200, addresses_state[self.alice.address].balance)
        self.assertEqual(0, addresses_state[self.bob.address].balance)
Beispiel #14
0
    def test_update_used_page_in_address_state(self):
        alice_xmss = get_alice_xmss(4)
        address = alice_xmss.address
        address_state = OptimizedAddressState.get_default(address)
        addresses_state = {address: address_state}
        paginated_bitfield = PaginatedBitfield(True, self.state._db)
        key = paginated_bitfield.generate_bitfield_key(address, 1)
        paginated_bitfield.update_used_page_in_address_state(address, addresses_state, 1)
        self.assertEqual(address_state.ots_bitfield_used_page, 0)

        for i in range(0, 16):
            paginated_bitfield.set_ots_key(addresses_state, address, i)
            if i != 15:
                self.assertEqual(address_state.ots_bitfield_used_page, 0)
            else:
                self.assertEqual(address_state.ots_bitfield_used_page, 1)

        for i in range(0, 16):
            ots_bitfield = paginated_bitfield.key_value[key]
            ots_key_index = i % config.dev.ots_tracking_per_page
            offset = ots_key_index >> 3
            relative = ots_key_index % 8
            bitfield = bytearray(ots_bitfield[offset])
            self.assertEqual(bytes([bitfield[0] >> relative & 1]), b'\x01')

        self.assertEqual(address_state.ots_bitfield_used_page, 1)
Beispiel #15
0
    def validate_all(self, state_container: StateContainer, check_nonce=True) -> bool:
        if self.pbdata.WhichOneof('transactionType') == 'coinbase':
            if not self._validate_extended(state_container):
                return False
            return True

        if not self.validate(True):  # It also calls _validate_custom
            return False
        if not self.validate_slave(state_container):
            return False
        if not self._validate_extended(state_container):
            return False

        addr_from_pk = bytes(QRLHelper.getAddress(self.PK))
        addr_from_pk_state = state_container.addresses_state[addr_from_pk]

        expected_nonce = addr_from_pk_state.nonce + 1

        if check_nonce and self.nonce != expected_nonce:
            logger.warning('nonce incorrect, invalid tx')
            logger.warning('subtype: %s', self.type)
            logger.warning('%s actual: %s expected: %s',
                           OptimizedAddressState.bin_to_qaddress(addr_from_pk),
                           self.nonce,
                           expected_nonce)
            return False

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

        return True
Beispiel #16
0
    def get_block_to_mine(self,
                          wallet_address,
                          tx_pool,
                          last_block,
                          last_block_difficulty) -> list:
        dev_config = self._chain_manager.get_config_by_block_number(last_block.block_number + 1)
        try:
            mining_address = bytes(hstr2bin(wallet_address[1:].decode()))

            if not OptimizedAddressState.address_is_valid(mining_address):
                raise ValueError("[get_block_to_mine] Invalid Wallet Address %s", wallet_address)
        except Exception as e:
            raise ValueError("Error while decoding wallet address %s", e)

        if self._mining_block:
            if last_block.headerhash == self._mining_block.prev_headerhash:
                if self._mining_block.transactions[0].coinbase.addr_to == mining_address:
                    return [bin2hstr(self._mining_block.mining_blob(dev_config)),
                            int(bin2hstr(self._current_difficulty), 16)]
                else:
                    self._mining_block.update_mining_address(dev_config, mining_address)  # Updates only Miner Address

        self.prepare_next_unmined_block_template(mining_address,
                                                 tx_pool,
                                                 last_block,
                                                 last_block_difficulty,
                                                 dev_config=dev_config)

        return [bin2hstr(self._mining_block.mining_blob(dev_config)),
                int(bin2hstr(self._current_difficulty), 16)]
Beispiel #17
0
    def test_get_paginated_data(self, mock_dev_config):
        with set_qrl_dir('no_data'):
            state = State()
            p = PaginatedData(b'p_tx_hash', True, state._db)
            alice_address_state = OptimizedAddressState.get_default(
                address=self.alice.address)

            total_hashes = 25
            expected_full_hash = []
            for i in range(0, total_hashes):
                tx_hash = b'p_tx_hash_' + i.to_bytes(
                    8, byteorder='big', signed=False)
                p.insert(alice_address_state, tx_hash)
                expected_full_hash.append(tx_hash)

            p.put_paginated_data(None)

            found_full_hash = []
            expected_data_count = [10, 10, 5]
            for i in range(0, (total_hashes // config.dev.data_per_page) + 1):
                data = p.get_paginated_data(
                    self.alice.address, (i + 1) * config.dev.data_per_page - 1)
                self.assertEqual(len(data), expected_data_count[i])
                found_full_hash.extend(data)

            self.assertEqual(expected_full_hash, found_full_hash)
Beispiel #18
0
    def test_revert_paginated_data2(self, mock_dev_config):
        with set_qrl_dir('no_data'):
            state = State()
            p = PaginatedData(b'p_tx_hash', True, state._db)
            alice_address_state = OptimizedAddressState.get_default(
                address=self.alice.address)

            for i in range(0, 25):
                p.insert(
                    alice_address_state, b'p_tx_hash_' +
                    i.to_bytes(8, byteorder='big', signed=False))

            p.put_paginated_data(None)

            full_hash = []
            for i in range(0, (25 // config.dev.data_per_page) + 1):
                data = p.get_paginated_data(
                    self.alice.address, (i + 1) * config.dev.data_per_page - 1)
                full_hash.extend(data)

            for tx_hash in full_hash[-1::-1]:
                p.remove(alice_address_state, tx_hash)
            p.put_paginated_data(None)

            self.assertEqual(
                alice_address_state.get_counter_by_name(b'p_tx_hash'), 0)

            self.assertEqual(
                len(p.get_paginated_data(alice_address_state.address, 22)), 0)

            self.assertEqual(
                len(p.get_paginated_data(alice_address_state.address, 12)), 0)

            self.assertEqual(
                len(p.get_paginated_data(alice_address_state.address, 2)), 0)
Beispiel #19
0
    def _load_multi_sig_spend_txn_hashes(self,
                                         address: bytes,
                                         item_per_page: int,
                                         page_number: int,
                                         mode: int) -> list:
        if OptimizedAddressState.address_is_valid(address):
            address_state = self._chain_manager.get_optimized_address_state(address)
        elif MultiSigAddressState.address_is_valid(address):
            address_state = self._chain_manager.get_multi_sig_address_state(address)
        else:
            return []

        start_item_index = max(0, address_state.multi_sig_spend_count() - item_per_page * page_number)
        end_item_index = min(address_state.multi_sig_spend_count(), start_item_index + item_per_page)

        if mode > 0:
            start_item_index = 0
            end_item_index = address_state.multi_sig_spend_count()

        transaction_hashes = self._chain_manager.get_multi_sig_spend_txn_hashes(address,
                                                                                start_item_index)
        actual_start_item_index = (start_item_index // config.dev.data_per_page) * config.dev.data_per_page
        multi_sig_spend_txn_hashes = transaction_hashes[start_item_index - actual_start_item_index:]
        while actual_start_item_index < end_item_index and len(multi_sig_spend_txn_hashes) < item_per_page:
            actual_start_item_index += config.dev.data_per_page
            multi_sig_spend_txn_hashes.extend(self._chain_manager.get_multi_sig_spend_txn_hashes(address,
                                                                                                 actual_start_item_index))
        return multi_sig_spend_txn_hashes[:item_per_page][-1::-1]
Beispiel #20
0
    def get_optimized_address_state(self, address: bytes) -> OptimizedAddressState:
        if address != config.dev.coinbase_address and not OptimizedAddressState.address_is_valid(address):
            raise ValueError("Invalid Address")

        address_state = self._chain_manager.get_optimized_address_state(address)

        return address_state
Beispiel #21
0
    def test_sync_state_change_synced(self):
        chain_manager = Mock()
        chain_manager.height = 0
        chain_manager.get_block = MagicMock(return_value=GenesisBlock())
        chain_manager.last_block = GenesisBlock()
        chain_manager.tx_pool = Mock()
        chain_manager.tx_pool.transaction_pool = []
        chain_manager.tx_pool.transactions = chain_manager.tx_pool.transaction_pool

        get_block_metadata_response = Mock()
        get_block_metadata_response.block_difficulty = StringToUInt256('2')
        chain_manager.get_block_metadata = MagicMock(
            return_value=get_block_metadata_response)

        alice_xmss = get_alice_xmss()
        chain_manager._state.get_address_state = MagicMock(
            return_value=OptimizedAddressState.get_default(alice_xmss.address))
        chain_manager._state.get_measurement = MagicMock(return_value=60)

        p2p_factory = Mock()
        sync_state = Mock()
        time_provider = Mock()
        # Setting mining enabled False, when update_note_state set to synced,
        # starts miner which is not exited properly by unit test
        with set_mining_enabled(False):
            node = POW(chain_manager=chain_manager,
                       p2p_factory=p2p_factory,
                       sync_state=sync_state,
                       time_provider=time_provider,
                       mining_address=get_random_xmss().address,
                       mining_thread_count=0)

            self.assertIsNotNone(node)
            node.update_node_state(ESyncState.synced)
Beispiel #22
0
    def test_ots_key_reuse(self, mock_ots_bitfield_size, mock_ots_tracking_per_page):
        """
        Randomly using OTS key
        :return:
        """
        with set_qrl_dir('no_data'):
            state = State()

            mock_ots_bitfield_size.return_value = ceil(config.dev.ots_tracking_per_page / 8)
            paginated_bitfield = PaginatedBitfield(True, state._db)

            alice_xmss = get_alice_xmss(12)
            address = alice_xmss.address
            address_state = OptimizedAddressState.get_default(address)
            addresses_state = {address: address_state}
            bitfield_data = paginated_bitfield.get_paginated_data(address, 1)
            self.assertFalse(paginated_bitfield.ots_key_reuse(bitfield_data, 0))

            paginated_bitfield.set_ots_key(addresses_state, address, 0)
            bitfield_data = paginated_bitfield.get_paginated_data(address, 1)
            # False, as bitfield has been set but has not been written to state.
            self.assertFalse(paginated_bitfield.ots_key_reuse(bitfield_data, 0))

            # Writing bitfield to the state.
            paginated_bitfield.put_addresses_bitfield(None)
            bitfield_data = paginated_bitfield.get_paginated_data(address, 1)
            self.assertTrue(paginated_bitfield.ots_key_reuse(bitfield_data, 0))
Beispiel #23
0
    def test_set_ots_key2(self, mock_ots_bitfield_size, mock_ots_tracking_per_page):
        """
        Randomly using OTS key
        :return:
        """
        with set_qrl_dir('no_data'):
            state = State()
            mock_ots_bitfield_size.return_value = ceil(config.dev.ots_tracking_per_page / 8)

            alice_xmss = get_alice_xmss(12)
            address = alice_xmss.address
            address_state = OptimizedAddressState.get_default(address)
            addresses_state = {address: address_state}
            paginated_bitfield = PaginatedBitfield(True, state._db)
            paginated_bitfield.update_used_page_in_address_state(address, addresses_state, 1)
            self.assertEqual(address_state.ots_bitfield_used_page, 0)

            ots_indexes = list(range(0, 2**alice_xmss.height))
            random.shuffle(ots_indexes)
            for i in ots_indexes:
                paginated_bitfield.set_ots_key(addresses_state, address, i)
                if i == ots_indexes[-1]:
                    self.assertEqual(address_state.ots_bitfield_used_page, 4)

            self.assertEqual(address_state.ots_bitfield_used_page, 4)
Beispiel #24
0
    def test_insert(self):
        with set_qrl_dir('no_data'):
            state = State()
            p = PaginatedData(b'p_tx_hash', True, state._db)

            p.insert(OptimizedAddressState.get_default(b'a'), b'10')
            self.assertEqual(p.get_value(b'a', 0), [b'10'])
Beispiel #25
0
    def test_getHeight(self):
        with set_qrl_dir('no_data'):
            db_state = State()
            alice_xmss = get_alice_xmss()
            optimized_address_state = OptimizedAddressState.create(address=alice_xmss.address,
                                                                   nonce=25,
                                                                   balance=10,
                                                                   ots_bitfield_used_page=0,
                                                                   transaction_hash_count=0,
                                                                   tokens_count=0,
                                                                   lattice_pk_count=0,
                                                                   slaves_count=0,
                                                                   multi_sig_address_count=0)
            addresses_state = {optimized_address_state.address: optimized_address_state}
            AddressState.put_addresses_state(db_state, addresses_state)

            p2p_factory = Mock(spec=P2PFactory)
            chain_manager = ChainManager(db_state)
            chain_manager._last_block = Mock()
            chain_manager._last_block.block_number = 100

            qrlnode = QRLNode(mining_address=b'')
            qrlnode.set_chain_manager(chain_manager)
            qrlnode._p2pfactory = p2p_factory
            qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1']

            service = PublicAPIService(qrlnode)
            context = Mock(spec=ServicerContext)
            request = qrl_pb2.GetHeightReq()
            response = service.GetHeight(request=request, context=context)
            self.assertEqual(response.height, 100)
Beispiel #26
0
    def test_update_used_page_in_address_state4(self, mock_ots_bitfield_size, mock_ots_tracking_per_page):
        mock_ots_bitfield_size.return_value = ceil(config.dev.ots_tracking_per_page / 8)

        alice_xmss = get_alice_xmss(12)
        address = alice_xmss.address
        address_state = OptimizedAddressState.get_default(address)
        addresses_state = {address: address_state}
        paginated_bitfield = PaginatedBitfield(True, self.state._db)
        paginated_bitfield.update_used_page_in_address_state(address, addresses_state, 1)
        self.assertEqual(address_state.ots_bitfield_used_page, 0)

        for i in range(2048, 3072):
            paginated_bitfield.set_ots_key(addresses_state, address, i)
            self.assertEqual(address_state.ots_bitfield_used_page, 0)

        for i in range(1024, 2048):
            paginated_bitfield.set_ots_key(addresses_state, address, i)
            self.assertEqual(address_state.ots_bitfield_used_page, 0)

        for i in range(0, 1024):
            paginated_bitfield.set_ots_key(addresses_state, address, i)
            if i + 1 == 1024:
                self.assertEqual(address_state.ots_bitfield_used_page, 3)

        for i in range(3072, 2 ** alice_xmss.height):
            paginated_bitfield.set_ots_key(addresses_state, address, i)
            if i + 1 == 2 ** alice_xmss.height:
                self.assertEqual(address_state.ots_bitfield_used_page, 4)
            else:
                self.assertEqual(address_state.ots_bitfield_used_page, 3)

        self.assertEqual(address_state.ots_bitfield_used_page, 4)
Beispiel #27
0
    def test_apply_transfer_txn_tx_sends_to_self(self, m_logger):
        """
        If you send coins to yourself, you should only lose the fee for the Transaction.
        """
        addresses_state = {
            self.alice.address:
            OptimizedAddressState.get_default(self.alice.address),
            self.bob.address:
            OptimizedAddressState.get_default(self.bob.address),
            self.slave.address:
            OptimizedAddressState.get_default(self.slave.address)
        }
        addresses_state[self.alice.address].pbdata.balance = 200

        tx = TransferTransaction.create(addrs_to=[self.alice.address],
                                        amounts=[100],
                                        message_data=None,
                                        fee=1,
                                        xmss_pk=self.alice.pk)
        tx.sign(self.alice)
        ots_key = self.alice.ots_index - 1
        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=1,
                                         total_coin_supply=100,
                                         current_dev_config=config.dev,
                                         write_access=True,
                                         my_db=self.state._db,
                                         batch=None)
        self.assertFalse(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, ots_key))
        tx.apply(self.state, state_container)
        self.assertTrue(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, ots_key))

        self.assertEqual(199, addresses_state[self.alice.address].balance)
        storage_key = state_container.paginated_tx_hash.generate_key(
            self.alice.address, 1)
        self.assertIn(tx.txhash,
                      state_container.paginated_tx_hash.key_value[storage_key])
Beispiel #28
0
    def _validate_extended(self, state_container: StateContainer):
        if len(self.symbol
               ) > state_container.current_dev_config.max_token_symbol_length:
            logger.warning('Token Symbol Length exceeds maximum limit')
            logger.warning('Found Symbol Length %s', len(self.symbol))
            logger.warning(
                'Expected Symbol length %s',
                state_container.current_dev_config.max_token_symbol_length)
            return False

        if len(self.name
               ) > state_container.current_dev_config.max_token_name_length:
            logger.warning('Token Name Length exceeds maximum limit')
            logger.warning('Found Name Length %s', len(self.symbol))
            logger.warning(
                'Expected Name length %s',
                state_container.current_dev_config.max_token_name_length)
            return False

        if not OptimizedAddressState.address_is_valid(self.addr_from):
            logger.warning('Invalid address addr_from: %s',
                           bin2hstr(self.addr_from))
            return False

        tx_balance = state_container.addresses_state[self.addr_from].balance

        if not OptimizedAddressState.address_is_valid(self.owner):
            logger.warning('Invalid address owner_addr: %s',
                           bin2hstr(self.owner))
            return False

        for address_balance in self.initial_balances:
            if not OptimizedAddressState.address_is_valid(
                    address_balance.address):
                logger.warning('Invalid address in initial_balances: %s',
                               bin2hstr(address_balance.address))
                return False

        if tx_balance < self.fee:
            logger.warning(
                'TokenTxn State validation failed for %s because: Insufficient funds',
                bin2hstr(self.txhash))
            logger.warning('balance: %s, Fee: %s', tx_balance, self.fee)
            return False

        return True
Beispiel #29
0
    def test_apply_transfer_txn_multi_send(self, m_logger):
        """
        Test that apply_state_changes() also works with multiple recipients.
        """
        addresses_state = {
            self.alice.address:
            OptimizedAddressState.get_default(self.alice.address),
            self.bob.address:
            OptimizedAddressState.get_default(self.bob.address),
            self.slave.address:
            OptimizedAddressState.get_default(self.slave.address)
        }
        addresses_state[self.alice.address].pbdata.balance = 200

        tx_multisend = TransferTransaction.create(
            addrs_to=[self.bob.address, self.slave.address],
            amounts=[20, 20],
            message_data=None,
            fee=1,
            xmss_pk=self.alice.pk)
        tx_multisend.sign(self.alice)
        ots_key = self.alice.ots_index - 1
        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=1,
                                         total_coin_supply=100,
                                         current_dev_config=config.dev,
                                         write_access=True,
                                         my_db=self.state._db,
                                         batch=None)
        self.assertFalse(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, ots_key))
        tx_multisend.apply(self.state, state_container)
        self.assertTrue(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, ots_key))

        self.assertEqual(159, addresses_state[self.alice.address].balance)
        self.assertEqual(20, addresses_state[self.bob.address].balance)
        self.assertEqual(20, addresses_state[self.slave.address].balance)
Beispiel #30
0
    def test_check_stale_txn(self, m_is_full_transaction_pool, m_config):
        """
        Stale Transactions are Transactions that were supposed to go into block 5, but for some reason didn't make it.
        They languish in TransactionPool until check_stale_txn() checks the Pool and updates the tx_info to make them
        go into a higher block.
        For each stale transaction, P2PFactory.broadcast_tx() will be called.
        """

        # Redefine at what point should txs be considered stale
        m_config.user.stale_transaction_threshold = 2
        bob_xmss = get_bob_xmss(4)
        alice_xmss = get_alice_xmss(4)

        tx1 = TransferTransaction.create(addrs_to=[bob_xmss.address],
                                         amounts=[1000000],
                                         message_data=None,
                                         fee=1,
                                         xmss_pk=alice_xmss.pk)
        tx1.sign(alice_xmss)
        tx2 = TransferTransaction.create(addrs_to=[bob_xmss.address],
                                         amounts=[10000],
                                         message_data=None,
                                         fee=1,
                                         xmss_pk=alice_xmss.pk)
        tx2.sign(alice_xmss)
        m_broadcast_tx = Mock(
            name='Mock Broadcast TX function (in P2PFactory)')
        self.txpool.add_tx_to_pool(tx1, 5)
        self.txpool.add_tx_to_pool(tx2, 5)
        self.txpool.set_broadcast_tx(m_broadcast_tx)

        with set_qrl_dir('no_data'):
            state = State()
            chain_manager = ChainManager(state)
            self.txpool.check_stale_txn(chain_manager.new_state_container,
                                        chain_manager.update_state_container,
                                        8)

            self.assertEqual(m_broadcast_tx.call_count, 0)

            m = MockFunction()
            bob_address_state = OptimizedAddressState.get_default(
                bob_xmss.address)
            bob_address_state.pbdata.balance = 1000000000000
            m.put(bob_xmss.address, bob_address_state)
            chain_manager.get_optimized_address_state = m.get
            tx3 = TransferTransaction.create(addrs_to=[alice_xmss.address],
                                             amounts=[10000],
                                             message_data=None,
                                             fee=1,
                                             xmss_pk=bob_xmss.pk)
            tx3.sign(bob_xmss)
            self.txpool.add_tx_to_pool(tx3, 5)
            self.txpool.check_stale_txn(chain_manager.new_state_container,
                                        chain_manager.update_state_container,
                                        8)

            self.assertEqual(m_broadcast_tx.call_count, 1)