def load(context: ExecutionContext, with_code=False): cls = type( MichelsonProgram.__name__, (MichelsonProgram, ), dict( parameter=ParameterSection.match(context.get_parameter_expr()), storage=StorageSection.match(context.get_storage_expr()), code=CodeSection.match( context.get_code_expr() if with_code else []), ), ) return cast(Type['MichelsonProgram'], cls)
def load(context: ExecutionContext, with_code=False): cls = type( TztMichelsonProgram.__name__, (TztMichelsonProgram, ), dict( input=InputSection.match(context.get_input_expr()), output=OutputSection.match(context.get_output_expr()), code=CodeSection.match( context.get_code_expr() if with_code else []), big_maps=BigMapsSection.match(context.get_big_maps_expr()) if context.get_big_maps_expr() else None, ), ) return cast(Type['TztMichelsonProgram'], cls)
def test_sandboxed(self) -> None: # Arrange # TODO: Update with florencenet response public_version_response = { "version": { "major": 8, "minor": 2, "additional_info": "release" }, "network_version": { "chain_name": "TEZOS_EDO2NET_2021-02-11T14:00:00Z", "distributed_db_version": 1, "p2p_version": 1 }, "commit_info": { "commit_hash": "6102c808a21b32e732ab9bb1825761cd056f3e86", "commit_date": "2021-02-10 22:57:06 +0100" }, } sandboxed_version_response = { "version": { "major": 8, "minor": 2, "additional_info": "release" }, "network_version": { "chain_name": "SANDBOXED_TEZOS", "distributed_db_version": 1, "p2p_version": 1 }, "commit_info": { "commit_hash": "6102c808a21b32e732ab9bb1825761cd056f3e86", "commit_date": "2021-02-10 22:57:06 +0100" }, } # Act with patch("pytezos.rpc.query.RpcQuery.__call__") as rpc_mock: rpc_mock.return_value = public_version_response public_result = ExecutionContext(shell=ShellQuery(None)).sandboxed with patch("pytezos.rpc.query.RpcQuery.__call__") as rpc_mock: rpc_mock.return_value = sandboxed_version_response sandboxed_result = ExecutionContext( shell=ShellQuery(None)).sandboxed # Assert self.assertFalse(public_result) self.assertTrue(sandboxed_result)
def run_view( entrypoint: str, parameter, storage, context: ExecutionContext, ) -> Tuple[Any, Any, List[str], Optional[Exception]]: """Execute view of contract loaded in context :param entrypoint: contract entrypoint :param parameter: parameter section :param storage: storage section :param context: execution context :returns: [operations, storage, stdout, error] """ ctx = ExecutionContext( shell=context.shell, key=context.key, block_id=context.block_id, script=context.script, address=context.address, ) stack = MichelsonStack() stdout = [] # type: ignore try: program = MichelsonProgram.load(ctx, with_code=True) res = program.instantiate(entrypoint=entrypoint, parameter=parameter, storage=storage) res.begin(stack, stdout, context) res.execute(stack, stdout, context) _, _, _, pair = res.end(stack, stdout) operations = cast(List[OperationType], list(pair.items[0])) storage = pair.items[1] return [op.to_python_object() for op in operations], storage.to_python_object(), stdout, None except MichelsonRuntimeError as e: stdout.append(e.format_stdout()) return None, None, stdout, e
def run_view( entrypoint, parameter, storage, context: ExecutionContext, ) -> Tuple[Any, List[str], Optional[Exception]]: ctx = ExecutionContext( shell=context.shell, key=context.key, block_id=context.block_id, script=context.script, address=context.address, ) stack = MichelsonStack() stdout = [] # type: ignore try: program = MichelsonProgram.load(ctx, with_code=True) res = program.instantiate(entrypoint=entrypoint, parameter=parameter, storage=storage) res.begin(stack, stdout, context) res.execute(stack, stdout, context) _, _, _, pair = res.end(stack, stdout) operations = cast(List[OperationType], list(pair.items[0])) if not len(operations) == 1: raise Exception( 'Multiple internal operations, not sure which one to pick') return operations[0].to_python_object(), stdout, None except MichelsonRuntimeError as e: stdout.append(e.format_stdout()) return None, stdout, e
def run_tzt( script, amount=None, chain_id=None, source=None, sender=None, balance=None, block_id=None, **kwargs, ) -> None: context = ExecutionContext( amount=amount, chain_id=chain_id, source=source, sender=sender, balance=balance, block_id=block_id, script=dict(code=script), tzt=True, **kwargs, ) stack = MichelsonStack() stdout: List[str] = [] program = TztMichelsonProgram.load(context, with_code=True) res = program.instantiate() res.fill_context(script, context) res.register_bigmaps(stack, stdout, context) res.begin(stack, stdout, context) res.execute(stack, stdout, context) res.end(stack, stdout, context)
def from_json(cls, metadata_json: Dict[str, Any], context: Optional[ExecutionContext] = None) -> 'ContractMetadata': metadata_json = cls.fix_metadata_json(metadata_json) cls.validate_metadata_json(metadata_json) res = Converter().structure(metadata_json, ContractMetadata) res.context = context if context else ExecutionContext() res.raw = metadata_json return res
def __init__(self, context: Optional[ExecutionContext] = None): super(ContextMixin, self).__init__() if context is None: context = ExecutionContext( shell=ShellQuery(RpcNode(nodes[default_network][0])), key=Key.from_encoded_key(default_key) if is_installed() else KeyHash(default_key_hash)) self.context = context
def from_ipfs( cls, multihash: str, context: Optional[ExecutionContext] = None) -> 'ContractMetadata': context = context or ExecutionContext() metadata_json = requests.get( f'{context.ipfs_gateway}/{multihash}').json() return cls.from_json(metadata_json, context)
def from_ipfs(cls, multihash: str, context: Optional[ExecutionContext] = None ) -> 'ContractTokenMetadata': """Fetch token metadata from IPFS network by multihash""" context = context or ExecutionContext() token_metadata_json = requests.get( f'{context.ipfs_gateway}/{multihash}').json() return cls.from_json(token_metadata_json, context)
def __init__( self, extra_primitives: Optional[List[str]] = None, debug: bool = False, ) -> None: self.stack = MichelsonStack() self.context = ExecutionContext() self.context.debug = debug self.parser = MichelsonParser(debug=debug, extra_primitives=extra_primitives)
def run_code( parameter, storage, script: str, entrypoint='default', output_mode='readable', amount=None, chain_id=None, source=None, sender=None, balance=None, block_id=None, **kwargs, ) -> Tuple[List[dict], Any, List[dict], List[str], Optional[Exception]]: """Execute contract in interpreter :param parameter: parameter expression :param storage: storage expression :param script: contract's Michelson code :param entrypoint: contract entrypoint :param output_mode: one of readable/optimized/legacy_optimized :param amount: patch AMOUNT :param chain_id: patch CHAIN_ID :param source: patch SOURCE :param sender: patch SENDER :param balance: patch BALANCE :param block_id: set block ID """ context = ExecutionContext( amount=amount, chain_id=chain_id, source=source, sender=sender, balance=balance, block_id=block_id, script=dict(code=script), **kwargs, ) stack = MichelsonStack() stdout = [] # type: ignore try: program = MichelsonProgram.load(context, with_code=True) res = program.instantiate( entrypoint=entrypoint, parameter=parameter, storage=storage, ) res.begin(stack, stdout, context) res.execute(stack, stdout, context) operations, storage, lazy_diff, _ = res.end( stack, stdout, output_mode=output_mode) return operations, storage, lazy_diff, stdout, None except MichelsonRuntimeError as e: stdout.append(e.format_stdout()) return [], None, [], stdout, e
def _spawn_context( self, shell: Optional[Union[ShellQuery, str]] = None, key: Optional[Union[Key, str, dict]] = None, address: Optional[str] = None, block_id: Optional[Union[str, int]] = None, mode: Optional[str] = None, script: Optional[dict] = None, ipfs_gateway: Optional[str] = None, ) -> ExecutionContext: if isinstance(shell, str): if shell.endswith('.pool'): shell = shell.split('.')[0] assert shell in nodes, f'unknown network {shell}' shell = ShellQuery(RpcMultiNode(nodes[shell])) elif shell in nodes: shell = ShellQuery(RpcNode(nodes[shell][0])) else: shell = ShellQuery(RpcNode(shell)) else: assert shell is None or isinstance( shell, ShellQuery), f'unexpected shell {shell}' if isinstance(key, str): if key in keys: key = Key.from_encoded_key(keys[key]) elif is_public_key(key): key = Key.from_encoded_key(key) elif is_pkh(key): key = KeyHash(key) elif exists(expanduser(key)): key = Key.from_faucet(key) else: key = Key.from_alias(key) elif isinstance(key, dict): key = Key.from_faucet(key) else: assert key is None or isinstance(key, Key), f'unexpected key {key}' if isinstance(address, str): try: script = self.shell.contracts[address].script() except RpcError as e: raise RpcError(f'Contract {address} not found', *e.args) from e return ExecutionContext( shell=shell or self.context.shell, key=key or self.context.key, address=address, block_id=block_id, script=script or self.context.script, mode=mode or self.context.mode, ipfs_gateway=ipfs_gateway, )
def from_json( cls, token_metadata_json: Dict[str, Any], context: Optional[ExecutionContext] = None ) -> 'ContractTokenMetadata': for key, value in token_metadata_json.items(): if isinstance(value, bytes): token_metadata_json[key] = value.decode() if 'decimals' in token_metadata_json: token_metadata_json['decimals'] = int( token_metadata_json['decimals']) cls.validate_token_metadata_json(token_metadata_json) res = Converter().structure(token_metadata_json, ContractTokenMetadata) res.context = context if context else ExecutionContext() res.raw = token_metadata_json return res
def run_view( entrypoint: str, parameter, storage, context: ExecutionContext, ) -> Tuple[Any, Any, List[str], Optional[Exception]]: """Execute view of contract loaded in context :param entrypoint: contract entrypoint :param parameter: parameter section :param storage: storage section :param context: execution context :returns: [operations, storage, stdout, error] """ ctx = ExecutionContext( shell=context.shell, key=context.key, block_id=context.block_id, script=context.script, address=context.address, ) stack = MichelsonStack() stdout = [] # type: ignore try: program = MichelsonProgram.load(ctx, with_code=True) res = program.instantiate(entrypoint=entrypoint, parameter=parameter, storage=storage) res.begin(stack, stdout, context) res.execute(stack, stdout, context) _, _, _, pair = res.end(stack, stdout) operations = cast(List[OperationType], list(pair.items[0])) storage = pair.items[1] # Note: the `storage` returned by the Michelson interpreter above is not # required to include the full annotations specified in the contract's storage. # The lack of annotations affects calls to `to_python_object()`, causing the storage # you get back from the view to not always be converted to the same object # as if you called ContractInterface.storage() directly. # Re-parsing using the contract's storage section here to recover the annotations. storage = program.storage.from_micheline_value(storage.to_micheline_value()) return [op.to_python_object() for op in operations], storage.to_python_object(), stdout, None except MichelsonRuntimeError as e: stdout.append(e.format_stdout()) return None, None, stdout, e
def run_code( parameter, storage, script, entrypoint='default', output_mode='readable', amount=None, chain_id=None, source=None, sender=None, balance=None, block_id=None, **kwargs, ) -> Tuple[List[dict], Any, List[dict], List[str], Optional[Exception]]: context = ExecutionContext( amount=amount, chain_id=chain_id, source=source, sender=sender, balance=balance, block_id=block_id, script=dict(code=script), **kwargs, ) stack = MichelsonStack() stdout = [] # type: ignore try: program = MichelsonProgram.load(context, with_code=True) res = program.instantiate( entrypoint=entrypoint, parameter=parameter, storage=storage, ) res.begin(stack, stdout, context) res.execute(stack, stdout, context) operations, storage, lazy_diff, _ = res.end( stack, stdout, output_mode=output_mode) return operations, storage, lazy_diff, stdout, None except MichelsonRuntimeError as e: stdout.append(e.format_stdout()) return [], None, [], stdout, e
def run_tzt( script: str, amount=None, chain_id=None, source=None, sender=None, balance=None, block_id=None, **kwargs, ) -> None: """Execute TZT test suite code :param script: test contract's Michelson code :param amount: patch AMOUNT :param chain_id: patch CHAIN_ID :param source: patch SOURCE :param sender: patch SENDER :param balance: patch BALANCE :param block_id: set block ID """ context = ExecutionContext( amount=amount, chain_id=chain_id, source=source, sender=sender, balance=balance, block_id=block_id, script=dict(code=script), tzt=True, **kwargs, ) stack = MichelsonStack() stdout: List[str] = [] program = TztMichelsonProgram.load(context, with_code=True) res = program.instantiate() res.fill_context(script, context) res.register_bigmaps(stack, stdout, context) res.begin(stack, stdout, context) res.execute(stack, stdout, context) res.end(stack, stdout, context)
def reset(self) -> None: self.stack = MichelsonStack() self.context = ExecutionContext()
def setUp(self): self.context = ExecutionContext() self.stack = MichelsonStack() self.stdout = []
def reset(self) -> None: """Reset interpreter's stack and context""" self.stack = MichelsonStack() self.context = ExecutionContext()
def fill_context(self, script, context: ExecutionContext) -> None: sender = context.get_sender_expr() if sender: context.sender = SenderSection.match( sender).args[0].get_string() # type: ignore amount = context.get_amount_expr() if amount: context.amount = AmountSection.match( amount).args[0].get_int() # type: ignore balance = context.get_balance_expr() if balance: context.balance = BalanceSection.match( balance).args[0].get_int() # type: ignore _self = context.get_self_expr() if _self: context.address = SelfSection.match( _self).args[0].get_string() # type: ignore now = context.get_now_expr() if now: context.now = NowSection.match( now).args[0].get_int() # type: ignore source = context.get_source_expr() if source: context.source = SourceSection.match( source).args[0].get_string() # type: ignore chain_id = context.get_chain_id_expr() if chain_id: # FIXME: Move to some common place context.chain_id = base58_encode( cast(bytes, ChainIdSection.match(chain_id).args[0].literal), prefix=b'Net', ).decode()