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
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)
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)
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)
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)
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)
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
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
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)
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)
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
def test_any_stack_item_from_json(self): stack_item = {'type': StackItemType.Any.name} result = stack_item_from_json(stack_item) self.assertIsNone(result)
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
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