From 39e93ff2e6d02cf9b12b4c63b6dfb10376c2857c Mon Sep 17 00:00:00 2001 From: Ben Guidarelli Date: Fri, 20 Jan 2023 09:57:25 -0500 Subject: [PATCH] fix: prevent blob from duplicating subroutine body (#174) --- beaker/lib/storage/global_blob.py | 190 ++-- beaker/lib/storage/local_blob.py | 173 ++- beaker/lib/strings/string.py | 38 +- .../DiskHungry.artifacts/application.json | 2 +- .../DiskHungry.artifacts/approval.teal | 248 ++-- .../StateExample.artifacts/application.json | 2 +- .../StateExample.artifacts/approval.teal | 1012 ++++++++--------- .../App.artifacts/application.json | 2 +- .../App.artifacts/approval.teal | 76 +- tests/global_blob_test.py | 23 + tests/local_blob_test.py | 21 + 11 files changed, 909 insertions(+), 878 deletions(-) diff --git a/beaker/lib/storage/global_blob.py b/beaker/lib/storage/global_blob.py index 8db2d302..d24cb550 100644 --- a/beaker/lib/storage/global_blob.py +++ b/beaker/lib/storage/global_blob.py @@ -27,13 +27,18 @@ class GlobalBlob(Blob): def __init__(self, /, *, keys: Optional[int | list[int]] = None): super().__init__(MAX_GLOBAL_STATE, keys=keys) + self.init_subroutines() - def zero(self) -> Expr: - """ - initializes global state of an application to all zero bytes - - This allows us to be lazy later and _assume_ all the strings are the same size - """ + def init_subroutines(self): + @Subroutine(TealType.none) + def set_byte_impl(idx: Expr, byte: Expr) -> Expr: + return Seq( + (key := ScratchVar()).store(self._key(self._key_idx(idx))), + App.globalPut( + key.load(), + SetByte(App.globalGet(key.load()), self._offset_for_idx(idx), byte), + ), + ) @Subroutine(TealType.none) def zero_impl() -> Expr: @@ -43,7 +48,7 @@ def zero_impl() -> Expr: - // ["00"*page_size, key-1] dup2 // ["00"*page_size, key, "00"*page_size, key] itob // ["00"*page_size, key, "00"*page_size, itob(key)] - extract 7 1 // ["00"*page_size, key, "00"*page_size, itob(key)[-1]] get the last byte of the int + extract 7 1 // ["00"*page_size, key, "00"*page_size, itob(key)[-1]] swap // ["00"*page_size, key, itob(key)[-1], "00"*page_size] app_global_put // ["00"*page_size, key] (removes top 2 elements) dup // ["00"*page_size, key-1, key-1] @@ -55,43 +60,12 @@ def zero_impl() -> Expr: """ return InlineAssembly(zloop, EMPTY_PAGE, self.max_keys, type=TealType.none) - return zero_impl() - - def get_byte(self, idx: Expr) -> Expr: - """ - Get a single byte from global storage of an application by index - """ - @Subroutine(TealType.uint64) def get_byte_impl(idx: Expr) -> Expr: return GetByte( App.globalGet(self._key(self._key_idx(idx))), self._offset_for_idx(idx) ) - return get_byte_impl(idx) - - def set_byte(self, idx: Expr, byte: Expr) -> Expr: - """ - Set a single byte from global storage of an application by index - """ - - @Subroutine(TealType.none) - def set_byte_impl(idx: Expr, byte: Expr) -> Expr: - return Seq( - (key := ScratchVar()).store(self._key(self._key_idx(idx))), - App.globalPut( - key.load(), - SetByte(App.globalGet(key.load()), self._offset_for_idx(idx), byte), - ), - ) - - return set_byte_impl(idx, byte) - - def read(self, bstart: Expr, bstop: Expr) -> Expr: - """ - read bytes between bstart and bend from global storage of an application by index - """ - @Subroutine(TealType.bytes) def read_impl(bstart: Expr, bstop: Expr) -> Expr: start_key = self._key_idx(bstart) @@ -113,33 +87,22 @@ def read_impl(bstart: Expr, bstop: Expr) -> Expr: return Seq( buff.store(Bytes("")), For(init, cond, incr).Do( - Seq( - start.store(If(key.load() == start_key, start_offset, Int(0))), - stop.store( - If(key.load() == stop_key, stop_offset, BLOB_PAGE_SIZE) - ), - buff.store( - Concat( - buff.load(), - Substring( - App.globalGet(self._key(key.load())), - start.load(), - stop.load(), - ), - ) - ), - ) + start.store(If(key.load() == start_key, start_offset, Int(0))), + stop.store(If(key.load() == stop_key, stop_offset, BLOB_PAGE_SIZE)), + buff.store( + Concat( + buff.load(), + Substring( + App.globalGet(self._key(key.load())), + start.load(), + stop.load(), + ), + ) + ), ), buff.load(), ) - return read_impl(bstart, bstop) - - def write(self, bstart: Expr, buff: Expr) -> Expr: - """ - write bytes between bstart and len(buff) to global storage of an application - """ - @Subroutine(TealType.none) def write_impl(bstart: Expr, buff: Expr) -> Expr: start_key = self._key_idx(bstart) @@ -162,47 +125,76 @@ def write_impl(bstart: Expr, buff: Expr) -> Expr: return Seq( written.store(Int(0)), For(init, cond, incr).Do( - Seq( - start.store(If(key.load() == start_key, start_offset, Int(0))), - stop.store( - If(key.load() == stop_key, stop_offset, BLOB_PAGE_SIZE) - ), - App.globalPut( - self._key(key.load()), - If( - Or( - stop.load() != BLOB_PAGE_SIZE, - start.load() != Int(0), - ) - ) # Its a partial write - .Then( - Seq( - delta.store(stop.load() - start.load()), - Concat( - Substring( - App.globalGet(self._key(key.load())), - Int(0), - start.load(), - ), - Extract(buff, written.load(), delta.load()), - Substring( - App.globalGet(self._key(key.load())), - stop.load(), - BLOB_PAGE_SIZE, - ), - ), - ) + start.store(If(key.load() == start_key, start_offset, Int(0))), + stop.store(If(key.load() == stop_key, stop_offset, BLOB_PAGE_SIZE)), + App.globalPut( + self._key(key.load()), + If( + Or( + stop.load() != BLOB_PAGE_SIZE, + start.load() != Int(0), ) - .Else( - Seq( - delta.store(BLOB_PAGE_SIZE), - Extract(buff, written.load(), BLOB_PAGE_SIZE), - ) + ) # Its a partial write + .Then( + delta.store(stop.load() - start.load()), + Concat( + Substring( + App.globalGet(self._key(key.load())), + Int(0), + start.load(), + ), + Extract(buff, written.load(), delta.load()), + Substring( + App.globalGet(self._key(key.load())), + stop.load(), + BLOB_PAGE_SIZE, + ), ), + ) + .Else( + delta.store(BLOB_PAGE_SIZE), + Extract(buff, written.load(), BLOB_PAGE_SIZE), ), - written.store(written.load() + delta.load()), - ) + ), + written.store(written.load() + delta.load()), ), ) - return write_impl(bstart, buff) + self.set_byte_impl = set_byte_impl + self.zero_impl = zero_impl + self.get_byte_impl = get_byte_impl + self.read_impl = read_impl + self.write_impl = write_impl + + def zero(self) -> Expr: + """ + initializes global state of an application to all zero bytes + + This allows us to be lazy later and _assume_ all the strings are the same size + """ + return self.zero_impl() + + def get_byte(self, idx: Expr) -> Expr: + """ + Get a single byte from global storage of an application by index + """ + return self.get_byte_impl(idx) + + def set_byte(self, idx: Expr, byte: Expr) -> Expr: + """ + Set a single byte from global storage of an application by index + """ + return self.set_byte_impl(idx, byte) + + def read(self, bstart: Expr, bstop: Expr) -> Expr: + """ + read bytes between bstart and bend from global storage + of an application by index + """ + return self.read_impl(bstart, bstop) + + def write(self, bstart: Expr, buff: Expr) -> Expr: + """ + write bytes between bstart and len(buff) to global storage of an application + """ + return self.write_impl(bstart, buff) diff --git a/beaker/lib/storage/local_blob.py b/beaker/lib/storage/local_blob.py index 1d7aa382..abc82ad8 100644 --- a/beaker/lib/storage/local_blob.py +++ b/beaker/lib/storage/local_blob.py @@ -25,51 +25,33 @@ class LocalBlob(Blob): """ - Blob is a class holding static methods to work with the local storage of an account as a binary large object + Blob is a class holding static methods to work with the local storage of an account + as a binary large object - The `zero` method must be called on an account on opt in and the schema of the local storage should be 16 bytes + Note: The `zero` method must be called on an account on opt in and the schema + of the local storage should be 16 bytes """ def __init__(self, /, *, keys: Optional[int | list[int]] = None): super().__init__(MAX_LOCAL_STATE, keys=keys) + self.init_subroutines() - def zero(self, acct: Expr = Txn.sender()) -> Expr: - """ - initializes local state of an account to all zero bytes - - This allows us to be lazy later and _assume_ all the strings are the same size - - """ - + def init_subroutines(self): @Subroutine(TealType.none) - def _impl(acct: Expr) -> Expr: + def zero_impl(acct: Expr) -> Expr: return Seq( *[App.localPut(acct, Bytes(bk), EMPTY_PAGE) for bk in self.byte_keys] ) - return _impl(acct) - - def get_byte(self, idx: Expr, acct: Expr = Txn.sender()) -> Expr: - """ - Get a single byte from local storage of an account by index - """ - @Subroutine(TealType.uint64) - def _impl(acct: Expr, idx: Expr) -> Expr: + def get_byte_impl(acct: Expr, idx: Expr) -> Expr: return GetByte( App.localGet(acct, self._key(self._key_idx(idx))), self._offset_for_idx(idx), ) - return _impl(acct, idx) - - def set_byte(self, idx: Expr, byte: Expr, acct: Expr = Txn.sender()) -> Expr: - """ - Set a single byte from local storage of an account by index - """ - @Subroutine(TealType.none) - def _impl(acct: Expr, idx: Expr, byte: Expr) -> Expr: + def set_byte_impl(acct: Expr, idx: Expr, byte: Expr) -> Expr: return Seq( (key := ScratchVar()).store(self._key(self._key_idx(idx))), App.localPut( @@ -81,15 +63,8 @@ def _impl(acct: Expr, idx: Expr, byte: Expr) -> Expr: ), ) - return _impl(acct, idx, byte) - - def read(self, bstart: Expr, bend: Expr, acct: Expr = Txn.sender()) -> Expr: - """ - read bytes between bstart and bend from local storage of an account by index - """ - @Subroutine(TealType.bytes) - def _impl(acct: Expr, bstart: Expr, bend: Expr) -> Expr: + def read_impl(acct: Expr, bstart: Expr, bend: Expr) -> Expr: start_key_idx = self._key_idx(bstart) start_offset = self._offset_for_idx(bstart) @@ -109,41 +84,32 @@ def _impl(acct: Expr, bstart: Expr, bend: Expr) -> Expr: return Seq( buff.store(Bytes("")), For(init, cond, incr).Do( - Seq( - start.store( - If(key_idx.load() == start_key_idx, start_offset, Int(0)) - ), - stop.store( - If( - key_idx.load() == stop_key_idx, - stop_offset, - BLOB_PAGE_SIZE, - ) - ), - buff.store( - Concat( - buff.load(), - Substring( - App.localGet(acct, self._key(key_idx.load())), - start.load(), - stop.load(), - ), - ) - ), - ) + start.store( + If(key_idx.load() == start_key_idx, start_offset, Int(0)) + ), + stop.store( + If( + key_idx.load() == stop_key_idx, + stop_offset, + BLOB_PAGE_SIZE, + ) + ), + buff.store( + Concat( + buff.load(), + Substring( + App.localGet(acct, self._key(key_idx.load())), + start.load(), + stop.load(), + ), + ) + ), ), buff.load(), ) - return _impl(acct, bstart, bend) - - def write(self, bstart: Expr, buff: Expr, acct: Expr = Txn.sender()) -> Expr: - """ - write bytes between bstart and len(buff) to local storage of an account - """ - @Subroutine(TealType.none) - def _impl(acct: Expr, bstart: Expr, buff: Expr) -> Expr: + def write_impl(acct: Expr, bstart: Expr, buff: Expr) -> Expr: start_key_idx = self._key_idx(bstart) start_offset = self._offset_for_idx(bstart) @@ -186,32 +152,24 @@ def _impl(acct: Expr, bstart: Expr, buff: Expr) -> Expr: ) ) # Its a partial write .Then( - Seq( - delta.store(stop.load() - start.load()), - Concat( - Substring( - App.localGet( - acct, self._key(key_idx.load()) - ), - Int(0), - start.load(), - ), - Extract(buff, written.load(), delta.load()), - Substring( - App.localGet( - acct, self._key(key_idx.load()) - ), - stop.load(), - BLOB_PAGE_SIZE, - ), + delta.store(stop.load() - start.load()), + Concat( + Substring( + App.localGet(acct, self._key(key_idx.load())), + Int(0), + start.load(), ), - ) + Extract(buff, written.load(), delta.load()), + Substring( + App.localGet(acct, self._key(key_idx.load())), + stop.load(), + BLOB_PAGE_SIZE, + ), + ), ) .Else( - Seq( - delta.store(BLOB_PAGE_SIZE), - Extract(buff, written.load(), BLOB_PAGE_SIZE), - ) + delta.store(BLOB_PAGE_SIZE), + Extract(buff, written.load(), BLOB_PAGE_SIZE), ), ), written.store(written.load() + delta.load()), @@ -219,4 +177,41 @@ def _impl(acct: Expr, bstart: Expr, buff: Expr) -> Expr: ), ) - return _impl(acct, bstart, buff) + self.write_impl = write_impl + self.read_impl = read_impl + self.set_byte_impl = set_byte_impl + self.get_byte_impl = get_byte_impl + self.zero_impl = zero_impl + + def zero(self, acct: Expr = Txn.sender()) -> Expr: + """ + initializes local state of an account to all zero bytes + + This allows us to be lazy later and _assume_ all the strings are the same size + + """ + return self.zero_impl(acct) + + def get_byte(self, idx: Expr, acct: Expr = Txn.sender()) -> Expr: + """ + Get a single byte from local storage of an account by index + """ + return self.get_byte_impl(acct, idx) + + def set_byte(self, idx: Expr, byte: Expr, acct: Expr = Txn.sender()) -> Expr: + """ + Set a single byte from local storage of an account by index + """ + return self.set_byte_impl(acct, idx, byte) + + def read(self, bstart: Expr, bend: Expr, acct: Expr = Txn.sender()) -> Expr: + """ + read bytes between bstart and bend from local storage of an account by index + """ + return self.read_impl(acct, bstart, bend) + + def write(self, bstart: Expr, buff: Expr, acct: Expr = Txn.sender()) -> Expr: + """ + write bytes between bstart and len(buff) to local storage of an account + """ + return self.write_impl(acct, bstart, buff) diff --git a/beaker/lib/strings/string.py b/beaker/lib/strings/string.py index 16ff97ca..50592693 100644 --- a/beaker/lib/strings/string.py +++ b/beaker/lib/strings/string.py @@ -120,6 +120,25 @@ def rest(s, n): return Substring(s, n, Len(s)) +@Subroutine(TealType.bytes) +def encode_uvarint_impl(val, b): + buff = ScratchVar() + return Seq( + buff.store(b), + Concat( + buff.load(), + If( + val >= Int(128), + encode_uvarint_impl( + val >> Int(7), + Extract(Itob((val & Int(255)) | Int(128)), Int(7), Int(1)), + ), + Extract(Itob(val & Int(255)), Int(7), Int(1)), + ), + ), + ) + + def encode_uvarint(val): """ Returns the uvarint encoding of an integer @@ -131,23 +150,4 @@ def encode_uvarint(val): the integer to be encoded and an empty bytestring """ - - @Subroutine(TealType.bytes) - def encode_uvarint_impl(val, b): - buff = ScratchVar() - return Seq( - buff.store(b), - Concat( - buff.load(), - If( - val >= Int(128), - encode_uvarint_impl( - val >> Int(7), - Extract(Itob((val & Int(255)) | Int(128)), Int(7), Int(1)), - ), - Extract(Itob(val & Int(255)), Int(7), Int(1)), - ), - ), - ) - return encode_uvarint_impl(val, Bytes("")) diff --git a/examples/account_storage/DiskHungry.artifacts/application.json b/examples/account_storage/DiskHungry.artifacts/application.json index c4d3d841..15c7e9d0 100644 --- a/examples/account_storage/DiskHungry.artifacts/application.json +++ b/examples/account_storage/DiskHungry.artifacts/application.json @@ -1,7 +1,7 @@ { "hints": {}, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDgKaW50Y2Jsb2NrIDEyNyAwIDEgOCAxMjggMjU1CmJ5dGVjYmxvY2sgMHggMHgwODgwMDAzNTAwODEwMTQzIDB4MDAwMTAyMDMwNDA1MDYwNzA4MDkwYTBiMGMwZDBlMGYKdHhuIE51bUFwcEFyZ3MKaW50Y18xIC8vIDAKPT0KYm56IG1haW5fbDYKdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMApwdXNoYnl0ZXMgMHg3NmUzYzZkYyAvLyAiYWRkX2FjY291bnQoYnl0ZVtdKXZvaWQiCj09CmJueiBtYWluX2w1CnR4bmEgQXBwbGljYXRpb25BcmdzIDAKcHVzaGJ5dGVzIDB4MTliMTRmZGEgLy8gImZsaXBfYml0KGFjY291bnQsdWludDMyKXZvaWQiCj09CmJueiBtYWluX2w0CmVycgptYWluX2w0Ogp0eG4gT25Db21wbGV0aW9uCmludGNfMSAvLyBOb09wCj09CnR4biBBcHBsaWNhdGlvbklECmludGNfMSAvLyAwCiE9CiYmCmFzc2VydAp0eG5hIEFwcGxpY2F0aW9uQXJncyAxCmludGNfMSAvLyAwCmdldGJ5dGUKc3RvcmUgMAp0eG5hIEFwcGxpY2F0aW9uQXJncyAyCmludGNfMSAvLyAwCmV4dHJhY3RfdWludDMyCnN0b3JlIDEKbG9hZCAwCmxvYWQgMQpjYWxsc3ViIGZsaXBiaXRfMgppbnRjXzIgLy8gMQpyZXR1cm4KbWFpbl9sNToKdHhuIE9uQ29tcGxldGlvbgppbnRjXzIgLy8gT3B0SW4KPT0KdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18xIC8vIDAKIT0KJiYKYXNzZXJ0CnR4bmEgQXBwbGljYXRpb25BcmdzIDEKY2FsbHN1YiBhZGRhY2NvdW50XzEKaW50Y18yIC8vIDEKcmV0dXJuCm1haW5fbDY6CnR4biBPbkNvbXBsZXRpb24KaW50Y18xIC8vIE5vT3AKPT0KYm56IG1haW5fbDgKZXJyCm1haW5fbDg6CnR4biBBcHBsaWNhdGlvbklECmludGNfMSAvLyAwCj09CmFzc2VydApjYWxsc3ViIGNyZWF0ZV8wCmludGNfMiAvLyAxCnJldHVybgoKLy8gY3JlYXRlCmNyZWF0ZV8wOgpwcm90byAwIDAKaW50Y18yIC8vIDEKcmV0dXJuCgovLyBhZGRfYWNjb3VudAphZGRhY2NvdW50XzE6CnByb3RvIDEgMAp0eG4gU2VuZGVyCnB1c2hieXRlcyAweDUwNzI2ZjY3NzI2MTZkIC8vICJQcm9ncmFtIgppbnRjXzEgLy8gMApzdG9yZSAyCmludGNfMSAvLyAwCnN0b3JlIDMKYnl0ZWNfMCAvLyAiIgpzdG9yZSA0CmJ5dGVjXzAgLy8gIiIKc3RvcmUgNQpmcmFtZV9kaWcgLTEKZXh0cmFjdCAyIDAKbGVuCmJ5dGVjXzAgLy8gIiIKY2FsbHN1YiBlbmNvZGV1dmFyaW50aW1wbF8zCmZyYW1lX2RpZyAtMQpleHRyYWN0IDIgMApjb25jYXQKc3RvcmUgNApsb2FkIDUKYnl0ZWNfMSAvLyAweDA4ODAwMDM1MDA4MTAxNDMKbG9hZCAyCnB1c2hpbnQgMiAvLyAyCnN1YnN0cmluZzMKY29uY2F0CmxvYWQgNApjb25jYXQKc3RvcmUgNQpsb2FkIDMKbG9hZCA0CmxlbgorCmludGNfMiAvLyAxCi0Kc3RvcmUgMwpwdXNoaW50IDIgLy8gMgppbnRjXzIgLy8gMQorCnN0b3JlIDIKbG9hZCA1CmJ5dGVjXzEgLy8gMHgwODgwMDAzNTAwODEwMTQzCmxvYWQgMgpkaWcgMQpsZW4Kc3Vic3RyaW5nMwpjb25jYXQKc3RvcmUgNQpsb2FkIDUKY29uY2F0CnNoYTUxMl8yNTYKPT0KYXNzZXJ0CnR4biBSZWtleVRvCmdsb2JhbCBDdXJyZW50QXBwbGljYXRpb25BZGRyZXNzCj09CmFzc2VydAp0eG4gU2VuZGVyCmNhbGxzdWIgaW1wbF80CnJldHN1YgoKLy8gZmxpcF9iaXQKZmxpcGJpdF8yOgpwcm90byAyIDAKZnJhbWVfZGlnIC0yCnR4bmFzIEFjY291bnRzCmZyYW1lX2RpZyAtMQppbnRjXzMgLy8gOAovCmNhbGxzdWIgaW1wbF81CnN0b3JlIDYKbG9hZCA2CmZyYW1lX2RpZyAtMQppbnRjXzMgLy8gOAolCmxvYWQgNgpmcmFtZV9kaWcgLTEKaW50Y18zIC8vIDgKJQpnZXRiaXQKIQpzZXRiaXQKc3RvcmUgNgpmcmFtZV9kaWcgLTIKdHhuYXMgQWNjb3VudHMKZnJhbWVfZGlnIC0xCmludGNfMyAvLyA4Ci8KbG9hZCA2CmNhbGxzdWIgaW1wbF82CnJldHN1YgoKLy8gZW5jb2RlX3V2YXJpbnRfaW1wbAplbmNvZGV1dmFyaW50aW1wbF8zOgpwcm90byAyIDEKZnJhbWVfZGlnIC0xCmZyYW1lX2RpZyAtMgppbnRjIDQgLy8gMTI4Cj49CmJueiBlbmNvZGV1dmFyaW50aW1wbF8zX2wyCmZyYW1lX2RpZyAtMgppbnRjIDUgLy8gMjU1CiYKaXRvYgpleHRyYWN0IDcgMQpiIGVuY29kZXV2YXJpbnRpbXBsXzNfbDMKZW5jb2RldXZhcmludGltcGxfM19sMjoKZnJhbWVfZGlnIC0yCnB1c2hpbnQgNyAvLyA3CnNocgpmcmFtZV9kaWcgLTIKaW50YyA1IC8vIDI1NQomCmludGMgNCAvLyAxMjgKfAppdG9iCmV4dHJhY3QgNyAxCmNhbGxzdWIgZW5jb2RldXZhcmludGltcGxfMwplbmNvZGV1dmFyaW50aW1wbF8zX2wzOgpjb25jYXQKcmV0c3ViCgovLyBfaW1wbAppbXBsXzQ6CnByb3RvIDEgMApmcmFtZV9kaWcgLTEKcHVzaGJ5dGVzIDB4MDAgLy8gMHgwMAppbnRjXzAgLy8gMTI3CmJ6ZXJvCmFwcF9sb2NhbF9wdXQKZnJhbWVfZGlnIC0xCnB1c2hieXRlcyAweDAxIC8vIDB4MDEKaW50Y18wIC8vIDEyNwpiemVybwphcHBfbG9jYWxfcHV0CmZyYW1lX2RpZyAtMQpwdXNoYnl0ZXMgMHgwMiAvLyAweDAyCmludGNfMCAvLyAxMjcKYnplcm8KYXBwX2xvY2FsX3B1dApmcmFtZV9kaWcgLTEKcHVzaGJ5dGVzIDB4MDMgLy8gMHgwMwppbnRjXzAgLy8gMTI3CmJ6ZXJvCmFwcF9sb2NhbF9wdXQKZnJhbWVfZGlnIC0xCnB1c2hieXRlcyAweDA0IC8vIDB4MDQKaW50Y18wIC8vIDEyNwpiemVybwphcHBfbG9jYWxfcHV0CmZyYW1lX2RpZyAtMQpwdXNoYnl0ZXMgMHgwNSAvLyAweDA1CmludGNfMCAvLyAxMjcKYnplcm8KYXBwX2xvY2FsX3B1dApmcmFtZV9kaWcgLTEKcHVzaGJ5dGVzIDB4MDYgLy8gMHgwNgppbnRjXzAgLy8gMTI3CmJ6ZXJvCmFwcF9sb2NhbF9wdXQKZnJhbWVfZGlnIC0xCnB1c2hieXRlcyAweDA3IC8vIDB4MDcKaW50Y18wIC8vIDEyNwpiemVybwphcHBfbG9jYWxfcHV0CmZyYW1lX2RpZyAtMQpwdXNoYnl0ZXMgMHgwOCAvLyAweDA4CmludGNfMCAvLyAxMjcKYnplcm8KYXBwX2xvY2FsX3B1dApmcmFtZV9kaWcgLTEKcHVzaGJ5dGVzIDB4MDkgLy8gMHgwOQppbnRjXzAgLy8gMTI3CmJ6ZXJvCmFwcF9sb2NhbF9wdXQKZnJhbWVfZGlnIC0xCnB1c2hieXRlcyAweDBhIC8vIDB4MGEKaW50Y18wIC8vIDEyNwpiemVybwphcHBfbG9jYWxfcHV0CmZyYW1lX2RpZyAtMQpwdXNoYnl0ZXMgMHgwYiAvLyAweDBiCmludGNfMCAvLyAxMjcKYnplcm8KYXBwX2xvY2FsX3B1dApmcmFtZV9kaWcgLTEKcHVzaGJ5dGVzIDB4MGMgLy8gMHgwYwppbnRjXzAgLy8gMTI3CmJ6ZXJvCmFwcF9sb2NhbF9wdXQKZnJhbWVfZGlnIC0xCnB1c2hieXRlcyAweDBkIC8vIDB4MGQKaW50Y18wIC8vIDEyNwpiemVybwphcHBfbG9jYWxfcHV0CmZyYW1lX2RpZyAtMQpwdXNoYnl0ZXMgMHgwZSAvLyAweDBlCmludGNfMCAvLyAxMjcKYnplcm8KYXBwX2xvY2FsX3B1dApmcmFtZV9kaWcgLTEKcHVzaGJ5dGVzIDB4MGYgLy8gMHgwZgppbnRjXzAgLy8gMTI3CmJ6ZXJvCmFwcF9sb2NhbF9wdXQKcmV0c3ViCgovLyBfaW1wbAppbXBsXzU6CnByb3RvIDIgMQpmcmFtZV9kaWcgLTIKYnl0ZWNfMiAvLyAweDAwMDEwMjAzMDQwNTA2MDcwODA5MGEwYjBjMGQwZTBmCmZyYW1lX2RpZyAtMQppbnRjXzAgLy8gMTI3Ci8KaW50Y18yIC8vIDEKZXh0cmFjdDMKYXBwX2xvY2FsX2dldApmcmFtZV9kaWcgLTEKaW50Y18wIC8vIDEyNwolCmdldGJ5dGUKcmV0c3ViCgovLyBfaW1wbAppbXBsXzY6CnByb3RvIDMgMApieXRlY18yIC8vIDB4MDAwMTAyMDMwNDA1MDYwNzA4MDkwYTBiMGMwZDBlMGYKZnJhbWVfZGlnIC0yCmludGNfMCAvLyAxMjcKLwppbnRjXzIgLy8gMQpleHRyYWN0MwpzdG9yZSA3CmZyYW1lX2RpZyAtMwpsb2FkIDcKZnJhbWVfZGlnIC0zCmxvYWQgNwphcHBfbG9jYWxfZ2V0CmZyYW1lX2RpZyAtMgppbnRjXzAgLy8gMTI3CiUKZnJhbWVfZGlnIC0xCnNldGJ5dGUKYXBwX2xvY2FsX3B1dApyZXRzdWI=", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDgKaW50Y2Jsb2NrIDEyNyAwIDEgOCAxMjggMjU1CmJ5dGVjYmxvY2sgMHggMHgwMDAxMDIwMzA0MDUwNjA3MDgwOTBhMGIwYzBkMGUwZiAweDA4ODAwMDM1MDA4MTAxNDMKdHhuIE51bUFwcEFyZ3MKaW50Y18xIC8vIDAKPT0KYm56IG1haW5fbDYKdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMApwdXNoYnl0ZXMgMHg3NmUzYzZkYyAvLyAiYWRkX2FjY291bnQoYnl0ZVtdKXZvaWQiCj09CmJueiBtYWluX2w1CnR4bmEgQXBwbGljYXRpb25BcmdzIDAKcHVzaGJ5dGVzIDB4MTliMTRmZGEgLy8gImZsaXBfYml0KGFjY291bnQsdWludDMyKXZvaWQiCj09CmJueiBtYWluX2w0CmVycgptYWluX2w0Ogp0eG4gT25Db21wbGV0aW9uCmludGNfMSAvLyBOb09wCj09CnR4biBBcHBsaWNhdGlvbklECmludGNfMSAvLyAwCiE9CiYmCmFzc2VydAp0eG5hIEFwcGxpY2F0aW9uQXJncyAxCmludGNfMSAvLyAwCmdldGJ5dGUKc3RvcmUgMQp0eG5hIEFwcGxpY2F0aW9uQXJncyAyCmludGNfMSAvLyAwCmV4dHJhY3RfdWludDMyCnN0b3JlIDIKbG9hZCAxCmxvYWQgMgpjYWxsc3ViIGZsaXBiaXRfNgppbnRjXzIgLy8gMQpyZXR1cm4KbWFpbl9sNToKdHhuIE9uQ29tcGxldGlvbgppbnRjXzIgLy8gT3B0SW4KPT0KdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18xIC8vIDAKIT0KJiYKYXNzZXJ0CnR4bmEgQXBwbGljYXRpb25BcmdzIDEKY2FsbHN1YiBhZGRhY2NvdW50XzUKaW50Y18yIC8vIDEKcmV0dXJuCm1haW5fbDY6CnR4biBPbkNvbXBsZXRpb24KaW50Y18xIC8vIE5vT3AKPT0KYm56IG1haW5fbDgKZXJyCm1haW5fbDg6CnR4biBBcHBsaWNhdGlvbklECmludGNfMSAvLyAwCj09CmFzc2VydApjYWxsc3ViIGNyZWF0ZV8xCmludGNfMiAvLyAxCnJldHVybgoKLy8gZW5jb2RlX3V2YXJpbnRfaW1wbAplbmNvZGV1dmFyaW50aW1wbF8wOgpwcm90byAyIDEKZnJhbWVfZGlnIC0xCmZyYW1lX2RpZyAtMgppbnRjIDQgLy8gMTI4Cj49CmJueiBlbmNvZGV1dmFyaW50aW1wbF8wX2wyCmZyYW1lX2RpZyAtMgppbnRjIDUgLy8gMjU1CiYKaXRvYgpleHRyYWN0IDcgMQpiIGVuY29kZXV2YXJpbnRpbXBsXzBfbDMKZW5jb2RldXZhcmludGltcGxfMF9sMjoKZnJhbWVfZGlnIC0yCnB1c2hpbnQgNyAvLyA3CnNocgpmcmFtZV9kaWcgLTIKaW50YyA1IC8vIDI1NQomCmludGMgNCAvLyAxMjgKfAppdG9iCmV4dHJhY3QgNyAxCmNhbGxzdWIgZW5jb2RldXZhcmludGltcGxfMAplbmNvZGV1dmFyaW50aW1wbF8wX2wzOgpjb25jYXQKcmV0c3ViCgovLyBjcmVhdGUKY3JlYXRlXzE6CnByb3RvIDAgMAppbnRjXzIgLy8gMQpyZXR1cm4KCi8vIHplcm9faW1wbAp6ZXJvaW1wbF8yOgpwcm90byAxIDAKZnJhbWVfZGlnIC0xCnB1c2hieXRlcyAweDAwIC8vIDB4MDAKaW50Y18wIC8vIDEyNwpiemVybwphcHBfbG9jYWxfcHV0CmZyYW1lX2RpZyAtMQpwdXNoYnl0ZXMgMHgwMSAvLyAweDAxCmludGNfMCAvLyAxMjcKYnplcm8KYXBwX2xvY2FsX3B1dApmcmFtZV9kaWcgLTEKcHVzaGJ5dGVzIDB4MDIgLy8gMHgwMgppbnRjXzAgLy8gMTI3CmJ6ZXJvCmFwcF9sb2NhbF9wdXQKZnJhbWVfZGlnIC0xCnB1c2hieXRlcyAweDAzIC8vIDB4MDMKaW50Y18wIC8vIDEyNwpiemVybwphcHBfbG9jYWxfcHV0CmZyYW1lX2RpZyAtMQpwdXNoYnl0ZXMgMHgwNCAvLyAweDA0CmludGNfMCAvLyAxMjcKYnplcm8KYXBwX2xvY2FsX3B1dApmcmFtZV9kaWcgLTEKcHVzaGJ5dGVzIDB4MDUgLy8gMHgwNQppbnRjXzAgLy8gMTI3CmJ6ZXJvCmFwcF9sb2NhbF9wdXQKZnJhbWVfZGlnIC0xCnB1c2hieXRlcyAweDA2IC8vIDB4MDYKaW50Y18wIC8vIDEyNwpiemVybwphcHBfbG9jYWxfcHV0CmZyYW1lX2RpZyAtMQpwdXNoYnl0ZXMgMHgwNyAvLyAweDA3CmludGNfMCAvLyAxMjcKYnplcm8KYXBwX2xvY2FsX3B1dApmcmFtZV9kaWcgLTEKcHVzaGJ5dGVzIDB4MDggLy8gMHgwOAppbnRjXzAgLy8gMTI3CmJ6ZXJvCmFwcF9sb2NhbF9wdXQKZnJhbWVfZGlnIC0xCnB1c2hieXRlcyAweDA5IC8vIDB4MDkKaW50Y18wIC8vIDEyNwpiemVybwphcHBfbG9jYWxfcHV0CmZyYW1lX2RpZyAtMQpwdXNoYnl0ZXMgMHgwYSAvLyAweDBhCmludGNfMCAvLyAxMjcKYnplcm8KYXBwX2xvY2FsX3B1dApmcmFtZV9kaWcgLTEKcHVzaGJ5dGVzIDB4MGIgLy8gMHgwYgppbnRjXzAgLy8gMTI3CmJ6ZXJvCmFwcF9sb2NhbF9wdXQKZnJhbWVfZGlnIC0xCnB1c2hieXRlcyAweDBjIC8vIDB4MGMKaW50Y18wIC8vIDEyNwpiemVybwphcHBfbG9jYWxfcHV0CmZyYW1lX2RpZyAtMQpwdXNoYnl0ZXMgMHgwZCAvLyAweDBkCmludGNfMCAvLyAxMjcKYnplcm8KYXBwX2xvY2FsX3B1dApmcmFtZV9kaWcgLTEKcHVzaGJ5dGVzIDB4MGUgLy8gMHgwZQppbnRjXzAgLy8gMTI3CmJ6ZXJvCmFwcF9sb2NhbF9wdXQKZnJhbWVfZGlnIC0xCnB1c2hieXRlcyAweDBmIC8vIDB4MGYKaW50Y18wIC8vIDEyNwpiemVybwphcHBfbG9jYWxfcHV0CnJldHN1YgoKLy8gZ2V0X2J5dGVfaW1wbApnZXRieXRlaW1wbF8zOgpwcm90byAyIDEKZnJhbWVfZGlnIC0yCmJ5dGVjXzEgLy8gMHgwMDAxMDIwMzA0MDUwNjA3MDgwOTBhMGIwYzBkMGUwZgpmcmFtZV9kaWcgLTEKaW50Y18wIC8vIDEyNwovCmludGNfMiAvLyAxCmV4dHJhY3QzCmFwcF9sb2NhbF9nZXQKZnJhbWVfZGlnIC0xCmludGNfMCAvLyAxMjcKJQpnZXRieXRlCnJldHN1YgoKLy8gc2V0X2J5dGVfaW1wbApzZXRieXRlaW1wbF80Ogpwcm90byAzIDAKYnl0ZWNfMSAvLyAweDAwMDEwMjAzMDQwNTA2MDcwODA5MGEwYjBjMGQwZTBmCmZyYW1lX2RpZyAtMgppbnRjXzAgLy8gMTI3Ci8KaW50Y18yIC8vIDEKZXh0cmFjdDMKc3RvcmUgMApmcmFtZV9kaWcgLTMKbG9hZCAwCmZyYW1lX2RpZyAtMwpsb2FkIDAKYXBwX2xvY2FsX2dldApmcmFtZV9kaWcgLTIKaW50Y18wIC8vIDEyNwolCmZyYW1lX2RpZyAtMQpzZXRieXRlCmFwcF9sb2NhbF9wdXQKcmV0c3ViCgovLyBhZGRfYWNjb3VudAphZGRhY2NvdW50XzU6CnByb3RvIDEgMAp0eG4gU2VuZGVyCnB1c2hieXRlcyAweDUwNzI2ZjY3NzI2MTZkIC8vICJQcm9ncmFtIgppbnRjXzEgLy8gMApzdG9yZSAzCmludGNfMSAvLyAwCnN0b3JlIDQKYnl0ZWNfMCAvLyAiIgpzdG9yZSA1CmJ5dGVjXzAgLy8gIiIKc3RvcmUgNgpmcmFtZV9kaWcgLTEKZXh0cmFjdCAyIDAKbGVuCmJ5dGVjXzAgLy8gIiIKY2FsbHN1YiBlbmNvZGV1dmFyaW50aW1wbF8wCmZyYW1lX2RpZyAtMQpleHRyYWN0IDIgMApjb25jYXQKc3RvcmUgNQpsb2FkIDYKYnl0ZWNfMiAvLyAweDA4ODAwMDM1MDA4MTAxNDMKbG9hZCAzCnB1c2hpbnQgMiAvLyAyCnN1YnN0cmluZzMKY29uY2F0CmxvYWQgNQpjb25jYXQKc3RvcmUgNgpsb2FkIDQKbG9hZCA1CmxlbgorCmludGNfMiAvLyAxCi0Kc3RvcmUgNApwdXNoaW50IDIgLy8gMgppbnRjXzIgLy8gMQorCnN0b3JlIDMKbG9hZCA2CmJ5dGVjXzIgLy8gMHgwODgwMDAzNTAwODEwMTQzCmxvYWQgMwpkaWcgMQpsZW4Kc3Vic3RyaW5nMwpjb25jYXQKc3RvcmUgNgpsb2FkIDYKY29uY2F0CnNoYTUxMl8yNTYKPT0KYXNzZXJ0CnR4biBSZWtleVRvCmdsb2JhbCBDdXJyZW50QXBwbGljYXRpb25BZGRyZXNzCj09CmFzc2VydAp0eG4gU2VuZGVyCmNhbGxzdWIgemVyb2ltcGxfMgpyZXRzdWIKCi8vIGZsaXBfYml0CmZsaXBiaXRfNjoKcHJvdG8gMiAwCmZyYW1lX2RpZyAtMgp0eG5hcyBBY2NvdW50cwpmcmFtZV9kaWcgLTEKaW50Y18zIC8vIDgKLwpjYWxsc3ViIGdldGJ5dGVpbXBsXzMKc3RvcmUgNwpsb2FkIDcKZnJhbWVfZGlnIC0xCmludGNfMyAvLyA4CiUKbG9hZCA3CmZyYW1lX2RpZyAtMQppbnRjXzMgLy8gOAolCmdldGJpdAohCnNldGJpdApzdG9yZSA3CmZyYW1lX2RpZyAtMgp0eG5hcyBBY2NvdW50cwpmcmFtZV9kaWcgLTEKaW50Y18zIC8vIDgKLwpsb2FkIDcKY2FsbHN1YiBzZXRieXRlaW1wbF80CnJldHN1Yg==", "clear": "I3ByYWdtYSB2ZXJzaW9uIDgKcHVzaGludCAwIC8vIDAKcmV0dXJu" }, "schema": { diff --git a/examples/account_storage/DiskHungry.artifacts/approval.teal b/examples/account_storage/DiskHungry.artifacts/approval.teal index d6785887..1b9ab8d5 100644 --- a/examples/account_storage/DiskHungry.artifacts/approval.teal +++ b/examples/account_storage/DiskHungry.artifacts/approval.teal @@ -1,6 +1,6 @@ #pragma version 8 intcblock 127 0 1 8 128 255 -bytecblock 0x 0x0880003500810143 0x000102030405060708090a0b0c0d0e0f +bytecblock 0x 0x000102030405060708090a0b0c0d0e0f 0x0880003500810143 txn NumAppArgs intc_1 // 0 == @@ -26,14 +26,14 @@ assert txna ApplicationArgs 1 intc_1 // 0 getbyte -store 0 +store 1 txna ApplicationArgs 2 intc_1 // 0 extract_uint32 -store 1 -load 0 +store 2 load 1 -callsub flipbit_2 +load 2 +callsub flipbit_6 intc_2 // 1 return main_l5: @@ -46,7 +46,7 @@ intc_1 // 0 && assert txna ApplicationArgs 1 -callsub addaccount_1 +callsub addaccount_5 intc_2 // 1 return main_l6: @@ -60,125 +60,25 @@ txn ApplicationID intc_1 // 0 == assert -callsub create_0 +callsub create_1 intc_2 // 1 return -// create -create_0: -proto 0 0 -intc_2 // 1 -return - -// add_account -addaccount_1: -proto 1 0 -txn Sender -pushbytes 0x50726f6772616d // "Program" -intc_1 // 0 -store 2 -intc_1 // 0 -store 3 -bytec_0 // "" -store 4 -bytec_0 // "" -store 5 -frame_dig -1 -extract 2 0 -len -bytec_0 // "" -callsub encodeuvarintimpl_3 -frame_dig -1 -extract 2 0 -concat -store 4 -load 5 -bytec_1 // 0x0880003500810143 -load 2 -pushint 2 // 2 -substring3 -concat -load 4 -concat -store 5 -load 3 -load 4 -len -+ -intc_2 // 1 -- -store 3 -pushint 2 // 2 -intc_2 // 1 -+ -store 2 -load 5 -bytec_1 // 0x0880003500810143 -load 2 -dig 1 -len -substring3 -concat -store 5 -load 5 -concat -sha512_256 -== -assert -txn RekeyTo -global CurrentApplicationAddress -== -assert -txn Sender -callsub impl_4 -retsub - -// flip_bit -flipbit_2: -proto 2 0 -frame_dig -2 -txnas Accounts -frame_dig -1 -intc_3 // 8 -/ -callsub impl_5 -store 6 -load 6 -frame_dig -1 -intc_3 // 8 -% -load 6 -frame_dig -1 -intc_3 // 8 -% -getbit -! -setbit -store 6 -frame_dig -2 -txnas Accounts -frame_dig -1 -intc_3 // 8 -/ -load 6 -callsub impl_6 -retsub - // encode_uvarint_impl -encodeuvarintimpl_3: +encodeuvarintimpl_0: proto 2 1 frame_dig -1 frame_dig -2 intc 4 // 128 >= -bnz encodeuvarintimpl_3_l2 +bnz encodeuvarintimpl_0_l2 frame_dig -2 intc 5 // 255 & itob extract 7 1 -b encodeuvarintimpl_3_l3 -encodeuvarintimpl_3_l2: +b encodeuvarintimpl_0_l3 +encodeuvarintimpl_0_l2: frame_dig -2 pushint 7 // 7 shr @@ -189,13 +89,19 @@ intc 4 // 128 | itob extract 7 1 -callsub encodeuvarintimpl_3 -encodeuvarintimpl_3_l3: +callsub encodeuvarintimpl_0 +encodeuvarintimpl_0_l3: concat retsub -// _impl -impl_4: +// create +create_1: +proto 0 0 +intc_2 // 1 +return + +// zero_impl +zeroimpl_2: proto 1 0 frame_dig -1 pushbytes 0x00 // 0x00 @@ -279,11 +185,11 @@ bzero app_local_put retsub -// _impl -impl_5: +// get_byte_impl +getbyteimpl_3: proto 2 1 frame_dig -2 -bytec_2 // 0x000102030405060708090a0b0c0d0e0f +bytec_1 // 0x000102030405060708090a0b0c0d0e0f frame_dig -1 intc_0 // 127 / @@ -296,20 +202,20 @@ intc_0 // 127 getbyte retsub -// _impl -impl_6: +// set_byte_impl +setbyteimpl_4: proto 3 0 -bytec_2 // 0x000102030405060708090a0b0c0d0e0f +bytec_1 // 0x000102030405060708090a0b0c0d0e0f frame_dig -2 intc_0 // 127 / intc_2 // 1 extract3 -store 7 +store 0 frame_dig -3 -load 7 +load 0 frame_dig -3 -load 7 +load 0 app_local_get frame_dig -2 intc_0 // 127 @@ -317,4 +223,98 @@ intc_0 // 127 frame_dig -1 setbyte app_local_put +retsub + +// add_account +addaccount_5: +proto 1 0 +txn Sender +pushbytes 0x50726f6772616d // "Program" +intc_1 // 0 +store 3 +intc_1 // 0 +store 4 +bytec_0 // "" +store 5 +bytec_0 // "" +store 6 +frame_dig -1 +extract 2 0 +len +bytec_0 // "" +callsub encodeuvarintimpl_0 +frame_dig -1 +extract 2 0 +concat +store 5 +load 6 +bytec_2 // 0x0880003500810143 +load 3 +pushint 2 // 2 +substring3 +concat +load 5 +concat +store 6 +load 4 +load 5 +len ++ +intc_2 // 1 +- +store 4 +pushint 2 // 2 +intc_2 // 1 ++ +store 3 +load 6 +bytec_2 // 0x0880003500810143 +load 3 +dig 1 +len +substring3 +concat +store 6 +load 6 +concat +sha512_256 +== +assert +txn RekeyTo +global CurrentApplicationAddress +== +assert +txn Sender +callsub zeroimpl_2 +retsub + +// flip_bit +flipbit_6: +proto 2 0 +frame_dig -2 +txnas Accounts +frame_dig -1 +intc_3 // 8 +/ +callsub getbyteimpl_3 +store 7 +load 7 +frame_dig -1 +intc_3 // 8 +% +load 7 +frame_dig -1 +intc_3 // 8 +% +getbit +! +setbit +store 7 +frame_dig -2 +txnas Accounts +frame_dig -1 +intc_3 // 8 +/ +load 7 +callsub setbyteimpl_4 retsub \ No newline at end of file diff --git a/examples/state/StateExample.artifacts/application.json b/examples/state/StateExample.artifacts/application.json index bee63002..d8887cad 100644 --- a/examples/state/StateExample.artifacts/application.json +++ b/examples/state/StateExample.artifacts/application.json @@ -14,7 +14,7 @@ } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDgKaW50Y2Jsb2NrIDAgMTI3IDEKYnl0ZWNibG9jayAweDE1MWY3Yzc1IDB4IDB4NjQ2NTYzNmM2MTcyNjU2NDVmNjE3MDcwNWY3NjYxNmM3NTY1IDB4NjQ2NTYzNmM2MTcyNjU2NDVmNjE2MzYzNmY3NTZlNzQ1Zjc2NjE2Yzc1NjUgMHgwMCAweDAwMDEwMiAweDAwMDEwMjAzMDQwNTA2MDcwODA5MGEwYjBjMGQwZTBmCnR4biBOdW1BcHBBcmdzCmludGNfMCAvLyAwCj09CmJueiBtYWluX2wyOAp0eG5hIEFwcGxpY2F0aW9uQXJncyAwCnB1c2hieXRlcyAweGFhNmExZDc5IC8vICJ3cml0ZV9hY2N0X2Jsb2Ioc3RyaW5nKXZvaWQiCj09CmJueiBtYWluX2wyNwp0eG5hIEFwcGxpY2F0aW9uQXJncyAwCnB1c2hieXRlcyAweDVhMjM0YTkwIC8vICJyZWFkX2FjY3RfYmxvYigpYnl0ZVtdIgo9PQpibnogbWFpbl9sMjYKdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMApwdXNoYnl0ZXMgMHgzZWIyNDVmYSAvLyAid3JpdGVfYXBwX2Jsb2Ioc3RyaW5nKXZvaWQiCj09CmJueiBtYWluX2wyNQp0eG5hIEFwcGxpY2F0aW9uQXJncyAwCnB1c2hieXRlcyAweGQ1Yzk1ZjZjIC8vICJyZWFkX2FwcF9ibG9iKClieXRlW10iCj09CmJueiBtYWluX2wyNAp0eG5hIEFwcGxpY2F0aW9uQXJncyAwCnB1c2hieXRlcyAweDI5ZDk0NzBmIC8vICJzZXRfYXBwX3N0YXRlX3ZhbChzdHJpbmcpdm9pZCIKPT0KYm56IG1haW5fbDIzCnR4bmEgQXBwbGljYXRpb25BcmdzIDAKcHVzaGJ5dGVzIDB4ZjRjMjI1NjYgLy8gImdldF9hcHBfc3RhdGVfdmFsKClzdHJpbmciCj09CmJueiBtYWluX2wyMgp0eG5hIEFwcGxpY2F0aW9uQXJncyAwCnB1c2hieXRlcyAweDA2YmM4NjA0IC8vICJzZXRfcmVzZXJ2ZWRfYXBwX3N0YXRlX3ZhbCh1aW50OCx1aW50NjQpdm9pZCIKPT0KYm56IG1haW5fbDIxCnR4bmEgQXBwbGljYXRpb25BcmdzIDAKcHVzaGJ5dGVzIDB4ZTk4NGUzYzMgLy8gImdldF9yZXNlcnZlZF9hcHBfc3RhdGVfdmFsKHVpbnQ4KXVpbnQ2NCIKPT0KYm56IG1haW5fbDIwCnR4bmEgQXBwbGljYXRpb25BcmdzIDAKcHVzaGJ5dGVzIDB4ZmU2MGI1MmEgLy8gInNldF9hY2NvdW50X3N0YXRlX3ZhbCh1aW50NjQpdm9pZCIKPT0KYm56IG1haW5fbDE5CnR4bmEgQXBwbGljYXRpb25BcmdzIDAKcHVzaGJ5dGVzIDB4YjhkYzliNTkgLy8gImluY3JfYWNjb3VudF9zdGF0ZV92YWwodWludDY0KXZvaWQiCj09CmJueiBtYWluX2wxOAp0eG5hIEFwcGxpY2F0aW9uQXJncyAwCnB1c2hieXRlcyAweDVhOThmMzcyIC8vICJnZXRfYWNjb3VudF9zdGF0ZV92YWwoKXVpbnQ2NCIKPT0KYm56IG1haW5fbDE3CnR4bmEgQXBwbGljYXRpb25BcmdzIDAKcHVzaGJ5dGVzIDB4ZTZlNjBhZGUgLy8gInNldF9yZXNlcnZlZF9hY2NvdW50X3N0YXRlX3ZhbCh1aW50OCxzdHJpbmcpdm9pZCIKPT0KYm56IG1haW5fbDE2CnR4bmEgQXBwbGljYXRpb25BcmdzIDAKcHVzaGJ5dGVzIDB4Y2JhMzM3N2UgLy8gImdldF9yZXNlcnZlZF9hY2NvdW50X3N0YXRlX3ZhbCh1aW50OClzdHJpbmciCj09CmJueiBtYWluX2wxNQplcnIKbWFpbl9sMTU6CnR4biBPbkNvbXBsZXRpb24KaW50Y18wIC8vIE5vT3AKPT0KdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18wIC8vIDAKIT0KJiYKYXNzZXJ0CnR4bmEgQXBwbGljYXRpb25BcmdzIDEKaW50Y18wIC8vIDAKZ2V0Ynl0ZQpjYWxsc3ViIGdldHJlc2VydmVkYWNjb3VudHN0YXRldmFsXzE4CnN0b3JlIDExCmJ5dGVjXzAgLy8gMHgxNTFmN2M3NQpsb2FkIDExCmNvbmNhdApsb2cKaW50Y18yIC8vIDEKcmV0dXJuCm1haW5fbDE2Ogp0eG4gT25Db21wbGV0aW9uCmludGNfMCAvLyBOb09wCj09CnR4biBBcHBsaWNhdGlvbklECmludGNfMCAvLyAwCiE9CiYmCmFzc2VydAp0eG5hIEFwcGxpY2F0aW9uQXJncyAxCmludGNfMCAvLyAwCmdldGJ5dGUKc3RvcmUgOQp0eG5hIEFwcGxpY2F0aW9uQXJncyAyCnN0b3JlIDEwCmxvYWQgOQpsb2FkIDEwCmNhbGxzdWIgc2V0cmVzZXJ2ZWRhY2NvdW50c3RhdGV2YWxfMTcKaW50Y18yIC8vIDEKcmV0dXJuCm1haW5fbDE3Ogp0eG4gT25Db21wbGV0aW9uCmludGNfMCAvLyBOb09wCj09CnR4biBBcHBsaWNhdGlvbklECmludGNfMCAvLyAwCiE9CiYmCmFzc2VydApjYWxsc3ViIGdldGFjY291bnRzdGF0ZXZhbF8xNgpzdG9yZSA4CmJ5dGVjXzAgLy8gMHgxNTFmN2M3NQpsb2FkIDgKaXRvYgpjb25jYXQKbG9nCmludGNfMiAvLyAxCnJldHVybgptYWluX2wxODoKdHhuIE9uQ29tcGxldGlvbgppbnRjXzAgLy8gTm9PcAo9PQp0eG4gQXBwbGljYXRpb25JRAppbnRjXzAgLy8gMAohPQomJgphc3NlcnQKdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQpidG9pCmNhbGxzdWIgaW5jcmFjY291bnRzdGF0ZXZhbF8xNQppbnRjXzIgLy8gMQpyZXR1cm4KbWFpbl9sMTk6CnR4biBPbkNvbXBsZXRpb24KaW50Y18wIC8vIE5vT3AKPT0KdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18wIC8vIDAKIT0KJiYKYXNzZXJ0CnR4bmEgQXBwbGljYXRpb25BcmdzIDEKYnRvaQpjYWxsc3ViIHNldGFjY291bnRzdGF0ZXZhbF8xNAppbnRjXzIgLy8gMQpyZXR1cm4KbWFpbl9sMjA6CnR4biBPbkNvbXBsZXRpb24KaW50Y18wIC8vIE5vT3AKPT0KdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18wIC8vIDAKIT0KJiYKYXNzZXJ0CnR4bmEgQXBwbGljYXRpb25BcmdzIDEKaW50Y18wIC8vIDAKZ2V0Ynl0ZQpjYWxsc3ViIGdldHJlc2VydmVkYXBwc3RhdGV2YWxfMTMKc3RvcmUgNwpieXRlY18wIC8vIDB4MTUxZjdjNzUKbG9hZCA3Cml0b2IKY29uY2F0CmxvZwppbnRjXzIgLy8gMQpyZXR1cm4KbWFpbl9sMjE6CnR4biBPbkNvbXBsZXRpb24KaW50Y18wIC8vIE5vT3AKPT0KdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18wIC8vIDAKIT0KJiYKYXNzZXJ0CnR4bmEgQXBwbGljYXRpb25BcmdzIDEKaW50Y18wIC8vIDAKZ2V0Ynl0ZQpzdG9yZSA1CnR4bmEgQXBwbGljYXRpb25BcmdzIDIKYnRvaQpzdG9yZSA2CmxvYWQgNQpsb2FkIDYKY2FsbHN1YiBzZXRyZXNlcnZlZGFwcHN0YXRldmFsXzEyCmludGNfMiAvLyAxCnJldHVybgptYWluX2wyMjoKdHhuIE9uQ29tcGxldGlvbgppbnRjXzAgLy8gTm9PcAo9PQp0eG4gQXBwbGljYXRpb25JRAppbnRjXzAgLy8gMAohPQomJgphc3NlcnQKY2FsbHN1YiBnZXRhcHBzdGF0ZXZhbF8xMQpzdG9yZSA0CmJ5dGVjXzAgLy8gMHgxNTFmN2M3NQpsb2FkIDQKY29uY2F0CmxvZwppbnRjXzIgLy8gMQpyZXR1cm4KbWFpbl9sMjM6CnR4biBPbkNvbXBsZXRpb24KaW50Y18wIC8vIE5vT3AKPT0KdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18wIC8vIDAKIT0KJiYKYXNzZXJ0CnR4bmEgQXBwbGljYXRpb25BcmdzIDEKY2FsbHN1YiBzZXRhcHBzdGF0ZXZhbF8xMAppbnRjXzIgLy8gMQpyZXR1cm4KbWFpbl9sMjQ6CnR4biBPbkNvbXBsZXRpb24KaW50Y18wIC8vIE5vT3AKPT0KdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18wIC8vIDAKIT0KJiYKYXNzZXJ0CmNhbGxzdWIgcmVhZGFwcGJsb2JfOQpzdG9yZSAzCmJ5dGVjXzAgLy8gMHgxNTFmN2M3NQpsb2FkIDMKY29uY2F0CmxvZwppbnRjXzIgLy8gMQpyZXR1cm4KbWFpbl9sMjU6CnR4biBPbkNvbXBsZXRpb24KaW50Y18wIC8vIE5vT3AKPT0KdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18wIC8vIDAKIT0KJiYKYXNzZXJ0CnR4bmEgQXBwbGljYXRpb25BcmdzIDEKY2FsbHN1YiB3cml0ZWFwcGJsb2JfOAppbnRjXzIgLy8gMQpyZXR1cm4KbWFpbl9sMjY6CnR4biBPbkNvbXBsZXRpb24KaW50Y18wIC8vIE5vT3AKPT0KdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18wIC8vIDAKIT0KJiYKYXNzZXJ0CmNhbGxzdWIgcmVhZGFjY3RibG9iXzcKc3RvcmUgMgpieXRlY18wIC8vIDB4MTUxZjdjNzUKbG9hZCAyCmNvbmNhdApsb2cKaW50Y18yIC8vIDEKcmV0dXJuCm1haW5fbDI3Ogp0eG4gT25Db21wbGV0aW9uCmludGNfMCAvLyBOb09wCj09CnR4biBBcHBsaWNhdGlvbklECmludGNfMCAvLyAwCiE9CiYmCmFzc2VydAp0eG5hIEFwcGxpY2F0aW9uQXJncyAxCmNhbGxzdWIgd3JpdGVhY2N0YmxvYl82CmludGNfMiAvLyAxCnJldHVybgptYWluX2wyODoKdHhuIE9uQ29tcGxldGlvbgppbnRjXzAgLy8gTm9PcAo9PQpibnogbWFpbl9sMzIKdHhuIE9uQ29tcGxldGlvbgppbnRjXzIgLy8gT3B0SW4KPT0KYm56IG1haW5fbDMxCmVycgptYWluX2wzMToKdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18wIC8vIDAKIT0KYXNzZXJ0CmNhbGxzdWIgb3B0aW5fMQppbnRjXzIgLy8gMQpyZXR1cm4KbWFpbl9sMzI6CnR4biBBcHBsaWNhdGlvbklECmludGNfMCAvLyAwCj09CmFzc2VydApjYWxsc3ViIGNyZWF0ZV8wCmludGNfMiAvLyAxCnJldHVybgoKLy8gY3JlYXRlCmNyZWF0ZV8wOgpwcm90byAwIDAKaW50Y18wIC8vIDAKYnl0ZWNfMiAvLyAiZGVjbGFyZWRfYXBwX3ZhbHVlIgphcHBfZ2xvYmFsX2dldF9leApzdG9yZSAxCnN0b3JlIDAKbG9hZCAxCiEKYXNzZXJ0CmJ5dGVjXzIgLy8gImRlY2xhcmVkX2FwcF92YWx1ZSIKcHVzaGJ5dGVzIDB4NDEyMDY0NjU2MzZjNjE3MjY1NjQyMDczNzQ2MTc0NjUyMDc2NjE2Yzc1NjUyMDc0Njg2MTc0MjA2OTczMjA3MDcyNmY3NDY1NjM3NDY1NjQyMDc3Njk3NDY4MjA3NDY4NjUyMDYwNzM3NDYxNzQ2OTYzNjAyMDY2NmM2MTY3IC8vICJBIGRlY2xhcmVkIHN0YXRlIHZhbHVlIHRoYXQgaXMgcHJvdGVjdGVkIHdpdGggdGhlIGBzdGF0aWNgIGZsYWciCmFwcF9nbG9iYWxfcHV0CmNhbGxzdWIgemVyb2ltcGxfNApyZXRzdWIKCi8vIG9wdF9pbgpvcHRpbl8xOgpwcm90byAwIDAKdHhuIFNlbmRlcgpieXRlY18zIC8vICJkZWNsYXJlZF9hY2NvdW50X3ZhbHVlIgppbnRjXzIgLy8gMQphcHBfbG9jYWxfcHV0CnR4biBTZW5kZXIKY2FsbHN1YiBpbXBsXzUKcmV0c3ViCgovLyBwcmVmaXhfa2V5X2dlbgpwcmVmaXhrZXlnZW5fMjoKcHJvdG8gMSAxCnB1c2hieXRlcyAweDcyNjU3MzY1NzI3NjY1NjQ1ZjYxNzA3MDVmNzY2MTZjNzU2NSAvLyAicmVzZXJ2ZWRfYXBwX3ZhbHVlIgpmcmFtZV9kaWcgLTEKY29uY2F0CnJldHN1YgoKLy8gcHJlZml4X2tleV9nZW4KcHJlZml4a2V5Z2VuXzM6CnByb3RvIDEgMQpwdXNoYnl0ZXMgMHg3MjY1NzM2NTcyNzY2NTY0NWY2MTYzNjM2Zjc1NmU3NDVmNzY2MTZjNzU2NSAvLyAicmVzZXJ2ZWRfYWNjb3VudF92YWx1ZSIKZnJhbWVfZGlnIC0xCmNvbmNhdApyZXRzdWIKCi8vIHplcm9faW1wbAp6ZXJvaW1wbF80Ogpwcm90byAwIDAKaW50Y18xIC8vIDEyNwpiemVybwpwdXNoaW50IDE2IC8vIDE2CgogICAgemVyb19sb29wOgogICAgICAgIGludCAxCiAgICAgICAgLSAgICAgICAgICAgICAgIC8vIFsiMDAiKnBhZ2Vfc2l6ZSwga2V5LTFdCiAgICAgICAgZHVwMiAgICAgICAgICAgIC8vIFsiMDAiKnBhZ2Vfc2l6ZSwga2V5LCAiMDAiKnBhZ2Vfc2l6ZSwga2V5XQogICAgICAgIGl0b2IgICAgICAgICAgICAvLyBbIjAwIipwYWdlX3NpemUsIGtleSwgIjAwIipwYWdlX3NpemUsIGl0b2Ioa2V5KV0KICAgICAgICBleHRyYWN0IDcgMSAgICAgLy8gWyIwMCIqcGFnZV9zaXplLCBrZXksICIwMCIqcGFnZV9zaXplLCBpdG9iKGtleSlbLTFdXSBnZXQgdGhlIGxhc3QgYnl0ZSBvZiB0aGUgaW50CiAgICAgICAgc3dhcCAgICAgICAgICAgIC8vIFsiMDAiKnBhZ2Vfc2l6ZSwga2V5LCBpdG9iKGtleSlbLTFdLCAiMDAiKnBhZ2Vfc2l6ZV0KICAgICAgICBhcHBfZ2xvYmFsX3B1dCAgLy8gWyIwMCIqcGFnZV9zaXplLCBrZXldICAocmVtb3ZlcyB0b3AgMiBlbGVtZW50cykKICAgICAgICBkdXAgICAgICAgICAgICAgLy8gWyIwMCIqcGFnZV9zaXplLCBrZXktMSwga2V5LTFdCiAgICAgICAgYm56IHplcm9fbG9vcCAgIC8vIHN0YXJ0IGxvb3Agb3ZlciBpZiBrZXktMT4wCiAgICAgICAgcG9wCiAgICAgICAgcG9wICAgICAgICAgICAgIC8vIHRha2UgZXh0cmEganVuayBvZmYgdGhlIHN0YWNrCiAgICAgICAgcmV0c3ViCiAgICBjYWxsc3ViIHplcm9fbG9vcAogICAgICAgICAgICAKcmV0c3ViCgovLyBfaW1wbAppbXBsXzU6CnByb3RvIDEgMApmcmFtZV9kaWcgLTEKYnl0ZWMgNCAvLyAweDAwCmludGNfMSAvLyAxMjcKYnplcm8KYXBwX2xvY2FsX3B1dApmcmFtZV9kaWcgLTEKcHVzaGJ5dGVzIDB4MDEgLy8gMHgwMQppbnRjXzEgLy8gMTI3CmJ6ZXJvCmFwcF9sb2NhbF9wdXQKZnJhbWVfZGlnIC0xCnB1c2hieXRlcyAweDAyIC8vIDB4MDIKaW50Y18xIC8vIDEyNwpiemVybwphcHBfbG9jYWxfcHV0CnJldHN1YgoKLy8gd3JpdGVfYWNjdF9ibG9iCndyaXRlYWNjdGJsb2JfNjoKcHJvdG8gMSAwCnR4biBTZW5kZXIKaW50Y18wIC8vIDAKZnJhbWVfZGlnIC0xCmV4dHJhY3QgMiAwCmNhbGxzdWIgaW1wbF8xOQpyZXRzdWIKCi8vIHJlYWRfYWNjdF9ibG9iCnJlYWRhY2N0YmxvYl83Ogpwcm90byAwIDEKYnl0ZWNfMSAvLyAiIgp0eG4gU2VuZGVyCmludGNfMCAvLyAwCnB1c2hpbnQgMzgxIC8vIDM4MQppbnRjXzIgLy8gMQotCmNhbGxzdWIgaW1wbF8yMApmcmFtZV9idXJ5IDAKZnJhbWVfZGlnIDAKbGVuCml0b2IKZXh0cmFjdCA2IDAKZnJhbWVfZGlnIDAKY29uY2F0CmZyYW1lX2J1cnkgMApyZXRzdWIKCi8vIHdyaXRlX2FwcF9ibG9iCndyaXRlYXBwYmxvYl84Ogpwcm90byAxIDAKaW50Y18wIC8vIDAKZnJhbWVfZGlnIC0xCmV4dHJhY3QgMiAwCmNhbGxzdWIgd3JpdGVpbXBsXzIxCnJldHN1YgoKLy8gcmVhZF9hcHBfYmxvYgpyZWFkYXBwYmxvYl85Ogpwcm90byAwIDEKYnl0ZWNfMSAvLyAiIgppbnRjXzAgLy8gMApwdXNoaW50IDIwMzIgLy8gMjAzMgppbnRjXzIgLy8gMQotCmNhbGxzdWIgcmVhZGltcGxfMjIKZnJhbWVfYnVyeSAwCmZyYW1lX2RpZyAwCmxlbgppdG9iCmV4dHJhY3QgNiAwCmZyYW1lX2RpZyAwCmNvbmNhdApmcmFtZV9idXJ5IDAKcmV0c3ViCgovLyBzZXRfYXBwX3N0YXRlX3ZhbApzZXRhcHBzdGF0ZXZhbF8xMDoKcHJvdG8gMSAwCmludGNfMCAvLyAwCmJ5dGVjXzIgLy8gImRlY2xhcmVkX2FwcF92YWx1ZSIKYXBwX2dsb2JhbF9nZXRfZXgKc3RvcmUgMzEKc3RvcmUgMzAKbG9hZCAzMQohCmFzc2VydApieXRlY18yIC8vICJkZWNsYXJlZF9hcHBfdmFsdWUiCmZyYW1lX2RpZyAtMQpleHRyYWN0IDIgMAphcHBfZ2xvYmFsX3B1dApyZXRzdWIKCi8vIGdldF9hcHBfc3RhdGVfdmFsCmdldGFwcHN0YXRldmFsXzExOgpwcm90byAwIDEKYnl0ZWNfMSAvLyAiIgpieXRlY18yIC8vICJkZWNsYXJlZF9hcHBfdmFsdWUiCmFwcF9nbG9iYWxfZ2V0CmZyYW1lX2J1cnkgMApmcmFtZV9kaWcgMApsZW4KaXRvYgpleHRyYWN0IDYgMApmcmFtZV9kaWcgMApjb25jYXQKZnJhbWVfYnVyeSAwCnJldHN1YgoKLy8gc2V0X3Jlc2VydmVkX2FwcF9zdGF0ZV92YWwKc2V0cmVzZXJ2ZWRhcHBzdGF0ZXZhbF8xMjoKcHJvdG8gMiAwCmJ5dGVjIDQgLy8gMHgwMAppbnRjXzAgLy8gMApmcmFtZV9kaWcgLTIKc2V0Ynl0ZQpjYWxsc3ViIHByZWZpeGtleWdlbl8yCmZyYW1lX2RpZyAtMQphcHBfZ2xvYmFsX3B1dApyZXRzdWIKCi8vIGdldF9yZXNlcnZlZF9hcHBfc3RhdGVfdmFsCmdldHJlc2VydmVkYXBwc3RhdGV2YWxfMTM6CnByb3RvIDEgMQppbnRjXzAgLy8gMApieXRlYyA0IC8vIDB4MDAKaW50Y18wIC8vIDAKZnJhbWVfZGlnIC0xCnNldGJ5dGUKY2FsbHN1YiBwcmVmaXhrZXlnZW5fMgphcHBfZ2xvYmFsX2dldApmcmFtZV9idXJ5IDAKcmV0c3ViCgovLyBzZXRfYWNjb3VudF9zdGF0ZV92YWwKc2V0YWNjb3VudHN0YXRldmFsXzE0Ogpwcm90byAxIDAKdHhuIFNlbmRlcgpieXRlY18zIC8vICJkZWNsYXJlZF9hY2NvdW50X3ZhbHVlIgpmcmFtZV9kaWcgLTEKYXBwX2xvY2FsX3B1dApyZXRzdWIKCi8vIGluY3JfYWNjb3VudF9zdGF0ZV92YWwKaW5jcmFjY291bnRzdGF0ZXZhbF8xNToKcHJvdG8gMSAwCnR4biBTZW5kZXIKYnl0ZWNfMyAvLyAiZGVjbGFyZWRfYWNjb3VudF92YWx1ZSIKdHhuIFNlbmRlcgpieXRlY18zIC8vICJkZWNsYXJlZF9hY2NvdW50X3ZhbHVlIgphcHBfbG9jYWxfZ2V0CmZyYW1lX2RpZyAtMQorCmFwcF9sb2NhbF9wdXQKcmV0c3ViCgovLyBnZXRfYWNjb3VudF9zdGF0ZV92YWwKZ2V0YWNjb3VudHN0YXRldmFsXzE2Ogpwcm90byAwIDEKaW50Y18wIC8vIDAKdHhuIFNlbmRlcgpieXRlY18zIC8vICJkZWNsYXJlZF9hY2NvdW50X3ZhbHVlIgphcHBfbG9jYWxfZ2V0CmZyYW1lX2J1cnkgMApyZXRzdWIKCi8vIHNldF9yZXNlcnZlZF9hY2NvdW50X3N0YXRlX3ZhbApzZXRyZXNlcnZlZGFjY291bnRzdGF0ZXZhbF8xNzoKcHJvdG8gMiAwCnR4biBTZW5kZXIKYnl0ZWMgNCAvLyAweDAwCmludGNfMCAvLyAwCmZyYW1lX2RpZyAtMgpzZXRieXRlCmNhbGxzdWIgcHJlZml4a2V5Z2VuXzMKZnJhbWVfZGlnIC0xCmV4dHJhY3QgMiAwCmFwcF9sb2NhbF9wdXQKcmV0c3ViCgovLyBnZXRfcmVzZXJ2ZWRfYWNjb3VudF9zdGF0ZV92YWwKZ2V0cmVzZXJ2ZWRhY2NvdW50c3RhdGV2YWxfMTg6CnByb3RvIDEgMQpieXRlY18xIC8vICIiCnR4biBTZW5kZXIKYnl0ZWMgNCAvLyAweDAwCmludGNfMCAvLyAwCmZyYW1lX2RpZyAtMQpzZXRieXRlCmNhbGxzdWIgcHJlZml4a2V5Z2VuXzMKYXBwX2xvY2FsX2dldApmcmFtZV9idXJ5IDAKZnJhbWVfZGlnIDAKbGVuCml0b2IKZXh0cmFjdCA2IDAKZnJhbWVfZGlnIDAKY29uY2F0CmZyYW1lX2J1cnkgMApyZXRzdWIKCi8vIF9pbXBsCmltcGxfMTk6CnByb3RvIDMgMAppbnRjXzAgLy8gMApzdG9yZSAxNQpmcmFtZV9kaWcgLTIKaW50Y18xIC8vIDEyNwovCnN0b3JlIDEyCmltcGxfMTlfbDE6CmxvYWQgMTIKZnJhbWVfZGlnIC0yCmZyYW1lX2RpZyAtMQpsZW4KKwppbnRjXzEgLy8gMTI3Ci8KPD0KYnogaW1wbF8xOV9sMTIKbG9hZCAxMgpmcmFtZV9kaWcgLTIKaW50Y18xIC8vIDEyNwovCj09CmJueiBpbXBsXzE5X2wxMQppbnRjXzAgLy8gMAppbXBsXzE5X2w0OgpzdG9yZSAxMwpsb2FkIDEyCmZyYW1lX2RpZyAtMgpmcmFtZV9kaWcgLTEKbGVuCisKaW50Y18xIC8vIDEyNwovCj09CmJueiBpbXBsXzE5X2wxMAppbnRjXzEgLy8gMTI3CmltcGxfMTlfbDY6CnN0b3JlIDE0CmZyYW1lX2RpZyAtMwpieXRlYyA1IC8vIDB4MDAwMTAyCmxvYWQgMTIKaW50Y18yIC8vIDEKZXh0cmFjdDMKbG9hZCAxNAppbnRjXzEgLy8gMTI3CiE9CmxvYWQgMTMKaW50Y18wIC8vIDAKIT0KfHwKYm56IGltcGxfMTlfbDkKaW50Y18xIC8vIDEyNwpzdG9yZSAxNgpmcmFtZV9kaWcgLTEKbG9hZCAxNQppbnRjXzEgLy8gMTI3CmV4dHJhY3QzCmltcGxfMTlfbDg6CmFwcF9sb2NhbF9wdXQKbG9hZCAxNQpsb2FkIDE2CisKc3RvcmUgMTUKbG9hZCAxMgppbnRjXzIgLy8gMQorCnN0b3JlIDEyCmIgaW1wbF8xOV9sMQppbXBsXzE5X2w5Ogpsb2FkIDE0CmxvYWQgMTMKLQpzdG9yZSAxNgpmcmFtZV9kaWcgLTMKYnl0ZWMgNSAvLyAweDAwMDEwMgpsb2FkIDEyCmludGNfMiAvLyAxCmV4dHJhY3QzCmFwcF9sb2NhbF9nZXQKaW50Y18wIC8vIDAKbG9hZCAxMwpzdWJzdHJpbmczCmZyYW1lX2RpZyAtMQpsb2FkIDE1CmxvYWQgMTYKZXh0cmFjdDMKY29uY2F0CmZyYW1lX2RpZyAtMwpieXRlYyA1IC8vIDB4MDAwMTAyCmxvYWQgMTIKaW50Y18yIC8vIDEKZXh0cmFjdDMKYXBwX2xvY2FsX2dldApsb2FkIDE0CmludGNfMSAvLyAxMjcKc3Vic3RyaW5nMwpjb25jYXQKYiBpbXBsXzE5X2w4CmltcGxfMTlfbDEwOgpmcmFtZV9kaWcgLTIKZnJhbWVfZGlnIC0xCmxlbgorCmludGNfMSAvLyAxMjcKJQpiIGltcGxfMTlfbDYKaW1wbF8xOV9sMTE6CmZyYW1lX2RpZyAtMgppbnRjXzEgLy8gMTI3CiUKYiBpbXBsXzE5X2w0CmltcGxfMTlfbDEyOgpyZXRzdWIKCi8vIF9pbXBsCmltcGxfMjA6CnByb3RvIDMgMQpieXRlY18xIC8vICIiCnN0b3JlIDE4CmZyYW1lX2RpZyAtMgppbnRjXzEgLy8gMTI3Ci8Kc3RvcmUgMTcKaW1wbF8yMF9sMToKbG9hZCAxNwpmcmFtZV9kaWcgLTEKaW50Y18xIC8vIDEyNwovCjw9CmJ6IGltcGxfMjBfbDkKbG9hZCAxNwpmcmFtZV9kaWcgLTIKaW50Y18xIC8vIDEyNwovCj09CmJueiBpbXBsXzIwX2w4CmludGNfMCAvLyAwCmltcGxfMjBfbDQ6CnN0b3JlIDE5CmxvYWQgMTcKZnJhbWVfZGlnIC0xCmludGNfMSAvLyAxMjcKLwo9PQpibnogaW1wbF8yMF9sNwppbnRjXzEgLy8gMTI3CmltcGxfMjBfbDY6CnN0b3JlIDIwCmxvYWQgMTgKZnJhbWVfZGlnIC0zCmJ5dGVjIDUgLy8gMHgwMDAxMDIKbG9hZCAxNwppbnRjXzIgLy8gMQpleHRyYWN0MwphcHBfbG9jYWxfZ2V0CmxvYWQgMTkKbG9hZCAyMApzdWJzdHJpbmczCmNvbmNhdApzdG9yZSAxOApsb2FkIDE3CmludGNfMiAvLyAxCisKc3RvcmUgMTcKYiBpbXBsXzIwX2wxCmltcGxfMjBfbDc6CmZyYW1lX2RpZyAtMQppbnRjXzEgLy8gMTI3CiUKYiBpbXBsXzIwX2w2CmltcGxfMjBfbDg6CmZyYW1lX2RpZyAtMgppbnRjXzEgLy8gMTI3CiUKYiBpbXBsXzIwX2w0CmltcGxfMjBfbDk6CmxvYWQgMTgKcmV0c3ViCgovLyB3cml0ZV9pbXBsCndyaXRlaW1wbF8yMToKcHJvdG8gMiAwCmludGNfMCAvLyAwCnN0b3JlIDI0CmZyYW1lX2RpZyAtMgppbnRjXzEgLy8gMTI3Ci8Kc3RvcmUgMjEKd3JpdGVpbXBsXzIxX2wxOgpsb2FkIDIxCmZyYW1lX2RpZyAtMgpmcmFtZV9kaWcgLTEKbGVuCisKaW50Y18xIC8vIDEyNwovCjw9CmJ6IHdyaXRlaW1wbF8yMV9sMTIKbG9hZCAyMQpmcmFtZV9kaWcgLTIKaW50Y18xIC8vIDEyNwovCj09CmJueiB3cml0ZWltcGxfMjFfbDExCmludGNfMCAvLyAwCndyaXRlaW1wbF8yMV9sNDoKc3RvcmUgMjIKbG9hZCAyMQpmcmFtZV9kaWcgLTIKZnJhbWVfZGlnIC0xCmxlbgorCmludGNfMSAvLyAxMjcKLwo9PQpibnogd3JpdGVpbXBsXzIxX2wxMAppbnRjXzEgLy8gMTI3CndyaXRlaW1wbF8yMV9sNjoKc3RvcmUgMjMKYnl0ZWMgNiAvLyAweDAwMDEwMjAzMDQwNTA2MDcwODA5MGEwYjBjMGQwZTBmCmxvYWQgMjEKaW50Y18yIC8vIDEKZXh0cmFjdDMKbG9hZCAyMwppbnRjXzEgLy8gMTI3CiE9CmxvYWQgMjIKaW50Y18wIC8vIDAKIT0KfHwKYm56IHdyaXRlaW1wbF8yMV9sOQppbnRjXzEgLy8gMTI3CnN0b3JlIDI1CmZyYW1lX2RpZyAtMQpsb2FkIDI0CmludGNfMSAvLyAxMjcKZXh0cmFjdDMKd3JpdGVpbXBsXzIxX2w4OgphcHBfZ2xvYmFsX3B1dApsb2FkIDI0CmxvYWQgMjUKKwpzdG9yZSAyNApsb2FkIDIxCmludGNfMiAvLyAxCisKc3RvcmUgMjEKYiB3cml0ZWltcGxfMjFfbDEKd3JpdGVpbXBsXzIxX2w5Ogpsb2FkIDIzCmxvYWQgMjIKLQpzdG9yZSAyNQpieXRlYyA2IC8vIDB4MDAwMTAyMDMwNDA1MDYwNzA4MDkwYTBiMGMwZDBlMGYKbG9hZCAyMQppbnRjXzIgLy8gMQpleHRyYWN0MwphcHBfZ2xvYmFsX2dldAppbnRjXzAgLy8gMApsb2FkIDIyCnN1YnN0cmluZzMKZnJhbWVfZGlnIC0xCmxvYWQgMjQKbG9hZCAyNQpleHRyYWN0Mwpjb25jYXQKYnl0ZWMgNiAvLyAweDAwMDEwMjAzMDQwNTA2MDcwODA5MGEwYjBjMGQwZTBmCmxvYWQgMjEKaW50Y18yIC8vIDEKZXh0cmFjdDMKYXBwX2dsb2JhbF9nZXQKbG9hZCAyMwppbnRjXzEgLy8gMTI3CnN1YnN0cmluZzMKY29uY2F0CmIgd3JpdGVpbXBsXzIxX2w4CndyaXRlaW1wbF8yMV9sMTA6CmZyYW1lX2RpZyAtMgpmcmFtZV9kaWcgLTEKbGVuCisKaW50Y18xIC8vIDEyNwolCmIgd3JpdGVpbXBsXzIxX2w2CndyaXRlaW1wbF8yMV9sMTE6CmZyYW1lX2RpZyAtMgppbnRjXzEgLy8gMTI3CiUKYiB3cml0ZWltcGxfMjFfbDQKd3JpdGVpbXBsXzIxX2wxMjoKcmV0c3ViCgovLyByZWFkX2ltcGwKcmVhZGltcGxfMjI6CnByb3RvIDIgMQpieXRlY18xIC8vICIiCnN0b3JlIDI3CmZyYW1lX2RpZyAtMgppbnRjXzEgLy8gMTI3Ci8Kc3RvcmUgMjYKcmVhZGltcGxfMjJfbDE6CmxvYWQgMjYKZnJhbWVfZGlnIC0xCmludGNfMSAvLyAxMjcKLwo8PQpieiByZWFkaW1wbF8yMl9sOQpsb2FkIDI2CmZyYW1lX2RpZyAtMgppbnRjXzEgLy8gMTI3Ci8KPT0KYm56IHJlYWRpbXBsXzIyX2w4CmludGNfMCAvLyAwCnJlYWRpbXBsXzIyX2w0OgpzdG9yZSAyOApsb2FkIDI2CmZyYW1lX2RpZyAtMQppbnRjXzEgLy8gMTI3Ci8KPT0KYm56IHJlYWRpbXBsXzIyX2w3CmludGNfMSAvLyAxMjcKcmVhZGltcGxfMjJfbDY6CnN0b3JlIDI5CmxvYWQgMjcKYnl0ZWMgNiAvLyAweDAwMDEwMjAzMDQwNTA2MDcwODA5MGEwYjBjMGQwZTBmCmxvYWQgMjYKaW50Y18yIC8vIDEKZXh0cmFjdDMKYXBwX2dsb2JhbF9nZXQKbG9hZCAyOApsb2FkIDI5CnN1YnN0cmluZzMKY29uY2F0CnN0b3JlIDI3CmxvYWQgMjYKaW50Y18yIC8vIDEKKwpzdG9yZSAyNgpiIHJlYWRpbXBsXzIyX2wxCnJlYWRpbXBsXzIyX2w3OgpmcmFtZV9kaWcgLTEKaW50Y18xIC8vIDEyNwolCmIgcmVhZGltcGxfMjJfbDYKcmVhZGltcGxfMjJfbDg6CmZyYW1lX2RpZyAtMgppbnRjXzEgLy8gMTI3CiUKYiByZWFkaW1wbF8yMl9sNApyZWFkaW1wbF8yMl9sOToKbG9hZCAyNwpyZXRzdWI=", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDgKaW50Y2Jsb2NrIDAgMTI3IDEKYnl0ZWNibG9jayAweDE1MWY3Yzc1IDB4IDB4MDAgMHg2NDY1NjM2YzYxNzI2NTY0NWY2MTcwNzA1Zjc2NjE2Yzc1NjUgMHg2NDY1NjM2YzYxNzI2NTY0NWY2MTYzNjM2Zjc1NmU3NDVmNzY2MTZjNzU2NSAweDAwMDEwMjAzMDQwNTA2MDcwODA5MGEwYjBjMGQwZTBmIDB4MDAwMTAyCnR4biBOdW1BcHBBcmdzCmludGNfMCAvLyAwCj09CmJueiBtYWluX2wyOAp0eG5hIEFwcGxpY2F0aW9uQXJncyAwCnB1c2hieXRlcyAweGFhNmExZDc5IC8vICJ3cml0ZV9hY2N0X2Jsb2Ioc3RyaW5nKXZvaWQiCj09CmJueiBtYWluX2wyNwp0eG5hIEFwcGxpY2F0aW9uQXJncyAwCnB1c2hieXRlcyAweDVhMjM0YTkwIC8vICJyZWFkX2FjY3RfYmxvYigpYnl0ZVtdIgo9PQpibnogbWFpbl9sMjYKdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMApwdXNoYnl0ZXMgMHgzZWIyNDVmYSAvLyAid3JpdGVfYXBwX2Jsb2Ioc3RyaW5nKXZvaWQiCj09CmJueiBtYWluX2wyNQp0eG5hIEFwcGxpY2F0aW9uQXJncyAwCnB1c2hieXRlcyAweGQ1Yzk1ZjZjIC8vICJyZWFkX2FwcF9ibG9iKClieXRlW10iCj09CmJueiBtYWluX2wyNAp0eG5hIEFwcGxpY2F0aW9uQXJncyAwCnB1c2hieXRlcyAweDI5ZDk0NzBmIC8vICJzZXRfYXBwX3N0YXRlX3ZhbChzdHJpbmcpdm9pZCIKPT0KYm56IG1haW5fbDIzCnR4bmEgQXBwbGljYXRpb25BcmdzIDAKcHVzaGJ5dGVzIDB4ZjRjMjI1NjYgLy8gImdldF9hcHBfc3RhdGVfdmFsKClzdHJpbmciCj09CmJueiBtYWluX2wyMgp0eG5hIEFwcGxpY2F0aW9uQXJncyAwCnB1c2hieXRlcyAweDA2YmM4NjA0IC8vICJzZXRfcmVzZXJ2ZWRfYXBwX3N0YXRlX3ZhbCh1aW50OCx1aW50NjQpdm9pZCIKPT0KYm56IG1haW5fbDIxCnR4bmEgQXBwbGljYXRpb25BcmdzIDAKcHVzaGJ5dGVzIDB4ZTk4NGUzYzMgLy8gImdldF9yZXNlcnZlZF9hcHBfc3RhdGVfdmFsKHVpbnQ4KXVpbnQ2NCIKPT0KYm56IG1haW5fbDIwCnR4bmEgQXBwbGljYXRpb25BcmdzIDAKcHVzaGJ5dGVzIDB4ZmU2MGI1MmEgLy8gInNldF9hY2NvdW50X3N0YXRlX3ZhbCh1aW50NjQpdm9pZCIKPT0KYm56IG1haW5fbDE5CnR4bmEgQXBwbGljYXRpb25BcmdzIDAKcHVzaGJ5dGVzIDB4YjhkYzliNTkgLy8gImluY3JfYWNjb3VudF9zdGF0ZV92YWwodWludDY0KXZvaWQiCj09CmJueiBtYWluX2wxOAp0eG5hIEFwcGxpY2F0aW9uQXJncyAwCnB1c2hieXRlcyAweDVhOThmMzcyIC8vICJnZXRfYWNjb3VudF9zdGF0ZV92YWwoKXVpbnQ2NCIKPT0KYm56IG1haW5fbDE3CnR4bmEgQXBwbGljYXRpb25BcmdzIDAKcHVzaGJ5dGVzIDB4ZTZlNjBhZGUgLy8gInNldF9yZXNlcnZlZF9hY2NvdW50X3N0YXRlX3ZhbCh1aW50OCxzdHJpbmcpdm9pZCIKPT0KYm56IG1haW5fbDE2CnR4bmEgQXBwbGljYXRpb25BcmdzIDAKcHVzaGJ5dGVzIDB4Y2JhMzM3N2UgLy8gImdldF9yZXNlcnZlZF9hY2NvdW50X3N0YXRlX3ZhbCh1aW50OClzdHJpbmciCj09CmJueiBtYWluX2wxNQplcnIKbWFpbl9sMTU6CnR4biBPbkNvbXBsZXRpb24KaW50Y18wIC8vIE5vT3AKPT0KdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18wIC8vIDAKIT0KJiYKYXNzZXJ0CnR4bmEgQXBwbGljYXRpb25BcmdzIDEKaW50Y18wIC8vIDAKZ2V0Ynl0ZQpjYWxsc3ViIGdldHJlc2VydmVkYWNjb3VudHN0YXRldmFsXzIyCnN0b3JlIDI5CmJ5dGVjXzAgLy8gMHgxNTFmN2M3NQpsb2FkIDI5CmNvbmNhdApsb2cKaW50Y18yIC8vIDEKcmV0dXJuCm1haW5fbDE2Ogp0eG4gT25Db21wbGV0aW9uCmludGNfMCAvLyBOb09wCj09CnR4biBBcHBsaWNhdGlvbklECmludGNfMCAvLyAwCiE9CiYmCmFzc2VydAp0eG5hIEFwcGxpY2F0aW9uQXJncyAxCmludGNfMCAvLyAwCmdldGJ5dGUKc3RvcmUgMjcKdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgpzdG9yZSAyOApsb2FkIDI3CmxvYWQgMjgKY2FsbHN1YiBzZXRyZXNlcnZlZGFjY291bnRzdGF0ZXZhbF8yMQppbnRjXzIgLy8gMQpyZXR1cm4KbWFpbl9sMTc6CnR4biBPbkNvbXBsZXRpb24KaW50Y18wIC8vIE5vT3AKPT0KdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18wIC8vIDAKIT0KJiYKYXNzZXJ0CmNhbGxzdWIgZ2V0YWNjb3VudHN0YXRldmFsXzIwCnN0b3JlIDI2CmJ5dGVjXzAgLy8gMHgxNTFmN2M3NQpsb2FkIDI2Cml0b2IKY29uY2F0CmxvZwppbnRjXzIgLy8gMQpyZXR1cm4KbWFpbl9sMTg6CnR4biBPbkNvbXBsZXRpb24KaW50Y18wIC8vIE5vT3AKPT0KdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18wIC8vIDAKIT0KJiYKYXNzZXJ0CnR4bmEgQXBwbGljYXRpb25BcmdzIDEKYnRvaQpjYWxsc3ViIGluY3JhY2NvdW50c3RhdGV2YWxfMTkKaW50Y18yIC8vIDEKcmV0dXJuCm1haW5fbDE5Ogp0eG4gT25Db21wbGV0aW9uCmludGNfMCAvLyBOb09wCj09CnR4biBBcHBsaWNhdGlvbklECmludGNfMCAvLyAwCiE9CiYmCmFzc2VydAp0eG5hIEFwcGxpY2F0aW9uQXJncyAxCmJ0b2kKY2FsbHN1YiBzZXRhY2NvdW50c3RhdGV2YWxfMTgKaW50Y18yIC8vIDEKcmV0dXJuCm1haW5fbDIwOgp0eG4gT25Db21wbGV0aW9uCmludGNfMCAvLyBOb09wCj09CnR4biBBcHBsaWNhdGlvbklECmludGNfMCAvLyAwCiE9CiYmCmFzc2VydAp0eG5hIEFwcGxpY2F0aW9uQXJncyAxCmludGNfMCAvLyAwCmdldGJ5dGUKY2FsbHN1YiBnZXRyZXNlcnZlZGFwcHN0YXRldmFsXzE3CnN0b3JlIDI1CmJ5dGVjXzAgLy8gMHgxNTFmN2M3NQpsb2FkIDI1Cml0b2IKY29uY2F0CmxvZwppbnRjXzIgLy8gMQpyZXR1cm4KbWFpbl9sMjE6CnR4biBPbkNvbXBsZXRpb24KaW50Y18wIC8vIE5vT3AKPT0KdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18wIC8vIDAKIT0KJiYKYXNzZXJ0CnR4bmEgQXBwbGljYXRpb25BcmdzIDEKaW50Y18wIC8vIDAKZ2V0Ynl0ZQpzdG9yZSAyMwp0eG5hIEFwcGxpY2F0aW9uQXJncyAyCmJ0b2kKc3RvcmUgMjQKbG9hZCAyMwpsb2FkIDI0CmNhbGxzdWIgc2V0cmVzZXJ2ZWRhcHBzdGF0ZXZhbF8xNgppbnRjXzIgLy8gMQpyZXR1cm4KbWFpbl9sMjI6CnR4biBPbkNvbXBsZXRpb24KaW50Y18wIC8vIE5vT3AKPT0KdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18wIC8vIDAKIT0KJiYKYXNzZXJ0CmNhbGxzdWIgZ2V0YXBwc3RhdGV2YWxfMTUKc3RvcmUgMjIKYnl0ZWNfMCAvLyAweDE1MWY3Yzc1CmxvYWQgMjIKY29uY2F0CmxvZwppbnRjXzIgLy8gMQpyZXR1cm4KbWFpbl9sMjM6CnR4biBPbkNvbXBsZXRpb24KaW50Y18wIC8vIE5vT3AKPT0KdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18wIC8vIDAKIT0KJiYKYXNzZXJ0CnR4bmEgQXBwbGljYXRpb25BcmdzIDEKY2FsbHN1YiBzZXRhcHBzdGF0ZXZhbF8xNAppbnRjXzIgLy8gMQpyZXR1cm4KbWFpbl9sMjQ6CnR4biBPbkNvbXBsZXRpb24KaW50Y18wIC8vIE5vT3AKPT0KdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18wIC8vIDAKIT0KJiYKYXNzZXJ0CmNhbGxzdWIgcmVhZGFwcGJsb2JfMTMKc3RvcmUgMjEKYnl0ZWNfMCAvLyAweDE1MWY3Yzc1CmxvYWQgMjEKY29uY2F0CmxvZwppbnRjXzIgLy8gMQpyZXR1cm4KbWFpbl9sMjU6CnR4biBPbkNvbXBsZXRpb24KaW50Y18wIC8vIE5vT3AKPT0KdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18wIC8vIDAKIT0KJiYKYXNzZXJ0CnR4bmEgQXBwbGljYXRpb25BcmdzIDEKY2FsbHN1YiB3cml0ZWFwcGJsb2JfMTIKaW50Y18yIC8vIDEKcmV0dXJuCm1haW5fbDI2Ogp0eG4gT25Db21wbGV0aW9uCmludGNfMCAvLyBOb09wCj09CnR4biBBcHBsaWNhdGlvbklECmludGNfMCAvLyAwCiE9CiYmCmFzc2VydApjYWxsc3ViIHJlYWRhY2N0YmxvYl8xMQpzdG9yZSAyMApieXRlY18wIC8vIDB4MTUxZjdjNzUKbG9hZCAyMApjb25jYXQKbG9nCmludGNfMiAvLyAxCnJldHVybgptYWluX2wyNzoKdHhuIE9uQ29tcGxldGlvbgppbnRjXzAgLy8gTm9PcAo9PQp0eG4gQXBwbGljYXRpb25JRAppbnRjXzAgLy8gMAohPQomJgphc3NlcnQKdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQpjYWxsc3ViIHdyaXRlYWNjdGJsb2JfMTAKaW50Y18yIC8vIDEKcmV0dXJuCm1haW5fbDI4Ogp0eG4gT25Db21wbGV0aW9uCmludGNfMCAvLyBOb09wCj09CmJueiBtYWluX2wzMgp0eG4gT25Db21wbGV0aW9uCmludGNfMiAvLyBPcHRJbgo9PQpibnogbWFpbl9sMzEKZXJyCm1haW5fbDMxOgp0eG4gQXBwbGljYXRpb25JRAppbnRjXzAgLy8gMAohPQphc3NlcnQKY2FsbHN1YiBvcHRpbl83CmludGNfMiAvLyAxCnJldHVybgptYWluX2wzMjoKdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18wIC8vIDAKPT0KYXNzZXJ0CmNhbGxzdWIgY3JlYXRlXzYKaW50Y18yIC8vIDEKcmV0dXJuCgovLyB6ZXJvX2ltcGwKemVyb2ltcGxfMDoKcHJvdG8gMCAwCmludGNfMSAvLyAxMjcKYnplcm8KcHVzaGludCAxNiAvLyAxNgoKICAgIHplcm9fbG9vcDoKICAgICAgICBpbnQgMQogICAgICAgIC0gICAgICAgICAgICAgICAvLyBbIjAwIipwYWdlX3NpemUsIGtleS0xXQogICAgICAgIGR1cDIgICAgICAgICAgICAvLyBbIjAwIipwYWdlX3NpemUsIGtleSwgIjAwIipwYWdlX3NpemUsIGtleV0KICAgICAgICBpdG9iICAgICAgICAgICAgLy8gWyIwMCIqcGFnZV9zaXplLCBrZXksICIwMCIqcGFnZV9zaXplLCBpdG9iKGtleSldCiAgICAgICAgZXh0cmFjdCA3IDEgICAgIC8vIFsiMDAiKnBhZ2Vfc2l6ZSwga2V5LCAiMDAiKnBhZ2Vfc2l6ZSwgaXRvYihrZXkpWy0xXV0KICAgICAgICBzd2FwICAgICAgICAgICAgLy8gWyIwMCIqcGFnZV9zaXplLCBrZXksIGl0b2Ioa2V5KVstMV0sICIwMCIqcGFnZV9zaXplXQogICAgICAgIGFwcF9nbG9iYWxfcHV0ICAvLyBbIjAwIipwYWdlX3NpemUsIGtleV0gIChyZW1vdmVzIHRvcCAyIGVsZW1lbnRzKQogICAgICAgIGR1cCAgICAgICAgICAgICAvLyBbIjAwIipwYWdlX3NpemUsIGtleS0xLCBrZXktMV0KICAgICAgICBibnogemVyb19sb29wICAgLy8gc3RhcnQgbG9vcCBvdmVyIGlmIGtleS0xPjAKICAgICAgICBwb3AKICAgICAgICBwb3AgICAgICAgICAgICAgLy8gdGFrZSBleHRyYSBqdW5rIG9mZiB0aGUgc3RhY2sKICAgICAgICByZXRzdWIKICAgIGNhbGxzdWIgemVyb19sb29wCiAgICAgICAgICAgIApyZXRzdWIKCi8vIHJlYWRfaW1wbApyZWFkaW1wbF8xOgpwcm90byAyIDEKYnl0ZWNfMSAvLyAiIgpzdG9yZSAxNwpmcmFtZV9kaWcgLTIKaW50Y18xIC8vIDEyNwovCnN0b3JlIDE2CnJlYWRpbXBsXzFfbDE6CmxvYWQgMTYKZnJhbWVfZGlnIC0xCmludGNfMSAvLyAxMjcKLwo8PQpieiByZWFkaW1wbF8xX2w5CmxvYWQgMTYKZnJhbWVfZGlnIC0yCmludGNfMSAvLyAxMjcKLwo9PQpibnogcmVhZGltcGxfMV9sOAppbnRjXzAgLy8gMApyZWFkaW1wbF8xX2w0OgpzdG9yZSAxOApsb2FkIDE2CmZyYW1lX2RpZyAtMQppbnRjXzEgLy8gMTI3Ci8KPT0KYm56IHJlYWRpbXBsXzFfbDcKaW50Y18xIC8vIDEyNwpyZWFkaW1wbF8xX2w2OgpzdG9yZSAxOQpsb2FkIDE3CmJ5dGVjIDUgLy8gMHgwMDAxMDIwMzA0MDUwNjA3MDgwOTBhMGIwYzBkMGUwZgpsb2FkIDE2CmludGNfMiAvLyAxCmV4dHJhY3QzCmFwcF9nbG9iYWxfZ2V0CmxvYWQgMTgKbG9hZCAxOQpzdWJzdHJpbmczCmNvbmNhdApzdG9yZSAxNwpsb2FkIDE2CmludGNfMiAvLyAxCisKc3RvcmUgMTYKYiByZWFkaW1wbF8xX2wxCnJlYWRpbXBsXzFfbDc6CmZyYW1lX2RpZyAtMQppbnRjXzEgLy8gMTI3CiUKYiByZWFkaW1wbF8xX2w2CnJlYWRpbXBsXzFfbDg6CmZyYW1lX2RpZyAtMgppbnRjXzEgLy8gMTI3CiUKYiByZWFkaW1wbF8xX2w0CnJlYWRpbXBsXzFfbDk6CmxvYWQgMTcKcmV0c3ViCgovLyB3cml0ZV9pbXBsCndyaXRlaW1wbF8yOgpwcm90byAyIDAKaW50Y18wIC8vIDAKc3RvcmUgMTQKZnJhbWVfZGlnIC0yCmludGNfMSAvLyAxMjcKLwpzdG9yZSAxMQp3cml0ZWltcGxfMl9sMToKbG9hZCAxMQpmcmFtZV9kaWcgLTIKZnJhbWVfZGlnIC0xCmxlbgorCmludGNfMSAvLyAxMjcKLwo8PQpieiB3cml0ZWltcGxfMl9sMTIKbG9hZCAxMQpmcmFtZV9kaWcgLTIKaW50Y18xIC8vIDEyNwovCj09CmJueiB3cml0ZWltcGxfMl9sMTEKaW50Y18wIC8vIDAKd3JpdGVpbXBsXzJfbDQ6CnN0b3JlIDEyCmxvYWQgMTEKZnJhbWVfZGlnIC0yCmZyYW1lX2RpZyAtMQpsZW4KKwppbnRjXzEgLy8gMTI3Ci8KPT0KYm56IHdyaXRlaW1wbF8yX2wxMAppbnRjXzEgLy8gMTI3CndyaXRlaW1wbF8yX2w2OgpzdG9yZSAxMwpieXRlYyA1IC8vIDB4MDAwMTAyMDMwNDA1MDYwNzA4MDkwYTBiMGMwZDBlMGYKbG9hZCAxMQppbnRjXzIgLy8gMQpleHRyYWN0Mwpsb2FkIDEzCmludGNfMSAvLyAxMjcKIT0KbG9hZCAxMgppbnRjXzAgLy8gMAohPQp8fApibnogd3JpdGVpbXBsXzJfbDkKaW50Y18xIC8vIDEyNwpzdG9yZSAxNQpmcmFtZV9kaWcgLTEKbG9hZCAxNAppbnRjXzEgLy8gMTI3CmV4dHJhY3QzCndyaXRlaW1wbF8yX2w4OgphcHBfZ2xvYmFsX3B1dApsb2FkIDE0CmxvYWQgMTUKKwpzdG9yZSAxNApsb2FkIDExCmludGNfMiAvLyAxCisKc3RvcmUgMTEKYiB3cml0ZWltcGxfMl9sMQp3cml0ZWltcGxfMl9sOToKbG9hZCAxMwpsb2FkIDEyCi0Kc3RvcmUgMTUKYnl0ZWMgNSAvLyAweDAwMDEwMjAzMDQwNTA2MDcwODA5MGEwYjBjMGQwZTBmCmxvYWQgMTEKaW50Y18yIC8vIDEKZXh0cmFjdDMKYXBwX2dsb2JhbF9nZXQKaW50Y18wIC8vIDAKbG9hZCAxMgpzdWJzdHJpbmczCmZyYW1lX2RpZyAtMQpsb2FkIDE0CmxvYWQgMTUKZXh0cmFjdDMKY29uY2F0CmJ5dGVjIDUgLy8gMHgwMDAxMDIwMzA0MDUwNjA3MDgwOTBhMGIwYzBkMGUwZgpsb2FkIDExCmludGNfMiAvLyAxCmV4dHJhY3QzCmFwcF9nbG9iYWxfZ2V0CmxvYWQgMTMKaW50Y18xIC8vIDEyNwpzdWJzdHJpbmczCmNvbmNhdApiIHdyaXRlaW1wbF8yX2w4CndyaXRlaW1wbF8yX2wxMDoKZnJhbWVfZGlnIC0yCmZyYW1lX2RpZyAtMQpsZW4KKwppbnRjXzEgLy8gMTI3CiUKYiB3cml0ZWltcGxfMl9sNgp3cml0ZWltcGxfMl9sMTE6CmZyYW1lX2RpZyAtMgppbnRjXzEgLy8gMTI3CiUKYiB3cml0ZWltcGxfMl9sNAp3cml0ZWltcGxfMl9sMTI6CnJldHN1YgoKLy8gemVyb19pbXBsCnplcm9pbXBsXzM6CnByb3RvIDEgMApmcmFtZV9kaWcgLTEKYnl0ZWNfMiAvLyAweDAwCmludGNfMSAvLyAxMjcKYnplcm8KYXBwX2xvY2FsX3B1dApmcmFtZV9kaWcgLTEKcHVzaGJ5dGVzIDB4MDEgLy8gMHgwMQppbnRjXzEgLy8gMTI3CmJ6ZXJvCmFwcF9sb2NhbF9wdXQKZnJhbWVfZGlnIC0xCnB1c2hieXRlcyAweDAyIC8vIDB4MDIKaW50Y18xIC8vIDEyNwpiemVybwphcHBfbG9jYWxfcHV0CnJldHN1YgoKLy8gcmVhZF9pbXBsCnJlYWRpbXBsXzQ6CnByb3RvIDMgMQpieXRlY18xIC8vICIiCnN0b3JlIDgKZnJhbWVfZGlnIC0yCmludGNfMSAvLyAxMjcKLwpzdG9yZSA3CnJlYWRpbXBsXzRfbDE6CmxvYWQgNwpmcmFtZV9kaWcgLTEKaW50Y18xIC8vIDEyNwovCjw9CmJ6IHJlYWRpbXBsXzRfbDkKbG9hZCA3CmZyYW1lX2RpZyAtMgppbnRjXzEgLy8gMTI3Ci8KPT0KYm56IHJlYWRpbXBsXzRfbDgKaW50Y18wIC8vIDAKcmVhZGltcGxfNF9sNDoKc3RvcmUgOQpsb2FkIDcKZnJhbWVfZGlnIC0xCmludGNfMSAvLyAxMjcKLwo9PQpibnogcmVhZGltcGxfNF9sNwppbnRjXzEgLy8gMTI3CnJlYWRpbXBsXzRfbDY6CnN0b3JlIDEwCmxvYWQgOApmcmFtZV9kaWcgLTMKYnl0ZWMgNiAvLyAweDAwMDEwMgpsb2FkIDcKaW50Y18yIC8vIDEKZXh0cmFjdDMKYXBwX2xvY2FsX2dldApsb2FkIDkKbG9hZCAxMApzdWJzdHJpbmczCmNvbmNhdApzdG9yZSA4CmxvYWQgNwppbnRjXzIgLy8gMQorCnN0b3JlIDcKYiByZWFkaW1wbF80X2wxCnJlYWRpbXBsXzRfbDc6CmZyYW1lX2RpZyAtMQppbnRjXzEgLy8gMTI3CiUKYiByZWFkaW1wbF80X2w2CnJlYWRpbXBsXzRfbDg6CmZyYW1lX2RpZyAtMgppbnRjXzEgLy8gMTI3CiUKYiByZWFkaW1wbF80X2w0CnJlYWRpbXBsXzRfbDk6CmxvYWQgOApyZXRzdWIKCi8vIHdyaXRlX2ltcGwKd3JpdGVpbXBsXzU6CnByb3RvIDMgMAppbnRjXzAgLy8gMApzdG9yZSA1CmZyYW1lX2RpZyAtMgppbnRjXzEgLy8gMTI3Ci8Kc3RvcmUgMgp3cml0ZWltcGxfNV9sMToKbG9hZCAyCmZyYW1lX2RpZyAtMgpmcmFtZV9kaWcgLTEKbGVuCisKaW50Y18xIC8vIDEyNwovCjw9CmJ6IHdyaXRlaW1wbF81X2wxMgpsb2FkIDIKZnJhbWVfZGlnIC0yCmludGNfMSAvLyAxMjcKLwo9PQpibnogd3JpdGVpbXBsXzVfbDExCmludGNfMCAvLyAwCndyaXRlaW1wbF81X2w0OgpzdG9yZSAzCmxvYWQgMgpmcmFtZV9kaWcgLTIKZnJhbWVfZGlnIC0xCmxlbgorCmludGNfMSAvLyAxMjcKLwo9PQpibnogd3JpdGVpbXBsXzVfbDEwCmludGNfMSAvLyAxMjcKd3JpdGVpbXBsXzVfbDY6CnN0b3JlIDQKZnJhbWVfZGlnIC0zCmJ5dGVjIDYgLy8gMHgwMDAxMDIKbG9hZCAyCmludGNfMiAvLyAxCmV4dHJhY3QzCmxvYWQgNAppbnRjXzEgLy8gMTI3CiE9CmxvYWQgMwppbnRjXzAgLy8gMAohPQp8fApibnogd3JpdGVpbXBsXzVfbDkKaW50Y18xIC8vIDEyNwpzdG9yZSA2CmZyYW1lX2RpZyAtMQpsb2FkIDUKaW50Y18xIC8vIDEyNwpleHRyYWN0Mwp3cml0ZWltcGxfNV9sODoKYXBwX2xvY2FsX3B1dApsb2FkIDUKbG9hZCA2CisKc3RvcmUgNQpsb2FkIDIKaW50Y18yIC8vIDEKKwpzdG9yZSAyCmIgd3JpdGVpbXBsXzVfbDEKd3JpdGVpbXBsXzVfbDk6CmxvYWQgNApsb2FkIDMKLQpzdG9yZSA2CmZyYW1lX2RpZyAtMwpieXRlYyA2IC8vIDB4MDAwMTAyCmxvYWQgMgppbnRjXzIgLy8gMQpleHRyYWN0MwphcHBfbG9jYWxfZ2V0CmludGNfMCAvLyAwCmxvYWQgMwpzdWJzdHJpbmczCmZyYW1lX2RpZyAtMQpsb2FkIDUKbG9hZCA2CmV4dHJhY3QzCmNvbmNhdApmcmFtZV9kaWcgLTMKYnl0ZWMgNiAvLyAweDAwMDEwMgpsb2FkIDIKaW50Y18yIC8vIDEKZXh0cmFjdDMKYXBwX2xvY2FsX2dldApsb2FkIDQKaW50Y18xIC8vIDEyNwpzdWJzdHJpbmczCmNvbmNhdApiIHdyaXRlaW1wbF81X2w4CndyaXRlaW1wbF81X2wxMDoKZnJhbWVfZGlnIC0yCmZyYW1lX2RpZyAtMQpsZW4KKwppbnRjXzEgLy8gMTI3CiUKYiB3cml0ZWltcGxfNV9sNgp3cml0ZWltcGxfNV9sMTE6CmZyYW1lX2RpZyAtMgppbnRjXzEgLy8gMTI3CiUKYiB3cml0ZWltcGxfNV9sNAp3cml0ZWltcGxfNV9sMTI6CnJldHN1YgoKLy8gY3JlYXRlCmNyZWF0ZV82Ogpwcm90byAwIDAKaW50Y18wIC8vIDAKYnl0ZWNfMyAvLyAiZGVjbGFyZWRfYXBwX3ZhbHVlIgphcHBfZ2xvYmFsX2dldF9leApzdG9yZSAxCnN0b3JlIDAKbG9hZCAxCiEKYXNzZXJ0CmJ5dGVjXzMgLy8gImRlY2xhcmVkX2FwcF92YWx1ZSIKcHVzaGJ5dGVzIDB4NDEyMDY0NjU2MzZjNjE3MjY1NjQyMDczNzQ2MTc0NjUyMDc2NjE2Yzc1NjUyMDc0Njg2MTc0MjA2OTczMjA3MDcyNmY3NDY1NjM3NDY1NjQyMDc3Njk3NDY4MjA3NDY4NjUyMDYwNzM3NDYxNzQ2OTYzNjAyMDY2NmM2MTY3IC8vICJBIGRlY2xhcmVkIHN0YXRlIHZhbHVlIHRoYXQgaXMgcHJvdGVjdGVkIHdpdGggdGhlIGBzdGF0aWNgIGZsYWciCmFwcF9nbG9iYWxfcHV0CmNhbGxzdWIgemVyb2ltcGxfMApyZXRzdWIKCi8vIG9wdF9pbgpvcHRpbl83Ogpwcm90byAwIDAKdHhuIFNlbmRlcgpieXRlYyA0IC8vICJkZWNsYXJlZF9hY2NvdW50X3ZhbHVlIgppbnRjXzIgLy8gMQphcHBfbG9jYWxfcHV0CnR4biBTZW5kZXIKY2FsbHN1YiB6ZXJvaW1wbF8zCnJldHN1YgoKLy8gcHJlZml4X2tleV9nZW4KcHJlZml4a2V5Z2VuXzg6CnByb3RvIDEgMQpwdXNoYnl0ZXMgMHg3MjY1NzM2NTcyNzY2NTY0NWY2MTcwNzA1Zjc2NjE2Yzc1NjUgLy8gInJlc2VydmVkX2FwcF92YWx1ZSIKZnJhbWVfZGlnIC0xCmNvbmNhdApyZXRzdWIKCi8vIHByZWZpeF9rZXlfZ2VuCnByZWZpeGtleWdlbl85Ogpwcm90byAxIDEKcHVzaGJ5dGVzIDB4NzI2NTczNjU3Mjc2NjU2NDVmNjE2MzYzNmY3NTZlNzQ1Zjc2NjE2Yzc1NjUgLy8gInJlc2VydmVkX2FjY291bnRfdmFsdWUiCmZyYW1lX2RpZyAtMQpjb25jYXQKcmV0c3ViCgovLyB3cml0ZV9hY2N0X2Jsb2IKd3JpdGVhY2N0YmxvYl8xMDoKcHJvdG8gMSAwCnR4biBTZW5kZXIKaW50Y18wIC8vIDAKZnJhbWVfZGlnIC0xCmV4dHJhY3QgMiAwCmNhbGxzdWIgd3JpdGVpbXBsXzUKcmV0c3ViCgovLyByZWFkX2FjY3RfYmxvYgpyZWFkYWNjdGJsb2JfMTE6CnByb3RvIDAgMQpieXRlY18xIC8vICIiCnR4biBTZW5kZXIKaW50Y18wIC8vIDAKcHVzaGludCAzODEgLy8gMzgxCmludGNfMiAvLyAxCi0KY2FsbHN1YiByZWFkaW1wbF80CmZyYW1lX2J1cnkgMApmcmFtZV9kaWcgMApsZW4KaXRvYgpleHRyYWN0IDYgMApmcmFtZV9kaWcgMApjb25jYXQKZnJhbWVfYnVyeSAwCnJldHN1YgoKLy8gd3JpdGVfYXBwX2Jsb2IKd3JpdGVhcHBibG9iXzEyOgpwcm90byAxIDAKaW50Y18wIC8vIDAKZnJhbWVfZGlnIC0xCmV4dHJhY3QgMiAwCmNhbGxzdWIgd3JpdGVpbXBsXzIKcmV0c3ViCgovLyByZWFkX2FwcF9ibG9iCnJlYWRhcHBibG9iXzEzOgpwcm90byAwIDEKYnl0ZWNfMSAvLyAiIgppbnRjXzAgLy8gMApwdXNoaW50IDIwMzIgLy8gMjAzMgppbnRjXzIgLy8gMQotCmNhbGxzdWIgcmVhZGltcGxfMQpmcmFtZV9idXJ5IDAKZnJhbWVfZGlnIDAKbGVuCml0b2IKZXh0cmFjdCA2IDAKZnJhbWVfZGlnIDAKY29uY2F0CmZyYW1lX2J1cnkgMApyZXRzdWIKCi8vIHNldF9hcHBfc3RhdGVfdmFsCnNldGFwcHN0YXRldmFsXzE0Ogpwcm90byAxIDAKaW50Y18wIC8vIDAKYnl0ZWNfMyAvLyAiZGVjbGFyZWRfYXBwX3ZhbHVlIgphcHBfZ2xvYmFsX2dldF9leApzdG9yZSAzMQpzdG9yZSAzMApsb2FkIDMxCiEKYXNzZXJ0CmJ5dGVjXzMgLy8gImRlY2xhcmVkX2FwcF92YWx1ZSIKZnJhbWVfZGlnIC0xCmV4dHJhY3QgMiAwCmFwcF9nbG9iYWxfcHV0CnJldHN1YgoKLy8gZ2V0X2FwcF9zdGF0ZV92YWwKZ2V0YXBwc3RhdGV2YWxfMTU6CnByb3RvIDAgMQpieXRlY18xIC8vICIiCmJ5dGVjXzMgLy8gImRlY2xhcmVkX2FwcF92YWx1ZSIKYXBwX2dsb2JhbF9nZXQKZnJhbWVfYnVyeSAwCmZyYW1lX2RpZyAwCmxlbgppdG9iCmV4dHJhY3QgNiAwCmZyYW1lX2RpZyAwCmNvbmNhdApmcmFtZV9idXJ5IDAKcmV0c3ViCgovLyBzZXRfcmVzZXJ2ZWRfYXBwX3N0YXRlX3ZhbApzZXRyZXNlcnZlZGFwcHN0YXRldmFsXzE2Ogpwcm90byAyIDAKYnl0ZWNfMiAvLyAweDAwCmludGNfMCAvLyAwCmZyYW1lX2RpZyAtMgpzZXRieXRlCmNhbGxzdWIgcHJlZml4a2V5Z2VuXzgKZnJhbWVfZGlnIC0xCmFwcF9nbG9iYWxfcHV0CnJldHN1YgoKLy8gZ2V0X3Jlc2VydmVkX2FwcF9zdGF0ZV92YWwKZ2V0cmVzZXJ2ZWRhcHBzdGF0ZXZhbF8xNzoKcHJvdG8gMSAxCmludGNfMCAvLyAwCmJ5dGVjXzIgLy8gMHgwMAppbnRjXzAgLy8gMApmcmFtZV9kaWcgLTEKc2V0Ynl0ZQpjYWxsc3ViIHByZWZpeGtleWdlbl84CmFwcF9nbG9iYWxfZ2V0CmZyYW1lX2J1cnkgMApyZXRzdWIKCi8vIHNldF9hY2NvdW50X3N0YXRlX3ZhbApzZXRhY2NvdW50c3RhdGV2YWxfMTg6CnByb3RvIDEgMAp0eG4gU2VuZGVyCmJ5dGVjIDQgLy8gImRlY2xhcmVkX2FjY291bnRfdmFsdWUiCmZyYW1lX2RpZyAtMQphcHBfbG9jYWxfcHV0CnJldHN1YgoKLy8gaW5jcl9hY2NvdW50X3N0YXRlX3ZhbAppbmNyYWNjb3VudHN0YXRldmFsXzE5Ogpwcm90byAxIDAKdHhuIFNlbmRlcgpieXRlYyA0IC8vICJkZWNsYXJlZF9hY2NvdW50X3ZhbHVlIgp0eG4gU2VuZGVyCmJ5dGVjIDQgLy8gImRlY2xhcmVkX2FjY291bnRfdmFsdWUiCmFwcF9sb2NhbF9nZXQKZnJhbWVfZGlnIC0xCisKYXBwX2xvY2FsX3B1dApyZXRzdWIKCi8vIGdldF9hY2NvdW50X3N0YXRlX3ZhbApnZXRhY2NvdW50c3RhdGV2YWxfMjA6CnByb3RvIDAgMQppbnRjXzAgLy8gMAp0eG4gU2VuZGVyCmJ5dGVjIDQgLy8gImRlY2xhcmVkX2FjY291bnRfdmFsdWUiCmFwcF9sb2NhbF9nZXQKZnJhbWVfYnVyeSAwCnJldHN1YgoKLy8gc2V0X3Jlc2VydmVkX2FjY291bnRfc3RhdGVfdmFsCnNldHJlc2VydmVkYWNjb3VudHN0YXRldmFsXzIxOgpwcm90byAyIDAKdHhuIFNlbmRlcgpieXRlY18yIC8vIDB4MDAKaW50Y18wIC8vIDAKZnJhbWVfZGlnIC0yCnNldGJ5dGUKY2FsbHN1YiBwcmVmaXhrZXlnZW5fOQpmcmFtZV9kaWcgLTEKZXh0cmFjdCAyIDAKYXBwX2xvY2FsX3B1dApyZXRzdWIKCi8vIGdldF9yZXNlcnZlZF9hY2NvdW50X3N0YXRlX3ZhbApnZXRyZXNlcnZlZGFjY291bnRzdGF0ZXZhbF8yMjoKcHJvdG8gMSAxCmJ5dGVjXzEgLy8gIiIKdHhuIFNlbmRlcgpieXRlY18yIC8vIDB4MDAKaW50Y18wIC8vIDAKZnJhbWVfZGlnIC0xCnNldGJ5dGUKY2FsbHN1YiBwcmVmaXhrZXlnZW5fOQphcHBfbG9jYWxfZ2V0CmZyYW1lX2J1cnkgMApmcmFtZV9kaWcgMApsZW4KaXRvYgpleHRyYWN0IDYgMApmcmFtZV9kaWcgMApjb25jYXQKZnJhbWVfYnVyeSAwCnJldHN1Yg==", "clear": "I3ByYWdtYSB2ZXJzaW9uIDgKcHVzaGludCAwIC8vIDAKcmV0dXJu" }, "schema": { diff --git a/examples/state/StateExample.artifacts/approval.teal b/examples/state/StateExample.artifacts/approval.teal index 81f8a45b..6a604a08 100644 --- a/examples/state/StateExample.artifacts/approval.teal +++ b/examples/state/StateExample.artifacts/approval.teal @@ -1,6 +1,6 @@ #pragma version 8 intcblock 0 127 1 -bytecblock 0x151f7c75 0x 0x6465636c617265645f6170705f76616c7565 0x6465636c617265645f6163636f756e745f76616c7565 0x00 0x000102 0x000102030405060708090a0b0c0d0e0f +bytecblock 0x151f7c75 0x 0x00 0x6465636c617265645f6170705f76616c7565 0x6465636c617265645f6163636f756e745f76616c7565 0x000102030405060708090a0b0c0d0e0f 0x000102 txn NumAppArgs intc_0 // 0 == @@ -70,10 +70,10 @@ assert txna ApplicationArgs 1 intc_0 // 0 getbyte -callsub getreservedaccountstateval_18 -store 11 +callsub getreservedaccountstateval_22 +store 29 bytec_0 // 0x151f7c75 -load 11 +load 29 concat log intc_2 // 1 @@ -90,12 +90,12 @@ assert txna ApplicationArgs 1 intc_0 // 0 getbyte -store 9 +store 27 txna ApplicationArgs 2 -store 10 -load 9 -load 10 -callsub setreservedaccountstateval_17 +store 28 +load 27 +load 28 +callsub setreservedaccountstateval_21 intc_2 // 1 return main_l17: @@ -107,10 +107,10 @@ intc_0 // 0 != && assert -callsub getaccountstateval_16 -store 8 +callsub getaccountstateval_20 +store 26 bytec_0 // 0x151f7c75 -load 8 +load 26 itob concat log @@ -127,7 +127,7 @@ intc_0 // 0 assert txna ApplicationArgs 1 btoi -callsub incraccountstateval_15 +callsub incraccountstateval_19 intc_2 // 1 return main_l19: @@ -141,7 +141,7 @@ intc_0 // 0 assert txna ApplicationArgs 1 btoi -callsub setaccountstateval_14 +callsub setaccountstateval_18 intc_2 // 1 return main_l20: @@ -156,10 +156,10 @@ assert txna ApplicationArgs 1 intc_0 // 0 getbyte -callsub getreservedappstateval_13 -store 7 +callsub getreservedappstateval_17 +store 25 bytec_0 // 0x151f7c75 -load 7 +load 25 itob concat log @@ -177,13 +177,13 @@ assert txna ApplicationArgs 1 intc_0 // 0 getbyte -store 5 +store 23 txna ApplicationArgs 2 btoi -store 6 -load 5 -load 6 -callsub setreservedappstateval_12 +store 24 +load 23 +load 24 +callsub setreservedappstateval_16 intc_2 // 1 return main_l22: @@ -195,10 +195,10 @@ intc_0 // 0 != && assert -callsub getappstateval_11 -store 4 +callsub getappstateval_15 +store 22 bytec_0 // 0x151f7c75 -load 4 +load 22 concat log intc_2 // 1 @@ -213,7 +213,7 @@ intc_0 // 0 && assert txna ApplicationArgs 1 -callsub setappstateval_10 +callsub setappstateval_14 intc_2 // 1 return main_l24: @@ -225,10 +225,10 @@ intc_0 // 0 != && assert -callsub readappblob_9 -store 3 +callsub readappblob_13 +store 21 bytec_0 // 0x151f7c75 -load 3 +load 21 concat log intc_2 // 1 @@ -243,7 +243,7 @@ intc_0 // 0 && assert txna ApplicationArgs 1 -callsub writeappblob_8 +callsub writeappblob_12 intc_2 // 1 return main_l26: @@ -255,10 +255,10 @@ intc_0 // 0 != && assert -callsub readacctblob_7 -store 2 +callsub readacctblob_11 +store 20 bytec_0 // 0x151f7c75 -load 2 +load 20 concat log intc_2 // 1 @@ -273,7 +273,7 @@ intc_0 // 0 && assert txna ApplicationArgs 1 -callsub writeacctblob_6 +callsub writeacctblob_10 intc_2 // 1 return main_l28: @@ -291,7 +291,7 @@ txn ApplicationID intc_0 // 0 != assert -callsub optin_1 +callsub optin_7 intc_2 // 1 return main_l32: @@ -299,56 +299,12 @@ txn ApplicationID intc_0 // 0 == assert -callsub create_0 +callsub create_6 intc_2 // 1 return -// create -create_0: -proto 0 0 -intc_0 // 0 -bytec_2 // "declared_app_value" -app_global_get_ex -store 1 -store 0 -load 1 -! -assert -bytec_2 // "declared_app_value" -pushbytes 0x41206465636c617265642073746174652076616c756520746861742069732070726f74656374656420776974682074686520607374617469636020666c6167 // "A declared state value that is protected with the `static` flag" -app_global_put -callsub zeroimpl_4 -retsub - -// opt_in -optin_1: -proto 0 0 -txn Sender -bytec_3 // "declared_account_value" -intc_2 // 1 -app_local_put -txn Sender -callsub impl_5 -retsub - -// prefix_key_gen -prefixkeygen_2: -proto 1 1 -pushbytes 0x72657365727665645f6170705f76616c7565 // "reserved_app_value" -frame_dig -1 -concat -retsub - -// prefix_key_gen -prefixkeygen_3: -proto 1 1 -pushbytes 0x72657365727665645f6163636f756e745f76616c7565 // "reserved_account_value" -frame_dig -1 -concat -retsub - // zero_impl -zeroimpl_4: +zeroimpl_0: proto 0 0 intc_1 // 127 bzero @@ -359,7 +315,7 @@ pushint 16 // 16 - // ["00"*page_size, key-1] dup2 // ["00"*page_size, key, "00"*page_size, key] itob // ["00"*page_size, key, "00"*page_size, itob(key)] - extract 7 1 // ["00"*page_size, key, "00"*page_size, itob(key)[-1]] get the last byte of the int + extract 7 1 // ["00"*page_size, key, "00"*page_size, itob(key)[-1]] swap // ["00"*page_size, key, itob(key)[-1], "00"*page_size] app_global_put // ["00"*page_size, key] (removes top 2 elements) dup // ["00"*page_size, key-1, key-1] @@ -371,401 +327,279 @@ pushint 16 // 16 retsub -// _impl -impl_5: -proto 1 0 +// read_impl +readimpl_1: +proto 2 1 +bytec_1 // "" +store 17 +frame_dig -2 +intc_1 // 127 +/ +store 16 +readimpl_1_l1: +load 16 frame_dig -1 -bytec 4 // 0x00 intc_1 // 127 -bzero -app_local_put +/ +<= +bz readimpl_1_l9 +load 16 +frame_dig -2 +intc_1 // 127 +/ +== +bnz readimpl_1_l8 +intc_0 // 0 +readimpl_1_l4: +store 18 +load 16 frame_dig -1 -pushbytes 0x01 // 0x01 intc_1 // 127 -bzero -app_local_put +/ +== +bnz readimpl_1_l7 +intc_1 // 127 +readimpl_1_l6: +store 19 +load 17 +bytec 5 // 0x000102030405060708090a0b0c0d0e0f +load 16 +intc_2 // 1 +extract3 +app_global_get +load 18 +load 19 +substring3 +concat +store 17 +load 16 +intc_2 // 1 ++ +store 16 +b readimpl_1_l1 +readimpl_1_l7: frame_dig -1 -pushbytes 0x02 // 0x02 intc_1 // 127 -bzero -app_local_put +% +b readimpl_1_l6 +readimpl_1_l8: +frame_dig -2 +intc_1 // 127 +% +b readimpl_1_l4 +readimpl_1_l9: +load 17 retsub -// write_acct_blob -writeacctblob_6: -proto 1 0 -txn Sender +// write_impl +writeimpl_2: +proto 2 0 intc_0 // 0 +store 14 +frame_dig -2 +intc_1 // 127 +/ +store 11 +writeimpl_2_l1: +load 11 +frame_dig -2 frame_dig -1 -extract 2 0 -callsub impl_19 -retsub - -// read_acct_blob -readacctblob_7: -proto 0 1 -bytec_1 // "" -txn Sender -intc_0 // 0 -pushint 381 // 381 -intc_2 // 1 -- -callsub impl_20 -frame_bury 0 -frame_dig 0 len -itob -extract 6 0 -frame_dig 0 -concat -frame_bury 0 -retsub - -// write_app_blob -writeappblob_8: -proto 1 0 ++ +intc_1 // 127 +/ +<= +bz writeimpl_2_l12 +load 11 +frame_dig -2 +intc_1 // 127 +/ +== +bnz writeimpl_2_l11 intc_0 // 0 +writeimpl_2_l4: +store 12 +load 11 +frame_dig -2 frame_dig -1 -extract 2 0 -callsub writeimpl_21 -retsub - -// read_app_blob -readappblob_9: -proto 0 1 -bytec_1 // "" +len ++ +intc_1 // 127 +/ +== +bnz writeimpl_2_l10 +intc_1 // 127 +writeimpl_2_l6: +store 13 +bytec 5 // 0x000102030405060708090a0b0c0d0e0f +load 11 +intc_2 // 1 +extract3 +load 13 +intc_1 // 127 +!= +load 12 intc_0 // 0 -pushint 2032 // 2032 +!= +|| +bnz writeimpl_2_l9 +intc_1 // 127 +store 15 +frame_dig -1 +load 14 +intc_1 // 127 +extract3 +writeimpl_2_l8: +app_global_put +load 14 +load 15 ++ +store 14 +load 11 intc_2 // 1 ++ +store 11 +b writeimpl_2_l1 +writeimpl_2_l9: +load 13 +load 12 - -callsub readimpl_22 -frame_bury 0 -frame_dig 0 -len -itob -extract 6 0 -frame_dig 0 +store 15 +bytec 5 // 0x000102030405060708090a0b0c0d0e0f +load 11 +intc_2 // 1 +extract3 +app_global_get +intc_0 // 0 +load 12 +substring3 +frame_dig -1 +load 14 +load 15 +extract3 concat -frame_bury 0 +bytec 5 // 0x000102030405060708090a0b0c0d0e0f +load 11 +intc_2 // 1 +extract3 +app_global_get +load 13 +intc_1 // 127 +substring3 +concat +b writeimpl_2_l8 +writeimpl_2_l10: +frame_dig -2 +frame_dig -1 +len ++ +intc_1 // 127 +% +b writeimpl_2_l6 +writeimpl_2_l11: +frame_dig -2 +intc_1 // 127 +% +b writeimpl_2_l4 +writeimpl_2_l12: retsub -// set_app_state_val -setappstateval_10: +// zero_impl +zeroimpl_3: proto 1 0 -intc_0 // 0 -bytec_2 // "declared_app_value" -app_global_get_ex -store 31 -store 30 -load 31 -! -assert -bytec_2 // "declared_app_value" frame_dig -1 -extract 2 0 -app_global_put -retsub - -// get_app_state_val -getappstateval_11: -proto 0 1 -bytec_1 // "" -bytec_2 // "declared_app_value" -app_global_get -frame_bury 0 -frame_dig 0 -len -itob -extract 6 0 -frame_dig 0 -concat -frame_bury 0 -retsub - -// set_reserved_app_state_val -setreservedappstateval_12: -proto 2 0 -bytec 4 // 0x00 -intc_0 // 0 -frame_dig -2 -setbyte -callsub prefixkeygen_2 -frame_dig -1 -app_global_put -retsub - -// get_reserved_app_state_val -getreservedappstateval_13: -proto 1 1 -intc_0 // 0 -bytec 4 // 0x00 -intc_0 // 0 -frame_dig -1 -setbyte -callsub prefixkeygen_2 -app_global_get -frame_bury 0 -retsub - -// set_account_state_val -setaccountstateval_14: -proto 1 0 -txn Sender -bytec_3 // "declared_account_value" -frame_dig -1 -app_local_put -retsub - -// incr_account_state_val -incraccountstateval_15: -proto 1 0 -txn Sender -bytec_3 // "declared_account_value" -txn Sender -bytec_3 // "declared_account_value" -app_local_get -frame_dig -1 -+ -app_local_put -retsub - -// get_account_state_val -getaccountstateval_16: -proto 0 1 -intc_0 // 0 -txn Sender -bytec_3 // "declared_account_value" -app_local_get -frame_bury 0 -retsub - -// set_reserved_account_state_val -setreservedaccountstateval_17: -proto 2 0 -txn Sender -bytec 4 // 0x00 -intc_0 // 0 -frame_dig -2 -setbyte -callsub prefixkeygen_3 -frame_dig -1 -extract 2 0 -app_local_put -retsub - -// get_reserved_account_state_val -getreservedaccountstateval_18: -proto 1 1 -bytec_1 // "" -txn Sender -bytec 4 // 0x00 -intc_0 // 0 -frame_dig -1 -setbyte -callsub prefixkeygen_3 -app_local_get -frame_bury 0 -frame_dig 0 -len -itob -extract 6 0 -frame_dig 0 -concat -frame_bury 0 -retsub - -// _impl -impl_19: -proto 3 0 -intc_0 // 0 -store 15 -frame_dig -2 -intc_1 // 127 -/ -store 12 -impl_19_l1: -load 12 -frame_dig -2 -frame_dig -1 -len -+ -intc_1 // 127 -/ -<= -bz impl_19_l12 -load 12 -frame_dig -2 -intc_1 // 127 -/ -== -bnz impl_19_l11 -intc_0 // 0 -impl_19_l4: -store 13 -load 12 -frame_dig -2 -frame_dig -1 -len -+ -intc_1 // 127 -/ -== -bnz impl_19_l10 -intc_1 // 127 -impl_19_l6: -store 14 -frame_dig -3 -bytec 5 // 0x000102 -load 12 -intc_2 // 1 -extract3 -load 14 -intc_1 // 127 -!= -load 13 -intc_0 // 0 -!= -|| -bnz impl_19_l9 -intc_1 // 127 -store 16 -frame_dig -1 -load 15 +bytec_2 // 0x00 intc_1 // 127 -extract3 -impl_19_l8: +bzero app_local_put -load 15 -load 16 -+ -store 15 -load 12 -intc_2 // 1 -+ -store 12 -b impl_19_l1 -impl_19_l9: -load 14 -load 13 -- -store 16 -frame_dig -3 -bytec 5 // 0x000102 -load 12 -intc_2 // 1 -extract3 -app_local_get -intc_0 // 0 -load 13 -substring3 frame_dig -1 -load 15 -load 16 -extract3 -concat -frame_dig -3 -bytec 5 // 0x000102 -load 12 -intc_2 // 1 -extract3 -app_local_get -load 14 +pushbytes 0x01 // 0x01 intc_1 // 127 -substring3 -concat -b impl_19_l8 -impl_19_l10: -frame_dig -2 +bzero +app_local_put frame_dig -1 -len -+ -intc_1 // 127 -% -b impl_19_l6 -impl_19_l11: -frame_dig -2 +pushbytes 0x02 // 0x02 intc_1 // 127 -% -b impl_19_l4 -impl_19_l12: +bzero +app_local_put retsub -// _impl -impl_20: +// read_impl +readimpl_4: proto 3 1 bytec_1 // "" -store 18 +store 8 frame_dig -2 intc_1 // 127 / -store 17 -impl_20_l1: -load 17 +store 7 +readimpl_4_l1: +load 7 frame_dig -1 intc_1 // 127 / <= -bz impl_20_l9 -load 17 +bz readimpl_4_l9 +load 7 frame_dig -2 intc_1 // 127 / == -bnz impl_20_l8 +bnz readimpl_4_l8 intc_0 // 0 -impl_20_l4: -store 19 -load 17 +readimpl_4_l4: +store 9 +load 7 frame_dig -1 intc_1 // 127 / == -bnz impl_20_l7 +bnz readimpl_4_l7 intc_1 // 127 -impl_20_l6: -store 20 -load 18 +readimpl_4_l6: +store 10 +load 8 frame_dig -3 -bytec 5 // 0x000102 -load 17 +bytec 6 // 0x000102 +load 7 intc_2 // 1 extract3 app_local_get -load 19 -load 20 +load 9 +load 10 substring3 concat -store 18 -load 17 +store 8 +load 7 intc_2 // 1 + -store 17 -b impl_20_l1 -impl_20_l7: +store 7 +b readimpl_4_l1 +readimpl_4_l7: frame_dig -1 intc_1 // 127 % -b impl_20_l6 -impl_20_l8: +b readimpl_4_l6 +readimpl_4_l8: frame_dig -2 intc_1 // 127 % -b impl_20_l4 -impl_20_l9: -load 18 +b readimpl_4_l4 +readimpl_4_l9: +load 8 retsub // write_impl -writeimpl_21: -proto 2 0 +writeimpl_5: +proto 3 0 intc_0 // 0 -store 24 +store 5 frame_dig -2 intc_1 // 127 / -store 21 -writeimpl_21_l1: -load 21 +store 2 +writeimpl_5_l1: +load 2 frame_dig -2 frame_dig -1 len @@ -773,17 +607,17 @@ len intc_1 // 127 / <= -bz writeimpl_21_l12 -load 21 +bz writeimpl_5_l12 +load 2 frame_dig -2 intc_1 // 127 / == -bnz writeimpl_21_l11 +bnz writeimpl_5_l11 intc_0 // 0 -writeimpl_21_l4: -store 22 -load 21 +writeimpl_5_l4: +store 3 +load 2 frame_dig -2 frame_dig -1 len @@ -791,143 +625,309 @@ len intc_1 // 127 / == -bnz writeimpl_21_l10 +bnz writeimpl_5_l10 intc_1 // 127 -writeimpl_21_l6: -store 23 -bytec 6 // 0x000102030405060708090a0b0c0d0e0f -load 21 +writeimpl_5_l6: +store 4 +frame_dig -3 +bytec 6 // 0x000102 +load 2 intc_2 // 1 extract3 -load 23 +load 4 intc_1 // 127 != -load 22 +load 3 intc_0 // 0 != || -bnz writeimpl_21_l9 +bnz writeimpl_5_l9 intc_1 // 127 -store 25 +store 6 frame_dig -1 -load 24 +load 5 intc_1 // 127 extract3 -writeimpl_21_l8: -app_global_put -load 24 -load 25 +writeimpl_5_l8: +app_local_put +load 5 +load 6 + -store 24 -load 21 +store 5 +load 2 intc_2 // 1 + -store 21 -b writeimpl_21_l1 -writeimpl_21_l9: -load 23 -load 22 +store 2 +b writeimpl_5_l1 +writeimpl_5_l9: +load 4 +load 3 - -store 25 -bytec 6 // 0x000102030405060708090a0b0c0d0e0f -load 21 +store 6 +frame_dig -3 +bytec 6 // 0x000102 +load 2 intc_2 // 1 extract3 -app_global_get +app_local_get intc_0 // 0 -load 22 +load 3 substring3 frame_dig -1 -load 24 -load 25 +load 5 +load 6 extract3 concat -bytec 6 // 0x000102030405060708090a0b0c0d0e0f -load 21 +frame_dig -3 +bytec 6 // 0x000102 +load 2 intc_2 // 1 extract3 -app_global_get -load 23 +app_local_get +load 4 intc_1 // 127 substring3 concat -b writeimpl_21_l8 -writeimpl_21_l10: +b writeimpl_5_l8 +writeimpl_5_l10: frame_dig -2 frame_dig -1 len + intc_1 // 127 % -b writeimpl_21_l6 -writeimpl_21_l11: +b writeimpl_5_l6 +writeimpl_5_l11: frame_dig -2 intc_1 // 127 % -b writeimpl_21_l4 -writeimpl_21_l12: +b writeimpl_5_l4 +writeimpl_5_l12: retsub -// read_impl -readimpl_22: -proto 2 1 -bytec_1 // "" -store 27 -frame_dig -2 -intc_1 // 127 -/ -store 26 -readimpl_22_l1: -load 26 +// create +create_6: +proto 0 0 +intc_0 // 0 +bytec_3 // "declared_app_value" +app_global_get_ex +store 1 +store 0 +load 1 +! +assert +bytec_3 // "declared_app_value" +pushbytes 0x41206465636c617265642073746174652076616c756520746861742069732070726f74656374656420776974682074686520607374617469636020666c6167 // "A declared state value that is protected with the `static` flag" +app_global_put +callsub zeroimpl_0 +retsub + +// opt_in +optin_7: +proto 0 0 +txn Sender +bytec 4 // "declared_account_value" +intc_2 // 1 +app_local_put +txn Sender +callsub zeroimpl_3 +retsub + +// prefix_key_gen +prefixkeygen_8: +proto 1 1 +pushbytes 0x72657365727665645f6170705f76616c7565 // "reserved_app_value" frame_dig -1 -intc_1 // 127 -/ -<= -bz readimpl_22_l9 -load 26 -frame_dig -2 -intc_1 // 127 -/ -== -bnz readimpl_22_l8 +concat +retsub + +// prefix_key_gen +prefixkeygen_9: +proto 1 1 +pushbytes 0x72657365727665645f6163636f756e745f76616c7565 // "reserved_account_value" +frame_dig -1 +concat +retsub + +// write_acct_blob +writeacctblob_10: +proto 1 0 +txn Sender intc_0 // 0 -readimpl_22_l4: -store 28 -load 26 frame_dig -1 -intc_1 // 127 -/ -== -bnz readimpl_22_l7 -intc_1 // 127 -readimpl_22_l6: -store 29 -load 27 -bytec 6 // 0x000102030405060708090a0b0c0d0e0f -load 26 +extract 2 0 +callsub writeimpl_5 +retsub + +// read_acct_blob +readacctblob_11: +proto 0 1 +bytec_1 // "" +txn Sender +intc_0 // 0 +pushint 381 // 381 intc_2 // 1 -extract3 -app_global_get -load 28 -load 29 -substring3 +- +callsub readimpl_4 +frame_bury 0 +frame_dig 0 +len +itob +extract 6 0 +frame_dig 0 concat -store 27 -load 26 +frame_bury 0 +retsub + +// write_app_blob +writeappblob_12: +proto 1 0 +intc_0 // 0 +frame_dig -1 +extract 2 0 +callsub writeimpl_2 +retsub + +// read_app_blob +readappblob_13: +proto 0 1 +bytec_1 // "" +intc_0 // 0 +pushint 2032 // 2032 intc_2 // 1 -+ -store 26 -b readimpl_22_l1 -readimpl_22_l7: +- +callsub readimpl_1 +frame_bury 0 +frame_dig 0 +len +itob +extract 6 0 +frame_dig 0 +concat +frame_bury 0 +retsub + +// set_app_state_val +setappstateval_14: +proto 1 0 +intc_0 // 0 +bytec_3 // "declared_app_value" +app_global_get_ex +store 31 +store 30 +load 31 +! +assert +bytec_3 // "declared_app_value" frame_dig -1 -intc_1 // 127 -% -b readimpl_22_l6 -readimpl_22_l8: +extract 2 0 +app_global_put +retsub + +// get_app_state_val +getappstateval_15: +proto 0 1 +bytec_1 // "" +bytec_3 // "declared_app_value" +app_global_get +frame_bury 0 +frame_dig 0 +len +itob +extract 6 0 +frame_dig 0 +concat +frame_bury 0 +retsub + +// set_reserved_app_state_val +setreservedappstateval_16: +proto 2 0 +bytec_2 // 0x00 +intc_0 // 0 frame_dig -2 -intc_1 // 127 -% -b readimpl_22_l4 -readimpl_22_l9: -load 27 +setbyte +callsub prefixkeygen_8 +frame_dig -1 +app_global_put +retsub + +// get_reserved_app_state_val +getreservedappstateval_17: +proto 1 1 +intc_0 // 0 +bytec_2 // 0x00 +intc_0 // 0 +frame_dig -1 +setbyte +callsub prefixkeygen_8 +app_global_get +frame_bury 0 +retsub + +// set_account_state_val +setaccountstateval_18: +proto 1 0 +txn Sender +bytec 4 // "declared_account_value" +frame_dig -1 +app_local_put +retsub + +// incr_account_state_val +incraccountstateval_19: +proto 1 0 +txn Sender +bytec 4 // "declared_account_value" +txn Sender +bytec 4 // "declared_account_value" +app_local_get +frame_dig -1 ++ +app_local_put +retsub + +// get_account_state_val +getaccountstateval_20: +proto 0 1 +intc_0 // 0 +txn Sender +bytec 4 // "declared_account_value" +app_local_get +frame_bury 0 +retsub + +// set_reserved_account_state_val +setreservedaccountstateval_21: +proto 2 0 +txn Sender +bytec_2 // 0x00 +intc_0 // 0 +frame_dig -2 +setbyte +callsub prefixkeygen_9 +frame_dig -1 +extract 2 0 +app_local_put +retsub + +// get_reserved_account_state_val +getreservedaccountstateval_22: +proto 1 1 +bytec_1 // "" +txn Sender +bytec_2 // 0x00 +intc_0 // 0 +frame_dig -1 +setbyte +callsub prefixkeygen_9 +app_local_get +frame_bury 0 +frame_dig 0 +len +itob +extract 6 0 +frame_dig 0 +concat +frame_bury 0 retsub \ No newline at end of file diff --git a/examples/templated_lsig/App.artifacts/application.json b/examples/templated_lsig/App.artifacts/application.json index 4cfb9044..2a823868 100644 --- a/examples/templated_lsig/App.artifacts/application.json +++ b/examples/templated_lsig/App.artifacts/application.json @@ -1,7 +1,7 @@ { "hints": {}, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDgKaW50Y2Jsb2NrIDAgMSAyIDEyOCAyNTUKYnl0ZWNibG9jayAweCAweDA4ODAwMDM1MDAzNjFhMDIzNTAxMzYxYTAzMzUwMjM0MDE1NzAyMDAzNDAyMzQwMDg0NDQ4MTAxNDMKdHhuIE51bUFwcEFyZ3MKaW50Y18wIC8vIDAKPT0KYm56IG1haW5fbDQKdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMApwdXNoYnl0ZXMgMHhhNWU1YzNkMSAvLyAiY2hlY2soYWRkcmVzcyxzdHJpbmcsYnl0ZVs2NF0pdm9pZCIKPT0KYm56IG1haW5fbDMKZXJyCm1haW5fbDM6CnR4biBPbkNvbXBsZXRpb24KaW50Y18wIC8vIE5vT3AKPT0KdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18wIC8vIDAKIT0KJiYKYXNzZXJ0CnR4bmEgQXBwbGljYXRpb25BcmdzIDEKc3RvcmUgMAp0eG5hIEFwcGxpY2F0aW9uQXJncyAyCnN0b3JlIDEKdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMwpzdG9yZSAyCmxvYWQgMApsb2FkIDEKbG9hZCAyCmNhbGxzdWIgY2hlY2tfMQppbnRjXzEgLy8gMQpyZXR1cm4KbWFpbl9sNDoKdHhuIE9uQ29tcGxldGlvbgppbnRjXzAgLy8gTm9PcAo9PQpibnogbWFpbl9sNgplcnIKbWFpbl9sNjoKdHhuIEFwcGxpY2F0aW9uSUQKaW50Y18wIC8vIDAKPT0KYXNzZXJ0CmNhbGxzdWIgY3JlYXRlXzAKaW50Y18xIC8vIDEKcmV0dXJuCgovLyBjcmVhdGUKY3JlYXRlXzA6CnByb3RvIDAgMAppbnRjXzEgLy8gMQpyZXR1cm4KCi8vIGNoZWNrCmNoZWNrXzE6CnByb3RvIDMgMAp0eG4gU2VuZGVyCnB1c2hieXRlcyAweDUwNzI2ZjY3NzI2MTZkIC8vICJQcm9ncmFtIgppbnRjXzAgLy8gMApzdG9yZSAzCmludGNfMCAvLyAwCnN0b3JlIDQKYnl0ZWNfMCAvLyAiIgpzdG9yZSA1CmJ5dGVjXzAgLy8gIiIKc3RvcmUgNgpmcmFtZV9kaWcgLTMKbGVuCmJ5dGVjXzAgLy8gIiIKY2FsbHN1YiBlbmNvZGV1dmFyaW50aW1wbF8yCmZyYW1lX2RpZyAtMwpjb25jYXQKc3RvcmUgNQpsb2FkIDYKYnl0ZWNfMSAvLyAweDA4ODAwMDM1MDAzNjFhMDIzNTAxMzYxYTAzMzUwMjM0MDE1NzAyMDAzNDAyMzQwMDg0NDQ4MTAxNDMKbG9hZCAzCmludGNfMiAvLyAyCnN1YnN0cmluZzMKY29uY2F0CmxvYWQgNQpjb25jYXQKc3RvcmUgNgpsb2FkIDQKbG9hZCA1CmxlbgorCmludGNfMSAvLyAxCi0Kc3RvcmUgNAppbnRjXzIgLy8gMgppbnRjXzEgLy8gMQorCnN0b3JlIDMKbG9hZCA2CmJ5dGVjXzEgLy8gMHgwODgwMDAzNTAwMzYxYTAyMzUwMTM2MWEwMzM1MDIzNDAxNTcwMjAwMzQwMjM0MDA4NDQ0ODEwMTQzCmxvYWQgMwpkaWcgMQpsZW4Kc3Vic3RyaW5nMwpjb25jYXQKc3RvcmUgNgpsb2FkIDYKY29uY2F0CnNoYTUxMl8yNTYKPT0KYXNzZXJ0CnJldHN1YgoKLy8gZW5jb2RlX3V2YXJpbnRfaW1wbAplbmNvZGV1dmFyaW50aW1wbF8yOgpwcm90byAyIDEKZnJhbWVfZGlnIC0xCmZyYW1lX2RpZyAtMgppbnRjXzMgLy8gMTI4Cj49CmJueiBlbmNvZGV1dmFyaW50aW1wbF8yX2wyCmZyYW1lX2RpZyAtMgppbnRjIDQgLy8gMjU1CiYKaXRvYgpleHRyYWN0IDcgMQpiIGVuY29kZXV2YXJpbnRpbXBsXzJfbDMKZW5jb2RldXZhcmludGltcGxfMl9sMjoKZnJhbWVfZGlnIC0yCnB1c2hpbnQgNyAvLyA3CnNocgpmcmFtZV9kaWcgLTIKaW50YyA0IC8vIDI1NQomCmludGNfMyAvLyAxMjgKfAppdG9iCmV4dHJhY3QgNyAxCmNhbGxzdWIgZW5jb2RldXZhcmludGltcGxfMgplbmNvZGV1dmFyaW50aW1wbF8yX2wzOgpjb25jYXQKcmV0c3Vi", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDgKaW50Y2Jsb2NrIDAgMSAxMjggMjU1CmJ5dGVjYmxvY2sgMHggMHgwODgwMDAzNTAwMzYxYTAyMzUwMTM2MWEwMzM1MDIzNDAxNTcwMjAwMzQwMjM0MDA4NDQ0ODEwMTQzCnR4biBOdW1BcHBBcmdzCmludGNfMCAvLyAwCj09CmJueiBtYWluX2w0CnR4bmEgQXBwbGljYXRpb25BcmdzIDAKcHVzaGJ5dGVzIDB4YTVlNWMzZDEgLy8gImNoZWNrKGFkZHJlc3Msc3RyaW5nLGJ5dGVbNjRdKXZvaWQiCj09CmJueiBtYWluX2wzCmVycgptYWluX2wzOgp0eG4gT25Db21wbGV0aW9uCmludGNfMCAvLyBOb09wCj09CnR4biBBcHBsaWNhdGlvbklECmludGNfMCAvLyAwCiE9CiYmCmFzc2VydAp0eG5hIEFwcGxpY2F0aW9uQXJncyAxCnN0b3JlIDAKdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgpzdG9yZSAxCnR4bmEgQXBwbGljYXRpb25BcmdzIDMKc3RvcmUgMgpsb2FkIDAKbG9hZCAxCmxvYWQgMgpjYWxsc3ViIGNoZWNrXzIKaW50Y18xIC8vIDEKcmV0dXJuCm1haW5fbDQ6CnR4biBPbkNvbXBsZXRpb24KaW50Y18wIC8vIE5vT3AKPT0KYm56IG1haW5fbDYKZXJyCm1haW5fbDY6CnR4biBBcHBsaWNhdGlvbklECmludGNfMCAvLyAwCj09CmFzc2VydApjYWxsc3ViIGNyZWF0ZV8xCmludGNfMSAvLyAxCnJldHVybgoKLy8gZW5jb2RlX3V2YXJpbnRfaW1wbAplbmNvZGV1dmFyaW50aW1wbF8wOgpwcm90byAyIDEKZnJhbWVfZGlnIC0xCmZyYW1lX2RpZyAtMgppbnRjXzIgLy8gMTI4Cj49CmJueiBlbmNvZGV1dmFyaW50aW1wbF8wX2wyCmZyYW1lX2RpZyAtMgppbnRjXzMgLy8gMjU1CiYKaXRvYgpleHRyYWN0IDcgMQpiIGVuY29kZXV2YXJpbnRpbXBsXzBfbDMKZW5jb2RldXZhcmludGltcGxfMF9sMjoKZnJhbWVfZGlnIC0yCnB1c2hpbnQgNyAvLyA3CnNocgpmcmFtZV9kaWcgLTIKaW50Y18zIC8vIDI1NQomCmludGNfMiAvLyAxMjgKfAppdG9iCmV4dHJhY3QgNyAxCmNhbGxzdWIgZW5jb2RldXZhcmludGltcGxfMAplbmNvZGV1dmFyaW50aW1wbF8wX2wzOgpjb25jYXQKcmV0c3ViCgovLyBjcmVhdGUKY3JlYXRlXzE6CnByb3RvIDAgMAppbnRjXzEgLy8gMQpyZXR1cm4KCi8vIGNoZWNrCmNoZWNrXzI6CnByb3RvIDMgMAp0eG4gU2VuZGVyCnB1c2hieXRlcyAweDUwNzI2ZjY3NzI2MTZkIC8vICJQcm9ncmFtIgppbnRjXzAgLy8gMApzdG9yZSAzCmludGNfMCAvLyAwCnN0b3JlIDQKYnl0ZWNfMCAvLyAiIgpzdG9yZSA1CmJ5dGVjXzAgLy8gIiIKc3RvcmUgNgpmcmFtZV9kaWcgLTMKbGVuCmJ5dGVjXzAgLy8gIiIKY2FsbHN1YiBlbmNvZGV1dmFyaW50aW1wbF8wCmZyYW1lX2RpZyAtMwpjb25jYXQKc3RvcmUgNQpsb2FkIDYKYnl0ZWNfMSAvLyAweDA4ODAwMDM1MDAzNjFhMDIzNTAxMzYxYTAzMzUwMjM0MDE1NzAyMDAzNDAyMzQwMDg0NDQ4MTAxNDMKbG9hZCAzCnB1c2hpbnQgMiAvLyAyCnN1YnN0cmluZzMKY29uY2F0CmxvYWQgNQpjb25jYXQKc3RvcmUgNgpsb2FkIDQKbG9hZCA1CmxlbgorCmludGNfMSAvLyAxCi0Kc3RvcmUgNApwdXNoaW50IDIgLy8gMgppbnRjXzEgLy8gMQorCnN0b3JlIDMKbG9hZCA2CmJ5dGVjXzEgLy8gMHgwODgwMDAzNTAwMzYxYTAyMzUwMTM2MWEwMzM1MDIzNDAxNTcwMjAwMzQwMjM0MDA4NDQ0ODEwMTQzCmxvYWQgMwpkaWcgMQpsZW4Kc3Vic3RyaW5nMwpjb25jYXQKc3RvcmUgNgpsb2FkIDYKY29uY2F0CnNoYTUxMl8yNTYKPT0KYXNzZXJ0CnJldHN1Yg==", "clear": "I3ByYWdtYSB2ZXJzaW9uIDgKcHVzaGludCAwIC8vIDAKcmV0dXJu" }, "schema": { diff --git a/examples/templated_lsig/App.artifacts/approval.teal b/examples/templated_lsig/App.artifacts/approval.teal index aa7be27d..3f55580c 100644 --- a/examples/templated_lsig/App.artifacts/approval.teal +++ b/examples/templated_lsig/App.artifacts/approval.teal @@ -1,5 +1,5 @@ #pragma version 8 -intcblock 0 1 2 128 255 +intcblock 0 1 128 255 bytecblock 0x 0x0880003500361a023501361a0335023401570200340234008444810143 txn NumAppArgs intc_0 // 0 @@ -28,7 +28,7 @@ store 2 load 0 load 1 load 2 -callsub check_1 +callsub check_2 intc_1 // 1 return main_l4: @@ -42,18 +42,48 @@ txn ApplicationID intc_0 // 0 == assert -callsub create_0 +callsub create_1 intc_1 // 1 return +// encode_uvarint_impl +encodeuvarintimpl_0: +proto 2 1 +frame_dig -1 +frame_dig -2 +intc_2 // 128 +>= +bnz encodeuvarintimpl_0_l2 +frame_dig -2 +intc_3 // 255 +& +itob +extract 7 1 +b encodeuvarintimpl_0_l3 +encodeuvarintimpl_0_l2: +frame_dig -2 +pushint 7 // 7 +shr +frame_dig -2 +intc_3 // 255 +& +intc_2 // 128 +| +itob +extract 7 1 +callsub encodeuvarintimpl_0 +encodeuvarintimpl_0_l3: +concat +retsub + // create -create_0: +create_1: proto 0 0 intc_1 // 1 return // check -check_1: +check_2: proto 3 0 txn Sender pushbytes 0x50726f6772616d // "Program" @@ -68,14 +98,14 @@ store 6 frame_dig -3 len bytec_0 // "" -callsub encodeuvarintimpl_2 +callsub encodeuvarintimpl_0 frame_dig -3 concat store 5 load 6 bytec_1 // 0x0880003500361a023501361a0335023401570200340234008444810143 load 3 -intc_2 // 2 +pushint 2 // 2 substring3 concat load 5 @@ -88,7 +118,7 @@ len intc_1 // 1 - store 4 -intc_2 // 2 +pushint 2 // 2 intc_1 // 1 + store 3 @@ -105,34 +135,4 @@ concat sha512_256 == assert -retsub - -// encode_uvarint_impl -encodeuvarintimpl_2: -proto 2 1 -frame_dig -1 -frame_dig -2 -intc_3 // 128 ->= -bnz encodeuvarintimpl_2_l2 -frame_dig -2 -intc 4 // 255 -& -itob -extract 7 1 -b encodeuvarintimpl_2_l3 -encodeuvarintimpl_2_l2: -frame_dig -2 -pushint 7 // 7 -shr -frame_dig -2 -intc 4 // 255 -& -intc_3 // 128 -| -itob -extract 7 1 -callsub encodeuvarintimpl_2 -encodeuvarintimpl_2_l3: -concat retsub \ No newline at end of file diff --git a/tests/global_blob_test.py b/tests/global_blob_test.py index f6502f9a..d11e1f20 100644 --- a/tests/global_blob_test.py +++ b/tests/global_blob_test.py @@ -108,3 +108,26 @@ def unit_test(self, *, output: pt.abi.Uint8): with pytest.raises(bkr.client.LogicException): assert_output(LB(), [], expected, opups=1) + + +def test_global_blob_single_subroutine(): + class LB(GlobalBlobTest): + @bkr.external + def unit_test(self, *, output: pt.abi.DynamicArray[pt.abi.Byte]): + return pt.Seq( + self.blob.zero(), + self.blob.write(pt.Int(0), pt.Bytes("deadbeef" * 8)), + self.blob.write(pt.Int(0), pt.Bytes("deadbeef" * 8)), + # Call read multiple times, in an earlier ver + pt.Pop(self.blob.read(pt.Int(32), pt.Int(40))), + pt.Pop(self.blob.read(pt.Int(32), pt.Int(40))), + (s := pt.abi.String()).set(self.blob.read(pt.Int(32), pt.Int(40))), + output.decode(s.encode()), + ) + + program = LB().approval_program + assert program.count("write_impl") == 1 + assert program.count("read_impl") == 1 + + expected = list(b"deadbeef") + assert_output(LB(), [], [expected], opups=1) diff --git a/tests/local_blob_test.py b/tests/local_blob_test.py index dfb9d692..d37e63ce 100644 --- a/tests/local_blob_test.py +++ b/tests/local_blob_test.py @@ -108,3 +108,24 @@ def unit_test(self, *, output: pt.abi.Uint8): with pytest.raises(bkr.client.LogicException): assert_output(LB(), [], expected) + + +def test_local_blob_single_subroutine(): + class LB(LocalBlobTest): + @bkr.external + def unit_test(self, *, output: pt.abi.DynamicArray[pt.abi.Byte]): + return pt.Seq( + self.blob.zero(), + self.blob.write(pt.Int(0), pt.Bytes("deadbeef" * 8)), + self.blob.write(pt.Int(0), pt.Bytes("deadbeef" * 8)), + pt.Pop(self.blob.read(pt.Int(32), pt.Int(40))), + (s := pt.abi.String()).set(self.blob.read(pt.Int(32), pt.Int(40))), + output.decode(s.encode()), + ) + + program = LB().approval_program + assert program.count("write_impl") == 1 + assert program.count("read_impl") == 1 + + expected = list(b"deadbeef") + assert_output(LB(), [], [expected])