def do_address(ctx: Context, prim, args, annots): top = ctx.pop1() assert_stack_type(top, Contract) res = Address.new(top.get_address()) if top.name: annots.append(f'@{top.name}.address') ctx.push(res, annots=annots)
def do_create_contract(ctx: Context, prim, args, annots): assert len(args[0]) == 3, 'expected { parameter ; storage ; code }' parameter_type, storage_type, code = args[0] delegate, amount, storage = ctx.pop3() assert_stack_type(amount, Mutez) decrease_balance(ctx, amount) assert_stack_type(delegate, Option) assert_equal_types(storage_type, storage.type_expr) originated_address = Address.new(ctx.dummy_gen.get_fresh_address()) content = { 'kind': 'origination', 'source': ctx.dummy_gen.self, 'balance': str(int(amount)), 'script': { 'storage': storage.val_expr, 'code': code }, 'originated_contract': str(originated_address) } if not delegate.is_none(): content['delegate'] = str(delegate.get_some()) orig = Operation.new(content) ctx.push(originated_address) ctx.push(orig)
def do_map(ctx: Context, prim, args, annots): container = ctx.pop1() assert_stack_type(container, [List, Map]) if type(container) == List: items = list() for item in container: ctx.push(item) do_interpret(ctx, args[0]) ret = ctx.pop1() items.append(ret) elif type(container) == Map: items = list() for key, val in container: ctx.push(Pair.new(key, val)) do_interpret(ctx, args[0]) ret = ctx.pop1() items.append((key, ret)) else: assert False if len(items) == 0: res = container else: res = type(container).new(items) ctx.push(res, annots=annots)
def do_commit(ctx: Context, prim, args, annots): debug, ctx.debug = ctx.debug, False output = ctx.pop1() assert_stack_type(output, Pair) operations = output.get_element(0) assert_stack_type(operations, List) assert operations.val_type() == Operation, f'expected list of operations' s_type_expr = ctx.get('storage') assert s_type_expr, f'storage type is not initialized' storage = output.get_element(1) assert_expr_equal(s_type_expr, storage.type_expr) storage, big_map_diff = ctx.big_maps.diff(storage) ctx.big_maps.commit(big_map_diff) res = Pair.new(operations, storage) ctx.push(res) ctx.debug = debug return {'kind': 'output', 'operations': operations, 'storage': storage, 'big_map_diff': big_map_diff}
def do_is_nat(ctx: Context, prim, args, annots): top = ctx.pop1() assert_stack_type(top, Int) if int(top) >= 0: res = Option.some(Nat(int(top))) else: res = Option.none(Nat().type_expr) ctx.push(res, annots=annots)
def do_lsl(ctx: Context, prim, args, annots): a, b = ctx.pop2() assert_stack_type(a, Nat) assert_stack_type(b, Nat) assert int(b) < 257, f'shift overflow {int(b)}, should not exceed 256' handlers = {'LSL': lambda x: x[0] << x[1], 'LSR': lambda x: x[0] >> x[1]} res = Nat(handlers[prim]((int(a), int(b)))) ctx.push(res, annots=annots)
def do_mem(ctx: Context, prim, args, annots): key, container = ctx.pop2() assert_stack_type(container, [Set, Map, BigMap]) if type(container) == BigMap: res = Bool(ctx.big_maps.contains(container, key)) else: res = Bool(key in container) ctx.push(res, annots=annots)
def do_slice(ctx: Context, prim, args, annots): offset, length, s = ctx.pop3() assert_stack_type(s, [String, Bytes]) offset, length = int(offset), int(length) if len(s) > 0 and offset + length <= len(s): res = Option.some(s[offset:offset+length]) else: res = Option.none(type(s)().type_expr) ctx.push(res, annots=annots)
def do_sha(ctx: Context, prim, args, annots): top = ctx.pop1() assert_stack_type(top, Bytes) handlers = { 'SHA256': lambda x: sha256(x).digest(), 'SHA512': lambda x: sha512(x).digest(), } res = Bytes(handlers[prim](bytes(top))) ctx.push(res, annots=annots)
def do_loop(ctx: Context, prim, args, annots): assert_no_annots(prim, annots) while True: top = ctx.pop1() assert_stack_type(top, Bool) if bool(top): do_interpret(ctx, args[0]) else: break
def do_if_left(ctx: Context, prim, args, annots): assert_no_annots(prim, annots) top = ctx.pop1() assert_stack_type(top, Option) if top.is_none(): do_interpret(ctx, args[0]) else: ctx.push(top.get_some()) do_interpret(ctx, args[1])
def do_not(ctx: Context, prim, args, annots): top = ctx.pop1() assert_stack_type(top, [Nat, Int, Bool]) if type(top) in [Nat, Int]: res = Int(~int(top)) elif type(top) == Bool: res = Bool(not bool(top)) else: assert False ctx.push(res, annots=annots)
def do_loop_left(ctx: Context, prim, args, annots): assert_no_annots(prim, annots) while True: top = ctx.pop1() assert_stack_type(top, Or) ctx.push(top.get_some()) if top.is_left(): do_interpret(ctx, args[0]) else: break
def do_exec(ctx: Context, prim, args, annots): param, lmbda = ctx.pop2() assert_stack_type(lmbda, Lambda) lmbda.assert_param_type(param) lmbda_ctx = ctx.spawn(stack=[param]) do_interpret(lmbda_ctx, lmbda.code) ret = lmbda_ctx.pop1() lmbda.assert_ret_type(ret) assert len(lmbda_ctx) == 0, f'lambda stack is not empty {lmbda_ctx}' ctx.push(ret, annots=annots)
def do_if_cons(ctx: Context, prim, args, annots): assert_no_annots(prim, annots) top = ctx.pop1() assert_stack_type(top, List) if len(top) > 0: head, tail = top.cut_head() ctx.push(tail) ctx.push(head) do_interpret(ctx, args[0]) else: do_interpret(ctx, args[1])
def do_unpack(ctx: Context, prim, args, annots): top = ctx.pop1() assert_stack_type(top, Bytes) try: val_expr = unpack(data=bytes(top), type_expr=args[0]) item = StackItem.parse(val_expr=val_expr, type_expr=args[0]) res = Option.some(item) except Exception as e: ctx.print(f'failed: {e}') res = Option.none(args[0]) ctx.push(res, annots=annots)
def do_set_delegate(ctx: Context, prim, args, annots): delegate = ctx.pop1() assert_stack_type(delegate, Option) content = { 'kind': 'delegation', 'source': ctx.dummy_gen.self, 'delegate': None if delegate.is_none() else str(delegate.get_some()) } res = Operation.new(content) ctx.push(res)
def do_eq(ctx: Context, prim, args, annots): top = ctx.pop1() assert_stack_type(top, Int) handlers = { 'EQ': lambda x: x == 0, 'GE': lambda x: x >= 0, 'GT': lambda x: x > 0, 'LE': lambda x: x <= 0, 'LT': lambda x: x < 0, 'NEQ': lambda x: x != 0 } res = Bool(handlers[prim](int(top))) ctx.push(res, annots=annots)
def do_get(ctx: Context, prim, args, annots): key, container = ctx.pop2() assert_stack_type(container, [Map, BigMap]) if type(container) == Map: val = container.find(key) else: val = ctx.big_maps.find(container, key) if val is not None: res = Option.some(val) else: res = Option.none(container.val_type_expr()) ctx.push(res, annots=annots)
def do_contract(ctx: Context, prim, args, annots): top = ctx.pop1() assert_stack_type(top, Address) entry_annot = next((a for a in annots if a[0] == '%'), '%default') contract = Contract.new(str(top) + entry_annot, type_expr=args[0]) if check_contract(ctx, address=str(top), entry_annot=entry_annot, type_expr=args[0]): res = Option.some(contract) else: res = Option.none(contract.type_expr) if top.name: annots.append(f'@{top.name}.contract') ctx.push(res, annots=[a for a in annots if a[0] != '%'])
def do_concat(ctx: Context, prim, args, annots): top = ctx.pop1() assert_stack_type(top, [String, Bytes, List]) if type(top) in [String, Bytes]: second = ctx.pop1() val_type = dispatch_type_map(top, second, { (String, String): str, (Bytes, Bytes): bytes }) res = type(top)(val_type(top) + val_type(second)) elif type(top) == List: res_type = top.val_type() val_type, sep = {String: (str, ''), Bytes: (bytes, b'')}[res_type] res = res_type(sep.join(map(val_type, top))) else: assert False ctx.push(res, annots=annots)
def do_transfer_tokens(ctx: Context, prim, args, annots): param, amount, dest = ctx.pop3() assert_stack_type(amount, Mutez) decrease_balance(ctx, amount) assert_stack_type(dest, Contract) dest.assert_param_type(param) content = { 'kind': 'transaction', 'source': ctx.dummy_gen.self, 'amount': str(int(amount)), 'destination': dest.get_address(), 'parameters': { 'entrypoint': dest.get_entrypoint(), 'value': param.val_expr } } res = Operation.new(content) ctx.push(res)
def do_check_sig(ctx: Context, prim, args, annots): pk, sig, msg = ctx.pop3() assert_stack_type(pk, Key) assert_stack_type(sig, Signature) assert_stack_type(msg, Bytes) key = crypto.Key.from_encoded_key(str(pk)) try: key.verify(signature=str(sig), message=bytes(msg)) except: res = Bool(False) else: res = Bool(True) ctx.push(res, annots=annots)
def do_update(ctx: Context, prim, args, annots): key, val, container = ctx.pop3() assert_stack_type(container, [Set, Map, BigMap]) if type(container) == Set: assert_stack_type(val, Bool) if val: res = container.add(key) else: res = container.remove(key) else: assert_stack_type(val, Option) if val.is_none(): res = container.remove(key) else: res = container.update(key, val.get_some()) ctx.push(res, annots=annots)
def do_cons(ctx: Context, prim, args, annots): val, container = ctx.pop2() assert_stack_type(container, List) res = container.prepend(val) ctx.push(res, annots=annots)
def do_car(ctx: Context, prim, args, annots): top = ctx.pop1() assert_stack_type(top, Pair) idx = {'CAR': 0, 'CDR': 1} res = top.get_element(idx[prim]) ctx.push(res, annots=annots)
def do_if_left(ctx: Context, prim, args, annots): assert_no_annots(prim, annots) top = ctx.pop1() # type: Or assert_stack_type(top, Or) ctx.push(top.get_some()) do_interpret(ctx, args[0 if top.is_left() else 1])
def do_implicit_account(ctx: Context, prim, args, annots): top = ctx.pop1() assert_stack_type(top, KeyHash) res = Contract.new(str(top), type_expr=UNIT_TYPE_EXPR) ctx.push(res, annots=annots)
def do_if(ctx: Context, prim, args, annots): assert_no_annots(prim, annots) cond = ctx.pop1() assert_stack_type(cond, Bool) do_interpret(ctx, args[0 if bool(cond) else 1])
def do_apply(ctx: Context, prim, args, annots): param, lmbda = ctx.pop2() assert_stack_type(lmbda, Lambda) res = lmbda.partial_apply(param) ctx.push(res)