예제 #1
0
    def _update_runner(self, result: Dict[str, Any]):
        self._error_message = result[
            'exception'] if 'exception' in result else None

        if 'state' in result:
            self._vm_state = VMState.get_vm_state(result['state'])

        if 'gasconsumed' in result:
            self._gas_consumed = int(
                float(result['gasconsumed']) * 10**constants.GAS_DECIMALS)

        if 'stack' in result:
            result_stack = result['stack']
            if isinstance(result_stack, list):
                self._result_stack = [
                    neo_utils.stack_item_from_json(value)
                    for value in result_stack
                ]
            else:
                self._result_stack = [
                    neo_utils.stack_item_from_json(result_stack)
                ]

        if 'notifications' in result:
            json_notifications = result['notifications']
            if not isinstance(json_notifications, list):
                json_notifications = [json_notifications]

            notifications = []
            for n in json_notifications:
                new = Notification.from_json(n)
                if new is not None:
                    notifications.append(new)
            self._notifications = notifications

        if 'logs' in result:
            json_logs = result['logs']
            if not isinstance(json_logs, list):
                json_logs = [json_logs]

            logs = []
            for l in json_logs:
                new = Log.from_json(l)
                if new is not None:
                    logs.append(new)
            self._logs = logs

        if 'storages' in result:
            json_storages = result['storages']
            if not isinstance(json_storages, list):
                json_storages = [json_storages]

            storages = []
            for s in json_storages:
                new = Storage.from_json(s, self._contracts)
                if new is not None:
                    storages.append(new)
            self._storages = storages
예제 #2
0
    def test_buffer_stack_item_from_json(self):
        stack_item = {
            'type': StackItemType.Buffer.name,
            'value': 'dW5pdHRlc3Q='
        }
        expected_result = 'unittest'
        result = stack_item_from_json(stack_item)
        self.assertEqual(expected_result, result)

        stack_item = {'type': StackItemType.Buffer.name, 'value': b'unittest'}
        with self.assertRaises(ValueError):
            stack_item_from_json(stack_item)
예제 #3
0
    def test_boolean_stack_item_from_json(self):
        stack_item = {'type': StackItemType.Boolean.name, 'value': False}
        expected_result = False
        result = stack_item_from_json(stack_item)
        self.assertEqual(expected_result, result)

        stack_item = {'type': StackItemType.Boolean.name, 'value': 'False'}
        result = stack_item_from_json(stack_item)
        self.assertEqual(expected_result, result)

        stack_item = {'type': StackItemType.Boolean.name, 'value': 1}
        with self.assertRaises(ValueError):
            stack_item_from_json(stack_item)
예제 #4
0
    def test_integer_stack_item_from_json(self):
        stack_item = {'type': StackItemType.Integer.name, 'value': 5}
        expected_result = 5
        result = stack_item_from_json(stack_item)
        self.assertEqual(expected_result, result)

        stack_item = {'type': StackItemType.Integer.name, 'value': '5'}
        result = stack_item_from_json(stack_item)
        self.assertEqual(expected_result, result)

        stack_item = {'type': StackItemType.Integer.name, 'value': 'xyz'}
        with self.assertRaises(ValueError):
            stack_item_from_json(stack_item)
예제 #5
0
    def from_json(cls, json: Dict[str, Any]) -> Notification:
        """
        Creates a Notification object from a json.

        :param json: json that contains the notification data
        :return: a Notification object
        :rtype: Notification
        """
        keys = set(json.keys())
        if not keys.issubset(
            [cls._event_name_key, cls._script_hash_key, cls._value_key]):
            return None

        name: str = json[
            cls._event_name_key] if cls._event_name_key in json else ""
        script: bytes = json[
            cls._script_hash_key] if cls._script_hash_key in json else b''
        try:
            value: Any = stack_item_from_json(
                json[cls._value_key]) if cls._value_key in json else []
        except ValueError:
            value = []

        if not isinstance(value, list):
            value = [value]

        if isinstance(script, str) and script.startswith('0x'):
            bytes_script = bytearray()
            for x in range(2, len(script), 2):
                bytes_script.append(int(script[x:x + 2], 16))
            bytes_script.reverse()
            script = bytes(bytes_script)

        return cls(name, script, *value)
예제 #6
0
    def from_json(cls, json: Dict[str, Any]) -> Notification:
        """
        Creates a Notification object from a json.

        :param json: json that contains the notification data
        :return: a Notification object
        :rtype: Notification
        """
        keys = set(json.keys())
        if not keys.issubset(
            [cls._event_name_key, cls._script_hash_key, cls._value_key]):
            return None

        name: str = json[
            cls._event_name_key] if cls._event_name_key in json else ""
        script: bytes = json[
            cls._script_hash_key] if cls._script_hash_key in json else b''
        try:
            value: Any = stack_item_from_json(
                json[cls._value_key]) if cls._value_key in json else []
        except ValueError:
            value = []

        if not isinstance(value, list):
            value = [value]

        if isinstance(script, str):
            script = cls._get_script_from_str(script)

        return cls(name, script, *value)
예제 #7
0
    def from_json(cls, json: Dict[str, Any]) -> StorageItem:
        value = stack_item_from_json(json['value'])
        if isinstance(value, str):
            from boa3.neo.vm.type.String import String
            value = String(value).to_bytes()

        item = StorageItem(value, json['isconstant'])
        return item
예제 #8
0
    def from_json(cls, json: Dict[str, Any]) -> StorageKey:
        k = stack_item_from_json(json['key'])
        if isinstance(k, str):
            from boa3.neo.vm.type.String import String
            k = String(k).to_bytes()

        key = StorageKey(k)
        key._ID = json['id']
        return key
예제 #9
0
    def from_json(cls, json: Dict[str, Any]):
        """
        Creates a Notification object from a json.

        :param json: json that contains the notification data
        :return: a Notification object
        :rtype: Notification
        """
        keys = set(json.keys())
        if not keys.issubset(['eventName', 'scriptHash', 'value']):
            return None

        name: str = json["eventName"] if "eventName" in json else ""
        script: bytes = json["scriptHash"] if "scriptHash" in json else b''
        try:
            value: Any = stack_item_from_json(json["value"]) if "value" in json else []
        except ValueError:
            value = []

        if not isinstance(value, list):
            value = [value]

        return cls(name, script, *value)
예제 #10
0
 def test_map_stack_item_from_json(self):
     stack_item = {
         'type':
         'Map',
         'value': [{
             'key': {
                 'type': StackItemType.Integer.name,
                 'value': 1
             },
             'value': {
                 'type': StackItemType.Boolean.name,
                 'value': True
             }
         }, {
             'key': {
                 'type': StackItemType.Integer.name,
                 'value': 2
             },
             'value': {
                 'type': StackItemType.Integer.name,
                 'value': 4
             }
         }, {
             'key': {
                 'type': StackItemType.Integer.name,
                 'value': 3
             },
             'value': {
                 'type': StackItemType.ByteString.name,
                 'value': 'bmluZQ=='
             }
         }]
     }
     expected_result = {1: True, 2: 4, 3: 'nine'}
     result = stack_item_from_json(stack_item)
     self.assertEqual(expected_result, result)
예제 #11
0
    def run(self,
            nef_path: Union[str, UInt160],
            method: str,
            *arguments: Any,
            reset_engine: bool = False,
            rollback_on_fault: bool = True) -> Any:
        import json
        import subprocess

        if isinstance(nef_path, str) and nef_path not in self._contract_paths:
            self._contract_paths.append(nef_path)

        test_engine_args = self.to_json(nef_path, method, *arguments)
        param_json = json.dumps(test_engine_args, separators=(',', ':'))

        process = subprocess.Popen(
            ['dotnet', self._test_engine_path, param_json],
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            text=True)
        stdout, stderr = process.communicate()

        if reset_engine:
            self.reset_engine()
        else:
            self.reset_state()

        stdout = stdout.splitlines()[-1]

        try:
            result = json.loads(stdout)

            self._error_message = result['error'] if 'error' in result else None

            if 'vm_state' in result:
                self._vm_state = VMState.get_vm_state(result['vm_state'])

            if 'gasconsumed' in result:
                self._gas_consumed = result['gasconsumed']

            if 'result_stack' in result:
                if isinstance(result['result_stack'], list):
                    self._result_stack = [
                        stack_item_from_json(value)
                        for value in result['result_stack']
                    ]
                else:
                    self._result_stack = [
                        stack_item_from_json(result['result_stack'])
                    ]

            if self._vm_state is VMState.HALT or not rollback_on_fault:
                if 'notifications' in result:
                    json_storage = result['notifications']
                    if not isinstance(json_storage, list):
                        json_storage = [json_storage]

                    notifications = []
                    for n in json_storage:
                        new = Notification.from_json(n)
                        if new is not None:
                            notifications.append(new)
                    self._notifications = notifications

                if 'storage' in result:
                    json_storage = result['storage']
                    self._storage = Storage.from_json(json_storage)

                if 'blocks' in result:
                    blocks_json = result['blocks']
                    if not isinstance(blocks_json, list):
                        blocks_json = [blocks_json]

                    self._blocks = sorted(
                        [Block.from_json(js) for js in blocks_json],
                        key=lambda b: b.index)

                if 'transaction' in result and self._vm_state is VMState.HALT:
                    block = self.current_block
                    if block is None:
                        block = self.increase_block(self.height)

                    tx = Transaction.from_json(result['transaction'])
                    block.add_transaction(tx)

        except BaseException as e:
            self._error_message = str(e)

        # TODO: convert the result to the return type of the function in the manifest
        return self._result_stack[-1] if len(
            self._result_stack) > 0 else VoidType
예제 #12
0
 def test_any_stack_item_from_json(self):
     stack_item = {'type': StackItemType.Any.name}
     result = stack_item_from_json(stack_item)
     self.assertIsNone(result)
예제 #13
0
    def run(self,
            nef_path: str,
            method: str,
            *arguments: Any,
            reset_engine: bool = False) -> Any:
        import json
        import subprocess

        contract_parameters = [
            contract_parameter_to_json(x) for x in arguments
        ]
        param_json = json.dumps(contract_parameters).replace(' ', '')

        process = subprocess.Popen(
            ['dotnet', self._test_engine_path, nef_path, method, param_json],
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            text=True)
        stdout, stderr = process.communicate()

        if reset_engine:
            self.reset_engine()
        else:
            self.reset_state()

        stdout = stdout.splitlines()[-1]

        try:
            result = json.loads(stdout)

            self._error_message = result['error'] if 'error' in result else None
            if 'vm_state' in result:
                self._vm_state = VMState.get_vm_state(result['vm_state'])

            if 'gasconsumed' in result:
                self._gas_consumed = result['gasconsumed']

            if 'result_stack' in result:
                if isinstance(result['result_stack'], list):
                    self._result_stack = [
                        stack_item_from_json(value)
                        for value in result['result_stack']
                    ]
                else:
                    self._result_stack = [
                        stack_item_from_json(result['result_stack'])
                    ]

            if 'notifications' in result:
                json_notifications = result['notifications']
                if not isinstance(json_notifications, list):
                    json_notifications = [json_notifications]

                notifications = []
                for n in json_notifications:
                    new = Notification.from_json(n)
                    if new is not None:
                        notifications.append(new)
                self._notifications = notifications

        except BaseException as e:
            self._error_message = str(e)

        # TODO: convert the result to the return type of the function in the manifest
        return self._result_stack[-1] if len(self._result_stack) > 0 else None
예제 #14
0
    def run(self, contract_id: Union[str, UInt160], method: str, *arguments: Any, reset_engine: bool = False,
            rollback_on_fault: bool = True) -> Any:
        import json
        import subprocess

        if isinstance(contract_id, str) and contract_id not in self.contracts:
            self.add_contract(contract_id)

        # build an UInt160 value if the contract_id is not a path
        if isinstance(contract_id, bytes) and not isinstance(contract_id, UInt160):
            contract_id = UInt160(contract_id)

        test_engine_args = self.to_json(contract_id, method, *arguments)
        param_json = json.dumps(test_engine_args, separators=(',', ':'))

        try:
            process = subprocess.Popen(['dotnet', self._test_engine_path, param_json],
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.STDOUT,
                                       text=True)
        except BaseException:
            json_path = '{0}/test-engine-test.json'.format(path.curdir)
            with open(json_path, 'wb+') as json_file:
                json_file.write(String(param_json).to_bytes())
                json_file.close()

            process = subprocess.Popen(['dotnet', self._test_engine_path, json_path],
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.STDOUT,
                                       text=True)

        stdout, stderr = process.communicate()

        if reset_engine:
            self.reset_engine()
        else:
            self.reset_state()

        stdout = stdout.splitlines()[-1]

        try:
            result = json.loads(stdout)

            self._error_message = result['error'] if 'error' in result else None

            if 'vmstate' in result:
                self._vm_state = VMState.get_vm_state(result['vmstate'])

            if 'executedscripthash' in result:
                self._executed_script_hash = UInt160.from_string(result['executedscripthash'])

            if 'gasconsumed' in result:
                self._gas_consumed = int(result['gasconsumed'])

            if 'resultstack' in result:
                if isinstance(result['resultstack'], list):
                    self._result_stack = [stack_item_from_json(value) for value in result['resultstack']]
                else:
                    self._result_stack = [stack_item_from_json(result['resultstack'])]

            if self._vm_state is VMState.HALT or not rollback_on_fault:
                if 'notifications' in result:
                    json_storage = result['notifications']
                    if not isinstance(json_storage, list):
                        json_storage = [json_storage]

                    notifications = []
                    for n in json_storage:
                        new = Notification.from_json(n)
                        if new is not None:
                            notifications.append(new)
                    self._notifications.extend(notifications)

                if 'storage' in result:
                    json_storage = result['storage']
                    self._storage = Storage.from_json(json_storage)

                    for contract in self._contract_paths.copy():
                        if (not isinstance(contract, TestContract)
                                or contract.script_hash is None
                                or not self._storage.has_contract(contract.script_hash)):
                            self.remove_contract(contract.path)

                if 'currentblock' in result:
                    current_block = Block.from_json(result['currentblock'])

                    existing_block = next((block for block in self._blocks if block.index == current_block.index), None)
                    if existing_block is not None:
                        self._blocks.remove(existing_block)
                    self._blocks.append(current_block)

                if 'transaction' in result and self._vm_state is VMState.HALT:
                    block = self.current_block
                    if block is None:
                        block = self.increase_block(self.height)

                    tx = Transaction.from_json(result['transaction'])
                    block.add_transaction(tx)

        except BaseException as e:
            self._error_message = str(e)

        # TODO: convert the result to the return type of the function in the manifest
        return self._result_stack[-1] if len(self._result_stack) > 0 else VoidType