예제 #1
0
    def test_out_of_step(self):
        tx_hash = bytes.hex(create_tx_hash())
        from_ = create_address(AddressPrefix.EOA)
        to_ = create_address(AddressPrefix.CONTRACT)

        request = create_request([ReqData(tx_hash, from_, to_, 'call', {})])

        # noinspection PyUnusedLocal
        def intercept_invoke(*args, **kwargs):
            ContextContainer._push_context(args[0])
            context_db = self._inner_task._icon_service_engine._icx_context_db
            score = SampleScore(IconScoreDatabase(to_, context_db))
            score.hash_writable(b'1234')

        IconScoreEngine.invoke = Mock(side_effect=intercept_invoke)

        raw_step_costs = {
            governance.STEP_TYPE_DEFAULT: 4000,
            governance.STEP_TYPE_CONTRACT_CALL: 1500,
            governance.STEP_TYPE_CONTRACT_CREATE: 20000,
            governance.STEP_TYPE_CONTRACT_UPDATE: 8000,
            governance.STEP_TYPE_CONTRACT_DESTRUCT: -7000,
            governance.STEP_TYPE_CONTRACT_SET: 1000,
            governance.STEP_TYPE_GET: 5,
            governance.STEP_TYPE_SET: 20,
            governance.STEP_TYPE_REPLACE: 5,
            governance.STEP_TYPE_DELETE: -15,
            governance.STEP_TYPE_INPUT: 20,
            governance.STEP_TYPE_EVENT_LOG: 10,
            governance.STEP_TYPE_API_CALL: 0
        }
        step_costs = {}

        for key, value in raw_step_costs.items():
            try:
                step_costs[StepType(key)] = value
            except ValueError:
                # Pass the unknown step type
                pass

        self.step_counter = IconScoreStepCounter(0, step_costs, 100)
        self.step_counter.reset(step_limit=100)
        factory = self._inner_task._icon_service_engine._step_counter_factory
        factory.create = Mock(return_value=self.step_counter)

        result = self._inner_task_invoke(request)
        self.assertTrue(result['txResults'][tx_hash]['failure']
                        ['message'].startswith("Out of step"))
예제 #2
0
    def setUp(self):
        self._inner_task = generate_inner_task()

        factory = self._inner_task._icon_service_engine._step_counter_factory
        self.step_counter = Mock(spec=IconScoreStepCounter)
        factory.create = Mock(return_value=self.step_counter)
        self.step_counter.step_used = 0
        self.step_counter.step_price = 0
        self.step_counter.step_limit = 5000000
        self.step_cost_dict = self._init_step_cost()
    def _assert_step_used(self, step_used: int, request: dict, tx_hash: bytes):
        self.step_counter = IconScoreStepCounter(self.step_cost_dict, 5000000,
                                                 0)
        factory = self._inner_task._icon_service_engine._step_counter_factory
        factory.create = Mock(return_value=self.step_counter)

        results = self._inner_task_invoke(request)
        result = results['txResults'][tx_hash]
        self.assertEqual(result['status'], '0x1')
        self.assertEqual(result['stepUsed'], hex(step_used))
def context():
    ctx = IconScoreContext(IconScoreContextType.DIRECT)
    ctx.tx = Transaction(tx_hash=create_tx_hash(), origin=EOA1)
    ctx.block = Block(block_height=0, block_hash=create_block_hash(), timestamp=0, prev_hash=None)
    ctx.msg = Message(sender=EOA1, value=0)
    ctx.icon_score_mapper = IconScoreMapper()
    ctx.new_icon_score_mapper = {}
    ctx.step_counter = IconScoreStepCounter(1, {}, 1000, False)
    ctx.event_logs = []
    ctx.traces = []
    ctx.current_address = EOA1
    IconScoreContext.storage = ContextStorage(deploy=Mock(spec=Storage), fee=None, icx=None, iiss=None, prep=None,
                                              issue=None, meta=None, rc=None, inv=None)

    ContextContainer._push_context(ctx)
    yield ctx
    ContextContainer._pop_context()
예제 #5
0
    def setUp(self):
        self._inner_task = generate_inner_task()

        self._inner_task._icon_service_engine._icon_pre_validator = \
            Mock(spec=IconPreValidator)

        factory = self._inner_task._icon_service_engine._step_counter_factory
        self.step_counter = Mock(spec=IconScoreStepCounter)
        factory.create = Mock(return_value=self.step_counter)
        self.step_counter.step_used = 0
        self.step_counter.step_price = 0
        self.step_counter.step_limit = 5000000
        self.step_cost_dict = self._init_step_cost()
        prep_engine = PRepEngine()
        prep_engine.preps = Mock()
        fee_engine = FeeEngine()
        icx_engine = IcxEngine()
        IconScoreContext.engine = ContextEngine(deploy=Mock(),
                                                fee=fee_engine,
                                                icx=icx_engine,
                                                iiss=None,
                                                prep=prep_engine,
                                                issue=None)
예제 #6
0
class TestIconScoreStepCounter(unittest.TestCase):
    def setUp(self):
        self._inner_task = generate_inner_task()

        factory = self._inner_task._icon_service_engine._step_counter_factory
        self.step_counter = Mock(spec=IconScoreStepCounter)
        factory.create = Mock(return_value=self.step_counter)
        self.step_counter.step_used = 0
        self.step_counter.step_price = 0
        self.step_counter.step_limit = 5000000
        self.step_cost_dict = self._init_step_cost()

    def tearDown(self):
        ContextContainer._clear_context()
        clear_inner_task()

    def test_install_step(self):
        # Ignores deploy
        deploy_engine_invoke = Mock()
        self._inner_task._icon_service_engine. \
            _icon_score_deploy_engine.invoke = deploy_engine_invoke

        tx_hash1 = bytes.hex(create_tx_hash())
        from_ = create_address(AddressPrefix.EOA)
        to_ = Address.from_string('cx0000000000000000000000000000000000000000')
        content_type = 'application/zip'
        data = {
            'contentType': content_type,
            'content': '0x1867291283973610982301923812873419826abcdef9182731',
        }

        request1 = create_request([
            ReqData(tx_hash1, from_, to_, 'deploy', data),
        ])

        # for StepType.CONTRACT_CREATE
        result = self._inner_task_invoke(request1)
        self.assertEqual(result['txResults'][tx_hash1]['status'], '0x1')

        # for StepType.CONTRACT_UPDATE
        to_ = result['txResults'][tx_hash1]['scoreAddress']
        tx_hash2 = bytes.hex(create_tx_hash())

        request2 = create_request([
            ReqData(tx_hash2, from_, to_, 'deploy', data),
        ])

        result = self._inner_task_invoke(request2)
        self.assertEqual(result['txResults'][tx_hash2]['status'], '0x1')

        deploy_engine_invoke.assert_called()

        input_length = (len(content_type.encode('utf-8')) + 25)

        call_args_for_apply_step = self.step_counter.apply_step.call_args_list

        self.assertEqual((StepType.DEFAULT, 1), call_args_for_apply_step[0][0])
        self.assertEqual((StepType.INPUT, input_length),
                         call_args_for_apply_step[1][0])
        self.assertEqual((StepType.CONTRACT_CREATE, 1),
                         call_args_for_apply_step[2][0])
        self.assertEqual((StepType.CONTRACT_SET, 25),
                         call_args_for_apply_step[3][0])
        self.assertEqual((StepType.DEFAULT, 1), call_args_for_apply_step[4][0])
        self.assertEqual((StepType.INPUT, input_length),
                         call_args_for_apply_step[5][0])
        self.assertEqual((StepType.CONTRACT_UPDATE, 1),
                         call_args_for_apply_step[6][0])
        self.assertEqual((StepType.CONTRACT_SET, 25),
                         call_args_for_apply_step[7][0])
        self.assertEqual(8, len(call_args_for_apply_step))

        step_used_create = self._calc_step_used(0, 4)
        step_used_update = self._calc_step_used(4, 4)

        # check SCORE install stepUsed value
        self._assert_step_used(step_used_create, request1, tx_hash1)

        # check SCORE update stepUsed value
        self._assert_step_used(step_used_update, request2, tx_hash2)

    def test_message_step(self):
        self._inner_task._icon_service_engine._validate_score_blacklist = Mock(
        )

        tx_hash1 = bytes.hex(create_tx_hash())
        from_ = create_address(AddressPrefix.EOA)
        to_ = from_
        # data size 25
        data = '0x01234abcde01234abcde01234abcde01234abcde01234abcde'

        request = create_request([
            ReqData(tx_hash1, from_, to_, 'message', data),
        ])

        result = self._inner_task_invoke(request)
        self.assertEqual(result['txResults'][tx_hash1]['status'], '0x1')

        input_length = 25

        self.assertEqual(self.step_counter.apply_step.call_args_list[0][0],
                         (StepType.DEFAULT, 1))
        self.assertEqual(self.step_counter.apply_step.call_args_list[1][0],
                         (StepType.INPUT, input_length))
        self.assertEqual(len(self.step_counter.apply_step.call_args_list), 2)

        step_used = self._calc_step_used(0, 2)

        self._assert_step_used(step_used, request, tx_hash1)

    def test_transfer_step(self):
        tx_hash = bytes.hex(create_tx_hash())
        from_ = create_address(AddressPrefix.EOA)
        to_ = create_address(AddressPrefix.EOA)

        request = create_request([
            ReqData(tx_hash, from_, to_, "", ""),
        ])

        result = self._inner_task_invoke(request)
        self.assertEqual(result['txResults'][tx_hash]['status'], '0x1')

        call_args_for_apply_step = self.step_counter.apply_step.call_args_list

        self.assertEqual((StepType.DEFAULT, 1), call_args_for_apply_step[0][0])
        self.assertEqual((StepType.INPUT, 0), call_args_for_apply_step[1][0])
        self.assertEqual(2, len(call_args_for_apply_step))

        step_used = self._calc_step_used(0, len(call_args_for_apply_step))

        # check stepUsed value
        self._assert_step_used(step_used, request, tx_hash)

    def test_internal_transfer_step(self):
        tx_hash = bytes.hex(create_tx_hash())
        from_ = create_address(AddressPrefix.EOA)
        to_ = create_address(AddressPrefix.CONTRACT)

        request = create_request([ReqData(tx_hash, from_, to_, 'call', {})])

        # noinspection PyUnusedLocal
        def intercept_invoke(*args, **kwargs):
            ContextContainer._push_context(args[0])
            context_db = self._inner_task._icon_service_engine._icx_context_db
            score = SampleScore(IconScoreDatabase(to_, context_db))
            score.transfer()
            ContextContainer._pop_context()

        IconScoreEngine.invoke = Mock(side_effect=intercept_invoke)

        result = self._inner_task_invoke(request)
        IconScoreEngine.invoke.assert_called()

        self.assertEqual(result['txResults'][tx_hash]['status'], '0x1')

        call_args_for_apply_step = self.step_counter.apply_step.call_args_list

        self.assertEqual((StepType.DEFAULT, 1), call_args_for_apply_step[0][0])
        self.assertEqual((StepType.INPUT, 0), call_args_for_apply_step[1][0])
        self.assertEqual((StepType.CONTRACT_CALL, 1),
                         call_args_for_apply_step[2][0])
        self.assertEqual((StepType.CONTRACT_CALL, 1),
                         call_args_for_apply_step[3][0])
        self.assertEqual(4, len(call_args_for_apply_step))

        step_used = self._calc_step_used(
            0, len(self.step_counter.apply_step.call_args_list))

        # check stepUsed value
        self._assert_step_used(step_used, request, tx_hash)

    def test_set_db(self):
        tx_hash = bytes.hex(create_tx_hash())
        from_ = create_address(AddressPrefix.EOA)
        to_ = create_address(AddressPrefix.CONTRACT)

        request = create_request([ReqData(tx_hash, from_, to_, 'call', {})])

        # noinspection PyUnusedLocal
        def intercept_invoke(*args, **kwargs):
            ContextContainer._push_context(args[0])
            context_db = self._inner_task._icon_service_engine._icx_context_db
            score = SampleScore(IconScoreDatabase(to_, context_db))
            score.set_db(100)
            ContextContainer._pop_context()

        IconScoreEngine.invoke = Mock(side_effect=intercept_invoke)

        # for StepType.SET
        result = self._inner_task_invoke(request)
        self.assertEqual(result['txResults'][tx_hash]['status'], '0x1')
        # for StepType.REPLACE
        result = self._inner_task_invoke(request)
        self.assertEqual(result['txResults'][tx_hash]['status'], '0x1')
        IconScoreEngine.invoke.assert_called()

        call_args_for_apply_step = self.step_counter.apply_step.call_args_list

        self.assertEqual((StepType.DEFAULT, 1), call_args_for_apply_step[0][0])
        self.assertEqual((StepType.INPUT, 0), call_args_for_apply_step[1][0])
        self.assertEqual((StepType.CONTRACT_CALL, 1),
                         call_args_for_apply_step[2][0])
        self.assertEqual((StepType.SET, 100), call_args_for_apply_step[3][0])
        self.assertEqual((StepType.DEFAULT, 1), call_args_for_apply_step[4][0])
        self.assertEqual((StepType.INPUT, 0), call_args_for_apply_step[5][0])
        self.assertEqual((StepType.CONTRACT_CALL, 1),
                         call_args_for_apply_step[6][0])
        self.assertEqual((StepType.REPLACE, 100),
                         call_args_for_apply_step[7][0])
        self.assertEqual(8, len(call_args_for_apply_step))

        step_used_replace = self._calc_step_used(4, 4)

        # check stepUsed value
        self._assert_step_used(step_used_replace, request, tx_hash)

    def test_get_db(self):
        tx_hash = bytes.hex(create_tx_hash())
        from_ = create_address(AddressPrefix.EOA)
        to_ = create_address(AddressPrefix.CONTRACT)

        request = create_request([ReqData(tx_hash, from_, to_, 'call', {})])

        self._inner_task._icon_service_engine.\
            _icx_context_db.get = Mock(return_value=b'1' * 100)

        # noinspection PyUnusedLocal
        def intercept_invoke(*args, **kwargs):
            ContextContainer._push_context(args[0])

            context_db = self._inner_task._icon_service_engine._icx_context_db
            score = SampleScore(IconScoreDatabase(to_, context_db))
            score.get_db()

            ContextContainer._pop_context()

        IconScoreEngine.invoke = Mock(side_effect=intercept_invoke)

        result = self._inner_task_invoke(request)
        IconScoreEngine.invoke.assert_called()

        self.assertEqual(result['txResults'][tx_hash]['status'], '0x1')

        call_args_for_apply_step = self.step_counter.apply_step.call_args_list

        self.assertEqual((StepType.DEFAULT, 1), call_args_for_apply_step[0][0])
        self.assertEqual((StepType.INPUT, 0), call_args_for_apply_step[1][0])
        self.assertEqual((StepType.CONTRACT_CALL, 1),
                         call_args_for_apply_step[2][0])
        self.assertEqual((StepType.GET, 100), call_args_for_apply_step[3][0])
        self.assertEqual(4, len(call_args_for_apply_step))

        step_used = self._calc_step_used(0, len(call_args_for_apply_step))

        # check stepUsed value
        self._assert_step_used(step_used, request, tx_hash)

    def test_query_db(self):
        from_ = create_address(AddressPrefix.EOA)
        to_ = create_address(AddressPrefix.CONTRACT)

        request = {
            'method': 'icx_call',
            'params': {
                'to': to_.__str__(),
                'from': from_.__str__(),
            },
        }

        self._inner_task._icon_service_engine. \
            _icx_context_db.get = Mock(return_value=b'1' * 100)

        # noinspection PyUnusedLocal
        def intercept_query(*args, **kwargs):
            ContextContainer._push_context(args[0])
            context_db = self._inner_task._icon_service_engine._icx_context_db
            score = SampleScore(IconScoreDatabase(to_, context_db))
            ret = score.query_db()
            ContextContainer._pop_context()
            return ret

        IconScoreEngine.query = Mock(side_effect=intercept_query)

        result = self._inner_task._query(request)
        IconScoreEngine.query.assert_called()

        self.assertIsNotNone(result)

        call_args_for_apply_step = self.step_counter.apply_step.call_args_list

        self.assertEqual((StepType.CONTRACT_CALL, 1),
                         call_args_for_apply_step[0][0])
        self.assertEqual((StepType.GET, 100), call_args_for_apply_step[1][0])

    def test_remove_db(self):
        tx_hash = bytes.hex(create_tx_hash())
        from_ = create_address(AddressPrefix.EOA)
        to_ = create_address(AddressPrefix.CONTRACT)

        request = create_request([ReqData(tx_hash, from_, to_, 'call', {})])

        self._inner_task._icon_service_engine.\
            _icx_context_db.get = Mock(return_value=b'1' * 100)

        # noinspection PyUnusedLocal
        def intercept_invoke(*args, **kwargs):
            ContextContainer._push_context(args[0])
            context_db = self._inner_task._icon_service_engine._icx_context_db
            score = SampleScore(IconScoreDatabase(to_, context_db))
            score.remove_db()
            ContextContainer._pop_context()

        IconScoreEngine.invoke = Mock(side_effect=intercept_invoke)

        result = self._inner_task_invoke(request)
        IconScoreEngine.invoke.assert_called()

        self.assertEqual(result['txResults'][tx_hash]['status'], '0x1')

        call_args_for_apply_step = self.step_counter.apply_step.call_args_list

        self.assertEqual((StepType.DEFAULT, 1), call_args_for_apply_step[0][0])
        self.assertEqual((StepType.INPUT, 0), call_args_for_apply_step[1][0])
        self.assertEqual((StepType.CONTRACT_CALL, 1),
                         call_args_for_apply_step[2][0])
        self.assertEqual((StepType.DELETE, 100),
                         call_args_for_apply_step[3][0])
        self.assertEqual(4, len(call_args_for_apply_step))

        step_used = self._calc_step_used(0, len(call_args_for_apply_step))

        # check stepUsed value
        self._assert_step_used(step_used, request, tx_hash)

    def test_event_log_step(self):
        tx_hash = bytes.hex(create_tx_hash())
        from_ = create_address(AddressPrefix.EOA)
        to_ = create_address(AddressPrefix.CONTRACT)

        request = create_request([ReqData(tx_hash, from_, to_, 'call', {})])

        # noinspection PyUnusedLocal
        def intercept_invoke(*args, **kwargs):
            ContextContainer._push_context(args[0])
            context_db = self._inner_task._icon_service_engine._icx_context_db
            address = create_address(AddressPrefix.EOA)
            score = SampleScore(IconScoreDatabase(address, context_db))
            i_data_param = b'i_data'
            data_param = b'data'
            text_param = 'text'
            score.SampleEvent(i_data_param, address, data_param, text_param)
            global event_log_data_size
            event_log_data_size = \
                len("SampleEvent(bytes,Address,bytes,str)".encode('utf-8')) + \
                len(i_data_param) + \
                len(address.body) + \
                len(data_param) + \
                len(text_param.encode('utf-8'))
            ContextContainer._pop_context()

        IconScoreEngine.invoke = Mock(side_effect=intercept_invoke)

        result = self._inner_task_invoke(request)
        IconScoreEngine.invoke.assert_called()

        self.assertEqual(result['txResults'][tx_hash]['status'], '0x1')

        call_args_for_apply_step = self.step_counter.apply_step.call_args_list

        self.assertEqual((StepType.DEFAULT, 1), call_args_for_apply_step[0][0])
        self.assertEqual((StepType.INPUT, 0), call_args_for_apply_step[1][0])
        self.assertEqual((StepType.CONTRACT_CALL, 1),
                         call_args_for_apply_step[2][0])
        self.assertEqual((StepType.EVENT_LOG, event_log_data_size),
                         call_args_for_apply_step[3][0])
        self.assertEqual(4, len(call_args_for_apply_step))

        step_used = self._calc_step_used(0, len(call_args_for_apply_step))

        # check stepUsed value
        self._assert_step_used(step_used, request, tx_hash)

    def test_event_log_step_revision3(self):
        tx_hash = bytes.hex(create_tx_hash())
        from_ = create_address(AddressPrefix.EOA)
        to_ = create_address(AddressPrefix.CONTRACT)

        request = create_request([ReqData(tx_hash, from_, to_, 'call', {})])

        # noinspection PyUnusedLocal
        def intercept_invoke(*args, **kwargs):
            args[0].revision = REVISION_3
            ContextContainer._push_context(args[0])

            context_db = self._inner_task._icon_service_engine._icx_context_db
            address = create_address(AddressPrefix.EOA)
            score = SampleScore(IconScoreDatabase(address, context_db))
            i_data_param = b'i_data'
            data_param = b'data'
            text_param = 'text'
            score.SampleEvent(i_data_param, address, data_param, text_param)
            global event_log_data_size
            event_log_data_size = \
                len("SampleEvent(bytes,Address,bytes,str)".encode('utf-8')) + \
                len(i_data_param) + \
                ICON_CONTRACT_ADDRESS_BYTES_SIZE + \
                len(data_param) + \
                len(text_param.encode('utf-8'))

            ContextContainer._pop_context()

        IconScoreEngine.invoke = Mock(side_effect=intercept_invoke)

        result = self._inner_task_invoke(request)
        IconScoreEngine.invoke.assert_called()

        self.assertEqual(result['txResults'][tx_hash]['status'], '0x1')

        call_args_for_apply_step = self.step_counter.apply_step.call_args_list

        self.assertEqual((StepType.DEFAULT, 1), call_args_for_apply_step[0][0])
        self.assertEqual((StepType.INPUT, 0), call_args_for_apply_step[1][0])
        self.assertEqual((StepType.CONTRACT_CALL, 1),
                         call_args_for_apply_step[2][0])
        self.assertEqual((StepType.EVENT_LOG, event_log_data_size),
                         call_args_for_apply_step[3][0])
        self.assertEqual(4, len(call_args_for_apply_step))

        step_used = self._calc_step_used(0, len(call_args_for_apply_step))

        # check stepUsed value
        self._assert_step_used(step_used, request, tx_hash)

    def test_hash_readonly(self):
        tx_hash = bytes.hex(create_tx_hash())
        from_ = create_address(AddressPrefix.EOA)
        to_ = create_address(AddressPrefix.CONTRACT)

        request = create_request([ReqData(tx_hash, from_, to_, 'call', {})])

        data_to_hash = b'1234'

        # noinspection PyUnusedLocal
        def intercept_invoke(*args, **kwargs):
            ContextContainer._push_context(args[0])

            context_db = self._inner_task._icon_service_engine._icx_context_db
            score = SampleScore(IconScoreDatabase(to_, context_db))
            score.hash_readonly(data_to_hash)

            ContextContainer._pop_context()

        IconScoreEngine.invoke = Mock(side_effect=intercept_invoke)

        result = self._inner_task_invoke(request)
        IconScoreEngine.invoke.assert_called()

        self.assertEqual(result['txResults'][tx_hash]['status'], '0x1')

        call_args_for_apply_step = self.step_counter.apply_step.call_args_list

        self.assertEqual((StepType.DEFAULT, 1), call_args_for_apply_step[0][0])
        self.assertEqual((StepType.INPUT, 0), call_args_for_apply_step[1][0])
        self.assertEqual((StepType.CONTRACT_CALL, 1),
                         call_args_for_apply_step[2][0])
        self.assertEqual(3, len(call_args_for_apply_step))

        # step_counter.consume_step should called in sha3_256() only if context.revision is more than 2
        self.step_counter.consume_step.assert_not_called()

        step_used = self._calc_step_used(0, len(call_args_for_apply_step))

        # check stepUsed value
        self._assert_step_used(step_used, request, tx_hash)

    def test_hash_writable(self):
        tx_hash = bytes.hex(create_tx_hash())
        from_ = create_address(AddressPrefix.EOA)
        to_ = create_address(AddressPrefix.CONTRACT)

        request = create_request([ReqData(tx_hash, from_, to_, 'call', {})])

        data_to_hash = b'1234'

        # noinspection PyUnusedLocal
        def intercept_invoke(*args, **kwargs):
            ContextContainer._push_context(args[0])
            context_db = self._inner_task._icon_service_engine._icx_context_db
            score = SampleScore(IconScoreDatabase(to_, context_db))
            score.hash_writable(data_to_hash)
            ContextContainer._pop_context()

        IconScoreEngine.invoke = Mock(side_effect=intercept_invoke)

        result = self._inner_task_invoke(request)
        IconScoreEngine.invoke.assert_called()

        self.assertEqual(result['txResults'][tx_hash]['status'], '0x1')

        call_args_for_apply_step = self.step_counter.apply_step.call_args_list

        self.assertEqual((StepType.DEFAULT, 1), call_args_for_apply_step[0][0])
        self.assertEqual((StepType.INPUT, 0), call_args_for_apply_step[1][0])
        self.assertEqual((StepType.CONTRACT_CALL, 1),
                         call_args_for_apply_step[2][0])
        self.assertEqual(3, len(call_args_for_apply_step))

        # step_counter.consume_step() should be called in sha3_256() only if context.revision is more than 2
        self.step_counter.consume_step.assert_not_called()

        step_used = self._calc_step_used(0, len(call_args_for_apply_step))

        # check stepUsed value
        self._assert_step_used(step_used, request, tx_hash)

    def test_out_of_step(self):
        tx_hash = bytes.hex(create_tx_hash())
        from_ = create_address(AddressPrefix.EOA)
        to_ = create_address(AddressPrefix.CONTRACT)

        request = create_request([ReqData(tx_hash, from_, to_, 'call', {})])

        # noinspection PyUnusedLocal
        def intercept_invoke(*args, **kwargs):
            ContextContainer._push_context(args[0])
            context_db = self._inner_task._icon_service_engine._icx_context_db
            score = SampleScore(IconScoreDatabase(to_, context_db))
            score.hash_writable(b'1234')

        IconScoreEngine.invoke = Mock(side_effect=intercept_invoke)

        raw_step_costs = {
            governance.STEP_TYPE_DEFAULT: 4000,
            governance.STEP_TYPE_CONTRACT_CALL: 1500,
            governance.STEP_TYPE_CONTRACT_CREATE: 20000,
            governance.STEP_TYPE_CONTRACT_UPDATE: 8000,
            governance.STEP_TYPE_CONTRACT_DESTRUCT: -7000,
            governance.STEP_TYPE_CONTRACT_SET: 1000,
            governance.STEP_TYPE_GET: 5,
            governance.STEP_TYPE_SET: 20,
            governance.STEP_TYPE_REPLACE: 5,
            governance.STEP_TYPE_DELETE: -15,
            governance.STEP_TYPE_INPUT: 20,
            governance.STEP_TYPE_EVENT_LOG: 10,
            governance.STEP_TYPE_API_CALL: 0
        }
        step_costs = {}

        for key, value in raw_step_costs.items():
            try:
                step_costs[StepType(key)] = value
            except ValueError:
                # Pass the unknown step type
                pass

        self.step_counter = IconScoreStepCounter(0, step_costs, 100)
        self.step_counter.reset(step_limit=100)
        factory = self._inner_task._icon_service_engine._step_counter_factory
        factory.create = Mock(return_value=self.step_counter)

        result = self._inner_task_invoke(request)
        self.assertTrue(result['txResults'][tx_hash]['failure']
                        ['message'].startswith("Out of step"))

    def test_set_step_costs(self):
        governance_score = Mock()
        governance_score.getStepCosts = Mock(
            return_value={
                governance.STEP_TYPE_DEFAULT: 4000,
                governance.STEP_TYPE_CONTRACT_CALL: 1500,
                governance.STEP_TYPE_CONTRACT_CREATE: 20000,
                governance.STEP_TYPE_CONTRACT_UPDATE: 8000,
                governance.STEP_TYPE_CONTRACT_DESTRUCT: -7000,
                governance.STEP_TYPE_CONTRACT_SET: 1000,
                governance.STEP_TYPE_GET: 5,
                governance.STEP_TYPE_SET: 20,
                governance.STEP_TYPE_REPLACE: 5,
                governance.STEP_TYPE_DELETE: -15,
                governance.STEP_TYPE_INPUT: 20,
                governance.STEP_TYPE_EVENT_LOG: 10
            })

        step_counter_factory = IconScoreStepCounterFactory()
        step_costs = governance_score.getStepCosts()

        for key, value in step_costs.items():
            try:
                step_counter_factory.set_step_cost(StepType(key), value)
            except ValueError:
                pass

        self.assertEqual(4000,
                         step_counter_factory.get_step_cost(StepType.DEFAULT))
        self.assertEqual(
            1500, step_counter_factory.get_step_cost(StepType.CONTRACT_CALL))
        self.assertEqual(
            20000,
            step_counter_factory.get_step_cost(StepType.CONTRACT_CREATE))
        self.assertEqual(
            8000, step_counter_factory.get_step_cost(StepType.CONTRACT_UPDATE))
        self.assertEqual(
            -7000,
            step_counter_factory.get_step_cost(StepType.CONTRACT_DESTRUCT))
        self.assertEqual(
            1000, step_counter_factory.get_step_cost(StepType.CONTRACT_SET))
        self.assertEqual(5, step_counter_factory.get_step_cost(StepType.GET))
        self.assertEqual(20, step_counter_factory.get_step_cost(StepType.SET))
        self.assertEqual(5,
                         step_counter_factory.get_step_cost(StepType.REPLACE))
        self.assertEqual(-15,
                         step_counter_factory.get_step_cost(StepType.DELETE))
        self.assertEqual(20,
                         step_counter_factory.get_step_cost(StepType.INPUT))
        self.assertEqual(
            10, step_counter_factory.get_step_cost(StepType.EVENT_LOG))

    @staticmethod
    def _init_step_cost() -> dict:
        raw_step_costs = {
            governance.STEP_TYPE_DEFAULT: 4000,
            governance.STEP_TYPE_CONTRACT_CALL: 1500,
            governance.STEP_TYPE_CONTRACT_CREATE: 20000,
            governance.STEP_TYPE_CONTRACT_UPDATE: 8000,
            governance.STEP_TYPE_CONTRACT_DESTRUCT: -7000,
            governance.STEP_TYPE_CONTRACT_SET: 1000,
            governance.STEP_TYPE_GET: 5,
            governance.STEP_TYPE_SET: 20,
            governance.STEP_TYPE_REPLACE: 5,
            governance.STEP_TYPE_DELETE: -15,
            governance.STEP_TYPE_INPUT: 20,
            governance.STEP_TYPE_EVENT_LOG: 10,
            governance.STEP_TYPE_API_CALL: 10000
        }
        step_costs = {}

        for key, value in raw_step_costs.items():
            try:
                step_costs[StepType(key)] = value
            except ValueError:
                # Pass the unknown step type
                pass

        # return IconScoreStepCounter(step_costs, 5000000, 0)
        return step_costs

    def _calc_step_used(self, offset: int, count: int):
        step_used: int = 0

        for i in range(offset, offset + count):
            (type, val) = self.step_counter.apply_step.call_args_list[i][0]
            step_used = step_used + self.step_cost_dict[type] * val

        return step_used

    def _assert_step_used(self, step_used: int, request: dict, tx_hash: bytes):
        self.step_counter = IconScoreStepCounter(0, self.step_cost_dict,
                                                 5_000_000)
        self.step_counter.reset(step_limit=5_000_000)
        factory = self._inner_task._icon_service_engine._step_counter_factory
        factory.create = Mock(return_value=self.step_counter)

        results = self._inner_task_invoke(request)
        result = results['txResults'][tx_hash]
        self.assertEqual(result['status'], '0x1')
        self.assertEqual(result['stepUsed'], hex(step_used))

    def _inner_task_invoke(self, request) -> dict:
        # Clear cached precommit data before calling inner_task._invoke
        self._inner_task._icon_service_engine._precommit_data_manager.clear()
        return self._inner_task._invoke(request)
예제 #7
0
 def mock_step_counter(self):
     counter = IconScoreStepCounter(step_price=mock.ANY,
                                    step_costs=mock.ANY,
                                    step_limit=mock.ANY,
                                    step_trace_flag=mock.ANY)
     return counter