def setUp(self): root_clear(self._score_root_path, self._state_db_root_path, self._iiss_db_root_path, self._precommit_log_path) self._block_height = -1 self._prev_block_hash = None config = IconConfig("", copy.deepcopy(default_icon_config)) config.load() config.update_conf( {ConfigKey.BUILTIN_SCORE_OWNER: str(self._admin.address)}) config.update_conf({ ConfigKey.SERVICE: { ConfigKey.SERVICE_AUDIT: False, ConfigKey.SERVICE_FEE: False, ConfigKey.SERVICE_SCORE_PACKAGE_VALIDATOR: False } }) config.update_conf({ ConfigKey.SCORE_ROOT_PATH: self._score_root_path, ConfigKey.STATE_DB_ROOT_PATH: self._state_db_root_path }) config.update_conf(self._make_init_config()) self._config: 'IconConfig' = config self.icon_service_engine = IconServiceEngine() self._mock_ipc() self.icon_service_engine.open(config) self._genesis_invoke()
def setUp(self): root_clear(self._score_root_path, self._state_db_root_path) self._block_height = 0 self._prev_block_hash = None config = IconConfig("", default_icon_config) config.load() config.update_conf({ConfigKey.BUILTIN_SCORE_OWNER: str(self._admin)}) config.update_conf({ ConfigKey.SERVICE: { ConfigKey.SERVICE_AUDIT: False, ConfigKey.SERVICE_FEE: False, ConfigKey.SERVICE_DEPLOYER_WHITELIST: False, ConfigKey.SERVICE_SCORE_PACKAGE_VALIDATOR: False } }) config.update_conf({ ConfigKey.SCORE_ROOT_PATH: self._score_root_path, ConfigKey.STATE_DB_ROOT_PATH: self._state_db_root_path }) config.update_conf(self._make_init_config()) self.icon_service_engine = IconServiceEngine() self.icon_service_engine.open(config) self._genesis_invoke()
class TestIntegrateServiceConfigurationInitial(TestIntegrateBase): def setUp(self): self._block_height = 0 self._prev_block_hash = None self.config = IconConfig("", default_icon_config) self.config.load() self.config.update_conf({ConfigKey.BUILTIN_SCORE_OWNER: str(self._admin.address)}) self.config.update_conf({ConfigKey.SERVICE: {ConfigKey.SERVICE_AUDIT: False, ConfigKey.SERVICE_FEE: False, ConfigKey.SERVICE_DEPLOYER_WHITE_LIST: False, ConfigKey.SERVICE_SCORE_PACKAGE_VALIDATOR: False}}) self.config.update_conf({ConfigKey.SCORE_ROOT_PATH: self._score_root_path, ConfigKey.STATE_DB_ROOT_PATH: self._state_db_root_path}) def test_service_configuration_fee_setting(self): self.config.update_conf({ConfigKey.SERVICE: {ConfigKey.SERVICE_FEE: True}}) self.icon_service_engine = IconServiceEngine() self.icon_service_engine.open(self.config) context = IconScoreContext(IconScoreContextType.INVOKE) self.assertEqual(context.icon_service_flag, IconServiceFlag.FEE) def test_service_configuration_audit_setting(self): self.config.update_conf({ConfigKey.SERVICE: {ConfigKey.SERVICE_AUDIT: True}}) self.icon_service_engine = IconServiceEngine() self.icon_service_engine.open(self.config) context = IconScoreContext(IconScoreContextType.INVOKE) self.assertEqual(context.icon_service_flag, IconServiceFlag.AUDIT) def test_service_configuration_deployer_white_list_setting(self): self.config.update_conf({ConfigKey.SERVICE: {ConfigKey.SERVICE_DEPLOYER_WHITE_LIST: True}}) self.icon_service_engine = IconServiceEngine() self.icon_service_engine.open(self.config) context = IconScoreContext(IconScoreContextType.INVOKE) self.assertEqual(context.icon_service_flag, IconServiceFlag.DEPLOYER_WHITE_LIST) def test_service_configuration_score_package_validiator_setting(self): self.config.update_conf({ConfigKey.SERVICE: {ConfigKey.SERVICE_SCORE_PACKAGE_VALIDATOR: True}}) self.icon_service_engine = IconServiceEngine() self.icon_service_engine.open(self.config) context = IconScoreContext(IconScoreContextType.INVOKE) self.assertEqual(context.icon_service_flag, IconServiceFlag.SCORE_PACKAGE_VALIDATOR) def test_service_configuration_multiple_setting(self): multiple_config = {ConfigKey.SERVICE: {ConfigKey.SERVICE_AUDIT: True, ConfigKey.SERVICE_FEE: True, ConfigKey.SERVICE_DEPLOYER_WHITE_LIST: True, ConfigKey.SERVICE_SCORE_PACKAGE_VALIDATOR: True}} self.config.update_conf(multiple_config) self.icon_service_engine = IconServiceEngine() self.icon_service_engine.open(self.config) context = IconScoreContext(IconScoreContextType.INVOKE) expected_flag = IconServiceFlag.FEE | IconServiceFlag.AUDIT | \ IconServiceFlag.SCORE_PACKAGE_VALIDATOR | IconServiceFlag.DEPLOYER_WHITE_LIST self.assertEqual(context.icon_service_flag, expected_flag)
def test_service_configuration_deployer_white_list_setting(self): self.config.update_conf({ConfigKey.SERVICE: {ConfigKey.SERVICE_DEPLOYER_WHITE_LIST: True}}) self.icon_service_engine = IconServiceEngine() self.icon_service_engine.open(self.config) context = IconScoreContext(IconScoreContextType.INVOKE) self.assertEqual(context.icon_service_flag, IconServiceFlag.DEPLOYER_WHITE_LIST)
def test_service_configuration_audit_setting(self): self.config.update_conf({ConfigKey.SERVICE: {ConfigKey.SERVICE_AUDIT: True}}) self.icon_service_engine = IconServiceEngine() self.icon_service_engine.open(self.config) context = IconScoreContext(IconScoreContextType.INVOKE) self.assertEqual(context.icon_service_flag, IconServiceFlag.AUDIT)
def test_service_configuration_score_package_validiator_setting(self): self.config.update_conf({ConfigKey.SERVICE: {ConfigKey.SERVICE_SCORE_PACKAGE_VALIDATOR: True}}) self.icon_service_engine = IconServiceEngine() self.icon_service_engine.open(self.config) context = IconScoreContext(IconScoreContextType.INVOKE) self.assertEqual(context.icon_service_flag, IconServiceFlag.SCORE_PACKAGE_VALIDATOR)
def _setUp_audit(self): self.config.update_conf({ConfigKey.SERVICE: {ConfigKey.SERVICE_AUDIT: True, ConfigKey.SERVICE_FEE: False, ConfigKey.SERVICE_SCORE_PACKAGE_VALIDATOR: False}}) self.icon_service_engine = IconServiceEngine() self.icon_service_engine.open(self.config) self._genesis_invoke() self.token_initial_params = {"init_supply": hex(1000), "decimal": "0x12"}
def setUp(self): self._state_db_root_path = '.db' self._score_root_path = '.score' rmtree(self._score_root_path) rmtree(self._state_db_root_path) engine = IconServiceEngine() conf = IconConfig("", default_icon_config) conf.load() conf.update_conf({ ConfigKey.BUILTIN_SCORE_OWNER: str(create_address(AddressPrefix.EOA)), ConfigKey.SCORE_ROOT_PATH: self._score_root_path, ConfigKey.STATE_DB_ROOT_PATH: self._state_db_root_path }) # engine._load_builtin_scores = Mock() # engine._init_global_value_by_governance_score = Mock() engine.open(conf) self._engine = engine self._genesis_address = create_address(AddressPrefix.EOA) self._treasury_address = create_address(AddressPrefix.EOA) self._governance_score_address =\ Address.from_string('cx0000000000000000000000000000000000000001') self.from_ = self._genesis_address self._to = create_address(AddressPrefix.EOA) self._icon_score_address = create_address(AddressPrefix.CONTRACT) self._total_supply = 100 * 10**18 accounts = [{ 'name': 'god', 'address': self._genesis_address, 'balance': self._total_supply }, { 'name': 'treasury', 'address': self._treasury_address, 'balance': 0 }] block = Block(0, create_block_hash(), 0, None) tx = { 'method': '', 'params': { 'txHash': create_tx_hash() }, 'genesisData': { 'accounts': accounts } } tx_lists = [tx] self._engine.invoke(block, tx_lists) self._engine.commit(block) self.genesis_block = block
def __init__(self, conf: 'IconConfig'): self._conf = conf self._thread_flag = ENABLE_THREAD_FLAG self._icon_service_engine = IconServiceEngine() self._open() self._thread_pool = {THREAD_INVOKE: ThreadPoolExecutor(1), THREAD_QUERY: ThreadPoolExecutor(1), THREAD_VALIDATE: ThreadPoolExecutor(1)}
def test_service_configuration_multiple_setting(self): multiple_config = {ConfigKey.SERVICE: {ConfigKey.SERVICE_AUDIT: True, ConfigKey.SERVICE_FEE: True, ConfigKey.SERVICE_SCORE_PACKAGE_VALIDATOR: True}} self.config.update_conf(multiple_config) self.icon_service_engine = IconServiceEngine() self.icon_service_engine.open(self.config) context = IconScoreContext(IconScoreContextType.INVOKE) expected_flag = IconServiceFlag.FEE | IconServiceFlag.AUDIT | \ IconServiceFlag.SCORE_PACKAGE_VALIDATOR self.assertEqual(context.icon_service_flag, expected_flag)
def setUp(self): root_clear(self._score_root_path, self._state_db_root_path, self._iiss_db_root_path) self._block_height = -1 self._prev_block_hash = None config = IconConfig("", default_icon_config) config.load() config.update_conf( {ConfigKey.BUILTIN_SCORE_OWNER: str(self._admin.address)}) config.update_conf({ ConfigKey.SERVICE: { ConfigKey.SERVICE_AUDIT: False, ConfigKey.SERVICE_FEE: True, ConfigKey.SERVICE_DEPLOYER_WHITE_LIST: False, ConfigKey.SERVICE_SCORE_PACKAGE_VALIDATOR: False } }) config.update_conf({ ConfigKey.SCORE_ROOT_PATH: self._score_root_path, ConfigKey.STATE_DB_ROOT_PATH: self._state_db_root_path }) config.update_conf(self._make_init_config()) self._mock_ipc() self.icon_service_engine = IconServiceEngine() self.icon_service_engine.open(config) self._genesis_invoke() self.update_governance(version="governance_for_fee2") tx_results: List['TransactionResult'] = self.deploy_score( score_root="sample_deploy_scores", score_name="install/sample_score_fee_sharing", from_=self._admin, deploy_params={"value": hex(100)}) self.score_address = tx_results[0].score_address tx_results: List['TransactionResult'] = self.deploy_score( score_root="sample_deploy_scores", score_name="install/sample_score_fee_sharing_inter_call", from_=self._admin, deploy_params={ "value": hex(100), "score_address": str(self.score_address) }) self.score_address2 = tx_results[0].score_address
def test_throw(self, IconServiceEngine_charge_transaction_fee): context = ContextContainer._get_context() self._icon_service_engine = IconServiceEngine() self._icon_service_engine._flag = 0 self._icon_service_engine._icx_engine = Mock(spec=IcxEngine) self._icon_service_engine._icon_score_deploy_engine = \ Mock(spec=IconScoreDeployEngine) self._icon_service_engine._icon_score_engine = Mock( spec=IconScoreEngine) self._icon_service_engine._icon_pre_validator = Mock( spec=IconPreValidator) context.tx_batch = TransactionBatch() from_ = Mock(spec=Address) to_ = Mock(spec=Address) def intercept_charge_transaction_fee(*args, **kwargs): return Mock(spec=int), Mock(spec=int) IconServiceEngine_charge_transaction_fee.side_effect = \ intercept_charge_transaction_fee self._icon_service_engine._icon_score_deploy_engine.attach_mock( Mock(return_value=False), 'is_data_type_supported') error = Mock(spec=str) code = ExceptionCode.SCORE_ERROR mock_exception = Mock(side_effect=IconScoreException(error, code)) self._icon_service_engine._icon_score_engine.attach_mock( mock_exception, "invoke") raise_exception_start_tag("test_throw") tx_result = self._icon_service_engine._handle_icx_send_transaction( context, { 'version': 3, 'from': from_, 'to': to_ }) raise_exception_end_tag("test_throw") self.assertEqual(0, tx_result.status) IconServiceEngine_charge_transaction_fee.assert_called() context.traces.append.assert_called() trace = context.traces.append.call_args[0][0] self.assertEqual(TraceType.THROW, trace.trace) self.assertEqual(code, trace.data[0]) self.assertEqual(error, trace.data[1])
def test_call_event_kwarg(self): context = ContextContainer._get_context() name = "name" address = Address.from_data(AddressPrefix.EOA, b'address') age = 10 # Call with ordered arguments self._mock_score.OneIndexEvent(name, address, age) self.assertEqual(len(context.event_logs), 1) event_log_ordered_args = context.event_logs[0] # Call with ordered arguments and keyword arguments self._mock_score.OneIndexEvent(name, age=age, address=address) self.assertEqual(len(context.event_logs), 2) event_log_keyword_args = context.event_logs[1] self.assertEqual(event_log_ordered_args.score_address, event_log_keyword_args.score_address) self.assertEqual(event_log_ordered_args.indexed, event_log_keyword_args.indexed) self.assertEqual(event_log_ordered_args.data, event_log_keyword_args.data) logs_bloom = IconServiceEngine._generate_logs_bloom(context.event_logs) one_event_bloom_data = \ int(0).to_bytes(1, DATA_BYTE_ORDER) + \ 'OneIndexEvent(str,Address,int)'.encode('utf-8') self.assertIn(one_event_bloom_data, logs_bloom) name_bloom_data = int(1).to_bytes( 1, DATA_BYTE_ORDER) + name.encode('utf-8') self.assertIn(name_bloom_data, logs_bloom)
def test_base_transaction_has_logs_bloom_after_revision_10(self): self._init_decentralized() # TEST: Before 'ADD_LOGS_BLOOM_ON_BASE_TX' revision, base transaction should not have logs bloom tx_list = [ self._create_dummy_tx() ] prev_block, hash_list = self._make_and_req_block_for_issue_test(tx_list, is_block_editable=True) self._write_precommit_state(prev_block) base_tx_result: 'TransactionResult' = self.get_tx_results(hash_list)[0] expected_logs_bloom = None self.assertEqual(expected_logs_bloom, base_tx_result.logs_bloom) # TEST: After 'ADD_LOGS_BLOOM_ON_BASE_TX' revision, base transaction should have logs bloom self.set_revision(Revision.ADD_LOGS_BLOOM_ON_BASE_TX.value) tx_list = [ self._create_dummy_tx() ] prev_block, hash_list = self._make_and_req_block_for_issue_test(tx_list, is_block_editable=True) self._write_precommit_state(prev_block) base_tx_result: 'TransactionResult' = self.get_tx_results(hash_list)[0] expected_logs_bloom = IconServiceEngine._generate_logs_bloom(base_tx_result.event_logs) self.assertEqual(expected_logs_bloom.value, base_tx_result.logs_bloom.value)
def setUp(self, genesis_accounts: List[Account] = None): root_clear(self._score_root_path, self._state_db_root_path) self._block_height = 0 self._prev_block_hash = None config = IconConfig("", default_icon_config) config.load() config.update_conf({ConfigKey.BUILTIN_SCORE_OWNER: self._test1.get_address()}) config.update_conf({ConfigKey.SCORE_ROOT_PATH: self._score_root_path, ConfigKey.STATE_DB_ROOT_PATH: self._state_db_root_path}) config.update_conf(self._make_init_config()) self.icon_service_engine = IconServiceEngine() self.icon_service_engine.open(config) self._genesis_invoke(genesis_accounts)
def test_bytes_index_event(self): context = ContextContainer._get_context() data = b'0123456789abc' # Tests simple event emit self._mock_score.BytesIndexEvent(data) self.assertEqual(len(context.event_logs), 1) event_log = context.event_logs[0] self.assertEqual(2, len(event_log.indexed)) self.assertEqual(0, len(event_log.data)) logs_bloom = IconServiceEngine._generate_logs_bloom(context.event_logs) # Asserts whether the SCORE address is included in the bloom self.assert_score_address_in_bloom(logs_bloom) event_bloom_data = \ int(0).to_bytes(1, DATA_BYTE_ORDER) + \ 'BytesIndexEvent(bytes)'.encode('utf-8') self.assertIn(event_bloom_data, logs_bloom) indexed_bloom_data = \ int(1).to_bytes(1, DATA_BYTE_ORDER) + data self.assertIn(indexed_bloom_data, logs_bloom)
def test_address_index_event(self): context = ContextContainer._get_context() address = Address.from_data(AddressPrefix.EOA, os.urandom(20)) # Tests simple event emit self._mock_score.AddressIndexEvent(address) self.assertEqual(1, len(context.event_logs)) event_log = context.event_logs[0] self.assertEqual(2, len(event_log.indexed)) self.assertEqual(0, len(event_log.data)) logs_bloom = IconServiceEngine._generate_logs_bloom(context.event_logs) # Asserts whether the SCORE address is included in the bloom self.assert_score_address_in_bloom(logs_bloom) event_bloom_data = \ int(0).to_bytes(1, DATA_BYTE_ORDER) + \ 'AddressIndexEvent(Address)'.encode('utf-8') self.assertIn(event_bloom_data, logs_bloom) indexed_bloom_data = int(1).to_bytes(1, DATA_BYTE_ORDER) + \ address.prefix.value.to_bytes(1, DATA_BYTE_ORDER) + address.body self.assertEqual(ICON_ADDRESS_BYTES_SIZE + 1, len(indexed_bloom_data)) self.assertIn(indexed_bloom_data, logs_bloom)
def _create_service_engine(rc_db_from_path, db_factory_create_by_name, icx_engine_open, icx_storage_open, iiss_engine_open, iiss_storage_open, prep_engine_open, inv_storage_open, inv_engine_open, inv_engine_load_inv_container): service_engine = IconServiceEngine() service_engine._load_builtin_scores = Mock() state_db = {} rc_db = {} def state_put(self, key, value): state_db[key] = value def state_get(self, key): return state_db.get(key) def rc_put(key, value): rc_db[key] = value def rc_get(key): return rc_db.get(key) context_db = Mock(spec=ContextDatabase) context_db.key_value_db = state_db context_db.get = state_get context_db.put = state_put iiss_mock_db = Mock(spec=KeyValueDatabase) iiss_mock_db.get = rc_get iiss_mock_db.put = rc_put db_factory_create_by_name.return_value = context_db rc_db_from_path.return_value = iiss_mock_db service_engine.open(IconConfig("", default_icon_config)) # Patches create_by_name to pass creating DB rc_db_from_path.assert_called() db_factory_create_by_name.assert_called() icx_engine_open.assert_called() service_engine._load_builtin_scores.assert_called() inv_engine_load_inv_container.assert_called() service_engine._icon_pre_validator._is_inactive_score = Mock() return service_engine
def test_throw(self, score_invoke, IconServiceEngine_charge_transaction_fee): context = ContextContainer._get_context() self._icon_service_engine = IconServiceEngine() self._icon_service_engine._icx_engine = Mock(spec=IcxEngine) self._icon_service_engine._icon_score_deploy_engine = \ Mock(spec=DeployEngine) self._icon_service_engine._icon_pre_validator = Mock( spec=IconPreValidator) context.tx_batch = TransactionBatch() context.clear_batch = Mock() context.update_batch = Mock() from_ = Address.from_data(AddressPrefix.EOA, os.urandom(20)) to_ = Address.from_data(AddressPrefix.CONTRACT, os.urandom(20)) tx_index = randrange(0, 100) context.tx = Transaction(os.urandom(32), tx_index, from_, 0) context.msg = Message(from_) def intercept_charge_transaction_fee(*args, **kwargs): return {}, Mock(spec=int) IconServiceEngine_charge_transaction_fee.side_effect = \ intercept_charge_transaction_fee self._icon_service_engine._icon_score_deploy_engine.attach_mock( Mock(return_value=False), 'is_data_type_supported') error = Mock(spec=str) code = ExceptionCode.INVALID_PARAMETER mock_exception = Mock(side_effect=InvalidParamsException(error)) score_invoke.side_effect = mock_exception raise_exception_start_tag("test_throw") tx_result = self._icon_service_engine._handle_icx_send_transaction( context, {'version': 3, 'from': from_, 'to': to_}) raise_exception_end_tag("test_throw") self.assertEqual(0, tx_result.status) IconServiceEngine_charge_transaction_fee.assert_called() context.traces.append.assert_called() trace = context.traces.append.call_args[0][0] self.assertEqual(TraceType.THROW, trace.trace) self.assertEqual(code, trace.data[0]) self.assertEqual(error, trace.data[1])
def generate_service_engine(db_factory_create_by_name, icx_engine_open): service_engine = IconServiceEngine() service_engine._load_builtin_scores = Mock() # Mocks _init_global_value_by_governance_score # to ignore initializing governance SCORE service_engine._init_global_value_by_governance_score = Mock() service_engine.open(IconConfig("", default_icon_config)) # Patches create_by_name to pass creating DB db_factory_create_by_name.assert_called() icx_engine_open.assert_called() service_engine._load_builtin_scores.assert_called() service_engine._init_global_value_by_governance_score.assert_called() # Ignores icx transfer service_engine._icx_engine._transfer = Mock() # Mocks get_balance so, it returns always 100 icx service_engine._icx_engine.get_balance = Mock(return_value=100 * 10**18) return service_engine
def setUp(self, genesis_accounts: List[Account] = None, block_confirm_interval: int = tbears_server_config[ TbConf.BLOCK_CONFIRM_INTERVAL], network_only: bool = False, network_delay_ms: int = tbears_server_config[ TbConf.NETWORK_DELAY_MS]): self._block_height = -1 self._prev_block_hash = None self._block_confirm_interval = block_confirm_interval self._network_only: bool = network_only self._network_delay: float = network_delay_ms / 1000 if self._network_only: return root_clear(self._score_root_path, self._state_db_root_path) config = IconConfig("", default_icon_config) config.load() config.update_conf( {ConfigKey.BUILTIN_SCORE_OWNER: self._test1.get_address()}) config.update_conf({ ConfigKey.SCORE_ROOT_PATH: self._score_root_path, ConfigKey.STATE_DB_ROOT_PATH: self._state_db_root_path }) config.update_conf(self._make_init_config()) self.icon_service_engine = IconServiceEngine() self._mock_rc_proxy() self.icon_service_engine.open(config) self._genesis_invoke(genesis_accounts) self._tx_results: dict = {}
def test_revert(self, mocker): mocker.patch.object(IconServiceEngine, "_charge_transaction_fee") mocker.patch.object(IconScoreEngine, "invoke") context = ContextContainer._get_context() icon_service_engine = IconServiceEngine() icon_service_engine._icx_engine = Mock(spec=IcxEngine) icon_service_engine._icon_score_deploy_engine = \ Mock(spec=DeployEngine) icon_service_engine._icon_pre_validator = Mock(spec=IconPreValidator) context.tx_batch = TransactionBatch() context.clear_batch = Mock() context.update_batch = Mock() from_ = Address.from_data(AddressPrefix.EOA, os.urandom(20)) to_ = Address.from_data(AddressPrefix.CONTRACT, os.urandom(20)) tx_index = randrange(0, 100) context.tx = Transaction(os.urandom(32), tx_index, from_, 0) context.msg = Message(from_) def intercept_charge_transaction_fee(*args, **kwargs): return {}, Mock(spec=int) IconServiceEngine._charge_transaction_fee.side_effect = \ intercept_charge_transaction_fee icon_service_engine._icon_score_deploy_engine.attach_mock( Mock(return_value=False), 'is_data_type_supported') reason = Mock(spec=str) code = ExceptionCode.SCORE_ERROR mock_revert = Mock(side_effect=IconScoreException(reason)) IconScoreEngine.invoke.side_effect = mock_revert raise_exception_start_tag("test_revert") tx_result = icon_service_engine._handle_icx_send_transaction( context, { 'version': 3, 'from': from_, 'to': to_ }) raise_exception_end_tag("test_revert") assert tx_result.status == 0 IconServiceEngine._charge_transaction_fee.assert_called() context.traces.append.assert_called() trace = context.traces.append.call_args[0][0] assert trace.trace == TraceType.REVERT assert trace.data[0] == code assert trace.data[1] == reason
def test_call_event(self): context = ContextContainer._get_context() name = "name" address = Address.from_data(AddressPrefix.EOA, os.urandom(20)) age = 10 phone_number = "000" # Tests simple event emit self._mock_score.ZeroIndexEvent(name, address, age) self.assertEqual(len(context.event_logs), 1) event_log = context.event_logs[0] self.assertEqual(1, len(event_log.indexed)) self.assertEqual(3, len(event_log.data)) # This event has a indexed parameter, # so the list of indexed Should have 2 items self._mock_score.OneIndexEvent(name, address, age) self.assertEqual(len(context.event_logs), 2) event_log = context.event_logs[1] self.assertEqual(2, len(event_log.indexed)) self.assertEqual(2, len(event_log.data)) logs_bloom = IconServiceEngine._generate_logs_bloom(context.event_logs) # Asserts whether the SCORE address is included in the bloom self.assert_score_address_in_bloom(logs_bloom) zero_event_bloom_data = \ int(0).to_bytes(1, DATA_BYTE_ORDER) + \ 'ZeroIndexEvent(str,Address,int)'.encode('utf-8') self.assertIn(zero_event_bloom_data, logs_bloom) one_event_bloom_data = \ int(0).to_bytes(1, DATA_BYTE_ORDER) + \ 'OneIndexEvent(str,Address,int)'.encode('utf-8') self.assertIn(one_event_bloom_data, logs_bloom) name_bloom_data = int(1).to_bytes( 1, DATA_BYTE_ORDER) + name.encode('utf-8') self.assertIn(name_bloom_data, logs_bloom)
def test_call_event_mismatch_arg(self): context = ContextContainer._get_context() name = "name" address = Address.from_data(AddressPrefix.EOA, b'address') age = "10" # The hint of 'age' is int type but argument is str type self.assertRaises(ScoreErrorException, self._mock_score.OneIndexEvent, name, address, age) logs_bloom = IconServiceEngine._generate_logs_bloom(context.event_logs) one_event_bloom_data = \ int(0).to_bytes(1, DATA_BYTE_ORDER) + \ 'OneIndexEvent(str,Address,int)'.encode('utf-8') self.assertNotIn(one_event_bloom_data, logs_bloom) name_bloom_data = int(1).to_bytes( 1, DATA_BYTE_ORDER) + name.encode('utf-8') self.assertNotIn(name_bloom_data, logs_bloom)
def test_address_index_event(self): context = ContextContainer._get_context() address = Address.from_data(AddressPrefix.EOA, b'address') # Tests simple event emit self._mock_score.AddressIndexEvent(address) self.assertEqual(len(context.event_logs), 1) event_log = context.event_logs[0] self.assertEqual(2, len(event_log.indexed)) self.assertEqual(0, len(event_log.data)) logs_bloom = IconServiceEngine._generate_logs_bloom(context.event_logs) event_bloom_data = \ int(0).to_bytes(1, DATA_BYTE_ORDER) + \ 'AddressIndexEvent(Address)'.encode('utf-8') self.assertIn(event_bloom_data, logs_bloom) indexed_bloom_data = \ int(1).to_bytes(1, DATA_BYTE_ORDER) + address.body self.assertIn(indexed_bloom_data, logs_bloom)
def test_bool_index_event(self): context = ContextContainer._get_context() yes_no = True # Tests simple event emit self._mock_score.BoolIndexEvent(yes_no) self.assertEqual(len(context.event_logs), 1) event_log = context.event_logs[0] self.assertEqual(2, len(event_log.indexed)) self.assertEqual(0, len(event_log.data)) logs_bloom = IconServiceEngine._generate_logs_bloom(context.event_logs) event_bloom_data = \ int(0).to_bytes(1, DATA_BYTE_ORDER) + \ 'BoolIndexEvent(bool)'.encode('utf-8') self.assertIn(event_bloom_data, logs_bloom) indexed_bloom_data = \ int(1).to_bytes(1, DATA_BYTE_ORDER) + int_to_bytes(yes_no) self.assertIn(indexed_bloom_data, logs_bloom)
def test_int_index_event(self): context = ContextContainer._get_context() amount = 123456789 # Tests simple event emit self._mock_score.IntIndexEvent(amount) self.assertEqual(len(context.event_logs), 1) event_log = context.event_logs[0] self.assertEqual(2, len(event_log.indexed)) self.assertEqual(0, len(event_log.data)) logs_bloom = IconServiceEngine._generate_logs_bloom(context.event_logs) event_bloom_data = \ int(0).to_bytes(1, DATA_BYTE_ORDER) + \ 'IntIndexEvent(int)'.encode('utf-8') self.assertIn(event_bloom_data, logs_bloom) indexed_bloom_data = \ int(1).to_bytes(1, DATA_BYTE_ORDER) + int_to_bytes(amount) self.assertIn(indexed_bloom_data, logs_bloom)
def test_call_event_mismatch_arg(self): context = ContextContainer._get_context() name = "name" address = Address.from_data(AddressPrefix.EOA, os.urandom(20)) age = "10" # The hint of 'age' is int type but argument is str type self.assertRaises(InvalidEventLogException, self._mock_score.OneIndexEvent, name, address, age) logs_bloom = IconServiceEngine._generate_logs_bloom(context.event_logs) # Asserts whether the SCORE address is not included in the bloom self.assert_score_address_not_in_bloom(logs_bloom) one_event_bloom_data = \ int(0).to_bytes(1, DATA_BYTE_ORDER) + \ 'OneIndexEvent(str,Address,int)'.encode('utf-8') self.assertNotIn(one_event_bloom_data, logs_bloom) name_bloom_data = int(1).to_bytes( 1, DATA_BYTE_ORDER) + name.encode('utf-8') self.assertNotIn(name_bloom_data, logs_bloom)
class TestRecoverUsingWAL(TestIISSBase): def setUp(self): super().setUp() self.init_decentralized() self.prep_to_be_unregistered: 'EOAAccount' = self._accounts[1] self.transfer_icx(self._admin, self.prep_to_be_unregistered, 100 * 10**18) self.delegated_prep: 'EOAAccount' = self._accounts[0] self.delegate_amount: int = 100 self.delegator: 'EOAAccount' = self._accounts[PREP_MAIN_PREPS] self.transfer_icx(self._admin, self.delegator, 100 * 10**18) self.set_stake(self.delegator, self.delegate_amount) self.staker: 'EOAAccount' = self._admin self.stake_amount: int = 100 self.log_path: str = self.icon_service_engine._get_write_ahead_log_path( ) self.rc_data_path: str = os.path.join(self._state_db_root_path, IISS_DB) def tearDown(self): super().tearDown() if os.path.exists(self.log_path): os.remove(self.log_path) pass def _get_precommit_data_after_invoke(self) -> 'PrecommitData': # Invoke the transactions and changed state is going be written to WAL. # To make manipulated WAL, return precommit data # Transactions are samely used to each tests stake_tx = self.create_set_stake_tx(self.staker, self.stake_amount) unregister_tx = self.create_unregister_prep_tx( self.prep_to_be_unregistered) delegation_tx = self.create_set_delegation_tx( self.delegator, [(self.delegated_prep, self.delegate_amount)]) block, hash_list = self.make_and_req_block( [stake_tx, unregister_tx, delegation_tx]) precommit_data = self.icon_service_engine._precommit_data_manager.get( block.hash) precommit_data.block_batch.set_block_to_batch(precommit_data.revision) return precommit_data def _get_wal_writer(self, precommit_data: 'PrecommitData', is_calc_period_start_block: bool): wal_writer: 'WriteAheadLogWriter' = WriteAheadLogWriter( precommit_data.revision, max_log_count=2, block=precommit_data.block, instant_block_hash=precommit_data.block.hash) wal_writer.open(self.log_path) state_wal: 'StateWAL' = StateWAL(precommit_data.block_batch) revision: int = precommit_data.rc_db_revision if is_calc_period_start_block else -1 tx_index: int = IconScoreContext.storage.rc.get_tx_index( is_calc_period_start_block) iiss_wal: 'IissWAL' = IissWAL(precommit_data.rc_block_batch, tx_index, revision) return wal_writer, state_wal, iiss_wal @staticmethod def _write_batch_to_wal(wal_writer: 'WriteAheadLogWriter', state_wal: 'StateWAL', iiss_wal: 'IissWAL', is_calc_period_start_block: bool): if is_calc_period_start_block: wal_writer.write_state(WALState.CALC_PERIOD_START_BLOCK.value, add=False) wal_writer.write_walogable(iiss_wal) wal_writer.write_walogable(state_wal) wal_writer.flush() def _get_last_block_from_icon_service(self) -> int: return self.icon_service_engine._get_last_block().height def _get_commit_context(self, block: 'Block'): return self.icon_service_engine._context_factory.create( IconScoreContextType.DIRECT, block) def _close_and_reopen_iconservice(self): self.icon_service_engine.close() self.icon_service_engine = IconServiceEngine() self.icon_service_engine.open(self._config) def _check_the_state_and_rc_db_after_recover( self, block_height: int, is_calc_period_start_block: bool): # Check if state is updated unregister_status: int = 1 self.assertEqual(unregister_status, self.get_prep(self.prep_to_be_unregistered)["status"]) del_info: list = self.get_delegation(self.delegator)['delegations'] self.assertEqual(self.delegated_prep.address, del_info[0]['address']) self.assertEqual(self.delegate_amount, del_info[0]['value']) self.assertEqual(self.stake_amount, self.get_stake(self.staker)['stake']) # Check if rc db is updated rc_data_path: str = os.path.join(self._state_db_root_path, IISS_DB) # Get_last_rc_db: str = TestRCDatabase.get_last_rc_db_data(rc_data_path) current_rc_db = KeyValueDatabase.from_path( os.path.join(rc_data_path, "current_db")) rc_data_flag = RCDataCheckFlag(0) for rc_data in current_rc_db.iterator(): if rc_data[0][:2] == PRepsData.PREFIX: pr: 'PRepsData' = PRepsData.from_bytes(rc_data[0], rc_data[1]) if pr.block_height == block_height: rc_data_flag |= RCDataCheckFlag.PREP if rc_data[0][:2] == TxData.PREFIX: tx: 'TxData' = TxData.from_bytes(rc_data[1]) expected_index: int = -1 tx_index: int = int.from_bytes(rc_data[0][2:], 'big') if tx.type == TxType.PREP_UNREGISTER: expected_index: int = 0 rc_data_flag |= RCDataCheckFlag.UNREGISTER_TX elif tx.type == TxType.DELEGATION: expected_index: int = 1 rc_data_flag |= RCDataCheckFlag.DELEGATION_TX self.assertEqual(expected_index, tx_index) self.assertEqual(block_height, tx.block_height) if rc_data[ 0] == RewardCalcStorage.KEY_FOR_GETTING_LAST_TRANSACTION_INDEX: rc_data_flag |= RCDataCheckFlag.TX_INDEX # In case of the start of calc, should check if version, header and gv has been put correctly if is_calc_period_start_block and rc_data[ 0] == RewardCalcStorage.KEY_FOR_VERSION_AND_REVISION: rc_data_flag |= RCDataCheckFlag.VERSION if is_calc_period_start_block and rc_data[0][:2] == Header.PREFIX: rc_data_flag |= RCDataCheckFlag.HEADER if is_calc_period_start_block and rc_data[ 0][:2] == GovernanceVariable.PREFIX: rc_data_flag |= RCDataCheckFlag.GOVERNANCE if is_calc_period_start_block: self.assertEqual(RCDataCheckFlag.ALL_ON_START, rc_data_flag) self.assertTrue( os.path.isdir( os.path.join( rc_data_path, f"{RewardCalcStorage.IISS_RC_DB_NAME_PREFIX}_{block_height - 1}" ))) else: self.assertEqual(RCDataCheckFlag.ALL_ON_CALC, rc_data_flag) def _check_the_db_after_recover(self, last_block_before_close: int, is_calc_period_start_block: bool): last_block_after_open: int = self._get_last_block_from_icon_service() self.assertEqual(last_block_before_close + 1, last_block_after_open) self.assertFalse(os.path.exists(self.log_path)) self._check_the_state_and_rc_db_after_recover( last_block_after_open, is_calc_period_start_block) def _remove_all_iiss_db_before_reopen(self): # For make same environment, remove all iiss_db for dir_name in os.listdir(self.rc_data_path): if dir_name.startswith(RewardCalcStorage.IISS_RC_DB_NAME_PREFIX): shutil.rmtree(os.path.join(self.rc_data_path, dir_name), ignore_errors=False, onerror=None) def test_remove_wal(self): # Success case: if WAL is incomplete, should remove the WAL last_block_before_close: int = self._get_last_block_from_icon_service() precommit_data: 'PrecommitData' = self._get_precommit_data_after_invoke( ) wal_writer, state_wal, iiss_wal = self._get_wal_writer( precommit_data, False) wal_writer.write_walogable(iiss_wal) wal_writer.close() self._close_and_reopen_iconservice() last_block_after_open: int = self._get_last_block_from_icon_service() self.assertFalse(os.path.exists(self.log_path)) self.assertEqual(last_block_before_close, last_block_after_open) def test_close_during_writing_rc_db_on_calc_period(self): # Success case: when iconservice is closed during writing rc data to rc db, should write state db when open self.make_blocks(self._get_last_block_from_icon_service() + 1) is_start_block: bool = False last_block_before_close: int = self._get_last_block_from_icon_service() precommit_data: 'PrecommitData' = self._get_precommit_data_after_invoke( ) context: 'IconScoreContext' = self._get_commit_context( precommit_data.block) wal_writer, state_wal, iiss_wal = self._get_wal_writer( precommit_data, is_start_block) self._write_batch_to_wal(wal_writer, state_wal, iiss_wal, is_start_block) wal_writer.close() # write rc data to rc db # do not write state of wal (which means overwriting the rc data to db) self.icon_service_engine._process_iiss_commit(context, precommit_data, iiss_wal, is_start_block) self._close_and_reopen_iconservice() self._check_the_db_after_recover(last_block_before_close, is_start_block) def test_close_after_writing_rc_db_on_calc_period(self): # Success case: when iconservice is closed after writing rc data to rc db, should write state db when open self.make_blocks(self._get_last_block_from_icon_service() + 1) is_start_block: bool = False last_block_before_close: int = self._get_last_block_from_icon_service() precommit_data: 'PrecommitData' = self._get_precommit_data_after_invoke( ) context: 'IconScoreContext' = self._get_commit_context( precommit_data.block) wal_writer, state_wal, iiss_wal = self._get_wal_writer( precommit_data, is_start_block) self._write_batch_to_wal(wal_writer, state_wal, iiss_wal, is_start_block) # write rc data to rc db self.icon_service_engine._process_iiss_commit(context, precommit_data, iiss_wal, is_start_block) wal_writer.write_state(WALState.WRITE_RC_DB.value, add=True) wal_writer.close() self._close_and_reopen_iconservice() self._check_the_db_after_recover(last_block_before_close, is_start_block) def test_close_before_change_current_to_standby_on_the_start(self): # Success case: Iconservice is closed before changing current db to standby db, # should change current db to iiss db and create new current db (That is before commit data to rc db) self.make_blocks_to_end_calculation() is_start_block: bool = True last_block_before_close: int = self._get_last_block_from_icon_service() precommit_data: 'PrecommitData' = self._get_precommit_data_after_invoke( ) wal_writer, state_wal, iiss_wal = self._get_wal_writer( precommit_data, is_start_block) self._write_batch_to_wal(wal_writer, state_wal, iiss_wal, is_start_block) wal_writer.close() # remove all iiss_db self._remove_all_iiss_db_before_reopen() self._close_and_reopen_iconservice() self._check_the_db_after_recover(last_block_before_close, is_start_block) def test_close_only_standby_exists_on_the_start(self): # Success case: Iconservice is closed after changing current db to standby db, # should change stanby db to iiss db and create new current db (That is before commit data to rc db) self.make_blocks_to_end_calculation() is_start_block: bool = True last_block_before_close: int = self._get_last_block_from_icon_service() precommit_data: 'PrecommitData' = self._get_precommit_data_after_invoke( ) wal_writer, state_wal, iiss_wal = self._get_wal_writer( precommit_data, is_start_block) self._write_batch_to_wal(wal_writer, state_wal, iiss_wal, is_start_block) wal_writer.close() # Change the current_db to standby_db RewardCalcStorage.rename_current_db_to_standby_db( self.rc_data_path, last_block_before_close) # Remove all iiss_db self._remove_all_iiss_db_before_reopen() self._close_and_reopen_iconservice() self._check_the_db_after_recover(last_block_before_close, is_start_block) def test_close_standby_and_current_exists_on_the_start(self): # Success case: Iconservice is closed after changing current db to standby db and create new current db, # should change standby db to iiss db (That is before commit data to rc db) self.make_blocks_to_end_calculation() is_start_block: bool = True last_block_before_close: int = self._get_last_block_from_icon_service() precommit_data: 'PrecommitData' = self._get_precommit_data_after_invoke( ) wal_writer, state_wal, iiss_wal = self._get_wal_writer( precommit_data, is_start_block) self._write_batch_to_wal(wal_writer, state_wal, iiss_wal, is_start_block) wal_writer.close() # Change the current_db to standby_db RewardCalcStorage.rename_current_db_to_standby_db( self.rc_data_path, last_block_before_close) RewardCalcStorage.create_current_db(self.rc_data_path) # Remove all iiss_db self._remove_all_iiss_db_before_reopen() self._close_and_reopen_iconservice() self._check_the_db_after_recover(last_block_before_close, is_start_block) def test_close_before_sending_calculate_on_the_start(self): # Success case: Iconservice is closed after changing current db to iiss db and create new current db, # should not recover. self.make_blocks_to_end_calculation() is_start_block: bool = True last_block_before_close: int = self._get_last_block_from_icon_service() precommit_data: 'PrecommitData' = self._get_precommit_data_after_invoke( ) context: 'IconScoreContext' = self._get_commit_context( precommit_data.block) wal_writer, state_wal, iiss_wal = self._get_wal_writer( precommit_data, is_start_block) self._write_batch_to_wal(wal_writer, state_wal, iiss_wal, is_start_block) # Finish the iiss commit standby_db_path = self.icon_service_engine._process_iiss_commit( context, precommit_data, iiss_wal, is_start_block) wal_writer.write_state(WALState.WRITE_RC_DB.value, add=True) wal_writer.flush() # Finish the state commit self.icon_service_engine._process_state_commit(context, precommit_data, state_wal) wal_writer.write_state(WALState.WRITE_STATE_DB.value, add=True) wal_writer.flush() wal_writer.close() # Remove all iiss_db self._remove_all_iiss_db_before_reopen() # Change the standby db to iiss_db RewardCalcStorage.rename_standby_db_to_iiss_db(standby_db_path.path) self._close_and_reopen_iconservice() self._check_the_db_after_recover(last_block_before_close, is_start_block)
def _close_and_reopen_iconservice(self): self.icon_service_engine.close() self.icon_service_engine = IconServiceEngine() self.icon_service_engine.open(self._config)