def test_generate_bitfield_key(self): with set_qrl_dir('no_data'): state = State() paginated_bitfield = PaginatedBitfield(True, state._db) address = b'addr1' page = 1 expected_key = b'bitfield_' + address + b'_' + page.to_bytes(8, byteorder='big', signed=False) found_key = paginated_bitfield.generate_bitfield_key(address, page) self.assertEqual(expected_key, found_key)
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)
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)
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)
def __init__(self, addresses_state: dict, tokens: Indexer, slaves: Indexer, lattice_pk: Indexer, multi_sig_spend_txs: dict, votes_stats: dict, block_number: int, total_coin_supply: int, current_dev_config: DevConfig, write_access: bool, my_db: db, batch): self.delete_keys = set() self.paginated_bitfield = PaginatedBitfield(write_access, my_db) self.paginated_tx_hash = PaginatedData(b'p_tx_hash', write_access, my_db) self.paginated_tokens_hash = PaginatedData(b'p_tokens', write_access, my_db) self.paginated_slaves_hash = PaginatedData(b'p_slaves', write_access, my_db) self.paginated_lattice_pk = PaginatedData(b'p_lattice_pk', write_access, my_db) self.paginated_multisig_address = PaginatedData( b'p_multisig_address', write_access, my_db) self.paginated_multi_sig_spend = PaginatedData(b'p_multi_sig_spend', write_access, my_db) self.paginated_inbox_message = PaginatedData(b'p_inbox_message', write_access, my_db) self.addresses_state = addresses_state self.tokens = tokens self.slaves = slaves self.lattice_pk = lattice_pk self.multi_sig_spend_txs = multi_sig_spend_txs self.votes_stats = votes_stats self.block_number = block_number # Block number that is being processed self.block_reward = int(block_reward(block_number, current_dev_config)) self.batch = batch self.db = my_db self.current_dev_config = current_dev_config # Keeps track of last update so that it can be reverted self.last_addresses_state = dict() self.last_tokens = Indexer(b'token', self.db) self.last_slaves = Indexer(b'slave', self.db) self.last_lattice_pk = Indexer(b'lattice_pk', self.db) self.last_multi_sig_spend_txs = dict() self.last_votes_stats = dict() self._total_coin_supply = total_coin_supply # TODO: Coinbase transaction of current block is not included
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))
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)
def test_getOTS(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) 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.GetOTSReq(address=alice_xmss.address) response = service.GetOTS(request=request, context=context) context.set_code.assert_not_called() self.assertEqual(0, response.next_unused_ots_index) paginated_bitfield = PaginatedBitfield(True, db_state._db) paginated_bitfield.set_ots_key(addresses_state, optimized_address_state.address, 0) paginated_bitfield.put_addresses_bitfield(None) response = service.GetOTS(request=request, context=context) context.set_code.assert_not_called() self.assertEqual(1, response.next_unused_ots_index)
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))
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)