def execute(cls, stack: MichelsonStack, stdout: List[str], context: AbstractContext): a, b = cast( Tuple[Union[IntType, NatType, MutezType, TimestampType], ...], stack.pop2()) q_type, r_type = dispatch_types( type(a), type(b), mapping={ # type: ignore (NatType, NatType): (NatType, NatType), (NatType, IntType): (IntType, NatType), (IntType, NatType): (IntType, NatType), (IntType, IntType): (IntType, NatType), (MutezType, NatType): (MutezType, MutezType), (MutezType, MutezType): (NatType, MutezType) } ) # type: Union[Type[IntType], Type[NatType], Type[TimestampType], Type[MutezType]] if int(b) == 0: res = OptionType.none(PairType.create_type(args=[q_type, r_type])) else: q, r = divmod(int(a), int(b)) if r < 0: r += abs(int(b)) q += 1 items = [q_type.from_value(q), r_type.from_value(r)] res = OptionType.from_some(PairType.from_comb(items)) stack.push(res) stdout.append(format_stdout(cls.prim, [a, b], [res])) # type: ignore return cls(stack_items_added=1)
def execute(cls, stack: MichelsonStack, stdout: List[str], context: AbstractContext): ticket, amounts = cast(Tuple[TicketType, PairType], stack.pop2()) ticket.assert_type_in(TicketType) amounts.assert_type_in(PairType) a, b = tuple(amounts) # type: NatType, NatType a.assert_type_equal(NatType) b.assert_type_equal(NatType) res = ticket.split(int(a), int(b)) if res is None: res = OptionType.none(PairType.create_type(args=[type(ticket), type(ticket)])) else: res = OptionType.from_some(PairType.from_comb(list(res))) stack.push(res) stdout.append(format_stdout(cls.prim, [ticket, amounts], [res])) return cls()
def execute(cls, stack: MichelsonStack, stdout: List[str], context: AbstractContext): stack_items_added = 0 src = cast(Union[ListType, MapType], stack.pop1()) executions = [] items = [] popped = [src] for elt in src: if isinstance(src, MapType): elt = PairType.from_comb(list(elt)) # type: ignore stack.push(elt) # type: ignore stack_items_added += 1 stdout.append(format_stdout(cls.prim, popped, [elt])) # type: ignore execution = cls.args[0].execute(stack, stdout, context=context) executions.append(execution) new_elt = stack.pop1() if isinstance(src, MapType): items.append((elt[0], new_elt)) else: items.append(new_elt) # type: ignore popped = [new_elt] # type: ignore if items: res = type(src).from_items(items) # type: ignore else: res = src # TODO: need to deduce argument types stack.push(res) stack_items_added += 1 stdout.append(format_stdout(cls.prim, popped, [res])) # type: ignore return cls(stack_items_added, executions)
def execute(cls, stack: MichelsonStack, stdout: List[str], context: AbstractContext): # FIXME: MichelsonProgram copypaste parameter_literal, storage_literal = cls.args # type: ignore parameter_type_expr = context.get_parameter_expr() storage_type_expr = context.get_storage_expr() if parameter_type_expr is None: raise Exception('parameter type is not initialized') if storage_type_expr is None: raise Exception('storage type is not initialized') parameter_type = ParameterSection.match(parameter_type_expr) storage_type = StorageSection.match(storage_type_expr) parameter = parameter_type.from_micheline_value( parameter_literal.as_micheline_expr()) storage = storage_type.from_micheline_value( storage_literal.as_micheline_expr()) parameter.attach_context(context) storage.attach_context(context) res = PairType.from_comb([parameter.item, storage.item]) stack.items = [] stack.push(res) stdout.append(format_stdout(f'BEGIN %default', [], [res])) return cls(stack_items_added=1)
def begin(self, stack: MichelsonStack, stdout: List[str], context: ExecutionContext): self.parameter_value.attach_context(context) self.storage_value.attach_context(context) res = PairType.from_comb( [self.parameter_value.item, self.storage_value.item]) stack.push(res) stdout.append(format_stdout(f'BEGIN %{self.entrypoint}', [], [res]))
def execute(cls, stack: MichelsonStack, stdout: List[str], context: AbstractContext): left, right = stack.pop2() res = PairType.from_comb([left, right]) stack.push(res) stdout.append(format_stdout(cls.prim, [left, right], [res])) # type: ignore return cls(stack_items_added=1)
def execute(cls, stack: MichelsonStack, stdout: List[str], context: AbstractContext): count = cls.args[0].get_int() assert count >= 2, f'invalid argument, must be >= 2' leaves = stack.pop(count=count) res = PairType.from_comb(leaves) stack.push(res) stdout.append(format_stdout(cls.prim, leaves, [res], count)) return cls()
def end(self, stack: MichelsonStack, stdout: List[str], output_mode='readable') \ -> Tuple[List[dict], Any, List[dict], PairType]: res = cast(PairType, stack.pop1()) assert len(stack) == 0, f'stack is not empty: {repr(stack)}' res.assert_type_equal(PairType.create_type(args=[ ListType.create_type(args=[OperationType]), self.storage.args[0] ]), message='list of operations + resulting storage') operations = [op.content for op in res.items[0]] lazy_diff = [] storage = res.items[1].aggregate_lazy_diff(lazy_diff).to_micheline_value(mode=output_mode) stdout.append(format_stdout(f'END %{self.entrypoint}', [res], [])) return operations, storage, lazy_diff, res
def execute(cls, stack: MichelsonStack, stdout: List[str], context: AbstractContext): src = cast(Union[ListType, MapType, SetType], stack.pop1()) executions = [] popped = [src] for elt in src: if isinstance(src, MapType): elt = PairType.from_comb(list(elt)) stack.push(elt) stdout.append(format_stdout(cls.prim, popped, [elt])) execution = cls.args[0].execute(stack, stdout, context=context) executions.append(execution) popped = [] return cls(executions)
def execute(cls, stack: MichelsonStack, stdout: List[str], context: AbstractContext): # FIXME: MichelsonProgram copypaste debug, context.debug = context.debug, False # type: ignore res = cast(PairType, stack.pop1()) if len(stack): raise Exception(f'Stack is not empty: {stack}') res.assert_type_equal( PairType.create_type( args=[ ListType.create_type(args=[OperationType]), StorageSection.match(context.get_storage_expr()).args[0] ], ), message='list of operations + resulting storage', ) operations = ListType(items=[op for op in res.items[0]]) # type: ignore lazy_diff = [] # type: ignore storage = res.items[1].aggregate_lazy_diff(lazy_diff) stdout.append(format_stdout(f'END %default', [res], [])) result = PairType.from_comb([operations, storage]) context.debug = debug # type: ignore return cls(lazy_diff=lazy_diff, result=result)
def execute(cls, stack: 'MichelsonStack', stdout: List[str], context: AbstractContext): points = cast(ListType, stack.pop1()) points.assert_type_equal( ListType.create_type(args=[ PairType.create_type(args=[BLS12_381_G1Type, BLS12_381_G2Type]) ])) prod = FQ12.one() for pair in points: g1, g2 = tuple( iter(pair)) # type: BLS12_381_G1Type, BLS12_381_G2Type prod = prod * bls12_381.pairing(g2.to_point(), g1.to_point()) res = BoolType.from_value(FQ12.one() == prod) stack.push(res) stdout.append(format_stdout(cls.prim, [points], [res])) return cls()
def test_execute(self) -> None: # Arrange interpreter = Interpreter() code = "PUSH int 1; PUSH int 2; PAIR" # Act result = interpreter.execute(code) # Assert self.assertEqual(None, result.error) self.assertEqual( [ "PUSH / _ => 1", "PUSH / _ => 2", "PAIR / 2 : 1 => (2 * 1)", ], result.stdout, ) self.assertEqual([PairType((IntType(2), IntType(1)))], interpreter.stack.items)
def test_execute_rollback(self) -> None: # Arrange interpreter = Interpreter() code = "PUSH int 1; PUSH int 2; PAIR" bad_code = "PUSH int 1; PAIR; PAIR;" # Act interpreter.execute(code) result = interpreter.execute(bad_code) # Assert self.assertIsInstance(result.error, MichelsonRuntimeError) self.assertEqual( [ "PUSH / _ => 1", "PAIR / 1 : (2 * 1) => (1 * (2 * 1))", "PAIR: got 1 items on the stack, want to pop 2", ], result.stdout, ) self.assertEqual([PairType((IntType(2), IntType(1)))], interpreter.stack.items)
def end(self, stack: MichelsonStack, stdout: List[str], output_mode='readable' ) -> Tuple[List[dict], Any, List[dict], PairType]: """Finish contract execution""" res = cast(PairType, stack.pop1()) if len(stack): raise Exception(f'Stack is not empty: {repr(stack)}') res.assert_type_equal( PairType.create_type(args=[ ListType.create_type(args=[OperationType]), self.storage.args[0] ], ), message='list of operations + resulting storage', ) operations = [op.content for op in res.items[0]] # type: ignore lazy_diff = [] # type: ignore storage = res.items[1].aggregate_lazy_diff( lazy_diff).to_micheline_value(mode=output_mode) stdout.append(format_stdout(f'END %{self.entrypoint}', [res], [])) return operations, storage, lazy_diff, res
def test_execute_contract_operations(self) -> None: # Arrange interpreter = Interpreter() code = """ PATCH SENDER "tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb" ; PATCH BALANCE 200 ; parameter mutez ; storage unit ; BEGIN 100 Unit ; CAR ; DUP ; BALANCE ; IFCMPLT { FAIL } { SENDER ; CONTRACT unit ; IF_NONE { FAIL } { SWAP ; UNIT ; TRANSFER_TOKENS ; NIL operation ; SWAP ; CONS ; UNIT ; SWAP ; PAIR } ; }; COMMIT """ # Act result = interpreter.execute(code) # Assert self.assertEqual(None, result.error) self.assertEqual( [ "parameter: updated", "storage: updated", "BEGIN %default / _ => (0.0001 * Unit)", "CAR / (0.0001 * Unit) => 0.0001", "DUP / 0.0001 => 0.0001 : 0.0001", "BALANCE / _ => 0.0002", "COMPARE / 0.0002 : 0.0001 => 1", "LT / 1 => False", "IF / False => _", "SENDER / _ => tz1VSU…cjb", "CONTRACT: skip type checking for tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb", "CONTRACT / tz1VSU…cjb => tz1VSU…cjb%default?", "IF_NONE / tz1VSU…cjb%default? => tz1VSU…cjb%default", "SWAP / tz1VSU…cjb%default : 0.0001 => 0.0001 : tz1VSU…cjb%default", "UNIT / _ => Unit", "TRANSFER_TOKENS / Unit : 0.0001 : tz1VSU…cjb%default => transaction", "NIL / _ => []", "SWAP / [] : transaction => transaction : []", "CONS / transaction : [] => [transaction]", "UNIT / _ => Unit", "SWAP / Unit : [transaction] => [transaction] : Unit", "PAIR / [transaction] : Unit => ([transaction] * Unit)", "END %default / ([transaction] * Unit) => _", ], result.stdout, ) commit_instruction = next((i for i in result.instructions.items[::-1] if isinstance(i, CommitInstruction))) self.assertEqual( PairType(( ListType([ OperationType({ "kind": "transaction", "source": "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi", "destination": "tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb", "amount": "100", "parameters": { "entrypoint": "default", "value": { "prim": "Unit" }, }, }) ]), UnitType(), )), commit_instruction.result, )