def test_concat_invalid(): with pytest.raises(pt.TealInputError): pt.Concat() with pytest.raises(pt.TealTypeError): pt.Concat(pt.Int(1), pt.Txn.receiver()) with pytest.raises(pt.TealTypeError): pt.Concat(pt.Txn.receiver(), pt.Int(1)) with pytest.raises(pt.TealTypeError): pt.Concat(pt.Int(1), pt.Int(2))
def logcat(some_bytes, an_int): catted = pt.ScratchVar(pt.TealType.bytes) return pt.Seq( catted.store(pt.Concat(some_bytes, pt.Itob(an_int))), pt.Log(catted.load()), catted.load(), )
def test_StaticBytes_expr(test_case: bytes | bytearray): value: abi.StaticBytes = abi.StaticBytes( abi.StaticBytesTypeSpec(len(test_case) * 2)) set_expr = pt.Concat(pt.Bytes(test_case), pt.Bytes(test_case)) expr = value.set(set_expr) assert expr.type_of() == pt.TealType.none assert not expr.has_return() actual, _ = expr.__teal__(options) actual.addIncoming() actual = actual.NormalizeBlocks(actual) expected = pt.TealSimpleBlock([ pt.TealOp(None, pt.Op.byte, "0x" + BYTE_HEX_TEST_CASE), pt.TealOp(None, pt.Op.byte, "0x" + BYTE_HEX_TEST_CASE), pt.TealOp(None, pt.Op.concat), pt.TealOp(None, pt.Op.store, value.stored_value.slot), pt.TealOp(None, pt.Op.int, 32), pt.TealOp(None, pt.Op.load, value.stored_value.slot), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.eq), pt.TealOp(None, pt.Op.assert_), ]) with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected
def subr_string_mult(s: pt.ScratchVar, n): tmp = pt.ScratchVar(pt.TealType.bytes) return (pt.If(n == pt.Int(0)).Then(s.store(pt.Bytes(""))).Else( pt.Seq( tmp.store(s.load()), subr_string_mult(s, n - pt.Int(1)), s.store(pt.Concat(s.load(), tmp.load())), )))
def test_concat_one(): arg = pt.Bytes("a") expr = pt.Concat(arg) assert expr.type_of() == pt.TealType.bytes expected = pt.TealSimpleBlock([pt.TealOp(arg, pt.Op.byte, '"a"')]) actual, _ = expr.__teal__(options) assert actual == expected
def string_mult(s: pt.ScratchVar, n): i = pt.ScratchVar(pt.TealType.uint64) tmp = pt.ScratchVar(pt.TealType.bytes) start = pt.Seq(i.store(pt.Int(1)), tmp.store(s.load()), s.store(pt.Bytes(""))) step = i.store(i.load() + pt.Int(1)) return pt.Seq( pt.For(start, i.load() <= n, step).Do(s.store(pt.Concat(s.load(), tmp.load()))), s.load(), )
def reverse(a: pt.abi.String, *, output: pt.abi.String) -> pt.Expr: idx = pt.ScratchVar() buff = pt.ScratchVar() init = idx.store(pt.Int(0)) cond = idx.load() < a.length() _iter = idx.store(idx.load() + pt.Int(1)) return pt.Seq( buff.store(pt.Bytes("")), pt.For(init, cond, _iter).Do( a[idx.load()].use(lambda v: buff.store(pt.Concat(v.encode(), buff.load()))) ), output.set(buff.load()), )
def concat_strings( b: pt.abi.DynamicArray[pt.abi.String], *, output: pt.abi.String ) -> pt.Expr: idx = pt.ScratchVar() buff = pt.ScratchVar() init = idx.store(pt.Int(0)) cond = idx.load() < b.length() _iter = idx.store(idx.load() + pt.Int(1)) return pt.Seq( buff.store(pt.Bytes("")), pt.For(init, cond, _iter).Do( b[idx.load()].use(lambda s: buff.store(pt.Concat(buff.load(), s.get()))) ), output.set(buff.load()), )
def test_concat_two(): args = [pt.Bytes("a"), pt.Bytes("b")] expr = pt.Concat(args[0], args[1]) assert expr.type_of() == pt.TealType.bytes expected = pt.TealSimpleBlock([ pt.TealOp(args[0], pt.Op.byte, '"a"'), pt.TealOp(args[1], pt.Op.byte, '"b"'), pt.TealOp(expr, pt.Op.concat), ]) actual, _ = expr.__teal__(options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected
def lots_o_vars(): z = pt.Int(0) one = pt.ScratchVar() two = pt.ScratchVar() three = pt.ScratchVar() four = pt.ScratchVar() five = pt.Bytes("five") six = pt.Bytes("six") seven = pt.Bytes("seven") eight = pt.Bytes("eight") nine = pt.Bytes("nine") ten = pt.Bytes("ten") eleven = pt.Bytes("eleven") twelve = pt.Bytes("twelve") int_cursor = pt.DynamicScratchVar(pt.TealType.uint64) bytes_cursor = pt.DynamicScratchVar(pt.TealType.bytes) thirteen = pt.ScratchVar(pt.TealType.uint64, 13) fourteen = pt.ScratchVar(pt.TealType.bytes, 14) fifteen = pt.ScratchVar(pt.TealType.uint64) sixteen = pt.ScratchVar(pt.TealType.bytes) leet = pt.Int(1337) ngl = pt.Bytes("NGL: ") return (pt.If( pt.Or(pt.App.id() == pt.Int(0), pt.Txn.application_args.length() == pt.Int(0))).Then( pt.Int(1)).Else( pt.Seq( one.store(pt.Int(1)), two.store(pt.Bytes("two")), three.store(pt.Int(3)), four.store(pt.Bytes("four")), pt.App.localPut(z, five, pt.Int(5)), pt.App.localPut(z, six, six), pt.App.localPut(z, seven, pt.Int(7)), pt.App.localPut(z, eight, eight), pt.App.globalPut(nine, pt.Int(9)), pt.App.globalPut(ten, ten), pt.App.globalPut(eleven, pt.Int(11)), pt.App.globalPut(twelve, twelve), one.store(one.load() + leet), two.store(pt.Concat(ngl, two.load())), three.store(three.load() + leet), four.store(pt.Concat(ngl, four.load())), pt.App.localPut(z, five, leet + pt.App.localGet(z, five)), pt.App.localPut( z, six, pt.Concat(ngl, pt.App.localGet(z, six))), pt.App.localPut(z, seven, pt.App.localGet(z, seven)), pt.App.localPut( z, eight, pt.Concat(ngl, pt.App.localGet(z, eight))), pt.App.globalPut(nine, leet + pt.App.globalGet(nine)), pt.App.globalPut( ten, pt.Concat(ngl, pt.App.globalGet(ten))), pt.App.globalPut(eleven, leet + pt.App.globalGet(eleven)), pt.App.globalPut( twelve, pt.Concat(ngl, pt.App.globalGet(twelve))), thirteen.store(pt.Btoi(pt.Txn.application_args[0])), fourteen.store(pt.Txn.application_args[1]), fifteen.store(pt.Btoi(pt.Txn.application_args[2])), sixteen.store(pt.Txn.application_args[3]), pt.Pop(one.load()), pt.Pop(two.load()), pt.Pop(three.load()), pt.Pop(four.load()), pt.Pop(pt.App.localGet(z, five)), pt.Pop(pt.App.localGet(z, six)), pt.Pop(pt.App.localGet(z, seven)), pt.Pop(pt.App.localGet(z, eight)), pt.Pop(pt.App.globalGet(nine)), pt.Pop(pt.App.globalGet(ten)), pt.Pop(pt.App.globalGet(eleven)), pt.Pop(pt.App.globalGet(twelve)), int_cursor.set_index(thirteen), pt.Log(pt.Itob(int_cursor.load())), bytes_cursor.set_index(fourteen), pt.Log(bytes_cursor.load()), int_cursor.set_index(fifteen), pt.Log(pt.Itob(int_cursor.load())), bytes_cursor.set_index(sixteen), pt.Log(bytes_cursor.load()), leet, )))
def mixed_annotations(x: pt.Expr, y: pt.Expr, z: pt.ScratchVar) -> pt.Expr: return pt.Seq( z.store(x), pt.Log(pt.Concat(y, pt.Bytes("="), pt.Itob(x))), x, )
def cat(x, y): return pt.Pop(pt.Concat(x, y))
def tally(n, result: pt.ScratchVar): return (pt.If(n == pt.Int(0)).Then(result.store(pt.Bytes(""))).Else( pt.Seq( tally(n - pt.Int(1), result), result.store(pt.Concat(result.load(), pt.Bytes("a"))), )))
def logcat_dynamic(first: pt.ScratchVar, an_int): return pt.Seq( first.store(pt.Concat(first.load(), pt.Itob(an_int))), pt.Log(first.load()), )
def test_encodeTuple(): class EncodeTest(NamedTuple): types: List[abi.BaseType] expected: pt.Expr # variables used to construct the tests uint64_a = abi.Uint64() uint64_b = abi.Uint64() uint16_a = abi.Uint16() uint16_b = abi.Uint16() bool_a = abi.Bool() bool_b = abi.Bool() tuple_a = abi.Tuple(abi.TupleTypeSpec(abi.BoolTypeSpec(), abi.BoolTypeSpec())) dynamic_array_a = abi.DynamicArray(abi.DynamicArrayTypeSpec(abi.Uint64TypeSpec())) dynamic_array_b = abi.DynamicArray(abi.DynamicArrayTypeSpec(abi.Uint16TypeSpec())) dynamic_array_c = abi.DynamicArray(abi.DynamicArrayTypeSpec(abi.BoolTypeSpec())) tail_holder = pt.ScratchVar() encoded_tail = pt.ScratchVar() tests: List[EncodeTest] = [ EncodeTest(types=[], expected=pt.Bytes("")), EncodeTest(types=[uint64_a], expected=uint64_a.encode()), EncodeTest( types=[uint64_a, uint64_b], expected=pt.Concat(uint64_a.encode(), uint64_b.encode()), ), EncodeTest(types=[bool_a], expected=bool_a.encode()), EncodeTest( types=[bool_a, bool_b], expected=_encode_bool_sequence([bool_a, bool_b]) ), EncodeTest( types=[bool_a, bool_b, uint64_a], expected=pt.Concat( _encode_bool_sequence([bool_a, bool_b]), uint64_a.encode() ), ), EncodeTest( types=[uint64_a, bool_a, bool_b], expected=pt.Concat( uint64_a.encode(), _encode_bool_sequence([bool_a, bool_b]) ), ), EncodeTest( types=[uint64_a, bool_a, bool_b, uint64_b], expected=pt.Concat( uint64_a.encode(), _encode_bool_sequence([bool_a, bool_b]), uint64_b.encode(), ), ), EncodeTest( types=[uint64_a, bool_a, uint64_b, bool_b], expected=pt.Concat( uint64_a.encode(), bool_a.encode(), uint64_b.encode(), bool_b.encode() ), ), EncodeTest(types=[tuple_a], expected=tuple_a.encode()), EncodeTest( types=[uint64_a, tuple_a, bool_a, bool_b], expected=pt.Concat( uint64_a.encode(), tuple_a.encode(), _encode_bool_sequence([bool_a, bool_b]), ), ), EncodeTest( types=[dynamic_array_a], expected=pt.Concat( pt.Seq( encoded_tail.store(dynamic_array_a.encode()), tail_holder.store(encoded_tail.load()), uint16_a.set(2), uint16_a.encode(), ), tail_holder.load(), ), ), EncodeTest( types=[uint64_a, dynamic_array_a], expected=pt.Concat( uint64_a.encode(), pt.Seq( encoded_tail.store(dynamic_array_a.encode()), tail_holder.store(encoded_tail.load()), uint16_a.set(8 + 2), uint16_a.encode(), ), tail_holder.load(), ), ), EncodeTest( types=[uint64_a, dynamic_array_a, uint64_b], expected=pt.Concat( uint64_a.encode(), pt.Seq( encoded_tail.store(dynamic_array_a.encode()), tail_holder.store(encoded_tail.load()), uint16_a.set(8 + 2 + 8), uint16_a.encode(), ), uint64_b.encode(), tail_holder.load(), ), ), EncodeTest( types=[uint64_a, dynamic_array_a, bool_a, bool_b], expected=pt.Concat( uint64_a.encode(), pt.Seq( encoded_tail.store(dynamic_array_a.encode()), tail_holder.store(encoded_tail.load()), uint16_a.set(8 + 2 + 1), uint16_a.encode(), ), _encode_bool_sequence([bool_a, bool_b]), tail_holder.load(), ), ), EncodeTest( types=[uint64_a, dynamic_array_a, uint64_b, dynamic_array_b], expected=pt.Concat( uint64_a.encode(), pt.Seq( encoded_tail.store(dynamic_array_a.encode()), tail_holder.store(encoded_tail.load()), uint16_a.set(8 + 2 + 8 + 2), uint16_b.set(uint16_a.get() + pt.Len(encoded_tail.load())), uint16_a.encode(), ), uint64_b.encode(), pt.Seq( encoded_tail.store(dynamic_array_b.encode()), tail_holder.store( pt.Concat(tail_holder.load(), encoded_tail.load()) ), uint16_a.set(uint16_b), uint16_a.encode(), ), tail_holder.load(), ), ), EncodeTest( types=[ uint64_a, dynamic_array_a, uint64_b, dynamic_array_b, bool_a, bool_b, dynamic_array_c, ], expected=pt.Concat( uint64_a.encode(), pt.Seq( encoded_tail.store(dynamic_array_a.encode()), tail_holder.store(encoded_tail.load()), uint16_a.set(8 + 2 + 8 + 2 + 1 + 2), uint16_b.set(uint16_a.get() + pt.Len(encoded_tail.load())), uint16_a.encode(), ), uint64_b.encode(), pt.Seq( encoded_tail.store(dynamic_array_b.encode()), tail_holder.store( pt.Concat(tail_holder.load(), encoded_tail.load()) ), uint16_a.set(uint16_b), uint16_b.set(uint16_a.get() + pt.Len(encoded_tail.load())), uint16_a.encode(), ), _encode_bool_sequence([bool_a, bool_b]), pt.Seq( encoded_tail.store(dynamic_array_c.encode()), tail_holder.store( pt.Concat(tail_holder.load(), encoded_tail.load()) ), uint16_a.set(uint16_b), uint16_a.encode(), ), tail_holder.load(), ), ), ] for i, test in enumerate(tests): expr = _encode_tuple(test.types) assert expr.type_of() == pt.TealType.bytes assert not expr.has_return() expected, _ = test.expected.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) actual, _ = expr.__teal__(options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) if any(t.type_spec().is_dynamic() for t in test.types): with pt.TealComponent.Context.ignoreExprEquality(): with pt.TealComponent.Context.ignoreScratchSlotEquality(): assert actual == expected, "Test at index {} failed".format(i) assert pt.TealBlock.MatchScratchSlotReferences( pt.TealBlock.GetReferencedScratchSlots(actual), pt.TealBlock.GetReferencedScratchSlots(expected), ) continue with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected, "Test at index {} failed".format(i)