class TestIconScoreDatabase(unittest.TestCase): def setUp(self): state_db_root_path = 'state_db' self.state_db_root_path = state_db_root_path rmtree(state_db_root_path) os.mkdir(state_db_root_path) address = Address.from_data(AddressPrefix.CONTRACT, b'0') db_path = os.path.join(state_db_root_path, 'db') context_db = ContextDatabase.from_path(db_path, True) self.db = IconScoreDatabase(address, context_db=context_db) self.address = address def tearDown(self): self.db.close() rmtree(self.state_db_root_path) def test_address(self): self.assertEqual(self.address, self.db.address) @patch('iconservice.iconscore.context.context.ContextGetter._context') def test_put_and_get(self, context): context.current_address = self.address context.revision = Revision.USE_RLP.value - 1 context.type = IconScoreContextType.DIRECT context.readonly = False db = self.db for i in range(3): key = f"key{i}".encode() self.assertIsNone(db.get(key)) for i in range(3): key = f"key{i}".encode() value = i.to_bytes(20, "big") self.assertIsNone(db.get(key)) db.put(key, value) self.assertEqual(value, db.get(key)) context.revision = Revision.USE_RLP.value for i in range(3): key = f"key{i}".encode() old_value = i.to_bytes(20, "big") new_value = i.to_bytes(30, "big") self.assertNotEqual(old_value, new_value) self.assertEqual(old_value, db.get(key)) db.put(key, new_value) self.assertEqual(new_value, db.get(key))
def setUp(self): state_db_root_path = 'state_db' self.state_db_root_path = state_db_root_path rmtree(state_db_root_path) os.mkdir(state_db_root_path) address = Address.from_data(AddressPrefix.CONTRACT, b'0') db_path = os.path.join(state_db_root_path, 'db') context_db = ContextDatabase.from_path(db_path, True) self.db = IconScoreDatabase(address, context_db=context_db) self.address = address
def test_var_db(self, context, key_value_db, old_value, new_value, value_type): context_db = ContextDatabase(key_value_db, is_shared=False) address = Address(AddressPrefix.CONTRACT, os.urandom(20)) score_db = IconScoreDatabase(address, context_db) self._init_context(context, address) self._set_revision(context, Revision.USE_RLP.value - 1) name = "var_db" var_db = VarDB(name, score_db, value_type) var_db.set(old_value) assert var_db.get() == old_value key = _get_final_key(address, ContainerTag.VAR, name.encode(), use_rlp=False) assert key_value_db.get(key) == ContainerUtil.encode_value(old_value) self._set_revision(context, Revision.USE_RLP.value) assert key_value_db.get(key) == ContainerUtil.encode_value(old_value) var_db.set(new_value) assert var_db.get() == new_value assert var_db.get() != old_value key = _get_final_key(address, ContainerTag.VAR, name.encode(), use_rlp=True) assert key_value_db.get(key) == ContainerUtil.encode_value(new_value) var_db.remove() assert var_db.get() == get_default_value(value_type) assert len(key_value_db) == 0
def test_1_depth_dict_db(self, context, key_value_db, keys, old_values, new_values, value_type): context_db = ContextDatabase(key_value_db, is_shared=False) score_address = Address(AddressPrefix.CONTRACT, os.urandom(20)) score_db = IconScoreDatabase(score_address, context_db) self._init_context(context, score_address) self._set_revision(context, Revision.USE_RLP.value - 1) name = "dict_db_depth_1" dict_db = DictDB(name, score_db, depth=1, value_type=value_type) # Put two items to dict_db for i in range(2): k, v = keys[i], old_values[i] dict_db[k] = v assert dict_db[k] == v key = _get_final_key( score_address, ContainerTag.DICT, name.encode(), ContainerUtil.encode_key(k), use_rlp=False ) assert key_value_db.get(key) == ContainerUtil.encode_value(v) self._set_revision(context, Revision.USE_RLP.value) # Read old-formatted data on Revision.USE_RLP for i in range(2): k, v = keys[i], old_values[i] assert dict_db[k] == v key = _get_final_key( score_address, ContainerTag.DICT, name.encode(), ContainerUtil.encode_key(k), use_rlp=False ) assert key_value_db.get(key) == ContainerUtil.encode_value(v) # Put 4 items to dict_db for i, k in enumerate(keys): old_v = old_values[i] new_v = new_values[i] dict_db[k] = new_v assert dict_db[k] == new_v assert dict_db[k] != old_v key = _get_final_key( score_address, ContainerTag.DICT, name.encode(), ContainerUtil.encode_key(k), use_rlp=True ) assert key_value_db.get(key) == ContainerUtil.encode_value(new_v) # If there is no value for a given key, default value is returned for k in keys: del dict_db[k] assert dict_db[k] == get_default_value(value_type) assert len(key_value_db) == 0
def get_score_db(score_address: Optional['Address'] = None): """Get db of SCORE that having score_address. create cx prefixed address and set it as SCORE's address if score_address is None :param score_address: address of score. :return: db SCORE use """ if not score_address: score_address = create_address(AddressPrefix.CONTRACT) score_db = IconScoreDatabase(score_address, context_db) return score_db
def intercept_invoke(*args, **kwargs): ContextContainer._push_context(args[0]) context_db = inner_task._icon_service_engine._icx_context_db score_address = create_address(AddressPrefix.CONTRACT, b'address') score = SampleScore(IconScoreDatabase(score_address, context_db)) address = create_address(AddressPrefix.EOA, b'address') score.SampleEvent(b'i_data', address, 10, b'data', 'text') ContextContainer._pop_context()
def test_array_db(self, context, key_value_db, values, value_type): context_db = ContextDatabase(key_value_db, is_shared=False) address = Address(AddressPrefix.CONTRACT, os.urandom(20)) score_db = IconScoreDatabase(address, context_db) self._init_context(context, score_db.address) self._set_revision(context, Revision.USE_RLP.value - 1) name = "array_db" array_db = ArrayDB(name, score_db, value_type) for i in range(2): array_db.put(values[i]) assert len(array_db) == 2 self._set_revision(context, Revision.USE_RLP.value) array_db.put(values[2]) array_db.put(values[3]) assert len(array_db) == 4 for i, value in enumerate(array_db): assert value == values[i] final_key: bytes = _get_final_key(address, ContainerTag.ARRAY, name.encode(), use_rlp=True) assert key_value_db.get(final_key) == int_to_bytes(len(array_db)) for i, use_rlp in enumerate((False, False, True, True)): key = _get_final_key( address.to_bytes(), ContainerTag.ARRAY.value, name.encode(), int_to_bytes(i), use_rlp=use_rlp, ) assert key_value_db.get(key) == ContainerUtil.encode_value(values[i]) for v in reversed(values): assert v == array_db.pop() assert len(array_db) == 0 # 2 values for array_db size still remain # even though all items in array_db have been popped. assert len(key_value_db) == 2
def score_db(context_db): return IconScoreDatabase(create_address(), context_db)
def test_score_db(self, context, key_value_db, prefixes, old_values, new_values): context_db = ContextDatabase(key_value_db, is_shared=False) score_address = Address(AddressPrefix.CONTRACT, os.urandom(20)) score_db = IconScoreDatabase(score_address, context_db) args = [score_address] self._init_context(context, score_address) self._set_revision(context, Revision.USE_RLP.value - 1) for prefix in prefixes: score_db = score_db.get_sub_db(prefix) args.append(prefix) for i, value in enumerate(old_values): key: bytes = f"key{i}".encode() encoded_value: bytes = ContainerUtil.encode_value(value) score_db.put(key, encoded_value) assert score_db.get(key) == encoded_value final_key: bytes = _get_final_key(*args, key, use_rlp=False) assert key_value_db.get(final_key) == encoded_value self._set_revision(context, Revision.USE_RLP.value) for i, value in enumerate(old_values): key: bytes = f"key{i}".encode() encoded_value: bytes = ContainerUtil.encode_value(value) assert score_db.get(key) == encoded_value final_key: bytes = _get_final_key(*args, key, use_rlp=False) assert key_value_db.get(final_key) == encoded_value for i, value in enumerate(new_values): key: bytes = f"key{i}".encode() encoded_value: bytes = ContainerUtil.encode_value(value) score_db.put(key, encoded_value) assert score_db.get(key) == encoded_value final_key: bytes = _get_final_key(*args, key, use_rlp=True) assert key_value_db.get(final_key) == encoded_value score_db.delete(key) assert score_db.get(key) is None assert key_value_db.get(final_key) is None
def test_2_depth_dict_db(self, context, key_value_db, keys1, keys2, old_values, new_values, value_type): context_db = ContextDatabase(key_value_db, is_shared=False) score_address = Address(AddressPrefix.CONTRACT, os.urandom(20)) score_db = IconScoreDatabase(score_address, context_db) self._init_context(context, score_address) self._set_revision(context, Revision.USE_RLP.value - 1) name = "dict_db_depth_2" dict_db = DictDB(name, score_db, depth=2, value_type=value_type) # To assign a value to middle-layer dict_db is forbidden for k1, v in zip(keys1, old_values): with pytest.raises(InvalidContainerAccessException): dict_db[k1] = v # Assign values to dict_db on Revision.USE_RLP - 1 for k1 in keys1: for k2, v in zip(keys2, old_values): dict_db[k1][k2] = v assert len(key_value_db) == len(keys1) * len(keys2) for k1 in keys1: for k2, v in zip(keys2, old_values): assert dict_db[k1][k2] == v key: bytes = _get_final_key( score_address, ContainerTag.DICT, name.encode(), ContainerTag.DICT, ContainerUtil.encode_key(k1), ContainerUtil.encode_key(k2), use_rlp=False ) assert key_value_db.get(key) == ContainerUtil.encode_value(v) self._set_revision(context, Revision.USE_RLP.value) # Check if reading old-formatted key:value data works on Revision.USE_RLP for k1 in keys1: for k2, v in zip(keys2, old_values): assert dict_db[k1][k2] == v # Replace all old_values with new_values on Revision.USE_RLP for k1 in keys1: for k2, v in zip(keys2, new_values): dict_db[k1][k2] = v # old_values + new_values assert len(key_value_db) == len(keys1) * len(keys2) * 2 for k1 in keys1: for k2, v in zip(keys2, new_values): assert dict_db[k1][k2] == v key: bytes = _get_final_key( score_address, ContainerTag.DICT, name.encode(), ContainerUtil.encode_key(k1), ContainerUtil.encode_key(k2), use_rlp=True ) assert key_value_db.get(key) == ContainerUtil.encode_value(v) for k1 in keys1: for k2 in keys2: del dict_db[k1][k2] assert dict_db[k1][k2] == get_default_value(value_type) assert len(key_value_db) == 0