Ejemplo n.º 1
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)
Ejemplo n.º 2
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)
Ejemplo n.º 3
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)
Ejemplo n.º 4
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])
Ejemplo n.º 5
0
    def test_apply_coinbase_txn(self, m_logger):
        """
        Alice earned some coins.
        """
        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 = 1000000000000000
        tx = CoinBase.create(config.dev, self.amount, self.alice.address,
                             self.mock_blockheader.block_number)
        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)
        # self.state.apply(tx, addresses_state)
        tx.apply(self.state, state_container)
        reward = int(
            block_reward(self.mock_blockheader.block_number, config.dev))
        self.assertEqual(1000000000000000 - reward,
                         addresses_state[config.dev.coinbase_address].balance)

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

        storage_key = state_container.paginated_tx_hash.generate_key(
            self.alice.address, 1)
        self.assertEqual(
            [tx.txhash],
            state_container.paginated_tx_hash.key_value[storage_key])
Ejemplo n.º 6
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)
Ejemplo n.º 7
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)
Ejemplo n.º 8
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)
Ejemplo n.º 9
0
    def test_validate_all(self):
        tx = MultiSigCreate.create(signatories=self.signatories,
                                   weights=self.weights,
                                   threshold=self.threshold,
                                   fee=5,
                                   xmss_pk=self.random.pk,
                                   master_addr=self.alice.address)
        tx.sign(self.random)
        tx.pbdata.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)

        addresses_state = {
            self.alice.address: alice_address_state,
            self.random.address: random_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.pbdata.nonce = 2
        result = tx.validate_all(state_container)
        self.assertFalse(result)  # False as nonce is invalid
Ejemplo n.º 10
0
    def test_put_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)

            for i in range(0, 10):
                p.insert(
                    alice_address_state, b'p_tx_hash_' +
                    i.to_bytes(8, byteorder='big', signed=False))
                self.assertEqual(
                    alice_address_state.get_counter_by_name(p.name), i + 1)

            p.put_paginated_data(None)
            self.assertEqual(alice_address_state.get_counter_by_name(p.name),
                             10)

            for i in range(10, 25):
                p.insert(
                    alice_address_state, b'p_tx_hash_' +
                    i.to_bytes(8, byteorder='big', signed=False))
                self.assertEqual(
                    alice_address_state.get_counter_by_name(p.name), i + 1)

            p.put_paginated_data(None)
            self.assertEqual(alice_address_state.get_counter_by_name(p.name),
                             25)
            self.assertEqual(len(p.key_value), 0)

            pages_data = []
            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)
                pages_data.append(data)

            self.assertEqual(len(pages_data), 3)

            self.assertEqual(len(pages_data[0]), 10)
            for i in range(0, 10):
                self.assertEqual(
                    pages_data[0][i], b'p_tx_hash_' +
                    i.to_bytes(8, byteorder='big', signed=False))

            self.assertEqual(len(pages_data[1]), 10)
            for i in range(10, 20):
                self.assertEqual(
                    pages_data[1][i - 10], b'p_tx_hash_' +
                    i.to_bytes(8, byteorder='big', signed=False))

            self.assertEqual(len(pages_data[2]), 5)
            for i in range(20, 25):
                self.assertEqual(
                    pages_data[2][i - 20], b'p_tx_hash_' +
                    i.to_bytes(8, byteorder='big', signed=False))
    def test_revert_transfer_token_txn_multi_send(self):
        """
        Alice has 1100 tokens and 100 QRL, Bob and Slave have none. Alice sends some tokens to Bob and Slave.
        Undo this.
        """
        slave = get_slave_xmss()
        self.params["addrs_to"] = [self.bob.address, slave.address]
        self.params["amounts"] = [100, 100]

        tx = TransferTokenTransaction.create(**self.params)
        tx.sign(self.alice)
        addresses_state = dict(self.addresses_state)
        addresses_state[self.alice.address].pbdata.balance = 100
        addresses_state[self.bob.address].pbdata.balance = 0
        addresses_state[slave.address] = OptimizedAddressState.get_default(
            slave.address)
        tokens = Indexer(b'token', None)
        tokens.data[(self.alice.address,
                     tx.token_txhash)] = TokenBalance(balance=1100)

        state_container = StateContainer(addresses_state=addresses_state,
                                         tokens=tokens,
                                         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=1000,
                                         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, 0)

        self.assertTrue(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, 0))
        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, 0))

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

        self.assertEqual(
            tokens.data[(self.alice.address, tx.token_txhash)].balance, 1100)
        self.assertEqual(
            tokens.data[(self.bob.address, tx.token_txhash)].balance, 0)
        self.assertEqual(tokens.data[(slave.address, tx.token_txhash)].balance,
                         0)
Ejemplo n.º 12
0
    def test_apply_token_txn_signed_by_slave_xmss(self):
        """
        Alice creates a token, gives herself and Bob some tokens.
        But she uses a XMSS slave to sign it.
        """
        initial_balances = [qrl_pb2.AddressAmount(address=self.alice.address, amount=1000),
                            qrl_pb2.AddressAmount(address=self.bob.address, amount=2000)]
        slave = get_slave_xmss()
        self.params["initial_balances"] = initial_balances
        self.params["xmss_pk"] = slave.pk
        self.params["master_addr"] = self.alice.address
        tx = TokenTransaction.create(**self.params)
        tx.sign(slave)

        # Now that we have the Slave XMSS address, we should add it to AddressState so that apply_state_changes()
        # can do something with it
        addresses_state = dict(self.addresses_state)
        addresses_state[slave.address] = OptimizedAddressState.get_default(slave.address)
        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=1000,
                                         current_dev_config=config.dev,
                                         write_access=True,
                                         my_db=self.state._db,
                                         batch=None)
        tx.apply(self.state, state_container)

        self.assertEqual(addresses_state[self.alice.address].balance, 99)
        self.assertEqual(3, len(state_container.paginated_tx_hash.key_value))

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

        storage_key = state_container.paginated_tx_hash.generate_key(self.bob.address, 1)
        self.assertIn(storage_key, state_container.paginated_tx_hash.key_value)
        self.assertEqual([tx.txhash], state_container.paginated_tx_hash.key_value[storage_key])

        storage_key = state_container.paginated_tx_hash.generate_key(slave.address, 1)
        self.assertIn(storage_key, state_container.paginated_tx_hash.key_value)
        self.assertEqual([tx.txhash], state_container.paginated_tx_hash.key_value[storage_key])

        self.assertEqual(2, len(state_container.tokens.data))
        self.assertIn((self.bob.address, tx.txhash), state_container.tokens.data)
        self.assertEqual(1000, state_container.tokens.data[(self.alice.address, tx.txhash)].balance)
        self.assertEqual(2000, state_container.tokens.data[(self.bob.address, tx.txhash)].balance)

        self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(slave.address, 0))
        self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0))
        self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.bob.address, 0))
Ejemplo n.º 13
0
    def test_apply_transfer_txn(self, m_logger):
        """
        apply_state_changes() is the part that actually updates everybody's balances.
        Then it forwards the addresses_state to _apply_state_changes_for_PK(), which updates everybody's addresses's
        nonce, OTS key index, and associated TX hashes
        If there is no AddressState for a particular Address, nothing is done.
        """
        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),
            self.slave.address:
            OptimizedAddressState.get_default(self.slave.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)
        self.assertFalse(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, ots_key))
        self.tx.apply(self.state, state_container)
        self.assertTrue(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, ots_key))

        # Now Alice should have 99 coins left (200 - 100 - 1) and Bob should have 100 coins.
        self.assertEqual(99, addresses_state[self.alice.address].balance)
        self.assertEqual(100, addresses_state[self.bob.address].balance)
Ejemplo n.º 14
0
    def test_unset_ots_key(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(3072, 2 ** alice_xmss.height))
            random.shuffle(ots_indexes)
            for i in ots_indexes:
                paginated_bitfield.set_ots_key(addresses_state, address, i)
                self.assertEqual(address_state.ots_bitfield_used_page, 0)

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

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

            ots_indexes = list(range(0, 1024))
            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)
                else:
                    self.assertEqual(address_state.ots_bitfield_used_page, 0)

            self.assertEqual(address_state.ots_bitfield_used_page, 4)

            paginated_bitfield.unset_ots_key(addresses_state, address, 2049)
            self.assertEqual(address_state.ots_bitfield_used_page, 2)

            paginated_bitfield.unset_ots_key(addresses_state, address, 1023)
            self.assertEqual(address_state.ots_bitfield_used_page, 0)

            paginated_bitfield.set_ots_key(addresses_state, address, 1023)
            self.assertEqual(address_state.ots_bitfield_used_page, 2)
Ejemplo n.º 15
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)
Ejemplo n.º 16
0
 def test_load_bitfield_and_ots_key_reuse(self):
     with set_qrl_dir('no_data'):
         state = State()
         alice_xmss = get_alice_xmss(4)
         paginated_bitfield = PaginatedBitfield(True, state._db)
         self.assertFalse(paginated_bitfield.load_bitfield_and_ots_key_reuse(alice_xmss.address,
                                                                             0))
         addresses_state = {
             alice_xmss.address: OptimizedAddressState.get_default(alice_xmss.address)
         }
         paginated_bitfield.set_ots_key(addresses_state, alice_xmss.address, 0)
         self.assertTrue(paginated_bitfield.load_bitfield_and_ots_key_reuse(alice_xmss.address,
                                                                            0))
Ejemplo n.º 17
0
    def setUp(self):
        with set_qrl_dir('no_data'):
            self.state = State()
        self.chain_manager = ChainManager(self.state)
        self.alice = get_alice_xmss()
        self.bob = get_bob_xmss()
        self.slave = get_slave_xmss()

        self.tx1 = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[10],
                                              message_data=None, fee=1, xmss_pk=self.alice.pk)
        self.tx2 = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[10],
                                              message_data=None, fee=1, xmss_pk=self.slave.pk,
                                              master_addr=self.alice.address)
        self.tx1._data.nonce = 3
        self.tx2._data.nonce = 6
        self.tx1.sign(self.alice)
        self.tx2.sign(self.slave)

        self.block_attrs = {
            "dev_config": config.dev,
            "block_number": 5,
            "prev_headerhash": bytes(sha2_256(b'test')),
            "prev_timestamp": 10,
            "transactions": [self.tx1, self.tx2],
            "miner_address": self.alice.address,
            "seed_height": 0,
            "seed_hash": None,
        }
        self.coinbase_addrstate_attrs = OptimizedAddressState.get_default(config.dev.coinbase_address)
        self.coinbase_addrstate_attrs.update_balance(None,
                                                     int(config.dev.coin_remaining_at_genesis * config.dev.shor_per_quanta))
        self.bob_addrstate_attrs = OptimizedAddressState.get_default(self.bob.address)
        self.bob_addrstate_attrs.update_balance(None, 20)
        self.alice_addrstate_attrs = OptimizedAddressState.get_default(self.alice.address)
        self.alice_addrstate_attrs.update_balance(None, 100)
        self.alice_addrstate_attrs.pbdata.nonce = 2
        self.slave_addrstate_attrs = OptimizedAddressState.get_default(self.slave.address)
        self.slave_addrstate_attrs.pbdata.nonce = 5
Ejemplo n.º 18
0
    def setUp(self):
        with set_qrl_dir('no_data'):
            self.state = State()

        self.alice = get_alice_xmss()
        self.slave = get_slave_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.slave.address:
            OptimizedAddressState.get_default(self.slave.address)
        }

        self.params = {
            "slave_pks": [self.slave.pk],
            "access_types": [0],
            "fee": 1,
            "xmss_pk": self.alice.pk
        }
        self.unused_chain_manager_mock = Mock(autospec=ChainManager,
                                              name='unused ChainManager')
Ejemplo n.º 19
0
    def test_validate_extended(self, m_logger):
        """
        validate_extended() handles these parts of the validation:
        1. Master/slave
        2. balance, amount + fee from AddressState
        3. OTS key reuse from AddressState
        :return:
        """
        alice_address_state = OptimizedAddressState.get_default(
            self.alice.address)
        addresses_state = {self.alice.address: alice_address_state}
        alice_address_state.pbdata.balance = 200

        self.tx.validate_slave = Mock(autospec=Transaction.validate_slave,
                                      return_value=True)

        self.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)
        result = self.tx.validate_all(state_container)
        self.assertTrue(result)

        # Suppose there was ots key reuse. The function should then return false.
        state_container.paginated_bitfield.set_ots_key(addresses_state,
                                                       self.tx.addr_from,
                                                       self.tx.ots_key)
        result = self.tx.validate_all(state_container)
        self.assertFalse(result)

        # Suppose the address doesn't have enough coins.
        alice_address_state.pbdata.balance = 99
        state_container.paginated_bitfield.set_ots_key(addresses_state,
                                                       self.tx.addr_from,
                                                       self.tx.ots_key)
        result = self.tx.validate_all(state_container)
        self.assertFalse(result)
Ejemplo n.º 20
0
    def test_update_used_page_in_address_state2(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)

        factor = min(config.dev.ots_tracking_per_page, 2 ** alice_xmss.height)
        for i in range(0, 2 ** alice_xmss.height):
            paginated_bitfield.set_ots_key(addresses_state, address, i)
            self.assertEqual(address_state.ots_bitfield_used_page, (i + 1) // factor)

        self.assertEqual(address_state.ots_bitfield_used_page, 4)
Ejemplo n.º 21
0
    def test_validate_extended(self):
        """
        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 = MultiSigCreate.create(signatories=self.signatories,
                                   weights=self.weights,
                                   threshold=self.threshold,
                                   fee=5,
                                   xmss_pk=self.alice.pk)
        tx.sign(self.alice)
        alice_address_state = OptimizedAddressState.get_default(
            address=self.alice.address)
        alice_address_state.pbdata.balance = 5

        addresses_state = {
            self.alice.address: alice_address_state,
        }
        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=10,
                                         total_coin_supply=100,
                                         current_dev_config=config.dev,
                                         write_access=True,
                                         my_db=None,
                                         batch=None)

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

        alice_address_state.pbdata.balance = 4
        result = tx._validate_extended(state_container)
        self.assertFalse(
            result)  # False due to insufficient balance to pay the txn fee

        alice_address_state.pbdata.balance = 6
        result = tx._validate_extended(state_container)
        self.assertTrue(result)
Ejemplo n.º 22
0
    def test_revert_state_changes_for_PK(self, m_logger):
        """
        This is just an undo function.
        :return:
        """
        addresses_state = {
            self.alice.address:
            OptimizedAddressState.get_default(self.alice.address)
        }
        addresses_state[self.alice.address].pbdata.balance = 101
        addresses_state[self.alice.address].pbdata.nonce = 1

        tx = TransferTransaction.create(addrs_to=[self.bob.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_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.alice.address, ots_key))
Ejemplo n.º 23
0
    def setUp(self):
        with set_qrl_dir('no_data'):
            self.state = State()

        self.alice = get_alice_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.params = {
            "message_hash": b'Test Message',
            "addr_to": None,
            "fee": 1,
            "xmss_pk": self.alice.pk
        }
        self.unused_chain_manager_mock = Mock(autospec=ChainManager,
                                              name='unused ChainManager')
Ejemplo n.º 24
0
    def test_unset_ots_key3(self, mock_ots_bitfield_size, mock_ots_tracking_per_page):
        """
        Features Tested
        - Sequentially marking OTS indexes as used
        - Sequentially marking OTS indexes as unused
        - ots_bitfield_used_page value with each OTS index being used

        Expectation
        - The ots_bitfield_used_page must increase by 1 for every sequential 1024 (ots_tracking_per_page) ots indexes
          marked as used

        :param mock_ots_bitfield_size:
        :param mock_ots_tracking_per_page:
        :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)

            total_ots = 2 ** alice_xmss.height
            for i in range(0, total_ots + 1):
                paginated_bitfield.set_ots_key(addresses_state, address, i)
                self.assertEqual(address_state.ots_bitfield_used_page, (i + 1) // config.dev.ots_tracking_per_page)

            self.assertEqual(address_state.ots_bitfield_used_page,
                             total_ots // config.dev.ots_tracking_per_page)
            self.assertEqual(total_ots // config.dev.ots_tracking_per_page, 4)

            paginated_bitfield.unset_ots_key(addresses_state, address, total_ots - 1)
            self.assertEqual(address_state.ots_bitfield_used_page, 3)

            for i in range(total_ots - 2, -1, -1):
                paginated_bitfield.unset_ots_key(addresses_state, address, i)
                self.assertEqual(address_state.ots_bitfield_used_page, i // config.dev.ots_tracking_per_page)
Ejemplo n.º 25
0
    def test_revert_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)

            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[24:18:-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'), 19)

            # page 2 data count must be 0
            self.assertEqual(
                len(
                    p.get_paginated_data(alice_address_state.address,
                                         2 * config.dev.data_per_page)), 0)

            # page 1 data count must be 9
            self.assertEqual(
                len(
                    p.get_paginated_data(alice_address_state.address,
                                         config.dev.data_per_page)), 9)

            # page 0 data count must be 10
            self.assertEqual(
                len(p.get_paginated_data(alice_address_state.address, 0)), 10)
Ejemplo n.º 26
0
    def test_apply_state_changes_for_PK(self, m_logger):
        """
        This updates the node's AddressState database with which OTS index a particular address should be on, and what
        tx hashes is this address associated with.
        Curiously enough, if the TX was signed by a master XMSS tree, it doesn't add this tx's txhash to the list of
        txs that address is associated with.
        :return:
        """
        addresses_state = {
            self.alice.address:
            OptimizedAddressState.get_default(self.alice.address)
        }
        self.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))
        self.tx._apply_state_changes_for_PK(state_container)
        self.assertTrue(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, ots_key))

        self.assertEqual(1, addresses_state[self.alice.address].nonce)
Ejemplo n.º 27
0
    def test_revert_transfer_txn_multi_send(self, m_logger):
        """
        Alice has sent 20 coins to Bob and Slave each, using 1 as Transaction fee. Now we need to undo this.
        """
        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

        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)
        }
        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)
        addresses_state[self.alice.address].pbdata.balance = 200
        addresses_state[self.bob.address].pbdata.balance = 0
        addresses_state[self.slave.address].pbdata.balance = 0

        self.assertTrue(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, ots_key))
        tx_multisend.apply(self.state, state_container)
        tx_multisend.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)
        self.assertEqual(0, addresses_state[self.slave.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])

        storage_key = state_container.paginated_tx_hash.generate_key(
            self.slave.address, 1)
        self.assertEqual(
            [], state_container.paginated_tx_hash.key_value[storage_key])
Ejemplo n.º 28
0
    def test_validate_extended(self, m_validate_slave, m_logger):
        """
        SlaveTransaction._validate_extended checks for:
        1. valid master/slave
        2. negative fee,
        3. addr_from has enough funds for the fee
        4. addr_from ots_key reuse
        """
        alice_address_state = OptimizedAddressState.get_default(
            self.alice.address)
        alice_address_state.pbdata.balance = 100
        addresses_state = {alice_address_state.address: alice_address_state}

        tx = SlaveTransaction.create(**self.params)
        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)
        result = tx._validate_extended(state_container)
        self.assertTrue(result)

        # Invalid master XMSS/slave XMSS relationship
        m_validate_slave.return_value = False
        result = tx.validate_all(state_container)
        self.assertFalse(result)
        m_validate_slave.return_value = True

        # fee = -1
        with patch('qrl.core.txs.SlaveTransaction.SlaveTransaction.fee',
                   new_callable=PropertyMock) as m_fee:
            m_fee.return_value = -1
            result = tx._validate_custom()
            self.assertFalse(result)

        # balance = 0, cannot pay the Transaction fee
        alice_address_state.pbdata.balance = 0
        result = tx._validate_extended(state_container)
        self.assertFalse(result)
        alice_address_state.pbdata.balance = 100

        addresses_state = {self.alice.address: alice_address_state}
        # addr_from_pk has used this OTS key before
        state_container.paginated_bitfield.set_ots_key(
            addresses_state, alice_address_state.address, tx.ots_key)
        result = tx.validate_all(state_container)
        self.assertFalse(result)

        bob = get_bob_xmss()
        # Too many slave_pks
        with patch('qrl.core.config', autospec=True) as m_config:
            m_config.dev = config.dev.create(config.dev.prev_state_key,
                                             config.dev.current_state_key, b'',
                                             10, True, True)
            m_config.dev.pbdata.transaction.multi_output_limit = 2
            state_container.current_dev_config = m_config.dev
            params = self.params.copy()
            params["slave_pks"] = [self.alice.pk, bob.pk, self.slave.pk]
            params["access_types"] = [0, 0, 0]

            tx = SlaveTransaction.create(**params)
            self.assertFalse(tx._validate_extended(state_container))
Ejemplo n.º 29
0
    def test_revert(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
        alice_address_state.update_ots_bitfield_used_page()
        alice_address_state.used_ots_key_count += 1
        alice_address_state.update_multi_sig_address_count()
        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)
        tx._data.nonce = 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, 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)

        tx.revert(self.state, state_container)
        self.assertNotIn(tx.txhash, state_container.votes_stats)
        self.assertFalse(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, tx.ots_key))
Ejemplo n.º 30
0
    def test_validate_extended(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.alice.pk)
        tx.sign(self.alice)

        alice_address_state = OptimizedAddressState.get_default(
            address=self.alice.address)
        alice_address_state.pbdata.balance = 5
        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,
            multi_sig_address: multi_sig_address_state,
        }
        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=10,
                                         total_coin_supply=100,
                                         current_dev_config=config.dev,
                                         write_access=True,
                                         my_db=None,
                                         batch=None)

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

        alice_address_state.pbdata.balance = 0
        result = tx._validate_extended(state_container)
        self.assertFalse(result)

        alice_address_state.pbdata.balance = 5
        result = tx._validate_extended(state_container)
        self.assertTrue(result)

        multi_sig_address_state.pbdata.balance = 99
        result = tx._validate_extended(state_container)
        self.assertFalse(result)

        multi_sig_address_state.pbdata.balance = 100
        result = tx._validate_extended(state_container)
        self.assertTrue(result)

        tx.pbdata.multi_sig_spend.expiry_block_number = 10
        result = tx._validate_extended(state_container)
        self.assertFalse(result)

        tx.pbdata.multi_sig_spend.expiry_block_number = 15000
        result = tx._validate_extended(state_container)
        self.assertTrue(result)