def _load_score(context: 'IconScoreContext', score_address: 'Address', builtin_score_owner: 'Address'): score: 'IconScoreBase' = IconScoreContextUtil.get_icon_score( context, score_address) assert score is not None if score.owner != builtin_score_owner: raise AccessDeniedException( f'score.owner({score.owner}) != builtin_score_owner({builtin_score_owner})' )
def load_builtin_scores(context: 'IconScoreContext', builtin_score_owner: 'Address'): for score_name, value in BUILTIN_SCORE_ADDRESS_MAPPER.items(): score_address = Address.from_string(value) # If builtin score has been already deployed, exit. if IconScoreContextUtil.is_score_active(context, score_address): IconBuiltinScoreLoader._load_score(context, score_address, builtin_score_owner) else: IconBuiltinScoreLoader._deploy_score(context, score_name, score_address, builtin_score_owner)
def _deploy_score(context: 'IconScoreContext', score_name: str, score_address: 'Address', builtin_score_owner: 'Address'): score_source_path_in_iconservice: str = os.path.join( IconBuiltinScoreLoader._pre_builtin_score_root_path(), score_name) # Save deploy_info for a builtin score to storage. deploy_info = IconScoreDeployInfo(score_address=score_address, deploy_state=DeployState.ACTIVE, owner=builtin_score_owner, current_tx_hash=ZERO_TX_HASH, next_tx_hash=ZERO_TX_HASH) context.storage.deploy.put_deploy_info(context, deploy_info) tx_hash: bytes = deploy_info.current_tx_hash # score_path is score_root_path/score_address/ directory. score_path: str = os.path.join(context.score_root_path, score_address.to_bytes().hex()) # Make a directory for a builtin score with a given score_address. os.makedirs(score_path, exist_ok=True) try: score_deploy_path: str = os.path.join(score_path, f'0x{tx_hash.hex()}') # remove_path() supports directory as well as file. remove_path(score_deploy_path) # Copy builtin score source files from iconservice package to score_deploy_path. copytree(score_source_path_in_iconservice, score_deploy_path) except FileExistsError: pass try: # Import score class from deployed builtin score sources score_info: 'IconScoreInfo' =\ IconScoreContextUtil.create_score_info(context, score_address, tx_hash) # Create a score instance from the imported score class. score = score_info.create_score() # Call on_install() to initialize the score database of the builtin score. score.on_install() except BaseException as e: Logger.exception( f'Failed to deploy a builtin score: {score_address}\n{str(e)}', ICON_DEPLOY_LOG_TAG) raise e
def test_score_invoke_with_revert(self): table = {ConfigKey.SERVICE_FEE: True, ConfigKey.SERVICE_AUDIT: False, ConfigKey.SERVICE_DEPLOYER_WHITE_LIST: False, ConfigKey.SERVICE_SCORE_PACKAGE_VALIDATOR: False} # TODO: must apply the service flags to the engine # self._engine._flag = self._engine._make_service_flag(table) block_height = 1 block_hash = create_block_hash(b'block') block_timestamp = 0 tx_hash = create_tx_hash() value = 1 * 10 ** 18 self._to = create_address(AddressPrefix.CONTRACT) tx_v3 = { 'method': 'icx_sendTransaction', 'params': { 'version': 3, 'from': self._genesis_address, 'to': self._to, 'value': value, 'stepLimit': 20000, 'timestamp': 1234567890, 'txHash': tx_hash } } block = Block(block_height, block_hash, block_timestamp, self.genesis_block.hash, 0) context = _create_context(IconScoreContextType.QUERY) before_from_balance: int = \ IconScoreContext.engine.icx.get_balance(context, self.from_) self._engine._handle_score_invoke = \ Mock(return_value=None, side_effect=IconScoreException("force revert")) raise_exception_start_tag("test_score_invoke_with_revert") tx_results, state_root_hash, _, _ = self._engine.invoke(block, [tx_v3]) raise_exception_end_tag("test_score_invoke_with_revert") self.assertIsInstance(state_root_hash, bytes) self.assertEqual(len(state_root_hash), 32) self.assertEqual(len(tx_results), 1) tx_result: 'TransactionResult' = tx_results[0] self.assertIsNotNone(tx_result.failure) self.assertIsNone(tx_result.score_address) self.assertEqual(tx_result.status, 0) self.assertEqual(tx_result.block_height, block_height) self.assertEqual(tx_result.block_hash, block_hash) self.assertEqual(tx_result.tx_index, 0) self.assertEqual(tx_result.tx_hash, tx_hash) # step_used MUST BE 10**6 on protocol v2 step_unit = self._engine._step_counter_factory.get_step_cost( StepType.DEFAULT) self.assertEqual(tx_result.step_used, step_unit) step_price = self._engine._step_counter_factory.get_step_price() if IconScoreContextUtil._is_flag_on(IconScoreContext.icon_service_flag, IconServiceFlag.FEE): # step_price MUST BE 10**10 on protocol v2 self.assertEqual( step_price, self._engine._step_counter_factory.get_step_price()) else: self.assertEqual(step_price, 0) self.assertEqual(tx_result.step_price, step_price) self._engine.commit(block.height, block.hash, None) # Check whether fee charging works well context = _create_context(IconScoreContextType.QUERY) after_from_balance: int = \ IconScoreContext.engine.icx.get_balance(context, self.from_) fee = tx_result.step_price * tx_result.step_used self.assertEqual(after_from_balance, before_from_balance - fee)
def test_invoke_v3_with_fee(self): table = {ConfigKey.SERVICE_FEE: True, ConfigKey.SERVICE_AUDIT: False, ConfigKey.SERVICE_DEPLOYER_WHITE_LIST: False, ConfigKey.SERVICE_SCORE_PACKAGE_VALIDATOR: False} # TODO: must apply the service flags to the engine # self._engine._flag = self._engine._make_service_flag(table) block_height = 1 block_hash = create_block_hash() block_timestamp = 0 tx_hash = create_tx_hash() value = 1 * 10 ** 18 step_limit = 1000000 tx_v3 = { 'method': 'icx_sendTransaction', 'params': { 'nid': 3, 'version': 3, 'from': self._genesis_address, 'to': self._to, 'value': value, 'stepLimit': step_limit, 'timestamp': 1234567890, 'txHash': tx_hash } } block = Block(block_height, block_hash, block_timestamp, self.genesis_block.hash, 0) context = _create_context(IconScoreContextType.DIRECT) before_from_balance: int = \ IconScoreContext.engine.icx.get_balance(context, self.from_) tx_results, state_root_hash, _, _ = self._engine.invoke(block, [tx_v3]) self.assertIsInstance(state_root_hash, bytes) self.assertEqual(len(state_root_hash), 32) self.assertEqual(len(tx_results), 1) tx_result: 'TransactionResult' = tx_results[0] self.assertIsNone(tx_result.failure) self.assertIsNone(tx_result.score_address) self.assertEqual(tx_result.status, 1) self.assertEqual(tx_result.block_height, block_height) self.assertEqual(tx_result.block_hash, block_hash) self.assertEqual(tx_result.tx_index, 0) self.assertEqual(tx_result.tx_hash, tx_hash) # step_used MUST BE 10**6 on protocol v2 step_cost = self._engine._step_counter_factory.get_step_cost( StepType.DEFAULT) self.assertEqual(tx_result.step_used, step_cost) step_price = self._engine._step_counter_factory.get_step_price() if IconScoreContextUtil._is_flag_on(IconScoreContext.icon_service_flag, IconServiceFlag.FEE): # step_price MUST BE 10**10 on protocol v2 self.assertEqual( step_price, self._engine._step_counter_factory.get_step_price()) else: self.assertEqual(step_price, 0) self.assertEqual(tx_result.step_price, step_price) self._engine.commit(block.height, block.hash, None) # Check whether fee charging works well after_from_balance: int = \ IconScoreContext.engine.icx.get_balance(context, self.from_) fee = tx_result.step_price * tx_result.step_used value = value if tx_result.status == TransactionResult.SUCCESS else 0 self.assertEqual(after_from_balance, before_from_balance - value - fee)
def test_invoke_v3_without_fee(self): block_height = 1 block_hash = create_block_hash() block_timestamp = 0 tx_hash = create_tx_hash() value = 1 * 10 ** 18 tx_v3 = { 'method': 'icx_sendTransaction', 'params': { 'nid': 3, 'version': 3, 'from': self._genesis_address, 'to': self._to, 'value': value, 'stepLimit': 1000000, 'timestamp': 1234567890, 'txHash': tx_hash } } block = Block(block_height, block_hash, block_timestamp, self.genesis_block.hash, 0) tx_results, state_root_hash, _, _ = self._engine.invoke(block, [tx_v3]) self.assertIsInstance(state_root_hash, bytes) self.assertEqual(len(state_root_hash), 32) self.assertEqual(len(tx_results), 1) tx_result: 'TransactionResult' = tx_results[0] self.assertIsNone(tx_result.failure) self.assertIsNone(tx_result.score_address) self.assertEqual(tx_result.status, 1) self.assertEqual(tx_result.block_height, block_height) self.assertEqual(tx_result.block_hash, block_hash) self.assertEqual(tx_result.tx_index, 0) self.assertEqual(tx_result.tx_hash, tx_hash) # step_used MUST BE 10**6 on protocol v2 step_unit = self._engine._step_counter_factory.get_step_cost( StepType.DEFAULT) self.assertEqual(tx_result.step_used, step_unit) step_price = self._engine._step_counter_factory.get_step_price() if IconScoreContextUtil._is_flag_on(IconScoreContext.icon_service_flag, IconServiceFlag.FEE): # step_used MUST BE 10**10 on protocol v2 self.assertEqual(step_price, 10 ** 10) else: self.assertEqual(step_price, 0) self.assertEqual(tx_result.step_price, step_price) self._engine.commit(block.height, block.hash, None) # Check whether fee charging works well context = _create_context(IconScoreContextType.DIRECT) from_balance: int = \ IconScoreContext.engine.icx.get_balance(context, self.from_) fee = tx_result.step_price * tx_result.step_used self.assertEqual(fee, 0) self.assertEqual(from_balance, self._total_supply - value - fee)
def test_invoke(self): block_height = 1 block_hash = create_block_hash() block_timestamp = 0 tx_hash = create_tx_hash() value = 1 * 10 ** 18 step_limit = 200000000000000 tx_v3 = { 'method': 'icx_sendTransaction', 'params': { 'version': 3, 'from': self._genesis_address, 'to': self._to, 'value': value, 'stepLimit': step_limit, 'timestamp': 1234567890, 'txHash': tx_hash } } block = Block(block_height, block_hash, block_timestamp, self.genesis_block.hash, 0) original_invoke_request = self._engine._invoke_request # noinspection PyUnusedLocal def intercept_invoke_req(*args, **kwargs): context: 'IconScoreContext' = args[0] request: dict = args[1] index: int = args[2] ret = original_invoke_request(context, request, index) # Requesting the very big number of step limit, # but there's a max step limit, # asserts max step limit is applied to step counting. self.assertNotEqual(step_limit, context.step_counter.step_limit) self.assertEqual( self._engine._step_counter_factory.get_max_step_limit( context.type), context.step_counter.step_limit) return ret self._engine._invoke_request = Mock(side_effect=intercept_invoke_req) tx_results, state_root_hash, _, _ = self._engine.invoke(block, [tx_v3]) self.assertIsInstance(state_root_hash, bytes) self.assertEqual(len(state_root_hash), 32) self.assertEqual(len(tx_results), 1) tx_result: 'TransactionResult' = tx_results[0] self.assertIsNone(tx_result.failure) self.assertIsNone(tx_result.score_address) self.assertEqual(tx_result.status, 1) self.assertEqual(tx_result.block_height, block_height) self.assertEqual(tx_result.block_hash, block_hash) self.assertEqual(tx_result.tx_index, 0) self.assertEqual(tx_result.tx_hash, tx_hash) # step_used MUST BE 10**6 on protocol v2 step_unit = self._engine._step_counter_factory.get_step_cost( StepType.DEFAULT) self.assertEqual(tx_result.step_used, step_unit) step_price = self._engine._step_counter_factory.get_step_price() if IconScoreContextUtil._is_flag_on(IconScoreContext.icon_service_flag, IconServiceFlag.FEE): # step_price MUST BE 10**10 on protocol v2 self.assertEqual(step_price, 10 ** 10) else: self.assertEqual(step_price, 0) self.assertEqual(tx_result.step_price, step_price) self._engine.commit(block.height, block_hash, None) # Check whether fee charging works well context = _create_context(IconScoreContextType.DIRECT) from_balance: int = \ IconScoreContext.engine.icx.get_balance(context, self.from_) fee = tx_result.step_price * tx_result.step_used self.assertEqual(fee, 0) self.assertEqual(from_balance, self._total_supply - value - fee)