コード例 #1
0
ファイル: __init__.py プロジェクト: CityOfZion/neo3-boa
    def _verify_is_valid_contract_hash(contract_hash: str) -> bool:
        """
        Verifies if a given contract hash is valid.

        :return: whether the given contract hash is valid or not
        """
        if contract_hash.startswith('0x'):
            try:
                from boa3.neo3.core.types import UInt160
                # if contract_hash is not a valid UInt160, it will raise a ValueError
                UInt160.from_string(contract_hash[2:])
                return True
            except ValueError:
                pass
        return False
コード例 #2
0
    def test_contract_interface_code_optimization(self):
        from boa3.model.builtin.interop.interop import Interop
        from boa3.neo.vm.opcode.Opcode import Opcode
        from boa3.neo.vm.type.Integer import Integer
        from boa3.neo.vm.type.String import String
        from boa3.neo3.core.types import UInt160

        external_contract_name = 'symbol'
        function_name_bytes = String(external_contract_name).to_bytes()
        contract_script_bytes = UInt160.from_string(
            '21f19f84e144f91abe755efb21a6798ac95c2e70').to_array()

        expected_output = (
            Opcode.NEWARRAY0  # arguments list
            + Opcode.PUSH15  # CallFlag
            + Opcode.PUSHDATA1  # function name
            + Integer(len(function_name_bytes)).to_byte_array() +
            function_name_bytes + Opcode.PUSHDATA1  # contract script
            + Integer(len(contract_script_bytes)).to_byte_array() +
            contract_script_bytes + Opcode.SYSCALL +
            Interop.CallContract.interop_method_hash + Opcode.RET)

        path = self.get_contract_path('ContractInterfaceCodeOptimization.py')
        output, manifest = self.compile_and_save(path)
        self.assertEqual(expected_output, output)

        nep17_path = self.get_contract_path('examples', 'nep17.py')
        engine = TestEngine()

        nep17_result = self.run_smart_contract(engine, nep17_path, 'symbol')
        result = self.run_smart_contract(engine, path, 'nep17_symbol')
        self.assertEqual(nep17_result, result)
コード例 #3
0
 def _get_script_hash(self) -> Optional[bytes]:
     try:
         return UInt160.from_string(
             self._contract_hash[2:] if self._contract_hash.
             startswith('0x') else self._contract_hash).to_array()
     except BaseException:
         return None
コード例 #4
0
ファイル: notification.py プロジェクト: CityOfZion/neo3-boa
    def _get_script_from_str(cls, script: str) -> bytes:
        if isinstance(script, str):
            if script.startswith('0x'):
                str_script = script[2:]
            else:
                str_script = script
            script = UInt160.from_string(str_script).to_array()

        return script
コード例 #5
0
    def test_contract_manual_interface_code_optimization(self):
        from boa3.model.builtin.interop.interop import Interop
        from boa3.neo.vm.opcode.Opcode import Opcode
        from boa3.neo.vm.type.Integer import Integer
        from boa3.neo.vm.type.String import String
        from boa3.neo3.core.types import UInt160

        external_contract_name = 'symbol'
        function_name_bytes = String(external_contract_name).to_bytes()
        contract_script_bytes = UInt160.from_string(
            '21f19f84e144f91abe755efb21a6798ac95c2e70').to_array()

        expected_output = (
            # start public method
            Opcode.LDSFLD0  # generated cls arg
            + Opcode.CALL + Integer(35).to_byte_array() + Opcode.RET
            # end public method
            # start initialize method
            + Opcode.INITSSLOT + b'\x01' + Opcode.PUSH1 + Opcode.NEWARRAY +
            Opcode.STSFLD0 + Opcode.PUSHDATA1 +
            Integer(len(contract_script_bytes)).to_byte_array() +
            contract_script_bytes + Opcode.PUSH0 + Opcode.LDSFLD0 +
            Opcode.REVERSE3 + Opcode.SETITEM + Opcode.RET
            # end initialize method
            # start 'symbol' class method
            + Opcode.INITSLOT + b'\x00\x01' +
            Opcode.NEWARRAY0  # arguments list
            + Opcode.PUSH15  # CallFlag
            + Opcode.PUSHDATA1  # function name
            + Integer(len(function_name_bytes)).to_byte_array() +
            function_name_bytes + Opcode.LDARG0  # contract script
            + Opcode.PUSH0 + Opcode.PICKITEM + Opcode.SYSCALL +
            Interop.CallContract.interop_method_hash + Opcode.RET
            # start class method
        )

        path = self.get_contract_path(
            'ContractManualInterfaceCodeOptimization.py')
        output, manifest = self.compile_and_save(path)
        self.assertEqual(expected_output, output)

        nep17_path = self.get_contract_path('examples', 'nep17.py')
        engine = TestEngine()

        nep17_result = self.run_smart_contract(engine, nep17_path, 'symbol')
        result = self.run_smart_contract(engine, path, 'nep17_symbol')
        self.assertEqual(nep17_result, result)
コード例 #6
0
    def from_json(cls, json: Dict[str, Any]) -> TestRunnerLog:
        """
        Creates a Log object from a json.

        :param json: json that contains the log data
        :return: a Log object
        :rtype: TestRunnerLog
        """
        keys = set(json.keys())
        if not keys.issubset([cls._contract_key, cls._message_key]):
            return None

        script: bytes = json[
            cls._contract_key] if cls._contract_key in json else b''
        message: str = json[
            cls._message_key] if cls._message_key in json else ""

        if isinstance(script, str):
            script = UInt160.from_string(
                script[2:] if script.startswith('0x') else script).to_array()

        return cls(script, message)
コード例 #7
0
    def _get_contract_hash_or_name(
            self, contract_id: Union[str, bytes]) -> Union[str, UInt160]:
        if isinstance(contract_id, str):
            if contract_id in self._contracts:
                contract = self._contracts[contract_id]
                return contract.name if hasattr(
                    contract, 'name') else contract.script_hash

            try:
                return UInt160.from_string(contract_id)
            except BaseException as e:
                if not contract_id.endswith('.nef'):
                    raise e
                manifest_file = contract_id.replace('.nef', '.manifest.json')
                if os.path.exists(manifest_file):
                    with open(manifest_file) as manifest_output:
                        import json
                        manifest = json.loads(manifest_output.read())
                        return manifest['name']

                raise e
        else:
            return UInt160(contract_id)
コード例 #8
0
ファイル: testengine.py プロジェクト: CityOfZion/neo3-boa
    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