snarkjs-algorand 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/dist/index.cjs +640 -0
- package/dist/index.d.cts +1482 -0
- package/dist/index.d.ts +1482 -0
- package/dist/index.js +601 -0
- package/package.json +55 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,601 @@
|
|
|
1
|
+
// contracts/clients/PlonkVerifier.ts
|
|
2
|
+
import "@algorandfoundation/algokit-utils/types/algorand-client";
|
|
3
|
+
import "@algorandfoundation/algokit-utils/types/app";
|
|
4
|
+
import { getArc56ReturnValue, getABIStructFromABITuple } from "@algorandfoundation/algokit-utils/types/app-arc56";
|
|
5
|
+
import {
|
|
6
|
+
AppClient as _AppClient
|
|
7
|
+
} from "@algorandfoundation/algokit-utils/types/app-client";
|
|
8
|
+
import { AppFactory as _AppFactory } from "@algorandfoundation/algokit-utils/types/app-factory";
|
|
9
|
+
import "@algorandfoundation/algokit-utils/types/composer";
|
|
10
|
+
import "@algorandfoundation/algokit-utils/types/transaction";
|
|
11
|
+
import "algosdk";
|
|
12
|
+
var APP_SPEC = { "name": "PlonkVerifier", "structs": { "Proof": [{ "name": "a", "type": "byte[96]" }, { "name": "b", "type": "byte[96]" }, { "name": "c", "type": "byte[96]" }, { "name": "z", "type": "byte[96]" }, { "name": "t1", "type": "byte[96]" }, { "name": "t2", "type": "byte[96]" }, { "name": "t3", "type": "byte[96]" }, { "name": "wxi", "type": "byte[96]" }, { "name": "wxiw", "type": "byte[96]" }, { "name": "evalA", "type": "uint256" }, { "name": "evalB", "type": "uint256" }, { "name": "evalC", "type": "uint256" }, { "name": "evalS1", "type": "uint256" }, { "name": "evalS2", "type": "uint256" }, { "name": "evalZw", "type": "uint256" }], "VerificationKey": [{ "name": "qm", "type": "byte[96]" }, { "name": "ql", "type": "byte[96]" }, { "name": "qr", "type": "byte[96]" }, { "name": "qo", "type": "byte[96]" }, { "name": "qc", "type": "byte[96]" }, { "name": "s1", "type": "byte[96]" }, { "name": "s2", "type": "byte[96]" }, { "name": "s3", "type": "byte[96]" }, { "name": "power", "type": "uint64" }, { "name": "nPublic", "type": "uint64" }, { "name": "k1", "type": "uint64" }, { "name": "k2", "type": "uint64" }, { "name": "x_2", "type": "byte[192]" }] }, "methods": [{ "name": "_dummy", "args": [{ "type": "(byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],uint64,uint64,uint64,uint64,byte[192])", "struct": "VerificationKey", "name": "_vk" }], "returns": { "type": "void" }, "actions": { "create": [], "call": ["CloseOut"] }, "readonly": false, "desc": "Dummy function that only exists so we can have the VerificationKey type in the generated client", "events": [], "recommendations": {} }, { "name": "verify", "args": [{ "type": "uint256[]", "name": "signals" }, { "type": "(byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],uint256,uint256,uint256,uint256,uint256,uint256)", "struct": "Proof", "name": "proof" }], "returns": { "type": "void" }, "actions": { "create": [], "call": ["NoOp"] }, "readonly": false, "events": [], "recommendations": {} }], "arcs": [22, 28], "networks": {}, "state": { "schema": { "global": { "ints": 0, "bytes": 0 }, "local": { "ints": 0, "bytes": 0 } }, "keys": { "global": {}, "local": {}, "box": {} }, "maps": { "global": {}, "local": {}, "box": {} } }, "bareActions": { "create": ["NoOp"], "call": [] }, "sourceInfo": { "approval": { "sourceInfo": [{ "pc": [1293], "errorMessage": "Fr inverse of zero" }, { "pc": [440], "errorMessage": "Length must be 192" }, { "pc": [104], "errorMessage": "Length must be 32" }, { "pc": [179, 202, 225, 248, 271, 294, 317, 340, 1849, 1858, 1989, 1999, 2026, 2035, 2042, 2109, 2119, 2345, 2364, 2374, 2403, 2412, 2423, 2430, 2458], "errorMessage": "Length must be 96" }, { "pc": [50], "errorMessage": "OnCompletion is not CloseOut" }, { "pc": [30], "errorMessage": "OnCompletion is not NoOp" }, { "pc": [2516], "errorMessage": "Verification failed" }, { "pc": [64], "errorMessage": "can only call when creating" }, { "pc": [33, 53], "errorMessage": "can only call when not creating" }, { "pc": [574, 758, 787, 790, 809, 1030, 1044, 1058, 1072, 1085, 1513, 1528, 2063, 2068, 2075, 2084, 2093], "errorMessage": "index access is out of bounds" }, { "pc": [1410], "errorMessage": "max array length exceeded" }, { "pc": [94, 133, 800, 1145, 1170, 1401, 1549, 1724], "errorMessage": "overflow" }], "pcOffsetMethod": "cblocks" }, "clear": { "sourceInfo": [], "pcOffsetMethod": "none" } }, "source": { "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCiNwcmFnbWEgdHlwZXRyYWNrIGZhbHNlCgovLyBAYWxnb3JhbmRmb3VuZGF0aW9uL2FsZ29yYW5kLXR5cGVzY3JpcHQvYXJjNC9pbmRleC5kLnRzOjpDb250cmFjdC5hcHByb3ZhbFByb2dyYW0oKSAtPiB1aW50NjQ6Cm1haW46CiAgICBpbnRjYmxvY2sgOTYgMzIgMSAwIDM4NCAxOTIgMjg4IDQ4MCA1NzYgNjcyIDc2OCA3NzYgNzg0IDc5MiA4MDAgOTkyIDM1MiBUTVBMX0RFQlVHX0xPR0dJTkcKICAgIGJ5dGVjYmxvY2sgMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxIFRNUExfVkVSSUZJQ0FUSU9OX0tFWSAweCAweDAxIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMCBUTVBMX1JPT1RfT0ZfVU5JVFkgMHgwMjRhYTJiMmYwOGYwYTkxMjYwODA1MjcyZGM1MTA1MWM2ZTQ3YWQ0ZmE0MDNiMDJiNDUxMGI2NDdhZTNkMTc3MGJhYzAzMjZhODA1YmJlZmQ0ODA1NmM4YzEyMWJkYjgxM2UwMmI2MDUyNzE5ZjYwN2RhY2QzYTA4ODI3NGY2NTU5NmJkMGQwOTkyMGI2MWFiNWRhNjFiYmRjN2Y1MDQ5MzM0Y2YxMTIxMzk0NWQ1N2U1YWM3ZDA1NWQwNDJiN2UwY2U1ZDUyNzcyN2Q2ZTExOGNjOWNkYzZkYTJlMzUxYWFkZmQ5YmFhOGNiZGQzYTc2ZDQyOWE2OTUxNjBkMTJjOTIzYWM5Y2MzYmFjYTI4OWUxOTM1NDg2MDhiODI4MDEwNjA2YzRhMDJlYTczNGNjMzJhY2QyYjAyYmMyOGI5OWNiM2UyODdlODVhNzYzYWYyNjc0OTJhYjU3MmU5OWFiM2YzNzBkMjc1Y2VjMWRhMWFhYTkwNzVmZjA1Zjc5YmUKICAgIC8vIGNvbnRyYWN0cy92ZXJpZmllci5hbGdvLnRzOjEwCiAgICAvLyBleHBvcnQgY2xhc3MgUGxvbmtWZXJpZmllciBleHRlbmRzIENvbnRyYWN0IHsKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBtYWluX2JhcmVfcm91dGluZ0A3CiAgICBwdXNoYnl0ZXNzIDB4OTVjMTBjZTQgMHg0M2Q5MGEzOCAvLyBtZXRob2QgIl9kdW1teSgoYnl0ZVs5Nl0sYnl0ZVs5Nl0sYnl0ZVs5Nl0sYnl0ZVs5Nl0sYnl0ZVs5Nl0sYnl0ZVs5Nl0sYnl0ZVs5Nl0sYnl0ZVs5Nl0sdWludDY0LHVpbnQ2NCx1aW50NjQsdWludDY0LGJ5dGVbMTkyXSkpdm9pZCIsIG1ldGhvZCAidmVyaWZ5KHVpbnQyNTZbXSwoYnl0ZVs5Nl0sYnl0ZVs5Nl0sYnl0ZVs5Nl0sYnl0ZVs5Nl0sYnl0ZVs5Nl0sYnl0ZVs5Nl0sYnl0ZVs5Nl0sYnl0ZVs5Nl0sYnl0ZVs5Nl0sdWludDI1Nix1aW50MjU2LHVpbnQyNTYsdWludDI1Nix1aW50MjU2LHVpbnQyNTYpKXZvaWQiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBtYWluX19kdW1teV9yb3V0ZUAzIG1haW5fdmVyaWZ5X3JvdXRlQDQKCm1haW5fYWZ0ZXJfaWZfZWxzZUAxMToKICAgIGVycgoKbWFpbl92ZXJpZnlfcm91dGVANDoKICAgIC8vIGNvbnRyYWN0cy92ZXJpZmllci5hbGdvLnRzOjE1CiAgICAvLyB2ZXJpZnkoc2lnbmFsczogUHVibGljU2lnbmFscywgcHJvb2Y6IFByb29mKTogdm9pZCB7CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIG5vdCBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGNhbiBvbmx5IGNhbGwgd2hlbiBub3QgY3JlYXRpbmcKICAgIC8vIGNvbnRyYWN0cy92ZXJpZmllci5hbGdvLnRzOjEwCiAgICAvLyBleHBvcnQgY2xhc3MgUGxvbmtWZXJpZmllciBleHRlbmRzIENvbnRyYWN0IHsKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDIKICAgIC8vIGNvbnRyYWN0cy92ZXJpZmllci5hbGdvLnRzOjE1CiAgICAvLyB2ZXJpZnkoc2lnbmFsczogUHVibGljU2lnbmFscywgcHJvb2Y6IFByb29mKTogdm9pZCB7CiAgICBjYWxsc3ViIHZlcmlmeQogICAgaW50Y18yIC8vIDEKICAgIHJldHVybgoKbWFpbl9fZHVtbXlfcm91dGVAMzoKICAgIC8vIGNvbnRyYWN0cy92ZXJpZmllci5hbGdvLnRzOjEyCiAgICAvLyBAYWJpbWV0aG9kKHsgYWxsb3dBY3Rpb25zOiAiQ2xvc2VPdXQiIH0pCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBwdXNoaW50IDIgLy8gQ2xvc2VPdXQKICAgID09CiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIG5vdCBDbG9zZU91dAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gbm90IGNyZWF0aW5nCiAgICBpbnRjXzIgLy8gMQogICAgcmV0dXJuCgptYWluX2JhcmVfcm91dGluZ0A3OgogICAgLy8gY29udHJhY3RzL3ZlcmlmaWVyLmFsZ28udHM6MTAKICAgIC8vIGV4cG9ydCBjbGFzcyBQbG9ua1ZlcmlmaWVyIGV4dGVuZHMgQ29udHJhY3QgewogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IG1haW5fYWZ0ZXJfaWZfZWxzZUAxMQogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gY3JlYXRpbmcKICAgIGludGNfMiAvLyAxCiAgICByZXR1cm4KCgovLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo6ZnJTdWIoYTogYnl0ZXMsIGI6IGJ5dGVzKSAtPiBieXRlczoKZnJTdWI6CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxMzMKICAgIC8vIGZ1bmN0aW9uIGZyU3ViKGE6IGJpZ3VpbnQsIGI6IGJpZ3VpbnQpOiBiaWd1aW50IHsKICAgIHByb3RvIDIgMQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MTM1CiAgICAvLyBjb25zdCBhTjogYmlndWludCA9IGEgJSByOwogICAgZnJhbWVfZGlnIC0yCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjEzNgogICAgLy8gY29uc3QgYk46IGJpZ3VpbnQgPSBiICUgcjsKICAgIGZyYW1lX2RpZyAtMQogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxMzcKICAgIC8vIHJldHVybiAoYU4gKyByIC0gYk4pICUgcjsKICAgIHN3YXAKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiKwogICAgc3dhcAogICAgYi0KICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiJQogICAgcmV0c3ViCgoKLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6OmIzMihhOiBieXRlcykgLT4gYnl0ZXM6CmIzMjoKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjE2NQogICAgLy8gZnVuY3Rpb24gYjMyKGE6IGJpZ3VpbnQpOiBieXRlczwzMj4gewogICAgcHJvdG8gMSAxCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNjYKICAgIC8vIHJldHVybiBuZXcgVWludDI1NihhKS5ieXRlcy50b0ZpeGVkKHsgbGVuZ3RoOiAzMiB9KTsKICAgIGZyYW1lX2RpZyAtMQogICAgbGVuCiAgICBpbnRjXzEgLy8gMzIKICAgIDw9CiAgICBhc3NlcnQgLy8gb3ZlcmZsb3cKICAgIGludGNfMSAvLyAzMgogICAgYnplcm8KICAgIGZyYW1lX2RpZyAtMQogICAgYnwKICAgIGR1cAogICAgbGVuCiAgICBpbnRjXzEgLy8gMzIKICAgID09CiAgICBhc3NlcnQgLy8gTGVuZ3RoIG11c3QgYmUgMzIKICAgIHJldHN1YgoKCi8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjpkZWJ1Z0xvZyhuYW1lOiBieXRlcywgdmFsdWU6IGJ5dGVzKSAtPiB2b2lkOgpkZWJ1Z0xvZzoKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjIxMgogICAgLy8gZnVuY3Rpb24gZGVidWdMb2cobmFtZTogc3RyaW5nLCB2YWx1ZTogYnl0ZXMpOiB2b2lkIHsKICAgIHByb3RvIDIgMAogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MjEzCiAgICAvLyBpZiAoVGVtcGxhdGVWYXI8Ym9vbGVhbj4oIkRFQlVHX0xPR0dJTkciKSkgewogICAgaW50YyAxNyAvLyBUTVBMX0RFQlVHX0xPR0dJTkcKICAgIGJ6IGRlYnVnTG9nX2FmdGVyX2lmX2Vsc2VAMgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MjE0CiAgICAvLyBsb2cobmFtZSk7CiAgICBmcmFtZV9kaWcgLTIKICAgIGxvZwogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MjE1CiAgICAvLyBsb2codmFsdWUpOwogICAgZnJhbWVfZGlnIC0xCiAgICBsb2cKCmRlYnVnTG9nX2FmdGVyX2lmX2Vsc2VAMjoKICAgIHJldHN1YgoKCi8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjpnZXRDaGFsbGVuZ2UodGQ6IGJ5dGVzKSAtPiBieXRlczoKZ2V0Q2hhbGxlbmdlOgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6Mzc3CiAgICAvLyBleHBvcnQgZnVuY3Rpb24gZ2V0Q2hhbGxlbmdlKHRkOiBieXRlcyk6IFVpbnQyNTYgewogICAgcHJvdG8gMSAxCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czozNzgKICAgIC8vIGxldCBoYXNoID0gb3Aua2VjY2FrMjU2KHRkKTsKICAgIGZyYW1lX2RpZyAtMQogICAga2VjY2FrMjU2CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNTgKICAgIC8vIHJldHVybiBhICUgQkxTMTJfMzgxX1NDQUxBUl9NT0RVTFVTOwogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czozNzkKICAgIC8vIHJldHVybiBuZXcgVWludDI1NihmclNjYWxhcihCaWdVaW50KGhhc2gpKSk7CiAgICBkdXAKICAgIGxlbgogICAgaW50Y18xIC8vIDMyCiAgICA8PQogICAgYXNzZXJ0IC8vIG92ZXJmbG93CiAgICBpbnRjXzEgLy8gMzIKICAgIGJ6ZXJvCiAgICBifAogICAgcmV0c3ViCgoKLy8gY29udHJhY3RzL3ZlcmlmaWVyLmFsZ28udHM6OlBsb25rVmVyaWZpZXIudmVyaWZ5KHNpZ25hbHM6IGJ5dGVzLCBwcm9vZjogYnl0ZXMpIC0+IHZvaWQ6CnZlcmlmeToKICAgIC8vIGNvbnRyYWN0cy92ZXJpZmllci5hbGdvLnRzOjE1CiAgICAvLyB2ZXJpZnkoc2lnbmFsczogUHVibGljU2lnbmFscywgcHJvb2Y6IFByb29mKTogdm9pZCB7CiAgICBwcm90byAyIDAKICAgIGludGNfMyAvLyAwCiAgICBkdXBuIDMzCiAgICBieXRlY18yIC8vICIiCiAgICBkdXBuIDQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjMwNAogICAgLy8gUW06IHZrQnl0ZXMuc2xpY2UoMCwgOTYpLnRvRml4ZWQoeyBsZW5ndGg6IDk2IH0pLAogICAgYnl0ZWNfMSAvLyBUTVBMX1ZFUklGSUNBVElPTl9LRVkKICAgIGxlbgogICAgaW50Y18zIC8vIDAKICAgIGRpZyAxCiAgICA+PQogICAgaW50Y18zIC8vIDAKICAgIGRpZyAyCiAgICB1bmNvdmVyIDIKICAgIHNlbGVjdAogICAgaW50Y18wIC8vIDk2CiAgICBkaWcgMgogICAgPj0KICAgIGludGNfMCAvLyA5NgogICAgZGlnIDMKICAgIHVuY292ZXIgMgogICAgc2VsZWN0CiAgICBieXRlY18xIC8vIFRNUExfVkVSSUZJQ0FUSU9OX0tFWQogICAgdW5jb3ZlciAyCiAgICBkaWcgMgogICAgc3Vic3RyaW5nMwogICAgZHVwCiAgICBsZW4KICAgIGludGNfMCAvLyA5NgogICAgPT0KICAgIGFzc2VydCAvLyBMZW5ndGggbXVzdCBiZSA5NgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MzA1CiAgICAvLyBRbDogdmtCeXRlcy5zbGljZSg5NiwgMTkyKS50b0ZpeGVkKHsgbGVuZ3RoOiA5NiB9KSwKICAgIGludGMgNSAvLyAxOTIKICAgIGRpZyAzCiAgICA+PQogICAgaW50YyA1IC8vIDE5MgogICAgZGlnIDQKICAgIHVuY292ZXIgMgogICAgc2VsZWN0CiAgICBieXRlY18xIC8vIFRNUExfVkVSSUZJQ0FUSU9OX0tFWQogICAgdW5jb3ZlciAzCiAgICBkaWcgMgogICAgc3Vic3RyaW5nMwogICAgZHVwCiAgICBsZW4KICAgIGludGNfMCAvLyA5NgogICAgPT0KICAgIGFzc2VydCAvLyBMZW5ndGggbXVzdCBiZSA5NgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MzA2CiAgICAvLyBRcjogdmtCeXRlcy5zbGljZSgxOTIsIDI4OCkudG9GaXhlZCh7IGxlbmd0aDogOTYgfSksCiAgICBpbnRjIDYgLy8gMjg4CiAgICBkaWcgNAogICAgPj0KICAgIGludGMgNiAvLyAyODgKICAgIGRpZyA1CiAgICB1bmNvdmVyIDIKICAgIHNlbGVjdAogICAgYnl0ZWNfMSAvLyBUTVBMX1ZFUklGSUNBVElPTl9LRVkKICAgIHVuY292ZXIgMwogICAgZGlnIDIKICAgIHN1YnN0cmluZzMKICAgIGR1cAogICAgbGVuCiAgICBpbnRjXzAgLy8gOTYKICAgID09CiAgICBhc3NlcnQgLy8gTGVuZ3RoIG11c3QgYmUgOTYKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjMwNwogICAgLy8gUW86IHZrQnl0ZXMuc2xpY2UoMjg4LCAzODQpLnRvRml4ZWQoeyBsZW5ndGg6IDk2IH0pLAogICAgaW50YyA0IC8vIDM4NAogICAgZGlnIDUKICAgID49CiAgICBpbnRjIDQgLy8gMzg0CiAgICBkaWcgNgogICAgdW5jb3ZlciAyCiAgICBzZWxlY3QKICAgIGJ5dGVjXzEgLy8gVE1QTF9WRVJJRklDQVRJT05fS0VZCiAgICB1bmNvdmVyIDMKICAgIGRpZyAyCiAgICBzdWJzdHJpbmczCiAgICBkdXAKICAgIGxlbgogICAgaW50Y18wIC8vIDk2CiAgICA9PQogICAgYXNzZXJ0IC8vIExlbmd0aCBtdXN0IGJlIDk2CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czozMDgKICAgIC8vIFFjOiB2a0J5dGVzLnNsaWNlKDM4NCwgNDgwKS50b0ZpeGVkKHsgbGVuZ3RoOiA5NiB9KSwKICAgIGludGMgNyAvLyA0ODAKICAgIGRpZyA2CiAgICA+PQogICAgaW50YyA3IC8vIDQ4MAogICAgZGlnIDcKICAgIHVuY292ZXIgMgogICAgc2VsZWN0CiAgICBieXRlY18xIC8vIFRNUExfVkVSSUZJQ0FUSU9OX0tFWQogICAgdW5jb3ZlciAzCiAgICBkaWcgMgogICAgc3Vic3RyaW5nMwogICAgZHVwCiAgICBsZW4KICAgIGludGNfMCAvLyA5NgogICAgPT0KICAgIGFzc2VydCAvLyBMZW5ndGggbXVzdCBiZSA5NgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MzA5CiAgICAvLyBTMTogdmtCeXRlcy5zbGljZSg0ODAsIDU3NikudG9GaXhlZCh7IGxlbmd0aDogOTYgfSksCiAgICBpbnRjIDggLy8gNTc2CiAgICBkaWcgNwogICAgPj0KICAgIGludGMgOCAvLyA1NzYKICAgIGRpZyA4CiAgICB1bmNvdmVyIDIKICAgIHNlbGVjdAogICAgYnl0ZWNfMSAvLyBUTVBMX1ZFUklGSUNBVElPTl9LRVkKICAgIHVuY292ZXIgMwogICAgZGlnIDIKICAgIHN1YnN0cmluZzMKICAgIGR1cAogICAgbGVuCiAgICBpbnRjXzAgLy8gOTYKICAgID09CiAgICBhc3NlcnQgLy8gTGVuZ3RoIG11c3QgYmUgOTYKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjMxMAogICAgLy8gUzI6IHZrQnl0ZXMuc2xpY2UoNTc2LCA2NzIpLnRvRml4ZWQoeyBsZW5ndGg6IDk2IH0pLAogICAgaW50YyA5IC8vIDY3MgogICAgZGlnIDgKICAgID49CiAgICBpbnRjIDkgLy8gNjcyCiAgICBkaWcgOQogICAgdW5jb3ZlciAyCiAgICBzZWxlY3QKICAgIGJ5dGVjXzEgLy8gVE1QTF9WRVJJRklDQVRJT05fS0VZCiAgICB1bmNvdmVyIDMKICAgIGRpZyAyCiAgICBzdWJzdHJpbmczCiAgICBkdXAKICAgIGxlbgogICAgaW50Y18wIC8vIDk2CiAgICA9PQogICAgYXNzZXJ0IC8vIExlbmd0aCBtdXN0IGJlIDk2CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czozMTEKICAgIC8vIFMzOiB2a0J5dGVzLnNsaWNlKDY3MiwgNzY4KS50b0ZpeGVkKHsgbGVuZ3RoOiA5NiB9KSwKICAgIGludGMgMTAgLy8gNzY4CiAgICBkaWcgOQogICAgPj0KICAgIGludGMgMTAgLy8gNzY4CiAgICBkaWcgMTAKICAgIHVuY292ZXIgMgogICAgc2VsZWN0CiAgICBieXRlY18xIC8vIFRNUExfVkVSSUZJQ0FUSU9OX0tFWQogICAgdW5jb3ZlciAzCiAgICBkaWcgMgogICAgc3Vic3RyaW5nMwogICAgZHVwCiAgICBsZW4KICAgIGludGNfMCAvLyA5NgogICAgPT0KICAgIGFzc2VydCAvLyBMZW5ndGggbXVzdCBiZSA5NgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MzEyCiAgICAvLyBwb3dlcjogb3AuYnRvaSh2a0J5dGVzLnNsaWNlKDc2OCwgNzc2KSksCiAgICBpbnRjIDExIC8vIDc3NgogICAgZGlnIDEwCiAgICA+PQogICAgaW50YyAxMSAvLyA3NzYKICAgIGRpZyAxMQogICAgdW5jb3ZlciAyCiAgICBzZWxlY3QKICAgIGJ5dGVjXzEgLy8gVE1QTF9WRVJJRklDQVRJT05fS0VZCiAgICB1bmNvdmVyIDMKICAgIGRpZyAyCiAgICBzdWJzdHJpbmczCiAgICBidG9pCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czozMTMKICAgIC8vIG5QdWJsaWM6IG9wLmJ0b2kodmtCeXRlcy5zbGljZSg3NzYsIDc4NCkpLAogICAgaW50YyAxMiAvLyA3ODQKICAgIGRpZyAxMQogICAgPj0KICAgIGludGMgMTIgLy8gNzg0CiAgICBkaWcgMTIKICAgIHVuY292ZXIgMgogICAgc2VsZWN0CiAgICBieXRlY18xIC8vIFRNUExfVkVSSUZJQ0FUSU9OX0tFWQogICAgdW5jb3ZlciAzCiAgICBkaWcgMgogICAgc3Vic3RyaW5nMwogICAgYnRvaQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MzE0CiAgICAvLyBrMTogb3AuYnRvaSh2a0J5dGVzLnNsaWNlKDc4NCwgNzkyKSksCiAgICBpbnRjIDEzIC8vIDc5MgogICAgZGlnIDEyCiAgICA+PQogICAgaW50YyAxMyAvLyA3OTIKICAgIGRpZyAxMwogICAgdW5jb3ZlciAyCiAgICBzZWxlY3QKICAgIGJ5dGVjXzEgLy8gVE1QTF9WRVJJRklDQVRJT05fS0VZCiAgICB1bmNvdmVyIDMKICAgIGRpZyAyCiAgICBzdWJzdHJpbmczCiAgICBidG9pCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czozMTUKICAgIC8vIGsyOiBvcC5idG9pKHZrQnl0ZXMuc2xpY2UoNzkyLCA4MDApKSwKICAgIGludGMgMTQgLy8gODAwCiAgICBkaWcgMTMKICAgID49CiAgICBpbnRjIDE0IC8vIDgwMAogICAgZGlnIDE0CiAgICB1bmNvdmVyIDIKICAgIHNlbGVjdAogICAgYnl0ZWNfMSAvLyBUTVBMX1ZFUklGSUNBVElPTl9LRVkKICAgIHVuY292ZXIgMwogICAgZGlnIDIKICAgIHN1YnN0cmluZzMKICAgIGJ0b2kKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjMxNgogICAgLy8gWF8yOiB2a0J5dGVzLnNsaWNlKDgwMCwgOTkyKS50b0ZpeGVkKHsgbGVuZ3RoOiAxOTIgfSksCiAgICBpbnRjIDE1IC8vIDk5MgogICAgZGlnIDE0CiAgICA+PQogICAgaW50YyAxNSAvLyA5OTIKICAgIHVuY292ZXIgMTUKICAgIHVuY292ZXIgMgogICAgc2VsZWN0CiAgICBieXRlY18xIC8vIFRNUExfVkVSSUZJQ0FUSU9OX0tFWQogICAgdW5jb3ZlciAzCiAgICB1bmNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIGR1cAogICAgbGVuCiAgICBpbnRjIDUgLy8gMTkyCiAgICA9PQogICAgYXNzZXJ0IC8vIExlbmd0aCBtdXN0IGJlIDE5MgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MzAzLTMxNwogICAgLy8gY29uc3Qgdms6IFZlcmlmaWNhdGlvbktleSA9IHsKICAgIC8vICAgUW06IHZrQnl0ZXMuc2xpY2UoMCwgOTYpLnRvRml4ZWQoeyBsZW5ndGg6IDk2IH0pLAogICAgLy8gICBRbDogdmtCeXRlcy5zbGljZSg5NiwgMTkyKS50b0ZpeGVkKHsgbGVuZ3RoOiA5NiB9KSwKICAgIC8vICAgUXI6IHZrQnl0ZXMuc2xpY2UoMTkyLCAyODgpLnRvRml4ZWQoeyBsZW5ndGg6IDk2IH0pLAogICAgLy8gICBRbzogdmtCeXRlcy5zbGljZSgyODgsIDM4NCkudG9GaXhlZCh7IGxlbmd0aDogOTYgfSksCiAgICAvLyAgIFFjOiB2a0J5dGVzLnNsaWNlKDM4NCwgNDgwKS50b0ZpeGVkKHsgbGVuZ3RoOiA5NiB9KSwKICAgIC8vICAgUzE6IHZrQnl0ZXMuc2xpY2UoNDgwLCA1NzYpLnRvRml4ZWQoeyBsZW5ndGg6IDk2IH0pLAogICAgLy8gICBTMjogdmtCeXRlcy5zbGljZSg1NzYsIDY3MikudG9GaXhlZCh7IGxlbmd0aDogOTYgfSksCiAgICAvLyAgIFMzOiB2a0J5dGVzLnNsaWNlKDY3MiwgNzY4KS50b0ZpeGVkKHsgbGVuZ3RoOiA5NiB9KSwKICAgIC8vICAgcG93ZXI6IG9wLmJ0b2kodmtCeXRlcy5zbGljZSg3NjgsIDc3NikpLAogICAgLy8gICBuUHVibGljOiBvcC5idG9pKHZrQnl0ZXMuc2xpY2UoNzc2LCA3ODQpKSwKICAgIC8vICAgazE6IG9wLmJ0b2kodmtCeXRlcy5zbGljZSg3ODQsIDc5MikpLAogICAgLy8gICBrMjogb3AuYnRvaSh2a0J5dGVzLnNsaWNlKDc5MiwgODAwKSksCiAgICAvLyAgIFhfMjogdmtCeXRlcy5zbGljZSg4MDAsIDk5MikudG9GaXhlZCh7IGxlbmd0aDogMTkyIH0pLAogICAgLy8gfTsKICAgIHVuY292ZXIgMTIKICAgIHVuY292ZXIgMTIKICAgIGNvbmNhdAogICAgdW5jb3ZlciAxMQogICAgY29uY2F0CiAgICB1bmNvdmVyIDEwCiAgICBjb25jYXQKICAgIHVuY292ZXIgOQogICAgY29uY2F0CiAgICB1bmNvdmVyIDgKICAgIGNvbmNhdAogICAgdW5jb3ZlciA3CiAgICBjb25jYXQKICAgIHVuY292ZXIgNgogICAgY29uY2F0CiAgICB1bmNvdmVyIDUKICAgIGl0b2IKICAgIGNvbmNhdAogICAgdW5jb3ZlciA0CiAgICBpdG9iCiAgICBjb25jYXQKICAgIHVuY292ZXIgMwogICAgaXRvYgogICAgY29uY2F0CiAgICB1bmNvdmVyIDIKICAgIGl0b2IKICAgIGNvbmNhdAogICAgc3dhcAogICAgY29uY2F0CiAgICBkdXBuIDIKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjM5NAogICAgLy8gbGV0IHRkID0gb3AuY29uY2F0KHZrLlFtLCB2ay5RbCk7CiAgICBleHRyYWN0IDAgOTYKICAgIGRpZyAxCiAgICBleHRyYWN0IDk2IDk2CiAgICBjb25jYXQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjM5NQogICAgLy8gdGQgPSBvcC5jb25jYXQodGQsIHZrLlFyKTsKICAgIGRpZyAxCiAgICBleHRyYWN0IDE5MiA5NgogICAgY29uY2F0CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czozOTYKICAgIC8vIHRkID0gb3AuY29uY2F0KHRkLCB2ay5Rbyk7CiAgICBkaWcgMQogICAgaW50YyA2IC8vIDI4OAogICAgaW50Y18wIC8vIDk2CiAgICBleHRyYWN0MwogICAgY29uY2F0CiAgICBkdXAKICAgIGNvdmVyIDIKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjM5NwogICAgLy8gdGQgPSBvcC5jb25jYXQodGQsIHZrLlFjKTsKICAgIGRpZyAxCiAgICBpbnRjIDQgLy8gMzg0CiAgICBpbnRjXzAgLy8gOTYKICAgIGV4dHJhY3QzCiAgICBkdXAKICAgIGNvdmVyIDMKICAgIGNvbmNhdAogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6Mzk4CiAgICAvLyB0ZCA9IG9wLmNvbmNhdCh0ZCwgdmsuUzEpOwogICAgZGlnIDEKICAgIGludGMgNyAvLyA0ODAKICAgIGludGNfMCAvLyA5NgogICAgZXh0cmFjdDMKICAgIGR1cAogICAgY292ZXIgMwogICAgY29uY2F0CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czozOTkKICAgIC8vIHRkID0gb3AuY29uY2F0KHRkLCB2ay5TMik7CiAgICBkaWcgMQogICAgaW50YyA4IC8vIDU3NgogICAgaW50Y18wIC8vIDk2CiAgICBleHRyYWN0MwogICAgZHVwCiAgICBjb3ZlciAzCiAgICBjb25jYXQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjQwMAogICAgLy8gdGQgPSBvcC5jb25jYXQodGQsIHZrLlMzKTsKICAgIHN3YXAKICAgIGludGMgOSAvLyA2NzIKICAgIGludGNfMCAvLyA5NgogICAgZXh0cmFjdDMKICAgIGR1cAogICAgY292ZXIgMgogICAgY29uY2F0CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo0MDIKICAgIC8vIGZvciAoY29uc3Qgc2lnbmFsIG9mIHNpZ25hbHMpIHsKICAgIGZyYW1lX2RpZyAtMgogICAgaW50Y18zIC8vIDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBpbnRjXzMgLy8gMAoKdmVyaWZ5X2Zvcl9oZWFkZXJAMjoKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjQwMgogICAgLy8gZm9yIChjb25zdCBzaWduYWwgb2Ygc2lnbmFscykgewogICAgZnJhbWVfZGlnIDQ3CiAgICBmcmFtZV9kaWcgNDYKICAgIDwKICAgIGJ6IHZlcmlmeV9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIC0yCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIDQ3CiAgICBkdXAKICAgIGNvdmVyIDIKICAgIGludGNfMSAvLyAzMgogICAgKgogICAgaW50Y18xIC8vIDMyCiAgICBleHRyYWN0MyAvLyBvbiBlcnJvcjogaW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjE1OAogICAgLy8gcmV0dXJuIGEgJSBCTFMxMl8zODFfU0NBTEFSX01PRFVMVVM7CiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjQwMwogICAgLy8gdGQgPSBvcC5jb25jYXQodGQsIGIzMihmclNjYWxhcihzaWduYWwubmF0aXZlKSkpOwogICAgY2FsbHN1YiBiMzIKICAgIGZyYW1lX2RpZyA0NQogICAgc3dhcAogICAgY29uY2F0CiAgICBmcmFtZV9idXJ5IDQ1CiAgICBpbnRjXzIgLy8gMQogICAgKwogICAgZnJhbWVfYnVyeSA0NwogICAgYiB2ZXJpZnlfZm9yX2hlYWRlckAyCgp2ZXJpZnlfYWZ0ZXJfZm9yQDQ6CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo0MDcKICAgIC8vIHRkID0gb3AuY29uY2F0KHRkLCBwcm9vZi5BKTsKICAgIGZyYW1lX2RpZyAtMQogICAgZXh0cmFjdCAwIDk2CiAgICBkdXAKICAgIGZyYW1lX2J1cnkgOQogICAgZnJhbWVfZGlnIDQ1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjQwOAogICAgLy8gdGQgPSBvcC5jb25jYXQodGQsIHByb29mLkIpOwogICAgZnJhbWVfZGlnIC0xCiAgICBleHRyYWN0IDk2IDk2CiAgICBkdXAKICAgIGZyYW1lX2J1cnkgMTAKICAgIGNvbmNhdAogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NDA5CiAgICAvLyB0ZCA9IG9wLmNvbmNhdCh0ZCwgcHJvb2YuQyk7CiAgICBmcmFtZV9kaWcgLTEKICAgIGV4dHJhY3QgMTkyIDk2CiAgICBkdXAKICAgIGZyYW1lX2J1cnkgNQogICAgY29uY2F0CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo0MTEKICAgIC8vIGNvbnN0IGJldGEgPSBnZXRDaGFsbGVuZ2UodGQpOwogICAgY2FsbHN1YiBnZXRDaGFsbGVuZ2UKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjQxNgogICAgLy8gY29uc3QgZ2FtbWEgPSBnZXRDaGFsbGVuZ2UodGQpOwogICAgZHVwCiAgICBjYWxsc3ViIGdldENoYWxsZW5nZQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NDIzCiAgICAvLyB0ZCA9IG9wLmNvbmNhdCh0ZCwgZ2FtbWEuYnl0ZXMpOwogICAgY29uY2F0CiAgICBkdXAKICAgIGZyYW1lX2J1cnkgNDUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjQyNAogICAgLy8gdGQgPSBvcC5jb25jYXQodGQsIHByb29mLlopOwogICAgZnJhbWVfZGlnIC0xCiAgICBpbnRjIDYgLy8gMjg4CiAgICBpbnRjXzAgLy8gOTYKICAgIGV4dHJhY3QzCiAgICBkdXAKICAgIGZyYW1lX2J1cnkgMjMKICAgIGNvbmNhdAogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NDI1CiAgICAvLyBjb25zdCBhbHBoYSA9IGdldENoYWxsZW5nZSh0ZCk7CiAgICBjYWxsc3ViIGdldENoYWxsZW5nZQogICAgZHVwCiAgICBmcmFtZV9idXJ5IDExCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo0MzIKICAgIC8vIHRkID0gb3AuY29uY2F0KHRkLCBwcm9vZi5UMSk7CiAgICBmcmFtZV9kaWcgLTEKICAgIGludGMgNCAvLyAzODQKICAgIGludGNfMCAvLyA5NgogICAgZXh0cmFjdDMKICAgIGR1cAogICAgZnJhbWVfYnVyeSA2CiAgICBjb25jYXQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjQzMwogICAgLy8gdGQgPSBvcC5jb25jYXQodGQsIHByb29mLlQyKTsKICAgIGZyYW1lX2RpZyAtMQogICAgaW50YyA3IC8vIDQ4MAogICAgaW50Y18wIC8vIDk2CiAgICBleHRyYWN0MwogICAgZHVwCiAgICBmcmFtZV9idXJ5IDcKICAgIGNvbmNhdAogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NDM0CiAgICAvLyB0ZCA9IG9wLmNvbmNhdCh0ZCwgcHJvb2YuVDMpOwogICAgZnJhbWVfZGlnIC0xCiAgICBpbnRjIDggLy8gNTc2CiAgICBpbnRjXzAgLy8gOTYKICAgIGV4dHJhY3QzCiAgICBkdXAKICAgIGZyYW1lX2J1cnkgOAogICAgY29uY2F0CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo0MzUKICAgIC8vIGNvbnN0IHhpID0gZ2V0Q2hhbGxlbmdlKHRkKTsKICAgIGNhbGxzdWIgZ2V0Q2hhbGxlbmdlCiAgICBkdXAKICAgIGZyYW1lX2J1cnkgMzIKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjQ0MgogICAgLy8gdGQgPSBvcC5jb25jYXQodGQsIHByb29mLmV2YWxfYS5ieXRlcyk7CiAgICBmcmFtZV9kaWcgLTEKICAgIHB1c2hpbnQgODY0IC8vIDg2NAogICAgaW50Y18xIC8vIDMyCiAgICBleHRyYWN0MwogICAgZHVwCiAgICBmcmFtZV9idXJ5IDE4CiAgICBjb25jYXQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjQ0MwogICAgLy8gdGQgPSBvcC5jb25jYXQodGQsIHByb29mLmV2YWxfYi5ieXRlcyk7CiAgICBmcmFtZV9kaWcgLTEKICAgIHB1c2hpbnQgODk2IC8vIDg5NgogICAgaW50Y18xIC8vIDMyCiAgICBleHRyYWN0MwogICAgZHVwCiAgICBmcmFtZV9idXJ5IDE5CiAgICBjb25jYXQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjQ0NAogICAgLy8gdGQgPSBvcC5jb25jYXQodGQsIHByb29mLmV2YWxfYy5ieXRlcyk7CiAgICBmcmFtZV9kaWcgLTEKICAgIHB1c2hpbnQgOTI4IC8vIDkyOAogICAgaW50Y18xIC8vIDMyCiAgICBleHRyYWN0MwogICAgZHVwCiAgICBmcmFtZV9idXJ5IDIwCiAgICBjb25jYXQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjQ0NQogICAgLy8gdGQgPSBvcC5jb25jYXQodGQsIHByb29mLmV2YWxfczEuYnl0ZXMpOwogICAgZnJhbWVfZGlnIC0xCiAgICBwdXNoaW50IDk2MCAvLyA5NjAKICAgIGludGNfMSAvLyAzMgogICAgZXh0cmFjdDMKICAgIGR1cAogICAgZnJhbWVfYnVyeSAxNQogICAgY29uY2F0CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo0NDYKICAgIC8vIHRkID0gb3AuY29uY2F0KHRkLCBwcm9vZi5ldmFsX3MyLmJ5dGVzKTsKICAgIGZyYW1lX2RpZyAtMQogICAgaW50YyAxNSAvLyA5OTIKICAgIGludGNfMSAvLyAzMgogICAgZXh0cmFjdDMKICAgIGR1cAogICAgZnJhbWVfYnVyeSAxMwogICAgY29uY2F0CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo0NDcKICAgIC8vIHRkID0gb3AuY29uY2F0KHRkLCBwcm9vZi5ldmFsX3p3LmJ5dGVzKTsKICAgIGZyYW1lX2RpZyAtMQogICAgcHVzaGludCAxMDI0IC8vIDEwMjQKICAgIGludGNfMSAvLyAzMgogICAgZXh0cmFjdDMKICAgIGR1cAogICAgZnJhbWVfYnVyeSAxNAogICAgY29uY2F0CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo0NDkKICAgIC8vIGNvbnN0IHYgPSBuZXcgRml4ZWRBcnJheTxVaW50MjU2LCA2PigpOwogICAgaW50YyA1IC8vIDE5MgogICAgYnplcm8KICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjQ1MAogICAgLy8gdlsxXSA9IGdldENoYWxsZW5nZSh0ZCk7IC8vIHYxCiAgICBzd2FwCiAgICBjYWxsc3ViIGdldENoYWxsZW5nZQogICAgcmVwbGFjZTIgMzIgLy8gb24gZXJyb3I6IGluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBmcmFtZV9idXJ5IDMwCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo0NTEKICAgIC8vIGZvciAobGV0IGk6IHVpbnQ2NCA9IDI7IGkgPCA2OyBpKyspIHsKICAgIHB1c2hpbnQgMiAvLyAyCiAgICBmcmFtZV9idXJ5IDM1Cgp2ZXJpZnlfd2hpbGVfdG9wQDU6CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo0NTEKICAgIC8vIGZvciAobGV0IGk6IHVpbnQ2NCA9IDI7IGkgPCA2OyBpKyspIHsKICAgIGZyYW1lX2RpZyAzNQogICAgcHVzaGludCA2IC8vIDYKICAgIDwKICAgIGJ6IHZlcmlmeV9hZnRlcl93aGlsZUA3CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo0NTIKICAgIC8vIHZbaV0gPSBuZXcgVWludDI1Nihmck11bCgodltpIC0gMV0gYXMgVWludDI1NikubmF0aXZlLCB2WzFdLm5hdGl2ZSkpOyAvLyB2W2ldID0gdjFeaQogICAgZnJhbWVfZGlnIDM1CiAgICBkdXAKICAgIGludGNfMiAvLyAxCiAgICAtCiAgICBpbnRjXzEgLy8gMzIKICAgICoKICAgIGZyYW1lX2RpZyAzMAogICAgZHVwCiAgICB1bmNvdmVyIDIKICAgIGludGNfMSAvLyAzMgogICAgZXh0cmFjdDMgLy8gb24gZXJyb3I6IGluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBkaWcgMQogICAgZXh0cmFjdCAzMiAzMiAvLyBvbiBlcnJvcjogaW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjY0CiAgICAvLyByZXR1cm4gKGEgKiBiKSAlIEJMUzEyXzM4MV9TQ0FMQVJfTU9EVUxVUzsKICAgIGIqCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjQ1MgogICAgLy8gdltpXSA9IG5ldyBVaW50MjU2KGZyTXVsKCh2W2kgLSAxXSBhcyBVaW50MjU2KS5uYXRpdmUsIHZbMV0ubmF0aXZlKSk7IC8vIHZbaV0gPSB2MV5pCiAgICBkdXAKICAgIGxlbgogICAgaW50Y18xIC8vIDMyCiAgICA8PQogICAgYXNzZXJ0IC8vIG92ZXJmbG93CiAgICBpbnRjXzEgLy8gMzIKICAgIGJ6ZXJvCiAgICBifAogICAgZGlnIDIKICAgIGludGNfMSAvLyAzMgogICAgKgogICAgc3dhcAogICAgcmVwbGFjZTMgLy8gb24gZXJyb3I6IGluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBmcmFtZV9idXJ5IDMwCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo0NTEKICAgIC8vIGZvciAobGV0IGk6IHVpbnQ2NCA9IDI7IGkgPCA2OyBpKyspIHsKICAgIGludGNfMiAvLyAxCiAgICArCiAgICBmcmFtZV9idXJ5IDM1CiAgICBiIHZlcmlmeV93aGlsZV90b3BANQoKdmVyaWZ5X2FmdGVyX3doaWxlQDc6CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo0NTkKICAgIC8vIHRkID0gb3AuY29uY2F0KHRkLCBwcm9vZi5XeGkpOwogICAgZnJhbWVfZGlnIC0xCiAgICBpbnRjIDkgLy8gNjcyCiAgICBpbnRjXzAgLy8gOTYKICAgIGV4dHJhY3QzCiAgICBkdXAKICAgIGZyYW1lX2J1cnkgMjgKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjQ2MAogICAgLy8gdGQgPSBvcC5jb25jYXQodGQsIHByb29mLld4aXcpOwogICAgZnJhbWVfZGlnIC0xCiAgICBpbnRjIDEwIC8vIDc2OAogICAgaW50Y18wIC8vIDk2CiAgICBleHRyYWN0MwogICAgZHVwCiAgICBmcmFtZV9idXJ5IDI0CiAgICBjb25jYXQKICAgIGR1cAogICAgZnJhbWVfYnVyeSAyOQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NDYxCiAgICAvLyBjb25zdCB1ID0gZ2V0Q2hhbGxlbmdlKHRkKTsKICAgIGNhbGxzdWIgZ2V0Q2hhbGxlbmdlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo0NjMtNDcyCiAgICAvLyByZXR1cm4gewogICAgLy8gICBiZXRhLAogICAgLy8gICBnYW1tYSwKICAgIC8vICAgYWxwaGEsCiAgICAvLyAgIHhpLAogICAgLy8gICB2LAogICAgLy8gICB1LAogICAgLy8gICB4aW46IG5ldyBVaW50MjU2KCksCiAgICAvLyAgIHpoOiBuZXcgVWludDI1NigpLAogICAgLy8gfTsKICAgIGZyYW1lX2RpZyA0NQogICAgZnJhbWVfZGlnIDExCiAgICBjb25jYXQKICAgIGZyYW1lX2RpZyAzMgogICAgY29uY2F0CiAgICBmcmFtZV9kaWcgMzAKICAgIGNvbmNhdAogICAgc3dhcAogICAgY29uY2F0CiAgICBwdXNoYnl0ZXMgMHgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAogICAgY29uY2F0CiAgICBkdXAKICAgIGZyYW1lX2J1cnkgMTYKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjMzMgogICAgLy8gZGVidWdMb2coImJldGEiLCBjaGFsbGVuZ2VzLmJldGEuYnl0ZXMpOwogICAgZHVwCiAgICBleHRyYWN0IDAgMzIKICAgIHB1c2hieXRlcyAiYmV0YSIKICAgIHN3YXAKICAgIGNhbGxzdWIgZGVidWdMb2cKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjMzMwogICAgLy8gZGVidWdMb2coImdhbW1hIiwgY2hhbGxlbmdlcy5nYW1tYS5ieXRlcyk7CiAgICBkdXAKICAgIGV4dHJhY3QgMzIgMzIKICAgIHB1c2hieXRlcyAiZ2FtbWEiCiAgICBzd2FwCiAgICBjYWxsc3ViIGRlYnVnTG9nCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czozMzQKICAgIC8vIGRlYnVnTG9nKCJhbHBoYSIsIGNoYWxsZW5nZXMuYWxwaGEuYnl0ZXMpOwogICAgZHVwCiAgICBleHRyYWN0IDY0IDMyCiAgICBwdXNoYnl0ZXMgImFscGhhIgogICAgc3dhcAogICAgY2FsbHN1YiBkZWJ1Z0xvZwogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MzM1CiAgICAvLyBkZWJ1Z0xvZygieGkiLCBjaGFsbGVuZ2VzLnhpLmJ5dGVzKTsKICAgIGR1cAogICAgZXh0cmFjdCA5NiAzMgogICAgZHVwCiAgICBmcmFtZV9idXJ5IDMzCiAgICBwdXNoYnl0ZXMgInhpIgogICAgc3dhcAogICAgY2FsbHN1YiBkZWJ1Z0xvZwogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MzM2CiAgICAvLyBkZWJ1Z0xvZygidSIsIGNoYWxsZW5nZXMudS5ieXRlcyk7CiAgICBkdXAKICAgIHB1c2hpbnQgMzIwIC8vIDMyMAogICAgaW50Y18xIC8vIDMyCiAgICBleHRyYWN0MwogICAgcHVzaGJ5dGVzICJ1IgogICAgc3dhcAogICAgY2FsbHN1YiBkZWJ1Z0xvZwogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MzM3CiAgICAvLyBkZWJ1Z0xvZygieGluIiwgY2hhbGxlbmdlcy54aW4uYnl0ZXMpOwogICAgZHVwCiAgICBpbnRjIDE2IC8vIDM1MgogICAgaW50Y18xIC8vIDMyCiAgICBleHRyYWN0MwogICAgcHVzaGJ5dGVzICJ4aW4iCiAgICBzd2FwCiAgICBjYWxsc3ViIGRlYnVnTG9nCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czozMzgKICAgIC8vIGRlYnVnTG9nKCJ6aCIsIGNoYWxsZW5nZXMuemguYnl0ZXMpOwogICAgZHVwCiAgICBpbnRjIDQgLy8gMzg0CiAgICBpbnRjXzEgLy8gMzIKICAgIGV4dHJhY3QzCiAgICBwdXNoYnl0ZXMgInpoIgogICAgc3dhcAogICAgY2FsbHN1YiBkZWJ1Z0xvZwogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MzM5CiAgICAvLyBkZWJ1Z0xvZygidlsxXSIsIChjaGFsbGVuZ2VzLnZbMV0gYXMgVWludDI1NikuYnl0ZXMpOwogICAgZXh0cmFjdCAxMjggMTkyCiAgICBkdXAKICAgIGV4dHJhY3QgMzIgMzIgLy8gb24gZXJyb3I6IGluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBwdXNoYnl0ZXMgInZbMV0iCiAgICBzd2FwCiAgICBjYWxsc3ViIGRlYnVnTG9nCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czozMzktMzQwCiAgICAvLyBkZWJ1Z0xvZygidlsxXSIsIChjaGFsbGVuZ2VzLnZbMV0gYXMgVWludDI1NikuYnl0ZXMpOwogICAgLy8gZGVidWdMb2coInZbMl0iLCAoY2hhbGxlbmdlcy52WzJdIGFzIFVpbnQyNTYpLmJ5dGVzKTsKICAgIGR1cAogICAgZXh0cmFjdCA2NCAzMiAvLyBvbiBlcnJvcjogaW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjM0MAogICAgLy8gZGVidWdMb2coInZbMl0iLCAoY2hhbGxlbmdlcy52WzJdIGFzIFVpbnQyNTYpLmJ5dGVzKTsKICAgIHB1c2hieXRlcyAidlsyXSIKICAgIHN3YXAKICAgIGNhbGxzdWIgZGVidWdMb2cKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjM0MQogICAgLy8gZGVidWdMb2coInZbM10iLCAoY2hhbGxlbmdlcy52WzNdIGFzIFVpbnQyNTYpLmJ5dGVzKTsKICAgIGR1cAogICAgZXh0cmFjdCA5NiAzMiAvLyBvbiBlcnJvcjogaW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIHB1c2hieXRlcyAidlszXSIKICAgIHN3YXAKICAgIGNhbGxzdWIgZGVidWdMb2cKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjM0MgogICAgLy8gZGVidWdMb2coInZbNF0iLCAoY2hhbGxlbmdlcy52WzRdIGFzIFVpbnQyNTYpLmJ5dGVzKTsKICAgIGR1cAogICAgZXh0cmFjdCAxMjggMzIgLy8gb24gZXJyb3I6IGluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBwdXNoYnl0ZXMgInZbNF0iCiAgICBzd2FwCiAgICBjYWxsc3ViIGRlYnVnTG9nCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czozNDMKICAgIC8vIGRlYnVnTG9nKCJ2WzVdIiwgKGNoYWxsZW5nZXMudls1XSBhcyBVaW50MjU2KS5ieXRlcyk7CiAgICBleHRyYWN0IDE2MCAzMiAvLyBvbiBlcnJvcjogaW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIHB1c2hieXRlcyAidls1XSIKICAgIHN3YXAKICAgIGNhbGxzdWIgZGVidWdMb2cKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjQ4NgogICAgLy8gbGV0IGRvbWFpblNpemU6IHVpbnQ2NCA9IDE7CiAgICBpbnRjXzIgLy8gMQogICAgZnJhbWVfYnVyeSAzNAogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NDg3CiAgICAvLyBmb3IgKGxldCBpOiB1aW50NjQgPSAwOyBpIDwgdmsucG93ZXI7IGkrKykgewogICAgaW50Y18zIC8vIDAKICAgIGZyYW1lX2J1cnkgMzUKCnZlcmlmeV93aGlsZV90b3BAMTA6CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo0ODcKICAgIC8vIGZvciAobGV0IGk6IHVpbnQ2NCA9IDA7IGkgPCB2ay5wb3dlcjsgaSsrKSB7CiAgICBmcmFtZV9kaWcgMzkKICAgIGludGMgMTAgLy8gNzY4CiAgICBleHRyYWN0X3VpbnQ2NAogICAgZnJhbWVfZGlnIDM1CiAgICA+CiAgICBieiB2ZXJpZnlfYWZ0ZXJfd2hpbGVAMTIKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjY0CiAgICAvLyByZXR1cm4gKGEgKiBiKSAlIEJMUzEyXzM4MV9TQ0FMQVJfTU9EVUxVUzsKICAgIGZyYW1lX2RpZyAzMwogICAgZHVwCiAgICBiKgogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICBmcmFtZV9idXJ5IDMzCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo0ODkKICAgIC8vIGRvbWFpblNpemUgKj0gMjsKICAgIGZyYW1lX2RpZyAzNAogICAgcHVzaGludCAyIC8vIDIKICAgICoKICAgIGZyYW1lX2J1cnkgMzQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjQ4NwogICAgLy8gZm9yIChsZXQgaTogdWludDY0ID0gMDsgaSA8IHZrLnBvd2VyOyBpKyspIHsKICAgIGZyYW1lX2RpZyAzNQogICAgaW50Y18yIC8vIDEKICAgICsKICAgIGZyYW1lX2J1cnkgMzUKICAgIGIgdmVyaWZ5X3doaWxlX3RvcEAxMAoKdmVyaWZ5X2FmdGVyX3doaWxlQDEyOgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NDkyCiAgICAvLyBjaGFsbGVuZ2VzLnhpbiA9IG5ldyBVaW50MjU2KHhpbik7CiAgICBmcmFtZV9kaWcgMzMKICAgIGR1cAogICAgbGVuCiAgICBpbnRjXzEgLy8gMzIKICAgIDw9CiAgICBhc3NlcnQgLy8gb3ZlcmZsb3cKICAgIGludGNfMSAvLyAzMgogICAgYnplcm8KICAgIGR1cAogICAgZnJhbWVfYnVyeSAzCiAgICBkdXAyCiAgICBifAogICAgZnJhbWVfZGlnIDE2CiAgICBpbnRjIDE2IC8vIDM1MgogICAgdW5jb3ZlciAyCiAgICByZXBsYWNlMwogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NDkzCiAgICAvLyBjaGFsbGVuZ2VzLnpoID0gbmV3IFVpbnQyNTYoZnJTdWIoeGluLCBCaWdVaW50KDEpKSk7IC8vIFZhbmlzaGluZyBwb2x5bm9taWFsIFpfSCjOvikgPSDOvl5uIC0gMQogICAgdW5jb3ZlciAyCiAgICBieXRlY18zIC8vIDB4MDEKICAgIGNhbGxzdWIgZnJTdWIKICAgIGR1cAogICAgbGVuCiAgICBpbnRjXzEgLy8gMzIKICAgIDw9CiAgICBhc3NlcnQgLy8gb3ZlcmZsb3cKICAgIHVuY292ZXIgMgogICAgYnwKICAgIGludGMgNCAvLyAzODQKICAgIHN3YXAKICAgIHJlcGxhY2UzCiAgICBmcmFtZV9idXJ5IDE2CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo0OTUKICAgIC8vIGNvbnN0IG4gPSBmclNjYWxhcihCaWdVaW50KGRvbWFpblNpemUpKTsKICAgIGZyYW1lX2RpZyAzNAogICAgaXRvYgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MTU4CiAgICAvLyByZXR1cm4gYSAlIEJMUzEyXzM4MV9TQ0FMQVJfTU9EVUxVUzsKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiJQogICAgZnJhbWVfYnVyeSAyMgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NTAxCiAgICAvLyBsZXQgdyA9IEJpZ1VpbnQoMSk7CiAgICBieXRlY18zIC8vIDB4MDEKICAgIGZyYW1lX2J1cnkgMzEKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjUxMAogICAgLy8gY29uc3QgTDogVWludDI1NltdID0gW25ldyBVaW50MjU2KCldOwogICAgcHVzaGJ5dGVzIDB4MDAwMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAKICAgIGZyYW1lX2J1cnkgMAogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NTEzCiAgICAvLyBjb25zdCBpdGVyYXRpb25zOiB1aW50NjQgPSB2ay5uUHVibGljID09PSAwID8gMSA6IHZrLm5QdWJsaWM7CiAgICBmcmFtZV9kaWcgMzkKICAgIGludGMgMTEgLy8gNzc2CiAgICBleHRyYWN0X3VpbnQ2NAogICAgZHVwCiAgICBmcmFtZV9idXJ5IDM4CiAgICBibnogdmVyaWZ5X3Rlcm5hcnlfZmFsc2VAMTQKICAgIGludGNfMiAvLyAxCiAgICBmcmFtZV9idXJ5IDM2Cgp2ZXJpZnlfdGVybmFyeV9tZXJnZUAxNToKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjUxNAogICAgLy8gZm9yIChsZXQgaTogdWludDY0ID0gMTsgaSA8PSBpdGVyYXRpb25zOyBpKyspIHsKICAgIGludGNfMiAvLyAxCiAgICBmcmFtZV9idXJ5IDM3Cgp2ZXJpZnlfd2hpbGVfdG9wQDE2OgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NTE0CiAgICAvLyBmb3IgKGxldCBpOiB1aW50NjQgPSAxOyBpIDw9IGl0ZXJhdGlvbnM7IGkrKykgewogICAgZnJhbWVfZGlnIDM3CiAgICBmcmFtZV9kaWcgMzYKICAgIDw9CiAgICBieiB2ZXJpZnlfYWZ0ZXJfd2hpbGVAMjMKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjUxOAogICAgLy8gZnJNdWwodywgY2hhbGxlbmdlcy56aC5uYXRpdmUpLAogICAgZnJhbWVfZGlnIDE2CiAgICBkdXAKICAgIGludGMgNCAvLyAzODQKICAgIGludGNfMSAvLyAzMgogICAgZXh0cmFjdDMKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjY0CiAgICAvLyByZXR1cm4gKGEgKiBiKSAlIEJMUzEyXzM4MV9TQ0FMQVJfTU9EVUxVUzsKICAgIGZyYW1lX2RpZyAzMQogICAgZHVwCiAgICB1bmNvdmVyIDIKICAgIGIqCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjUxOQogICAgLy8gZnJNdWwobiwgZnJTdWIoY2hhbGxlbmdlcy54aS5uYXRpdmUsIHcpKSwKICAgIHVuY292ZXIgMgogICAgZXh0cmFjdCA5NiAzMgogICAgdW5jb3ZlciAyCiAgICBjYWxsc3ViIGZyU3ViCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo2NAogICAgLy8gcmV0dXJuIChhICogYikgJSBCTFMxMl8zODFfU0NBTEFSX01PRFVMVVM7CiAgICBmcmFtZV9kaWcgMjIKICAgIGIqCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjE1OAogICAgLy8gcmV0dXJuIGEgJSBCTFMxMl8zODFfU0NBTEFSX01PRFVMVVM7CiAgICBzd2FwCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIGZyYW1lX2J1cnkgMQogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxMTEKICAgIC8vIGFzc2VydCh4ICE9PSAoMG4gYXMgYmlndWludCksICJGciBpbnZlcnNlIG9mIHplcm8iKTsKICAgIGR1cAogICAgYnl0ZWNfMiAvLyAweAogICAgYiE9CiAgICBhc3NlcnQgLy8gRnIgaW52ZXJzZSBvZiB6ZXJvCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxMTIKICAgIC8vIGNvbnN0IGludiA9IG1vZFBvdyh4LCBCTFMxMl8zODFfUl9NSU5VU18yLCByKTsKICAgIHB1c2hieXRlcyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZlZmZmZmZmZmYKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjkwCiAgICAvLyBsZXQgcmVzdWx0ID0gMW4gYXMgYmlndWludDsKICAgIGJ5dGVjXzMgLy8gMHgwMQogICAgZnJhbWVfYnVyeSAyNgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6OTEKICAgIC8vIGxldCBiOiBiaWd1aW50ID0gYmFzZSAlIG1vZDsKICAgIHN3YXAKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjExMgogICAgLy8gY29uc3QgaW52ID0gbW9kUG93KHgsIEJMUzEyXzM4MV9SX01JTlVTXzIsIHIpOwogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjkxCiAgICAvLyBsZXQgYjogYmlndWludCA9IGJhc2UgJSBtb2Q7CiAgICBiJQogICAgZnJhbWVfYnVyeSAxMgogICAgZnJhbWVfYnVyeSAxNwoKdmVyaWZ5X3doaWxlX3RvcEAxODoKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjkzCiAgICAvLyB3aGlsZSAoZSA+ICgwbiBhcyBiaWd1aW50KSkgewogICAgZnJhbWVfZGlnIDE3CiAgICBieXRlY18yIC8vIDB4CiAgICBiPgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6OTMtOTkKICAgIC8vIHdoaWxlIChlID4gKDBuIGFzIGJpZ3VpbnQpKSB7CiAgICAvLyAgIGlmICgoZSAmICgxbiBhcyBiaWd1aW50KSkgIT09ICgwbiBhcyBiaWd1aW50KSkgewogICAgLy8gICAgIHJlc3VsdCA9IChyZXN1bHQgKiBiKSAlIG1vZDsKICAgIC8vICAgfQogICAgLy8gICBiID0gKGIgKiBiKSAlIG1vZDsKICAgIC8vICAgZSA9IGUgLyBCaWdVaW50KDIpOwogICAgLy8gfQogICAgYnogdmVyaWZ5X2FmdGVyX3doaWxlQDIyCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo5NAogICAgLy8gaWYgKChlICYgKDFuIGFzIGJpZ3VpbnQpKSAhPT0gKDBuIGFzIGJpZ3VpbnQpKSB7CiAgICBmcmFtZV9kaWcgMTcKICAgIGJ5dGVjXzMgLy8gMHgwMQogICAgYiYKICAgIGJ5dGVjXzIgLy8gMHgKICAgIGIhPQogICAgZnJhbWVfZGlnIDI2CiAgICBmcmFtZV9idXJ5IDI3CiAgICBieiB2ZXJpZnlfYWZ0ZXJfaWZfZWxzZUAyMQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6OTUKICAgIC8vIHJlc3VsdCA9IChyZXN1bHQgKiBiKSAlIG1vZDsKICAgIGZyYW1lX2RpZyAyNgogICAgZnJhbWVfZGlnIDEyCiAgICBiKgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MTEyCiAgICAvLyBjb25zdCBpbnYgPSBtb2RQb3coeCwgQkxTMTJfMzgxX1JfTUlOVVNfMiwgcik7CiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6OTUKICAgIC8vIHJlc3VsdCA9IChyZXN1bHQgKiBiKSAlIG1vZDsKICAgIGIlCiAgICBmcmFtZV9idXJ5IDI3Cgp2ZXJpZnlfYWZ0ZXJfaWZfZWxzZUAyMToKICAgIGZyYW1lX2RpZyAyNwogICAgZnJhbWVfYnVyeSAyNgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6OTcKICAgIC8vIGIgPSAoYiAqIGIpICUgbW9kOwogICAgZnJhbWVfZGlnIDEyCiAgICBkdXAKICAgIGIqCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxMTIKICAgIC8vIGNvbnN0IGludiA9IG1vZFBvdyh4LCBCTFMxMl8zODFfUl9NSU5VU18yLCByKTsKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo5NwogICAgLy8gYiA9IChiICogYikgJSBtb2Q7CiAgICBiJQogICAgZnJhbWVfYnVyeSAxMgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6OTgKICAgIC8vIGUgPSBlIC8gQmlnVWludCgyKTsKICAgIGZyYW1lX2RpZyAxNwogICAgcHVzaGJ5dGVzIDB4MDIKICAgIGIvCiAgICBmcmFtZV9idXJ5IDE3CiAgICBiIHZlcmlmeV93aGlsZV90b3BAMTgKCnZlcmlmeV9hZnRlcl93aGlsZUAyMjoKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjEyNQogICAgLy8gcmV0dXJuIChhTiAqIGJJbnYpICUgcjsKICAgIGZyYW1lX2RpZyAxCiAgICBmcmFtZV9kaWcgMjYKICAgIGIqCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjUxNi01MjEKICAgIC8vIG5ldyBVaW50MjU2KAogICAgLy8gICBmckRpdigKICAgIC8vICAgICBmck11bCh3LCBjaGFsbGVuZ2VzLnpoLm5hdGl2ZSksCiAgICAvLyAgICAgZnJNdWwobiwgZnJTdWIoY2hhbGxlbmdlcy54aS5uYXRpdmUsIHcpKSwKICAgIC8vICAgKSwKICAgIC8vICksCiAgICBkdXAKICAgIGxlbgogICAgaW50Y18xIC8vIDMyCiAgICA8PQogICAgYXNzZXJ0IC8vIG92ZXJmbG93CiAgICBmcmFtZV9kaWcgMwogICAgYnwKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjUxNS01MjIKICAgIC8vIEwucHVzaCgKICAgIC8vICAgbmV3IFVpbnQyNTYoCiAgICAvLyAgICAgZnJEaXYoCiAgICAvLyAgICAgICBmck11bCh3LCBjaGFsbGVuZ2VzLnpoLm5hdGl2ZSksCiAgICAvLyAgICAgICBmck11bChuLCBmclN1YihjaGFsbGVuZ2VzLnhpLm5hdGl2ZSwgdykpLAogICAgLy8gICAgICksCiAgICAvLyAgICksCiAgICAvLyApOwogICAgZnJhbWVfZGlnIDAKICAgIGR1cAogICAgdW5jb3ZlciAyCiAgICBjb25jYXQgLy8gb24gZXJyb3I6IG1heCBhcnJheSBsZW5ndGggZXhjZWVkZWQKICAgIHN3YXAKICAgIGludGNfMyAvLyAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50Y18yIC8vIDEKICAgICsKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICByZXBsYWNlMiAwCiAgICBmcmFtZV9idXJ5IDAKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjY0CiAgICAvLyByZXR1cm4gKGEgKiBiKSAlIEJMUzEyXzM4MV9TQ0FMQVJfTU9EVUxVUzsKICAgIGZyYW1lX2RpZyAzMQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NTIzCiAgICAvLyB3ID0gZnJNdWwodywgUk9PVF9PRl9VTklUWSk7IC8vIE5leHQgcm9vdCBvZiB1bml0eSBzdGVwICjPiV5pKQogICAgYnl0ZWMgNSAvLyBUTVBMX1JPT1RfT0ZfVU5JVFkKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjY0CiAgICAvLyByZXR1cm4gKGEgKiBiKSAlIEJMUzEyXzM4MV9TQ0FMQVJfTU9EVUxVUzsKICAgIGIqCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIGZyYW1lX2J1cnkgMzEKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjUxNAogICAgLy8gZm9yIChsZXQgaTogdWludDY0ID0gMTsgaSA8PSBpdGVyYXRpb25zOyBpKyspIHsKICAgIGZyYW1lX2RpZyAzNwogICAgaW50Y18yIC8vIDEKICAgICsKICAgIGZyYW1lX2J1cnkgMzcKICAgIGIgdmVyaWZ5X3doaWxlX3RvcEAxNgoKdmVyaWZ5X2FmdGVyX3doaWxlQDIzOgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NTI1CiAgICAvLyByZXR1cm4geyBMLCBjaGFsbGVuZ2VzIH07CiAgICBwdXNoYnl0ZXMgMHgwMWEyCiAgICBmcmFtZV9kaWcgMTYKICAgIGNvbmNhdAogICAgZnJhbWVfZGlnIDAKICAgIGNvbmNhdAogICAgZHVwCiAgICBmcmFtZV9idXJ5IDQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjM0Ni0zNTAKICAgIC8vIGNvbnN0IHsgTCwgY2hhbGxlbmdlczogdXBkYXRlZENoYWxsZW5nZXMgfSA9IGNhbGN1bGF0ZUxhZ3JhbmdlRXZhbHVhdGlvbnMoCiAgICAvLyAgIGNoYWxsZW5nZXMsCiAgICAvLyAgIHZrLAogICAgLy8gKTsKICAgIC8vIGRlYnVnTG9nKCJMMSh4aSkiLCAoTFsxXSBhcyBVaW50MjU2KS5ieXRlcyk7CiAgICBkdXAKICAgIGludGNfMyAvLyAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgZGlnIDEKICAgIGxlbgogICAgc3Vic3RyaW5nMwogICAgZHVwCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfYnVyeSAyCiAgICBleHRyYWN0IDM0IDMyCiAgICBkdXAKICAgIGZyYW1lX2J1cnkgMjEKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjM1MAogICAgLy8gZGVidWdMb2coIkwxKHhpKSIsIChMWzFdIGFzIFVpbnQyNTYpLmJ5dGVzKTsKICAgIHB1c2hieXRlcyAiTDEoeGkpIgogICAgc3dhcAogICAgY2FsbHN1YiBkZWJ1Z0xvZwogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NTM1CiAgICAvLyBsZXQgcGkgPSBCaWdVaW50KDApOwogICAgYnl0ZWNfMiAvLyAweAogICAgZnJhbWVfYnVyeSAyNQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NTM2CiAgICAvLyBmb3IgKGxldCBpOiB1aW50NjQgPSAwOyBpIDwgcHVibGljU2lnbmFscy5sZW5ndGg7IGkrKykgewogICAgaW50Y18zIC8vIDAKICAgIGZyYW1lX2J1cnkgMzUKCnZlcmlmeV93aGlsZV90b3BAMjY6CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo1MzYKICAgIC8vIGZvciAobGV0IGk6IHVpbnQ2NCA9IDA7IGkgPCBwdWJsaWNTaWduYWxzLmxlbmd0aDsgaSsrKSB7CiAgICBmcmFtZV9kaWcgMzUKICAgIGZyYW1lX2RpZyA0NgogICAgPAogICAgYnogdmVyaWZ5X2FmdGVyX3doaWxlQDI4CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo1MzcKICAgIC8vIGNvbnN0IHcgPSBmclNjYWxhcigocHVibGljU2lnbmFsc1tpXSBhcyBVaW50MjU2KS5uYXRpdmUpOwogICAgZnJhbWVfZGlnIC0yCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIDM1CiAgICBkdXAKICAgIGNvdmVyIDIKICAgIGludGNfMSAvLyAzMgogICAgKgogICAgaW50Y18xIC8vIDMyCiAgICBleHRyYWN0MyAvLyBvbiBlcnJvcjogaW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjE1OAogICAgLy8gcmV0dXJuIGEgJSBCTFMxMl8zODFfU0NBTEFSX01PRFVMVVM7CiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjUzOAogICAgLy8gcGkgPSBmclN1YihwaSwgZnJNdWwodywgKExbaSArIDFdIGFzIFVpbnQyNTYpLm5hdGl2ZSkpOwogICAgc3dhcAogICAgaW50Y18yIC8vIDEKICAgICsKICAgIGR1cAogICAgZnJhbWVfYnVyeSAzNQogICAgaW50Y18xIC8vIDMyCiAgICAqCiAgICBmcmFtZV9kaWcgMgogICAgc3dhcAogICAgaW50Y18xIC8vIDMyCiAgICBleHRyYWN0MyAvLyBvbiBlcnJvcjogaW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjY0CiAgICAvLyByZXR1cm4gKGEgKiBiKSAlIEJMUzEyXzM4MV9TQ0FMQVJfTU9EVUxVUzsKICAgIGIqCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjUzOAogICAgLy8gcGkgPSBmclN1YihwaSwgZnJNdWwodywgKExbaSArIDFdIGFzIFVpbnQyNTYpLm5hdGl2ZSkpOwogICAgZnJhbWVfZGlnIDI1CiAgICBzd2FwCiAgICBjYWxsc3ViIGZyU3ViCiAgICBmcmFtZV9idXJ5IDI1CiAgICBiIHZlcmlmeV93aGlsZV90b3BAMjYKCnZlcmlmeV9hZnRlcl93aGlsZUAyODoKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjU0MAogICAgLy8gcmV0dXJuIG5ldyBVaW50MjU2KHBpKTsKICAgIGZyYW1lX2RpZyAyNQogICAgZHVwCiAgICBsZW4KICAgIGludGNfMSAvLyAzMgogICAgPD0KICAgIGFzc2VydCAvLyBvdmVyZmxvdwogICAgZnJhbWVfZGlnIDMKICAgIGR1cAogICAgY292ZXIgMgogICAgYnwKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjM1NQogICAgLy8gZGVidWdMb2coIlBJKHhpKSIsIHBpLmJ5dGVzKTsKICAgIHB1c2hieXRlcyAiUEkoeGkpIgogICAgZGlnIDEKICAgIGNhbGxzdWIgZGVidWdMb2cKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjU2MQogICAgLy8gZnJNdWwoY2hhbGxlbmdlcy5hbHBoYS5uYXRpdmUsIGNoYWxsZW5nZXMuYWxwaGEubmF0aXZlKSwKICAgIGZyYW1lX2RpZyA0CiAgICBwdXNoaW50cyAyIDQxNiAvLyAyLCA0MTYKICAgIGV4dHJhY3QzCiAgICBkdXAKICAgIGV4dHJhY3QgNjQgMzIKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjY0CiAgICAvLyByZXR1cm4gKGEgKiBiKSAlIEJMUzEyXzM4MV9TQ0FMQVJfTU9EVUxVUzsKICAgIGR1cAogICAgZGlnIDEKICAgIGIqCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIGZyYW1lX2RpZyAyMQogICAgYioKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiJQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NTY4CiAgICAvLyBmck11bChjaGFsbGVuZ2VzLmJldGEubmF0aXZlLCBwcm9vZi5ldmFsX3MxLm5hdGl2ZSksCiAgICBkaWcgMgogICAgZXh0cmFjdCAwIDMyCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo2NAogICAgLy8gcmV0dXJuIChhICogYikgJSBCTFMxMl8zODFfU0NBTEFSX01PRFVMVVM7CiAgICBkdXAKICAgIGZyYW1lX2RpZyAxNQogICAgZHVwCiAgICBjb3ZlciA4CiAgICBiKgogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNDcKICAgIC8vIGNvbnN0IGFOOiBiaWd1aW50ID0gYSAlIHI7CiAgICBmcmFtZV9kaWcgMTgKICAgIGR1cAogICAgY292ZXIgNgogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNDgKICAgIC8vIGNvbnN0IGJOOiBiaWd1aW50ID0gYiAlIHI7CiAgICBzd2FwCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjE0OQogICAgLy8gcmV0dXJuIChhTiArIGJOKSAlIHI7CiAgICBkaWcgMQogICAgYisKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiJQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NTcwCiAgICAvLyBlM2EgPSBmckFkZChlM2EsIGNoYWxsZW5nZXMuZ2FtbWEubmF0aXZlKTsKICAgIGRpZyA1CiAgICBleHRyYWN0IDMyIDMyCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNDcKICAgIC8vIGNvbnN0IGFOOiBiaWd1aW50ID0gYSAlIHI7CiAgICBzd2FwCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjE0OAogICAgLy8gY29uc3QgYk46IGJpZ3VpbnQgPSBiICUgcjsKICAgIHN3YXAKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiJQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MTQ5CiAgICAvLyByZXR1cm4gKGFOICsgYk4pICUgcjsKICAgIHN3YXAKICAgIGRpZyAxCiAgICBiKwogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo2NAogICAgLy8gcmV0dXJuIChhICogYikgJSBCTFMxMl8zODFfU0NBTEFSX01PRFVMVVM7CiAgICBkaWcgMwogICAgZnJhbWVfZGlnIDEzCiAgICBkdXAKICAgIGNvdmVyIDEyCiAgICBiKgogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNDcKICAgIC8vIGNvbnN0IGFOOiBiaWd1aW50ID0gYSAlIHI7CiAgICBmcmFtZV9kaWcgMTkKICAgIGR1cAogICAgY292ZXIgNAogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNDgKICAgIC8vIGNvbnN0IGJOOiBiaWd1aW50ID0gYiAlIHI7CiAgICBzd2FwCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjE0OQogICAgLy8gcmV0dXJuIChhTiArIGJOKSAlIHI7CiAgICBkaWcgMQogICAgYisKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiJQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MTQ3CiAgICAvLyBjb25zdCBhTjogYmlndWludCA9IGEgJSByOwogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNDkKICAgIC8vIHJldHVybiAoYU4gKyBiTikgJSByOwogICAgZGlnIDMKICAgIGIrCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjE0NwogICAgLy8gY29uc3QgYU46IGJpZ3VpbnQgPSBhICUgcjsKICAgIGZyYW1lX2RpZyAyMAogICAgZHVwCiAgICBjb3ZlciAxMAogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNDkKICAgIC8vIHJldHVybiAoYU4gKyBiTikgJSByOwogICAgZHVwCiAgICBkaWcgNQogICAgYisKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiJQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NjQKICAgIC8vIHJldHVybiAoYSAqIGIpICUgQkxTMTJfMzgxX1NDQUxBUl9NT0RVTFVTOwogICAgdW5jb3ZlciA0CiAgICB1bmNvdmVyIDMKICAgIGIqCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIGR1cAogICAgdW5jb3ZlciAyCiAgICBiKgogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICBmcmFtZV9kaWcgMTQKICAgIGR1cAogICAgY292ZXIgMTUKICAgIGIqCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIGRpZyA5CiAgICBiKgogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo1ODUKICAgIC8vIGNvbnN0IHIwID0gZnJTdWIoZnJTdWIoZTEsIGUyKSwgZTMpOwogICAgdW5jb3ZlciAxMwogICAgZGlnIDkKICAgIGNhbGxzdWIgZnJTdWIKICAgIHN3YXAKICAgIGNhbGxzdWIgZnJTdWIKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjU4NgogICAgLy8gcmV0dXJuIG5ldyBVaW50MjU2KHIwKTsKICAgIGR1cAogICAgbGVuCiAgICBpbnRjXzEgLy8gMzIKICAgIDw9CiAgICBhc3NlcnQgLy8gb3ZlcmZsb3cKICAgIHVuY292ZXIgMTQKICAgIGJ8CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czozNTkKICAgIC8vIGRlYnVnTG9nKCJyMCIsIHIwLmJ5dGVzKTsKICAgIHB1c2hieXRlcyAicjAiCiAgICBkaWcgMQogICAgY2FsbHN1YiBkZWJ1Z0xvZwogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NjEyCiAgICAvLyBkUG9pbnRzID0gb3AuY29uY2F0KGRQb2ludHMsIHByb29mLlQxKTsKICAgIGZyYW1lX2RpZyA0MAogICAgZnJhbWVfZGlnIDYKICAgIGNvbmNhdAogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NjEzCiAgICAvLyBkUG9pbnRzID0gb3AuY29uY2F0KGRQb2ludHMsIHByb29mLlQyKTsKICAgIGZyYW1lX2RpZyA3CiAgICBjb25jYXQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjYxNAogICAgLy8gZFBvaW50cyA9IG9wLmNvbmNhdChkUG9pbnRzLCBwcm9vZi5UMyk7CiAgICBmcmFtZV9kaWcgOAogICAgY29uY2F0CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo2NAogICAgLy8gcmV0dXJuIChhICogYikgJSBCTFMxMl8zODFfU0NBTEFSX01PRFVMVVM7CiAgICBkaWcgMTMKICAgIGRpZyA3CiAgICBiKgogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo2MjUKICAgIC8vIGZyTXVsKEJpZ1VpbnQoMSksIGNoYWxsZW5nZXMuemgubmF0aXZlKSwKICAgIGRpZyAxMwogICAgaW50YyA0IC8vIDM4NAogICAgaW50Y18xIC8vIDMyCiAgICBleHRyYWN0MwogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NjQKICAgIC8vIHJldHVybiAoYSAqIGIpICUgQkxTMTJfMzgxX1NDQUxBUl9NT0RVTFVTOwogICAgZHVwCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjYyNAogICAgLy8gQmlnVWludCgwKSwKICAgIGJ5dGVjXzIgLy8gMHgKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjYyMy02MjYKICAgIC8vIGNvbnN0IHF1b3RpZW50U2NhbGFyMSA9IGZyU3ViKAogICAgLy8gICBCaWdVaW50KDApLAogICAgLy8gICBmck11bChCaWdVaW50KDEpLCBjaGFsbGVuZ2VzLnpoLm5hdGl2ZSksCiAgICAvLyApOyAvLyAtVDEqemgKICAgIHN3YXAKICAgIGNhbGxzdWIgZnJTdWIKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjYyOQogICAgLy8gZnJNdWwoY2hhbGxlbmdlcy54aW4ubmF0aXZlLCBjaGFsbGVuZ2VzLnpoLm5hdGl2ZSksCiAgICBkaWcgMTUKICAgIGludGMgMTYgLy8gMzUyCiAgICBpbnRjXzEgLy8gMzIKICAgIGV4dHJhY3QzCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo2NAogICAgLy8gcmV0dXJuIChhICogYikgJSBCTFMxMl8zODFfU0NBTEFSX01PRFVMVVM7CiAgICBkdXAKICAgIGRpZyAzCiAgICBiKgogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo2MjgKICAgIC8vIEJpZ1VpbnQoMCksCiAgICBieXRlY18yIC8vIDB4CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo2MjctNjMwCiAgICAvLyBjb25zdCBxdW90aWVudFNjYWxhcjIgPSBmclN1YigKICAgIC8vICAgQmlnVWludCgwKSwKICAgIC8vICAgZnJNdWwoY2hhbGxlbmdlcy54aW4ubmF0aXZlLCBjaGFsbGVuZ2VzLnpoLm5hdGl2ZSksCiAgICAvLyApOyAvLyAtVDIqeGluKnpoCiAgICBzd2FwCiAgICBjYWxsc3ViIGZyU3ViCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo2NAogICAgLy8gcmV0dXJuIChhICogYikgJSBCTFMxMl8zODFfU0NBTEFSX01PRFVMVVM7CiAgICBkaWcgMQogICAgdW5jb3ZlciAyCiAgICBiKgogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICB1bmNvdmVyIDMKICAgIGIqCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjYzMgogICAgLy8gQmlnVWludCgwKSwKICAgIGJ5dGVjXzIgLy8gMHgKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjYzMS02MzcKICAgIC8vIGNvbnN0IHF1b3RpZW50U2NhbGFyMyA9IGZyU3ViKAogICAgLy8gICBCaWdVaW50KDApLAogICAgLy8gICBmck11bCgKICAgIC8vICAgICBmck11bChjaGFsbGVuZ2VzLnhpbi5uYXRpdmUsIGNoYWxsZW5nZXMueGluLm5hdGl2ZSksCiAgICAvLyAgICAgY2hhbGxlbmdlcy56aC5uYXRpdmUsCiAgICAvLyAgICksCiAgICAvLyApOyAvLyAtVDMqeGluwrIqemgKICAgIHN3YXAKICAgIGNhbGxzdWIgZnJTdWIKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjY0MAogICAgLy8gbGV0IGRTY2FsYXJzID0gb3AuY29uY2F0KGIzMihnYXRlU2NhbGFyMSksIGIzMihnYXRlU2NhbGFyMikpOwogICAgdW5jb3ZlciAzCiAgICBjYWxsc3ViIGIzMgogICAgZGlnIDE3CiAgICBjYWxsc3ViIGIzMgogICAgY29uY2F0CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo2NDEKICAgIC8vIGRTY2FsYXJzID0gb3AuY29uY2F0KGRTY2FsYXJzLCBiMzIoZ2F0ZVNjYWxhcjMpKTsKICAgIGRpZyAxMAogICAgY2FsbHN1YiBiMzIKICAgIGNvbmNhdAogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NjQyCiAgICAvLyBkU2NhbGFycyA9IG9wLmNvbmNhdChkU2NhbGFycywgYjMyKGdhdGVTY2FsYXI0KSk7CiAgICBkaWcgMTUKICAgIGNhbGxzdWIgYjMyCiAgICBjb25jYXQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjY0MwogICAgLy8gZFNjYWxhcnMgPSBvcC5jb25jYXQoZFNjYWxhcnMsIGIzMihxdW90aWVudFNjYWxhcjEpKTsKICAgIHVuY292ZXIgMwogICAgY2FsbHN1YiBiMzIKICAgIGNvbmNhdAogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NjQ0CiAgICAvLyBkU2NhbGFycyA9IG9wLmNvbmNhdChkU2NhbGFycywgYjMyKHF1b3RpZW50U2NhbGFyMikpOwogICAgdW5jb3ZlciAyCiAgICBjYWxsc3ViIGIzMgogICAgY29uY2F0CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo2NDUKICAgIC8vIGRTY2FsYXJzID0gb3AuY29uY2F0KGRTY2FsYXJzLCBiMzIocXVvdGllbnRTY2FsYXIzKSk7CiAgICBzd2FwCiAgICBjYWxsc3ViIGIzMgogICAgY29uY2F0CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo2NDgtNjUyCiAgICAvLyBjb25zdCBkQmF0Y2hlZCA9IG9wLkVsbGlwdGljQ3VydmUuc2NhbGFyTXVsTXVsdGkoCiAgICAvLyAgIG9wLkVjLkJMUzEyXzM4MWcxLAogICAgLy8gICBkUG9pbnRzLAogICAgLy8gICBkU2NhbGFycywKICAgIC8vICk7CiAgICBlY19tdWx0aV9zY2FsYXJfbXVsIEJMUzEyXzM4MWcxCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo2NTMKICAgIC8vIGxldCBEID0gZzFBZGQoZEJhdGNoZWQudG9GaXhlZCh7IGxlbmd0aDogOTYgfSksIHZrLlFjKTsgLy8gQWRkIFFjIGNvbnN0YW50IHRlcm0KICAgIGR1cAogICAgbGVuCiAgICBpbnRjXzAgLy8gOTYKICAgID09CiAgICBhc3NlcnQgLy8gTGVuZ3RoIG11c3QgYmUgOTYKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjIzNgogICAgLy8gcmV0dXJuIG9wLkVsbGlwdGljQ3VydmUuYWRkKG9wLkVjLkJMUzEyXzM4MWcxLCBwMSwgcDIpLnRvRml4ZWQoewogICAgZnJhbWVfZGlnIDQxCiAgICBlY19hZGQgQkxTMTJfMzgxZzEKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjIzNi0yMzgKICAgIC8vIHJldHVybiBvcC5FbGxpcHRpY0N1cnZlLmFkZChvcC5FYy5CTFMxMl8zODFnMSwgcDEsIHAyKS50b0ZpeGVkKHsKICAgIC8vICAgbGVuZ3RoOiA5NiwKICAgIC8vIH0pOwogICAgZHVwCiAgICBsZW4KICAgIGludGNfMCAvLyA5NgogICAgPT0KICAgIGFzc2VydCAvLyBMZW5ndGggbXVzdCBiZSA5NgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NjU2CiAgICAvLyBjb25zdCBiZXRheGkgPSBmck11bChjaGFsbGVuZ2VzLmJldGEubmF0aXZlLCBjaGFsbGVuZ2VzLnhpLm5hdGl2ZSk7CiAgICBkaWcgMTIKICAgIGV4dHJhY3QgOTYgMzIKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjY0CiAgICAvLyByZXR1cm4gKGEgKiBiKSAlIEJMUzEyXzM4MV9TQ0FMQVJfTU9EVUxVUzsKICAgIGRpZyA5CiAgICBkaWcgMQogICAgYioKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiJQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MTQ4CiAgICAvLyBjb25zdCBiTjogYmlndWludCA9IGIgJSByOwogICAgZHVwCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjE0OQogICAgLy8gcmV0dXJuIChhTiArIGJOKSAlIHI7CiAgICB1bmNvdmVyIDEwCiAgICBiKwogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNDcKICAgIC8vIGNvbnN0IGFOOiBiaWd1aW50ID0gYSAlIHI7CiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjE0OQogICAgLy8gcmV0dXJuIChhTiArIGJOKSAlIHI7CiAgICBkaWcgOAogICAgYisKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiJQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NjYyCiAgICAvLyBmckFkZChwcm9vZi5ldmFsX2IubmF0aXZlLCBmck11bChiZXRheGksIEJpZ1VpbnQodmsuazEpKSksCiAgICBmcmFtZV9kaWcgMzkKICAgIGR1cAogICAgY292ZXIgMwogICAgaW50YyAxMiAvLyA3ODQKICAgIHB1c2hpbnQgOCAvLyA4CiAgICBleHRyYWN0MwogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NjQKICAgIC8vIHJldHVybiAoYSAqIGIpICUgQkxTMTJfMzgxX1NDQUxBUl9NT0RVTFVTOwogICAgZGlnIDIKICAgIGIqCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjE0OAogICAgLy8gY29uc3QgYk46IGJpZ3VpbnQgPSBiICUgcjsKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiJQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MTQ5CiAgICAvLyByZXR1cm4gKGFOICsgYk4pICUgcjsKICAgIHVuY292ZXIgOQogICAgYisKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiJQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MTQ3CiAgICAvLyBjb25zdCBhTjogYmlndWludCA9IGEgJSByOwogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNDkKICAgIC8vIHJldHVybiAoYU4gKyBiTikgJSByOwogICAgZGlnIDkKICAgIGIrCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjY2NgogICAgLy8gZnJBZGQocHJvb2YuZXZhbF9jLm5hdGl2ZSwgZnJNdWwoYmV0YXhpLCBCaWdVaW50KHZrLmsyKSkpLAogICAgZGlnIDMKICAgIGludGMgMTMgLy8gNzkyCiAgICBwdXNoaW50IDggLy8gOAogICAgZXh0cmFjdDMKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjY0CiAgICAvLyByZXR1cm4gKGEgKiBiKSAlIEJMUzEyXzM4MV9TQ0FMQVJfTU9EVUxVUzsKICAgIHVuY292ZXIgMwogICAgYioKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiJQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MTQ4CiAgICAvLyBjb25zdCBiTjogYmlndWludCA9IGIgJSByOwogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNDkKICAgIC8vIHJldHVybiAoYU4gKyBiTikgJSByOwogICAgdW5jb3ZlciA4CiAgICBiKwogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNDcKICAgIC8vIGNvbnN0IGFOOiBiaWd1aW50ID0gYSAlIHI7CiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjE0OQogICAgLy8gcmV0dXJuIChhTiArIGJOKSAlIHI7CiAgICB1bmNvdmVyIDgKICAgIGIrCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjY0CiAgICAvLyByZXR1cm4gKGEgKiBiKSAlIEJMUzEyXzM4MV9TQ0FMQVJfTU9EVUxVUzsKICAgIGNvdmVyIDIKICAgIGIqCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIGIqCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIGRpZyA5CiAgICBiKgogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNDcKICAgIC8vIGNvbnN0IGFOOiBiaWd1aW50ID0gYSAlIHI7CiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjE0OAogICAgLy8gY29uc3QgYk46IGJpZ3VpbnQgPSBiICUgcjsKICAgIHVuY292ZXIgOAogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNDkKICAgIC8vIHJldHVybiAoYU4gKyBiTikgJSByOwogICAgYisKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiJQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6Njc0CiAgICAvLyBjb25zdCB6U2NhbGFyID0gZnJBZGQoZnJBZGQoZDJhLCBkMmIpLCBjaGFsbGVuZ2VzLnUubmF0aXZlKTsKICAgIGRpZyAxMAogICAgcHVzaGludCAzMjAgLy8gMzIwCiAgICBpbnRjXzEgLy8gMzIKICAgIGV4dHJhY3QzCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNDcKICAgIC8vIGNvbnN0IGFOOiBiaWd1aW50ID0gYSAlIHI7CiAgICBzd2FwCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjE0OAogICAgLy8gY29uc3QgYk46IGJpZ3VpbnQgPSBiICUgcjsKICAgIGRpZyAxCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjE0OQogICAgLy8gcmV0dXJuIChhTiArIGJOKSAlIHI7CiAgICBiKwogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoyMjUKICAgIC8vIHJldHVybiBvcC5FbGxpcHRpY0N1cnZlLnNjYWxhck11bChvcC5FYy5CTFMxMl8zODFnMSwgcCwgQnl0ZXMocykpLnRvRml4ZWQoewogICAgZnJhbWVfZGlnIDIzCiAgICBzd2FwCiAgICBlY19zY2FsYXJfbXVsIEJMUzEyXzM4MWcxCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoyMjUtMjI3CiAgICAvLyByZXR1cm4gb3AuRWxsaXB0aWNDdXJ2ZS5zY2FsYXJNdWwob3AuRWMuQkxTMTJfMzgxZzEsIHAsIEJ5dGVzKHMpKS50b0ZpeGVkKHsKICAgIC8vICAgbGVuZ3RoOiA5NiwKICAgIC8vIH0pOwogICAgZHVwCiAgICBsZW4KICAgIGludGNfMCAvLyA5NgogICAgPT0KICAgIGFzc2VydCAvLyBMZW5ndGggbXVzdCBiZSA5NgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MjM2CiAgICAvLyByZXR1cm4gb3AuRWxsaXB0aWNDdXJ2ZS5hZGQob3AuRWMuQkxTMTJfMzgxZzEsIHAxLCBwMikudG9GaXhlZCh7CiAgICB1bmNvdmVyIDQKICAgIHN3YXAKICAgIGVjX2FkZCBCTFMxMl8zODFnMQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MjM2LTIzOAogICAgLy8gcmV0dXJuIG9wLkVsbGlwdGljQ3VydmUuYWRkKG9wLkVjLkJMUzEyXzM4MWcxLCBwMSwgcDIpLnRvRml4ZWQoewogICAgLy8gICBsZW5ndGg6IDk2LAogICAgLy8gfSk7CiAgICBkdXAKICAgIGxlbgogICAgaW50Y18wIC8vIDk2CiAgICA9PQogICAgYXNzZXJ0IC8vIExlbmd0aCBtdXN0IGJlIDk2CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo2NAogICAgLy8gcmV0dXJuIChhICogYikgJSBCTFMxMl8zODFfU0NBTEFSX01PRFVMVVM7CiAgICB1bmNvdmVyIDgKICAgIHVuY292ZXIgOAogICAgYioKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiJQogICAgZGlnIDExCiAgICBiKgogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICB1bmNvdmVyIDYKICAgIGIqCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjIyNQogICAgLy8gcmV0dXJuIG9wLkVsbGlwdGljQ3VydmUuc2NhbGFyTXVsKG9wLkVjLkJMUzEyXzM4MWcxLCBwLCBCeXRlcyhzKSkudG9GaXhlZCh7CiAgICBmcmFtZV9kaWcgNDQKICAgIHN3YXAKICAgIGVjX3NjYWxhcl9tdWwgQkxTMTJfMzgxZzEKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjIyNS0yMjcKICAgIC8vIHJldHVybiBvcC5FbGxpcHRpY0N1cnZlLnNjYWxhck11bChvcC5FYy5CTFMxMl8zODFnMSwgcCwgQnl0ZXMocykpLnRvRml4ZWQoewogICAgLy8gICBsZW5ndGg6IDk2LAogICAgLy8gfSk7CiAgICBkdXAKICAgIGxlbgogICAgaW50Y18wIC8vIDk2CiAgICA9PQogICAgYXNzZXJ0IC8vIExlbmd0aCBtdXN0IGJlIDk2CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoyNDcKICAgIC8vIHJldHVybiBnMVRpbWVzRnIocCwgUl9NSU5VU18xKTsKICAgIGJ5dGVjIDQgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAwCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoyMjUKICAgIC8vIHJldHVybiBvcC5FbGxpcHRpY0N1cnZlLnNjYWxhck11bChvcC5FYy5CTFMxMl8zODFnMSwgcCwgQnl0ZXMocykpLnRvRml4ZWQoewogICAgZWNfc2NhbGFyX211bCBCTFMxMl8zODFnMQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MjI1LTIyNwogICAgLy8gcmV0dXJuIG9wLkVsbGlwdGljQ3VydmUuc2NhbGFyTXVsKG9wLkVjLkJMUzEyXzM4MWcxLCBwLCBCeXRlcyhzKSkudG9GaXhlZCh7CiAgICAvLyAgIGxlbmd0aDogOTYsCiAgICAvLyB9KTsKICAgIGR1cAogICAgbGVuCiAgICBpbnRjXzAgLy8gOTYKICAgID09CiAgICBhc3NlcnQgLy8gTGVuZ3RoIG11c3QgYmUgOTYKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjIzNgogICAgLy8gcmV0dXJuIG9wLkVsbGlwdGljQ3VydmUuYWRkKG9wLkVjLkJMUzEyXzM4MWcxLCBwMSwgcDIpLnRvRml4ZWQoewogICAgZWNfYWRkIEJMUzEyXzM4MWcxCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoyMzYtMjM4CiAgICAvLyByZXR1cm4gb3AuRWxsaXB0aWNDdXJ2ZS5hZGQob3AuRWMuQkxTMTJfMzgxZzEsIHAxLCBwMikudG9GaXhlZCh7CiAgICAvLyAgIGxlbmd0aDogOTYsCiAgICAvLyB9KTsKICAgIGR1cAogICAgbGVuCiAgICBpbnRjXzAgLy8gOTYKICAgID09CiAgICBhc3NlcnQgLy8gTGVuZ3RoIG11c3QgYmUgOTYKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjcwMwogICAgLy8gbGV0IGZQb2ludHMgPSBvcC5jb25jYXQocHJvb2YuQSwgcHJvb2YuQik7CiAgICBmcmFtZV9kaWcgOQogICAgZnJhbWVfZGlnIDEwCiAgICBjb25jYXQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjcwNAogICAgLy8gZlBvaW50cyA9IG9wLmNvbmNhdChmUG9pbnRzLCBwcm9vZi5DKTsKICAgIGZyYW1lX2RpZyA1CiAgICBjb25jYXQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjcwNQogICAgLy8gZlBvaW50cyA9IG9wLmNvbmNhdChmUG9pbnRzLCB2ay5TMSk7CiAgICBmcmFtZV9kaWcgNDIKICAgIGNvbmNhdAogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NzA2CiAgICAvLyBmUG9pbnRzID0gb3AuY29uY2F0KGZQb2ludHMsIHZrLlMyKTsKICAgIGZyYW1lX2RpZyA0MwogICAgY29uY2F0CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo3MTAKICAgIC8vIChjaGFsbGVuZ2VzLnZbMV0gYXMgVWludDI1NikuYnl0ZXMsCiAgICB1bmNvdmVyIDgKICAgIGV4dHJhY3QgMTI4IDE5MgogICAgZHVwCiAgICBleHRyYWN0IDMyIDMyIC8vIG9uIGVycm9yOiBpbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NzEwLTcxMQogICAgLy8gKGNoYWxsZW5nZXMudlsxXSBhcyBVaW50MjU2KS5ieXRlcywKICAgIC8vIChjaGFsbGVuZ2VzLnZbMl0gYXMgVWludDI1NikuYnl0ZXMsCiAgICBkaWcgMQogICAgZXh0cmFjdCA2NCAzMiAvLyBvbiBlcnJvcjogaW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjcwOS03MTIKICAgIC8vIGxldCBmU2NhbGFycyA9IG9wLmNvbmNhdCgKICAgIC8vICAgKGNoYWxsZW5nZXMudlsxXSBhcyBVaW50MjU2KS5ieXRlcywKICAgIC8vICAgKGNoYWxsZW5nZXMudlsyXSBhcyBVaW50MjU2KS5ieXRlcywKICAgIC8vICk7CiAgICBkdXAyCiAgICBjb25jYXQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjcxMwogICAgLy8gZlNjYWxhcnMgPSBvcC5jb25jYXQoZlNjYWxhcnMsIChjaGFsbGVuZ2VzLnZbM10gYXMgVWludDI1NikuYnl0ZXMpOwogICAgZGlnIDMKICAgIGV4dHJhY3QgOTYgMzIgLy8gb24gZXJyb3I6IGluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBzd2FwCiAgICBkaWcgMQogICAgY29uY2F0CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo3MTQKICAgIC8vIGZTY2FsYXJzID0gb3AuY29uY2F0KGZTY2FsYXJzLCAoY2hhbGxlbmdlcy52WzRdIGFzIFVpbnQyNTYpLmJ5dGVzKTsKICAgIGRpZyA0CiAgICBleHRyYWN0IDEyOCAzMiAvLyBvbiBlcnJvcjogaW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIHN3YXAKICAgIGRpZyAxCiAgICBjb25jYXQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjcxNQogICAgLy8gZlNjYWxhcnMgPSBvcC5jb25jYXQoZlNjYWxhcnMsIChjaGFsbGVuZ2VzLnZbNV0gYXMgVWludDI1NikuYnl0ZXMpOwogICAgdW5jb3ZlciA1CiAgICBleHRyYWN0IDE2MCAzMiAvLyBvbiBlcnJvcjogaW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIHN3YXAKICAgIGRpZyAxCiAgICBjb25jYXQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjcxNy03MjEKICAgIC8vIGNvbnN0IGZCYXRjaGVkID0gb3AuRWxsaXB0aWNDdXJ2ZS5zY2FsYXJNdWxNdWx0aSgKICAgIC8vICAgb3AuRWMuQkxTMTJfMzgxZzEsCiAgICAvLyAgIGZQb2ludHMsCiAgICAvLyAgIGZTY2FsYXJzLAogICAgLy8gKTsKICAgIHVuY292ZXIgNgogICAgc3dhcAogICAgZWNfbXVsdGlfc2NhbGFyX211bCBCTFMxMl8zODFnMQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NzIyCiAgICAvLyBjb25zdCBGID0gZzFBZGQoRCwgZkJhdGNoZWQudG9GaXhlZCh7IGxlbmd0aDogOTYgfSkpOwogICAgZHVwCiAgICBsZW4KICAgIGludGNfMCAvLyA5NgogICAgPT0KICAgIGFzc2VydCAvLyBMZW5ndGggbXVzdCBiZSA5NgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MjM2CiAgICAvLyByZXR1cm4gb3AuRWxsaXB0aWNDdXJ2ZS5hZGQob3AuRWMuQkxTMTJfMzgxZzEsIHAxLCBwMikudG9GaXhlZCh7CiAgICBkaWcgNgogICAgc3dhcAogICAgZWNfYWRkIEJMUzEyXzM4MWcxCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoyMzYtMjM4CiAgICAvLyByZXR1cm4gb3AuRWxsaXB0aWNDdXJ2ZS5hZGQob3AuRWMuQkxTMTJfMzgxZzEsIHAxLCBwMikudG9GaXhlZCh7CiAgICAvLyAgIGxlbmd0aDogOTYsCiAgICAvLyB9KTsKICAgIGR1cAogICAgbGVuCiAgICBpbnRjXzAgLy8gOTYKICAgID09CiAgICBhc3NlcnQgLy8gTGVuZ3RoIG11c3QgYmUgOTYKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjcyNAogICAgLy8gcmV0dXJuIHsgRCwgRiB9OwogICAgdW5jb3ZlciA2CiAgICBzd2FwCiAgICBjb25jYXQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjM2MgogICAgLy8gY29uc3QgeyBEOiBkLCBGOiBmIH0gPSBjYWxjdWxhdGVERihwcm9vZiwgY2hhbGxlbmdlcywgdmssIExbMV0gYXMgVWludDI1Nik7CiAgICBkdXAKICAgIGV4dHJhY3QgMCA5NgogICAgc3dhcAogICAgZXh0cmFjdCA5NiA5NgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MzYzCiAgICAvLyBkZWJ1Z0xvZygiRCIsIGQpOwogICAgcHVzaGJ5dGVzICJEIgogICAgdW5jb3ZlciAyCiAgICBjYWxsc3ViIGRlYnVnTG9nCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czozNjQKICAgIC8vIGRlYnVnTG9nKCJGIiwgZik7CiAgICBwdXNoYnl0ZXMgIkYiCiAgICBkaWcgMQogICAgY2FsbHN1YiBkZWJ1Z0xvZwogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NjQKICAgIC8vIHJldHVybiAoYSAqIGIpICUgQkxTMTJfMzgxX1NDQUxBUl9NT0RVTFVTOwogICAgdW5jb3ZlciA1CiAgICB1bmNvdmVyIDEyCiAgICBiKgogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo3MzgtNzQxCiAgICAvLyBsZXQgZSA9IGZyU3ViKAogICAgLy8gICBmck11bCgoY2hhbGxlbmdlcy52WzFdIGFzIFVpbnQyNTYpLm5hdGl2ZSwgcHJvb2YuZXZhbF9hLm5hdGl2ZSksCiAgICAvLyAgIHIwLm5hdGl2ZSwKICAgIC8vICk7CiAgICB1bmNvdmVyIDkKICAgIGNhbGxzdWIgZnJTdWIKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjY0CiAgICAvLyByZXR1cm4gKGEgKiBiKSAlIEJMUzEyXzM4MV9TQ0FMQVJfTU9EVUxVUzsKICAgIHVuY292ZXIgNQogICAgdW5jb3ZlciA5CiAgICBiKgogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNDcKICAgIC8vIGNvbnN0IGFOOiBiaWd1aW50ID0gYSAlIHI7CiAgICBzd2FwCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjE0OAogICAgLy8gY29uc3QgYk46IGJpZ3VpbnQgPSBiICUgcjsKICAgIHN3YXAKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiJQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MTQ5CiAgICAvLyByZXR1cm4gKGFOICsgYk4pICUgcjsKICAgIGIrCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjY0CiAgICAvLyByZXR1cm4gKGEgKiBiKSAlIEJMUzEyXzM4MV9TQ0FMQVJfTU9EVUxVUzsKICAgIHVuY292ZXIgNAogICAgdW5jb3ZlciA4CiAgICBiKgogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNDcKICAgIC8vIGNvbnN0IGFOOiBiaWd1aW50ID0gYSAlIHI7CiAgICBzd2FwCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjE0OAogICAgLy8gY29uc3QgYk46IGJpZ3VpbnQgPSBiICUgcjsKICAgIHN3YXAKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiJQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MTQ5CiAgICAvLyByZXR1cm4gKGFOICsgYk4pICUgcjsKICAgIGIrCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjY0CiAgICAvLyByZXR1cm4gKGEgKiBiKSAlIEJMUzEyXzM4MV9TQ0FMQVJfTU9EVUxVUzsKICAgIHVuY292ZXIgMwogICAgdW5jb3ZlciA5CiAgICBiKgogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNDcKICAgIC8vIGNvbnN0IGFOOiBiaWd1aW50ID0gYSAlIHI7CiAgICBzd2FwCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjE0OAogICAgLy8gY29uc3QgYk46IGJpZ3VpbnQgPSBiICUgcjsKICAgIHN3YXAKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiJQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MTQ5CiAgICAvLyByZXR1cm4gKGFOICsgYk4pICUgcjsKICAgIGIrCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjY0CiAgICAvLyByZXR1cm4gKGEgKiBiKSAlIEJMUzEyXzM4MV9TQ0FMQVJfTU9EVUxVUzsKICAgIHVuY292ZXIgMgogICAgdW5jb3ZlciA3CiAgICBiKgogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNDcKICAgIC8vIGNvbnN0IGFOOiBiaWd1aW50ID0gYSAlIHI7CiAgICBzd2FwCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjE0OAogICAgLy8gY29uc3QgYk46IGJpZ3VpbnQgPSBiICUgcjsKICAgIHN3YXAKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiJQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MTQ5CiAgICAvLyByZXR1cm4gKGFOICsgYk4pICUgcjsKICAgIGIrCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjY0CiAgICAvLyByZXR1cm4gKGEgKiBiKSAlIEJMUzEyXzM4MV9TQ0FMQVJfTU9EVUxVUzsKICAgIGRpZyAyCiAgICB1bmNvdmVyIDYKICAgIGIqCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjE0NwogICAgLy8gY29uc3QgYU46IGJpZ3VpbnQgPSBhICUgcjsKICAgIHN3YXAKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiJQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MTQ4CiAgICAvLyBjb25zdCBiTjogYmlndWludCA9IGIgJSByOwogICAgc3dhcAogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoxNDkKICAgIC8vIHJldHVybiAoYU4gKyBiTikgJSByOwogICAgYisKICAgIGJ5dGVjXzAgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxCiAgICBiJQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6NzU0CiAgICAvLyBjb25zdCByZXMgPSBnMVRpbWVzRnIoRzFfT05FLnRvRml4ZWQoeyBsZW5ndGg6IDk2IH0pLCBlKTsKICAgIHB1c2hieXRlcyAweDE3ZjFkM2E3MzE5N2Q3OTQyNjk1NjM4YzRmYTlhYzBmYzM2ODhjNGY5Nzc0YjkwNWExNGUzYTNmMTcxYmFjNTg2YzU1ZTgzZmY5N2ExYWVmZmIzYWYwMGFkYjIyYzZiYjA4YjNmNDgxZTNhYWEwZjFhMDllMzBlZDc0MWQ4YWU0ZmNmNWUwOTVkNWQwMGFmNjAwZGIxOGNiMmMwNGIzZWRkMDNjYzc0NGEyODg4YWU0MGNhYTIzMjk0NmM1ZTdlMQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MjI1CiAgICAvLyByZXR1cm4gb3AuRWxsaXB0aWNDdXJ2ZS5zY2FsYXJNdWwob3AuRWMuQkxTMTJfMzgxZzEsIHAsIEJ5dGVzKHMpKS50b0ZpeGVkKHsKICAgIHN3YXAKICAgIGVjX3NjYWxhcl9tdWwgQkxTMTJfMzgxZzEKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjIyNS0yMjcKICAgIC8vIHJldHVybiBvcC5FbGxpcHRpY0N1cnZlLnNjYWxhck11bChvcC5FYy5CTFMxMl8zODFnMSwgcCwgQnl0ZXMocykpLnRvRml4ZWQoewogICAgLy8gICBsZW5ndGg6IDk2LAogICAgLy8gfSk7CiAgICBkdXAKICAgIGxlbgogICAgaW50Y18wIC8vIDk2CiAgICA9PQogICAgYXNzZXJ0IC8vIExlbmd0aCBtdXN0IGJlIDk2CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czozNjgKICAgIC8vIGRlYnVnTG9nKCJFIiwgZSk7CiAgICBwdXNoYnl0ZXMgIkUiCiAgICBkaWcgMQogICAgY2FsbHN1YiBkZWJ1Z0xvZwogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MjI1CiAgICAvLyByZXR1cm4gb3AuRWxsaXB0aWNDdXJ2ZS5zY2FsYXJNdWwob3AuRWMuQkxTMTJfMzgxZzEsIHAsIEJ5dGVzKHMpKS50b0ZpeGVkKHsKICAgIGZyYW1lX2RpZyAyNAogICAgZGlnIDMKICAgIGVjX3NjYWxhcl9tdWwgQkxTMTJfMzgxZzEKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjIyNS0yMjcKICAgIC8vIHJldHVybiBvcC5FbGxpcHRpY0N1cnZlLnNjYWxhck11bChvcC5FYy5CTFMxMl8zODFnMSwgcCwgQnl0ZXMocykpLnRvRml4ZWQoewogICAgLy8gICBsZW5ndGg6IDk2LAogICAgLy8gfSk7CiAgICBkdXAKICAgIGxlbgogICAgaW50Y18wIC8vIDk2CiAgICA9PQogICAgYXNzZXJ0IC8vIExlbmd0aCBtdXN0IGJlIDk2CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoyMzYKICAgIC8vIHJldHVybiBvcC5FbGxpcHRpY0N1cnZlLmFkZChvcC5FYy5CTFMxMl8zODFnMSwgcDEsIHAyKS50b0ZpeGVkKHsKICAgIGZyYW1lX2RpZyAyOAogICAgc3dhcAogICAgZWNfYWRkIEJMUzEyXzM4MWcxCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoyMzYtMjM4CiAgICAvLyByZXR1cm4gb3AuRWxsaXB0aWNDdXJ2ZS5hZGQob3AuRWMuQkxTMTJfMzgxZzEsIHAxLCBwMikudG9GaXhlZCh7CiAgICAvLyAgIGxlbmd0aDogOTYsCiAgICAvLyB9KTsKICAgIGR1cAogICAgbGVuCiAgICBpbnRjXzAgLy8gOTYKICAgID09CiAgICBhc3NlcnQgLy8gTGVuZ3RoIG11c3QgYmUgOTYKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjY0CiAgICAvLyByZXR1cm4gKGEgKiBiKSAlIEJMUzEyXzM4MV9TQ0FMQVJfTU9EVUxVUzsKICAgIHVuY292ZXIgMwogICAgZGlnIDUKICAgIGIqCiAgICBieXRlY18wIC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMQogICAgYiUKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjc4NgogICAgLy8gUk9PVF9PRl9VTklUWSwKICAgIGJ5dGVjIDUgLy8gVE1QTF9ST09UX09GX1VOSVRZCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo2NAogICAgLy8gcmV0dXJuIChhICogYikgJSBCTFMxMl8zODFfU0NBTEFSX01PRFVMVVM7CiAgICBiKgogICAgYnl0ZWNfMCAvLyAweDczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDEKICAgIGIlCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo3ODgKICAgIC8vIGNvbnN0IHBhaXJpbmdTY2FsYXJzID0gb3AuY29uY2F0KGNoYWxsZW5nZXMueGkuYnl0ZXMsIGIzMihzKSk7CiAgICBjYWxsc3ViIGIzMgogICAgdW5jb3ZlciA1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjc5MC03OTQKICAgIC8vIGxldCBCMSA9IG9wLkVsbGlwdGljQ3VydmUuc2NhbGFyTXVsTXVsdGkoCiAgICAvLyAgIG9wLkVjLkJMUzEyXzM4MWcxLAogICAgLy8gICBwYWlyaW5nUG9pbnRzLAogICAgLy8gICBwYWlyaW5nU2NhbGFycywKICAgIC8vICkudG9GaXhlZCh7IGxlbmd0aDogOTYgfSk7CiAgICBmcmFtZV9kaWcgMjkKICAgIHN3YXAKICAgIGVjX211bHRpX3NjYWxhcl9tdWwgQkxTMTJfMzgxZzEKICAgIGR1cAogICAgbGVuCiAgICBpbnRjXzAgLy8gOTYKICAgID09CiAgICBhc3NlcnQgLy8gTGVuZ3RoIG11c3QgYmUgOTYKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjIzNgogICAgLy8gcmV0dXJuIG9wLkVsbGlwdGljQ3VydmUuYWRkKG9wLkVjLkJMUzEyXzM4MWcxLCBwMSwgcDIpLnRvRml4ZWQoewogICAgdW5jb3ZlciAzCiAgICBlY19hZGQgQkxTMTJfMzgxZzEKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjIzNi0yMzgKICAgIC8vIHJldHVybiBvcC5FbGxpcHRpY0N1cnZlLmFkZChvcC5FYy5CTFMxMl8zODFnMSwgcDEsIHAyKS50b0ZpeGVkKHsKICAgIC8vICAgbGVuZ3RoOiA5NiwKICAgIC8vIH0pOwogICAgZHVwCiAgICBsZW4KICAgIGludGNfMCAvLyA5NgogICAgPT0KICAgIGFzc2VydCAvLyBMZW5ndGggbXVzdCBiZSA5NgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MjI1CiAgICAvLyByZXR1cm4gb3AuRWxsaXB0aWNDdXJ2ZS5zY2FsYXJNdWwob3AuRWMuQkxTMTJfMzgxZzEsIHAsIEJ5dGVzKHMpKS50b0ZpeGVkKHsKICAgIHVuY292ZXIgMgogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MjQ3CiAgICAvLyByZXR1cm4gZzFUaW1lc0ZyKHAsIFJfTUlOVVNfMSk7CiAgICBieXRlYyA0IC8vIDB4NzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMAogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MjI1CiAgICAvLyByZXR1cm4gb3AuRWxsaXB0aWNDdXJ2ZS5zY2FsYXJNdWwob3AuRWMuQkxTMTJfMzgxZzEsIHAsIEJ5dGVzKHMpKS50b0ZpeGVkKHsKICAgIGVjX3NjYWxhcl9tdWwgQkxTMTJfMzgxZzEKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjIyNS0yMjcKICAgIC8vIHJldHVybiBvcC5FbGxpcHRpY0N1cnZlLnNjYWxhck11bChvcC5FYy5CTFMxMl8zODFnMSwgcCwgQnl0ZXMocykpLnRvRml4ZWQoewogICAgLy8gICBsZW5ndGg6IDk2LAogICAgLy8gfSk7CiAgICBkdXAKICAgIGxlbgogICAgaW50Y18wIC8vIDk2CiAgICA9PQogICAgYXNzZXJ0IC8vIExlbmd0aCBtdXN0IGJlIDk2CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoyMzYKICAgIC8vIHJldHVybiBvcC5FbGxpcHRpY0N1cnZlLmFkZChvcC5FYy5CTFMxMl8zODFnMSwgcDEsIHAyKS50b0ZpeGVkKHsKICAgIGVjX2FkZCBCTFMxMl8zODFnMQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MjM2LTIzOAogICAgLy8gcmV0dXJuIG9wLkVsbGlwdGljQ3VydmUuYWRkKG9wLkVjLkJMUzEyXzM4MWcxLCBwMSwgcDIpLnRvRml4ZWQoewogICAgLy8gICBsZW5ndGg6IDk2LAogICAgLy8gfSk7CiAgICBkdXAKICAgIGxlbgogICAgaW50Y18wIC8vIDk2CiAgICA9PQogICAgYXNzZXJ0IC8vIExlbmd0aCBtdXN0IGJlIDk2CiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czo3OTgKICAgIC8vIGRlYnVnTG9nKCJBMSIsIEExKTsKICAgIHB1c2hieXRlcyAiQTEiCiAgICBkaWcgMgogICAgY2FsbHN1YiBkZWJ1Z0xvZwogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6Nzk5CiAgICAvLyBkZWJ1Z0xvZygiQjEiLCBCMSk7CiAgICBwdXNoYnl0ZXMgIkIxIgogICAgZGlnIDEKICAgIGNhbGxzdWIgZGVidWdMb2cKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjIyNQogICAgLy8gcmV0dXJuIG9wLkVsbGlwdGljQ3VydmUuc2NhbGFyTXVsKG9wLkVjLkJMUzEyXzM4MWcxLCBwLCBCeXRlcyhzKSkudG9GaXhlZCh7CiAgICBzd2FwCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoyNDcKICAgIC8vIHJldHVybiBnMVRpbWVzRnIocCwgUl9NSU5VU18xKTsKICAgIGJ5dGVjIDQgLy8gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAwCiAgICAvLyBjb250cmFjdHMvcGxvbmtfYmxzMTIzODEuYWxnby50czoyMjUKICAgIC8vIHJldHVybiBvcC5FbGxpcHRpY0N1cnZlLnNjYWxhck11bChvcC5FYy5CTFMxMl8zODFnMSwgcCwgQnl0ZXMocykpLnRvRml4ZWQoewogICAgZWNfc2NhbGFyX211bCBCTFMxMl8zODFnMQogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6MjI1LTIyNwogICAgLy8gcmV0dXJuIG9wLkVsbGlwdGljQ3VydmUuc2NhbGFyTXVsKG9wLkVjLkJMUzEyXzM4MWcxLCBwLCBCeXRlcyhzKSkudG9GaXhlZCh7CiAgICAvLyAgIGxlbmd0aDogOTYsCiAgICAvLyB9KTsKICAgIGR1cAogICAgbGVuCiAgICBpbnRjXzAgLy8gOTYKICAgID09CiAgICBhc3NlcnQgLy8gTGVuZ3RoIG11c3QgYmUgOTYKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjgwMAogICAgLy8gZGVidWdMb2coIm5lZyhBMSkiLCBnMU5lZyhBMSkpOwogICAgcHVzaGJ5dGVzICJuZWcoQTEpIgogICAgZGlnIDEKICAgIGNhbGxzdWIgZGVidWdMb2cKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjgwMQogICAgLy8gZGVidWdMb2coInZrLlhfMiIsIHZrLlhfMik7CiAgICB1bmNvdmVyIDIKICAgIGludGMgMTQgLy8gODAwCiAgICBpbnRjIDUgLy8gMTkyCiAgICBleHRyYWN0MwogICAgcHVzaGJ5dGVzICJ2ay5YXzIiCiAgICBkaWcgMQogICAgY2FsbHN1YiBkZWJ1Z0xvZwogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6ODAyCiAgICAvLyBkZWJ1Z0xvZygiRzJfT05FIiwgRzJfT05FKTsKICAgIHB1c2hieXRlcyAiRzJfT05FIgogICAgYnl0ZWMgNiAvLyAweDAyNGFhMmIyZjA4ZjBhOTEyNjA4MDUyNzJkYzUxMDUxYzZlNDdhZDRmYTQwM2IwMmI0NTEwYjY0N2FlM2QxNzcwYmFjMDMyNmE4MDViYmVmZDQ4MDU2YzhjMTIxYmRiODEzZTAyYjYwNTI3MTlmNjA3ZGFjZDNhMDg4Mjc0ZjY1NTk2YmQwZDA5OTIwYjYxYWI1ZGE2MWJiZGM3ZjUwNDkzMzRjZjExMjEzOTQ1ZDU3ZTVhYzdkMDU1ZDA0MmI3ZTBjZTVkNTI3NzI3ZDZlMTE4Y2M5Y2RjNmRhMmUzNTFhYWRmZDliYWE4Y2JkZDNhNzZkNDI5YTY5NTE2MGQxMmM5MjNhYzljYzNiYWNhMjg5ZTE5MzU0ODYwOGI4MjgwMTA2MDZjNGEwMmVhNzM0Y2MzMmFjZDJiMDJiYzI4Yjk5Y2IzZTI4N2U4NWE3NjNhZjI2NzQ5MmFiNTcyZTk5YWIzZjM3MGQyNzVjZWMxZGExYWFhOTA3NWZmMDVmNzliZQogICAgY2FsbHN1YiBkZWJ1Z0xvZwogICAgLy8gY29udHJhY3RzL3Bsb25rX2JsczEyMzgxLmFsZ28udHM6ODA3CiAgICAvLyBvcC5jb25jYXQoZzFOZWcoQTEpLCBCMSksIC8vIEcxIHBvaW50cwogICAgc3dhcAogICAgdW5jb3ZlciAyCiAgICBjb25jYXQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjgwOAogICAgLy8gb3AuY29uY2F0KHZrLlhfMiwgRzJfT05FKSwgLy8gRzIgcG9pbnRzCiAgICBzd2FwCiAgICBieXRlYyA2IC8vIDB4MDI0YWEyYjJmMDhmMGE5MTI2MDgwNTI3MmRjNTEwNTFjNmU0N2FkNGZhNDAzYjAyYjQ1MTBiNjQ3YWUzZDE3NzBiYWMwMzI2YTgwNWJiZWZkNDgwNTZjOGMxMjFiZGI4MTNlMDJiNjA1MjcxOWY2MDdkYWNkM2EwODgyNzRmNjU1OTZiZDBkMDk5MjBiNjFhYjVkYTYxYmJkYzdmNTA0OTMzNGNmMTEyMTM5NDVkNTdlNWFjN2QwNTVkMDQyYjdlMGNlNWQ1Mjc3MjdkNmUxMThjYzljZGM2ZGEyZTM1MWFhZGZkOWJhYThjYmRkM2E3NmQ0MjlhNjk1MTYwZDEyYzkyM2FjOWNjM2JhY2EyODllMTkzNTQ4NjA4YjgyODAxMDYwNmM0YTAyZWE3MzRjYzMyYWNkMmIwMmJjMjhiOTljYjNlMjg3ZTg1YTc2M2FmMjY3NDkyYWI1NzJlOTlhYjNmMzcwZDI3NWNlYzFkYTFhYWE5MDc1ZmYwNWY3OWJlCiAgICBjb25jYXQKICAgIC8vIGNvbnRyYWN0cy9wbG9ua19ibHMxMjM4MS5hbGdvLnRzOjgwNS04MDkKICAgIC8vIGNvbnN0IHJlcyA9IG9wLkVsbGlwdGljQ3VydmUucGFpcmluZ0NoZWNrKAogICAgLy8gICBvcC5FYy5CTFMxMl8zODFnMSwKICAgIC8vICAgb3AuY29uY2F0KGcxTmVnKEExKSwgQjEpLCAvLyBHMSBwb2ludHMKICAgIC8vICAgb3AuY29uY2F0KHZrLlhfMiwgRzJfT05FKSwgLy8gRzIgcG9pbnRzCiAgICAvLyApOwogICAgZWNfcGFpcmluZ19jaGVjayBCTFMxMl8zODFnMQogICAgLy8gY29udHJhY3RzL3ZlcmlmaWVyLmFsZ28udHM6MTYKICAgIC8vIGFzc2VydCh2ZXJpZnlGcm9tVGVtcGxhdGUoc2lnbmFscywgcHJvb2YpLCAiVmVyaWZpY2F0aW9uIGZhaWxlZCIpOwogICAgYXNzZXJ0IC8vIFZlcmlmaWNhdGlvbiBmYWlsZWQKICAgIHJldHN1YgoKdmVyaWZ5X3Rlcm5hcnlfZmFsc2VAMTQ6CiAgICBmcmFtZV9kaWcgMzgKICAgIGZyYW1lX2J1cnkgMzYKICAgIGIgdmVyaWZ5X3Rlcm5hcnlfbWVyZ2VAMTUK", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCiNwcmFnbWEgdHlwZXRyYWNrIGZhbHNlCgovLyBAYWxnb3JhbmRmb3VuZGF0aW9uL2FsZ29yYW5kLXR5cGVzY3JpcHQvYmFzZS1jb250cmFjdC5kLnRzOjpCYXNlQ29udHJhY3QuY2xlYXJTdGF0ZVByb2dyYW0oKSAtPiB1aW50NjQ6Cm1haW46CiAgICBwdXNoaW50IDEgLy8gMQogICAgcmV0dXJuCg==" }, "byteCode": { "approval": "CiASYCABAIADwAGgAuADwASgBYAGiAaQBpgGoAbgB+ACACYHIHPtp1MpnX1IMznYCAmh2AVTvaQC//5b/v////8AAAABAAABASBz7adTKZ19SDM52AgJodgFU72kAv/+W/7/////AAAAAADAAQJKorLwjwqRJggFJy3FEFHG5HrU+kA7ArRRC2R649F3C6wDJqgFu+/UgFbIwSG9uBPgK2BScZ9gfazToIgnT2VZa9DQmSC2GrXaYbvcf1BJM0zxEhOUXVflrH0FXQQrfgzl1SdyfW4RjMnNxtouNRqt/ZuqjL3Tp21CmmlRYNEskjrJzDusoonhk1SGCLgoAQYGxKAupzTMMqzSsCvCi5nLPih+hadjryZ0kqtXLpmrPzcNJ1zsHaGqqQdf8F95vjEbQQAzggIElcEM5ARD2Qo4NhoAjgIAEwABADEZFEQxGEQ2GgE2GgKIAF8kQzEZgQISRDEYRCRDMRlA/90xGBREJEOKAgGL/iiqi/8oqkwooEyhKKqJigEBi/8VIw5EI6+L/6tJFSMSRImKAgAhEUEABov+sIv/sImKAQGL/wIoqkkVIw5EI6+riYoCACVHISpHBCkVJUsBDyVLAk8CTSJLAg8iSwNPAk0pTwJLAlJJFSISRCEFSwMPIQVLBE8CTSlPA0sCUkkVIhJEIQZLBA8hBksFTwJNKU8DSwJSSRUiEkQhBEsFDyEESwZPAk0pTwNLAlJJFSISRCEHSwYPIQdLB08CTSlPA0sCUkkVIhJEIQhLBw8hCEsITwJNKU8DSwJSSRUiEkQhCUsIDyEJSwlPAk0pTwNLAlJJFSISRCEKSwkPIQpLCk8CTSlPA0sCUkkVIhJEIQtLCg8hC0sLTwJNKU8DSwJSFyEMSwsPIQxLDE8CTSlPA0sCUhchDUsMDyENSw1PAk0pTwNLAlIXIQ5LDQ8hDksOTwJNKU8DSwJSFyEPSw4PIQ9PD08CTSlPA08CUkkVIQUSRE8MTwxQTwtQTwpQTwlQTwhQTwdQTwZQTwUWUE8EFlBPAxZQTwIWUExQRwJXAGBLAVdgYFBLAVfAYFBLASEGIlhQSU4CSwEhBCJYSU4DUEsBIQciWElOA1BLASEIIlhJTgNQTCEJIlhJTgJQi/4lWSWLL4suDEEAIIv+VwIAiy9JTgIjCyNYKKqI/hKLLUxQjC0kCIwvQv/Yi/9XAGBJjAmLLUxQi/9XYGBJjApQi/9XwGBJjAVQiP4HSYj+A1BJjC2L/yEGIlhJjBdQiP3ySYwLi/8hBCJYSYwGUIv/IQciWEmMB1CL/yEIIlhJjAhQiP3OSYwgi/+B4AYjWEmMElCL/4GAByNYSYwTUIv/gaAHI1hJjBRQi/+BwAcjWEmMD1CL/yEPI1hJjA1Qi/+BgAgjWEmMDlAhBa9MiP2DXCCMHoECjCOLI4EGDEEALYsjSSQJIwuLHklPAiNYSwFXICCjKKpJFSMORCOvq0sCIwtMXYweJAiMI0L/y4v/IQkiWEmMHIv/IQoiWEmMGFBJjB2I/S2LLYsLUIsgUIseUExQgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUEmMEElXACCABGJldGFMiPy9SVcgIIAFZ2FtbWFMiPyuSVdAIIAFYWxwaGFMiPyfSVdgIEmMIYACeGlMiPyQSYHAAiNYgAF1TIj8g0khECNYgAN4aW5MiPx1SSEEI1iAAnpoTIj8aFeAwElXICCABHZbMV1MiPxXSVdAIIAEdlsyXUyI/ElJV2AggAR2WzNdTIj8O0lXgCCABHZbNF1MiPwtV6AggAR2WzVdTIj8ICSMIiWMI4snIQpbiyMNQQAYiyFJoyiqjCGLIoECC4wiiyMkCIwjQv/diyFJFSMORCOvSYwDSquLECEQTwJdTwIriPu1SRUjDkRPAqshBExdjBCLIhYoqowWK4wfgCIAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjACLJyELW0mMJkAE/ySMJCSMJYsliyQOQQC9ixBJIQQjWIsfSU8CoyiqTwJXYCBPAoj7RYsWoyiqTCiqjAEoqkkqqUSAIHPtp1MpnX1IMznYCAmh2AVTvaQC//5b/v////7/////K4waTCiqjAyMEYsRKqVBAC2LESusKqmLGowbQQAJixqLDKMoqowbixuMGosMSaMoqowMixGAAQKijBFC/8yLAYsaoyiqSRUjDkSLA6uLAElPAlBMJVkkCBZXBgJcAIwAix8nBaMoqowfiyUkCIwlQv87gAIBoosQUIsAUEmMBEklWUsBFVJJVwIAjAJXIiBJjBWABkwxKHhpKUyI+pwqjBkljCOLI4suDEEAK4v+VwIAiyNJTgIjCyNYKKpMJAhJjCMjC4sCTCNYoyiqixlMiPpBjBlC/82LGUkVIw5EiwNJTgKrgAZQSSh4aSlLAYj6SYsEgwICoANYSVdAIElLAaMoqosVoyiqSwJXACBJiw9JTgijKKqLEklOBiiqTCiqSwGgKKpLBVcgIEwoqkwoqkxLAaAoqksDiw1JTgyjKKqLE0lOBCiqTCiqSwGgKKooqksDoCiqixRJTgooqklLBaAoqk8ETwOjKKpJTwKjKKqLDklOD6MoqksJoyiqTw1LCYj5j0yI+YtJFSMORE8Oq4ACcjBLAYj5oYsoiwZQiwdQiwhQSw1LB6MoqksNIQQjWEkoqipMiPlaSw8hECNYSUsDoyiqKkyI+UlLAU8CoyiqTwOjKKoqTIj5OE8DiPlGSxGI+UFQSwqI+TtQSw+I+TVQTwOI+S9QTwKI+SlQTIj5JFDjAkkVIhJEiyngAkkVIhJESwxXYCBLCUsBoyiqSSiqTwqgKKooqksIoCiqiydJTgMhDIEIWEsCoyiqKKpPCaAoqiiqSwmgKKpLAyENgQhYTwOjKKooqk8IoCiqKKpPCKAoqk4CoyiqoyiqSwmjKKooqk8IKKqgKKpLCoHAAiNYTCiqSwEoqqAoqosXTOECSRUiEkRPBEzgAkkVIhJETwhPCKMoqksLoyiqTwajKKqLLEzhAkkVIhJEJwThAkkVIhJE4AJJFSISRIsJiwpQiwVQiypQiytQTwhXgMBJVyAgSwFXQCBKUEsDV2AgTEsBUEsEV4AgTEsBUE8FV6AgTEsBUE8GTOMCSRUiEkRLBkzgAkkVIhJETwZMUElXAGBMV2BggAFETwKI+A6AAUZLAYj4Bk8FTwyjKKpPCYj3008FTwmjKKpMKKpMKKqgKKpPBE8IoyiqTCiqTCiqoCiqTwNPCaMoqkwoqkwoqqAoqk8CTwejKKpMKKpMKKqgKKpLAk8GoyiqTCiqTCiqoCiqgGAX8dOnMZfXlCaVY4xPqawPw2iMT5d0uQWhTjo/FxusWGxV6D/5ehrv+zrwCtsixrsIs/SB46qg8aCeMO10HYrk/PXgldXQCvYA2xjLLASz7dA8x0SiiIrkDKojKUbF5+FM4QJJFSISRIABRUsBiPc4ixhLA+ECSRUiEkSLHEzgAkkVIhJETwNLBaMoqicFoyiqiPcATwVMUIsdTOMCSRUiEkRPA+ACSRUiEkRPAicE4QJJFSISROACSRUiEkSAAkExSwKI9uKAAkIxSwGI9tlMJwThAkkVIhJEgAduZWcoQTEpSwGI9sFPAiEOIQVYgAZ2ay5YXzJLAYj2rYAGRzJfT05FJwaI9qBMTwJQTCcGUOICRImLJowkQvr9", "clear": "CoEBQw==" }, "events": [], "templateVariables": { "DEBUG_LOGGING": { "type": "AVMUint64" }, "VERIFICATION_KEY": { "type": "AVMBytes" }, "ROOT_OF_UNITY": { "type": "AVMBytes" } } };
|
|
13
|
+
var PlonkVerifierParamsFactory = class {
|
|
14
|
+
/**
|
|
15
|
+
* Gets available closeOut ABI call param factories
|
|
16
|
+
*/
|
|
17
|
+
static get closeOut() {
|
|
18
|
+
return {
|
|
19
|
+
/**
|
|
20
|
+
* Constructs close out ABI call params for the PlonkVerifier smart contract using the _dummy((byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],uint64,uint64,uint64,uint64,byte[192]))void ABI method
|
|
21
|
+
*
|
|
22
|
+
* @param params Parameters for the call
|
|
23
|
+
* @returns An `AppClientMethodCallParams` object for the call
|
|
24
|
+
*/
|
|
25
|
+
_dummy(params) {
|
|
26
|
+
return {
|
|
27
|
+
...params,
|
|
28
|
+
method: "_dummy((byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],uint64,uint64,uint64,uint64,byte[192]))void",
|
|
29
|
+
args: Array.isArray(params.args) ? params.args : [params.args._vk]
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Constructs a no op call for the verify(uint256[],(byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],uint256,uint256,uint256,uint256,uint256,uint256))void ABI method
|
|
36
|
+
*
|
|
37
|
+
* @param params Parameters for the call
|
|
38
|
+
* @returns An `AppClientMethodCallParams` object for the call
|
|
39
|
+
*/
|
|
40
|
+
static verify(params) {
|
|
41
|
+
return {
|
|
42
|
+
...params,
|
|
43
|
+
method: "verify(uint256[],(byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],uint256,uint256,uint256,uint256,uint256,uint256))void",
|
|
44
|
+
args: Array.isArray(params.args) ? params.args : [params.args.signals, params.args.proof]
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var PlonkVerifierFactory = class {
|
|
49
|
+
/**
|
|
50
|
+
* The underlying `AppFactory` for when you want to have more flexibility
|
|
51
|
+
*/
|
|
52
|
+
appFactory;
|
|
53
|
+
/**
|
|
54
|
+
* Creates a new instance of `PlonkVerifierFactory`
|
|
55
|
+
*
|
|
56
|
+
* @param params The parameters to initialise the app factory with
|
|
57
|
+
*/
|
|
58
|
+
constructor(params) {
|
|
59
|
+
this.appFactory = new _AppFactory({
|
|
60
|
+
...params,
|
|
61
|
+
appSpec: APP_SPEC
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/** The name of the app (from the ARC-32 / ARC-56 app spec or override). */
|
|
65
|
+
get appName() {
|
|
66
|
+
return this.appFactory.appName;
|
|
67
|
+
}
|
|
68
|
+
/** The ARC-56 app spec being used */
|
|
69
|
+
get appSpec() {
|
|
70
|
+
return APP_SPEC;
|
|
71
|
+
}
|
|
72
|
+
/** A reference to the underlying `AlgorandClient` this app factory is using. */
|
|
73
|
+
get algorand() {
|
|
74
|
+
return this.appFactory.algorand;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Returns a new `AppClient` client for an app instance of the given ID.
|
|
78
|
+
*
|
|
79
|
+
* Automatically populates appName, defaultSender and source maps from the factory
|
|
80
|
+
* if not specified in the params.
|
|
81
|
+
* @param params The parameters to create the app client
|
|
82
|
+
* @returns The `AppClient`
|
|
83
|
+
*/
|
|
84
|
+
getAppClientById(params) {
|
|
85
|
+
return new PlonkVerifierClient(this.appFactory.getAppClientById(params));
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Returns a new `AppClient` client, resolving the app by creator address and name
|
|
89
|
+
* using AlgoKit app deployment semantics (i.e. looking for the app creation transaction note).
|
|
90
|
+
*
|
|
91
|
+
* Automatically populates appName, defaultSender and source maps from the factory
|
|
92
|
+
* if not specified in the params.
|
|
93
|
+
* @param params The parameters to create the app client
|
|
94
|
+
* @returns The `AppClient`
|
|
95
|
+
*/
|
|
96
|
+
async getAppClientByCreatorAndName(params) {
|
|
97
|
+
return new PlonkVerifierClient(await this.appFactory.getAppClientByCreatorAndName(params));
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Idempotently deploys the PlonkVerifier smart contract.
|
|
101
|
+
*
|
|
102
|
+
* @param params The arguments for the contract calls and any additional parameters for the call
|
|
103
|
+
* @returns The deployment result
|
|
104
|
+
*/
|
|
105
|
+
async deploy(params = {}) {
|
|
106
|
+
const result = await this.appFactory.deploy({
|
|
107
|
+
...params
|
|
108
|
+
});
|
|
109
|
+
return { result: result.result, appClient: new PlonkVerifierClient(result.appClient) };
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Get parameters to create transactions (create and deploy related calls) for the current app. A good mental model for this is that these parameters represent a deferred transaction creation.
|
|
113
|
+
*/
|
|
114
|
+
params = {
|
|
115
|
+
/**
|
|
116
|
+
* Gets available create methods
|
|
117
|
+
*/
|
|
118
|
+
create: {
|
|
119
|
+
/**
|
|
120
|
+
* Creates a new instance of the PlonkVerifier smart contract using a bare call.
|
|
121
|
+
*
|
|
122
|
+
* @param params The params for the bare (raw) call
|
|
123
|
+
* @returns The params for a create call
|
|
124
|
+
*/
|
|
125
|
+
bare: (params) => {
|
|
126
|
+
return this.appFactory.params.bare.create(params);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* Create transactions for the current app
|
|
132
|
+
*/
|
|
133
|
+
createTransaction = {
|
|
134
|
+
/**
|
|
135
|
+
* Gets available create methods
|
|
136
|
+
*/
|
|
137
|
+
create: {
|
|
138
|
+
/**
|
|
139
|
+
* Creates a new instance of the PlonkVerifier smart contract using a bare call.
|
|
140
|
+
*
|
|
141
|
+
* @param params The params for the bare (raw) call
|
|
142
|
+
* @returns The transaction for a create call
|
|
143
|
+
*/
|
|
144
|
+
bare: (params) => {
|
|
145
|
+
return this.appFactory.createTransaction.bare.create(params);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
/**
|
|
150
|
+
* Send calls to the current app
|
|
151
|
+
*/
|
|
152
|
+
send = {
|
|
153
|
+
/**
|
|
154
|
+
* Gets available create methods
|
|
155
|
+
*/
|
|
156
|
+
create: {
|
|
157
|
+
/**
|
|
158
|
+
* Creates a new instance of the PlonkVerifier smart contract using a bare call.
|
|
159
|
+
*
|
|
160
|
+
* @param params The params for the bare (raw) call
|
|
161
|
+
* @returns The create result
|
|
162
|
+
*/
|
|
163
|
+
bare: async (params) => {
|
|
164
|
+
const result = await this.appFactory.send.bare.create(params);
|
|
165
|
+
return { result: result.result, appClient: new PlonkVerifierClient(result.appClient) };
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
};
|
|
170
|
+
var PlonkVerifierClient = class _PlonkVerifierClient {
|
|
171
|
+
/**
|
|
172
|
+
* The underlying `AppClient` for when you want to have more flexibility
|
|
173
|
+
*/
|
|
174
|
+
appClient;
|
|
175
|
+
constructor(appClientOrParams) {
|
|
176
|
+
this.appClient = appClientOrParams instanceof _AppClient ? appClientOrParams : new _AppClient({
|
|
177
|
+
...appClientOrParams,
|
|
178
|
+
appSpec: APP_SPEC
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Checks for decode errors on the given return value and maps the return value to the return type for the given method
|
|
183
|
+
* @returns The typed return value or undefined if there was no value
|
|
184
|
+
*/
|
|
185
|
+
decodeReturnValue(method, returnValue) {
|
|
186
|
+
return returnValue !== void 0 ? getArc56ReturnValue(returnValue, this.appClient.getABIMethod(method), APP_SPEC.structs) : void 0;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Returns a new `PlonkVerifierClient` client, resolving the app by creator address and name
|
|
190
|
+
* using AlgoKit app deployment semantics (i.e. looking for the app creation transaction note).
|
|
191
|
+
* @param params The parameters to create the app client
|
|
192
|
+
*/
|
|
193
|
+
static async fromCreatorAndName(params) {
|
|
194
|
+
return new _PlonkVerifierClient(await _AppClient.fromCreatorAndName({ ...params, appSpec: APP_SPEC }));
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Returns an `PlonkVerifierClient` instance for the current network based on
|
|
198
|
+
* pre-determined network-specific app IDs specified in the ARC-56 app spec.
|
|
199
|
+
*
|
|
200
|
+
* If no IDs are in the app spec or the network isn't recognised, an error is thrown.
|
|
201
|
+
* @param params The parameters to create the app client
|
|
202
|
+
*/
|
|
203
|
+
static async fromNetwork(params) {
|
|
204
|
+
return new _PlonkVerifierClient(await _AppClient.fromNetwork({ ...params, appSpec: APP_SPEC }));
|
|
205
|
+
}
|
|
206
|
+
/** The ID of the app instance this client is linked to. */
|
|
207
|
+
get appId() {
|
|
208
|
+
return this.appClient.appId;
|
|
209
|
+
}
|
|
210
|
+
/** The app address of the app instance this client is linked to. */
|
|
211
|
+
get appAddress() {
|
|
212
|
+
return this.appClient.appAddress;
|
|
213
|
+
}
|
|
214
|
+
/** The name of the app. */
|
|
215
|
+
get appName() {
|
|
216
|
+
return this.appClient.appName;
|
|
217
|
+
}
|
|
218
|
+
/** The ARC-56 app spec being used */
|
|
219
|
+
get appSpec() {
|
|
220
|
+
return this.appClient.appSpec;
|
|
221
|
+
}
|
|
222
|
+
/** A reference to the underlying `AlgorandClient` this app client is using. */
|
|
223
|
+
get algorand() {
|
|
224
|
+
return this.appClient.algorand;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Get parameters to create transactions for the current app. A good mental model for this is that these parameters represent a deferred transaction creation.
|
|
228
|
+
*/
|
|
229
|
+
params = {
|
|
230
|
+
/**
|
|
231
|
+
* Gets available closeOut methods
|
|
232
|
+
*/
|
|
233
|
+
closeOut: {
|
|
234
|
+
/**
|
|
235
|
+
* Makes a close out call to an existing instance of the PlonkVerifier smart contract using the `_dummy((byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],uint64,uint64,uint64,uint64,byte[192]))void` ABI method.
|
|
236
|
+
*
|
|
237
|
+
* Dummy function that only exists so we can have the VerificationKey type in the generated client
|
|
238
|
+
*
|
|
239
|
+
* @param params The params for the smart contract call
|
|
240
|
+
* @returns The closeOut params
|
|
241
|
+
*/
|
|
242
|
+
_dummy: (params) => {
|
|
243
|
+
return this.appClient.params.closeOut(PlonkVerifierParamsFactory.closeOut._dummy(params));
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
/**
|
|
247
|
+
* Makes a clear_state call to an existing instance of the PlonkVerifier smart contract.
|
|
248
|
+
*
|
|
249
|
+
* @param params The params for the bare (raw) call
|
|
250
|
+
* @returns The clearState result
|
|
251
|
+
*/
|
|
252
|
+
clearState: (params) => {
|
|
253
|
+
return this.appClient.params.bare.clearState(params);
|
|
254
|
+
},
|
|
255
|
+
/**
|
|
256
|
+
* Makes a call to the PlonkVerifier smart contract using the `verify(uint256[],(byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],uint256,uint256,uint256,uint256,uint256,uint256))void` ABI method.
|
|
257
|
+
*
|
|
258
|
+
* @param params The params for the smart contract call
|
|
259
|
+
* @returns The call params
|
|
260
|
+
*/
|
|
261
|
+
verify: (params) => {
|
|
262
|
+
return this.appClient.params.call(PlonkVerifierParamsFactory.verify(params));
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
/**
|
|
266
|
+
* Create transactions for the current app
|
|
267
|
+
*/
|
|
268
|
+
createTransaction = {
|
|
269
|
+
/**
|
|
270
|
+
* Gets available closeOut methods
|
|
271
|
+
*/
|
|
272
|
+
closeOut: {
|
|
273
|
+
/**
|
|
274
|
+
* Makes a close out call to an existing instance of the PlonkVerifier smart contract using the `_dummy((byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],uint64,uint64,uint64,uint64,byte[192]))void` ABI method.
|
|
275
|
+
*
|
|
276
|
+
* Dummy function that only exists so we can have the VerificationKey type in the generated client
|
|
277
|
+
*
|
|
278
|
+
* @param params The params for the smart contract call
|
|
279
|
+
* @returns The closeOut transaction
|
|
280
|
+
*/
|
|
281
|
+
_dummy: (params) => {
|
|
282
|
+
return this.appClient.createTransaction.closeOut(PlonkVerifierParamsFactory.closeOut._dummy(params));
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
/**
|
|
286
|
+
* Makes a clear_state call to an existing instance of the PlonkVerifier smart contract.
|
|
287
|
+
*
|
|
288
|
+
* @param params The params for the bare (raw) call
|
|
289
|
+
* @returns The clearState result
|
|
290
|
+
*/
|
|
291
|
+
clearState: (params) => {
|
|
292
|
+
return this.appClient.createTransaction.bare.clearState(params);
|
|
293
|
+
},
|
|
294
|
+
/**
|
|
295
|
+
* Makes a call to the PlonkVerifier smart contract using the `verify(uint256[],(byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],uint256,uint256,uint256,uint256,uint256,uint256))void` ABI method.
|
|
296
|
+
*
|
|
297
|
+
* @param params The params for the smart contract call
|
|
298
|
+
* @returns The call transaction
|
|
299
|
+
*/
|
|
300
|
+
verify: (params) => {
|
|
301
|
+
return this.appClient.createTransaction.call(PlonkVerifierParamsFactory.verify(params));
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
/**
|
|
305
|
+
* Send calls to the current app
|
|
306
|
+
*/
|
|
307
|
+
send = {
|
|
308
|
+
/**
|
|
309
|
+
* Gets available closeOut methods
|
|
310
|
+
*/
|
|
311
|
+
closeOut: {
|
|
312
|
+
/**
|
|
313
|
+
* Makes a close out call to an existing instance of the PlonkVerifier smart contract using the `_dummy((byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],uint64,uint64,uint64,uint64,byte[192]))void` ABI method.
|
|
314
|
+
*
|
|
315
|
+
* Dummy function that only exists so we can have the VerificationKey type in the generated client
|
|
316
|
+
*
|
|
317
|
+
* @param params The params for the smart contract call
|
|
318
|
+
* @returns The closeOut result
|
|
319
|
+
*/
|
|
320
|
+
_dummy: async (params) => {
|
|
321
|
+
const result = await this.appClient.send.closeOut(PlonkVerifierParamsFactory.closeOut._dummy(params));
|
|
322
|
+
return { ...result, return: result.return };
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
/**
|
|
326
|
+
* Makes a clear_state call to an existing instance of the PlonkVerifier smart contract.
|
|
327
|
+
*
|
|
328
|
+
* @param params The params for the bare (raw) call
|
|
329
|
+
* @returns The clearState result
|
|
330
|
+
*/
|
|
331
|
+
clearState: (params) => {
|
|
332
|
+
return this.appClient.send.bare.clearState(params);
|
|
333
|
+
},
|
|
334
|
+
/**
|
|
335
|
+
* Makes a call to the PlonkVerifier smart contract using the `verify(uint256[],(byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],uint256,uint256,uint256,uint256,uint256,uint256))void` ABI method.
|
|
336
|
+
*
|
|
337
|
+
* @param params The params for the smart contract call
|
|
338
|
+
* @returns The call result
|
|
339
|
+
*/
|
|
340
|
+
verify: async (params) => {
|
|
341
|
+
const result = await this.appClient.send.call(PlonkVerifierParamsFactory.verify(params));
|
|
342
|
+
return { ...result, return: result.return };
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
/**
|
|
346
|
+
* Clone this app client with different params
|
|
347
|
+
*
|
|
348
|
+
* @param params The params to use for the the cloned app client. Omit a param to keep the original value. Set a param to override the original value. Setting to undefined will clear the original value.
|
|
349
|
+
* @returns A new app client with the altered params
|
|
350
|
+
*/
|
|
351
|
+
clone(params) {
|
|
352
|
+
return new _PlonkVerifierClient(this.appClient.clone(params));
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Methods to access state for the current PlonkVerifier app
|
|
356
|
+
*/
|
|
357
|
+
state = {};
|
|
358
|
+
newGroup() {
|
|
359
|
+
const client = this;
|
|
360
|
+
const composer = this.algorand.newGroup();
|
|
361
|
+
let promiseChain = Promise.resolve();
|
|
362
|
+
const resultMappers = [];
|
|
363
|
+
return {
|
|
364
|
+
/**
|
|
365
|
+
* Add a verify(uint256[],(byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],byte[96],uint256,uint256,uint256,uint256,uint256,uint256))void method call against the PlonkVerifier contract
|
|
366
|
+
*/
|
|
367
|
+
verify(params) {
|
|
368
|
+
promiseChain = promiseChain.then(async () => composer.addAppCallMethodCall(await client.params.verify(params)));
|
|
369
|
+
resultMappers.push(void 0);
|
|
370
|
+
return this;
|
|
371
|
+
},
|
|
372
|
+
get closeOut() {
|
|
373
|
+
return {
|
|
374
|
+
_dummy: (params) => {
|
|
375
|
+
promiseChain = promiseChain.then(async () => composer.addAppCallMethodCall(await client.params.closeOut._dummy(params)));
|
|
376
|
+
resultMappers.push(void 0);
|
|
377
|
+
return this;
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
},
|
|
381
|
+
/**
|
|
382
|
+
* Add a clear state call to the PlonkVerifier contract
|
|
383
|
+
*/
|
|
384
|
+
clearState(params) {
|
|
385
|
+
promiseChain = promiseChain.then(() => composer.addAppCall(client.params.clearState(params)));
|
|
386
|
+
return this;
|
|
387
|
+
},
|
|
388
|
+
addTransaction(txn, signer) {
|
|
389
|
+
promiseChain = promiseChain.then(() => composer.addTransaction(txn, signer));
|
|
390
|
+
return this;
|
|
391
|
+
},
|
|
392
|
+
async composer() {
|
|
393
|
+
await promiseChain;
|
|
394
|
+
return composer;
|
|
395
|
+
},
|
|
396
|
+
async simulate(options) {
|
|
397
|
+
await promiseChain;
|
|
398
|
+
const result = await (!options ? composer.simulate() : composer.simulate(options));
|
|
399
|
+
return {
|
|
400
|
+
...result,
|
|
401
|
+
returns: result.returns?.map((val, i) => resultMappers[i] !== void 0 ? resultMappers[i](val) : val.returnValue)
|
|
402
|
+
};
|
|
403
|
+
},
|
|
404
|
+
async send(params) {
|
|
405
|
+
await promiseChain;
|
|
406
|
+
const result = await composer.send(params);
|
|
407
|
+
return {
|
|
408
|
+
...result,
|
|
409
|
+
returns: result.returns?.map((val, i) => resultMappers[i] !== void 0 ? resultMappers[i](val) : val.returnValue)
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
// src/index.ts
|
|
417
|
+
import * as snarkjs from "snarkjs";
|
|
418
|
+
import {
|
|
419
|
+
getABIEncodedValue
|
|
420
|
+
} from "@algorandfoundation/algokit-utils/types/app-arc56";
|
|
421
|
+
import { readFileSync } from "fs";
|
|
422
|
+
import "algosdk";
|
|
423
|
+
function stringValuesToBigints(obj) {
|
|
424
|
+
for (const key in obj) {
|
|
425
|
+
if (typeof obj[key] === "string" && /^\d+$/.test(obj[key])) {
|
|
426
|
+
obj[key] = BigInt(obj[key]);
|
|
427
|
+
} else if (typeof obj[key] === "object" && obj[key] !== null) {
|
|
428
|
+
stringValuesToBigints(obj[key]);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
async function getVkey(zKey2, curve) {
|
|
433
|
+
const vkey = await snarkjs.zKey.exportVerificationKey(zKey2, console);
|
|
434
|
+
["Ql", "Qr", "Qo", "Qm", "Qc", "S1", "S2", "S3"].forEach((p) => {
|
|
435
|
+
stringValuesToBigints(vkey[p]);
|
|
436
|
+
const point = curve.G1.fromObject(vkey[p]);
|
|
437
|
+
vkey[`${p}Bytes`] = curve.G1.toUncompressed(point);
|
|
438
|
+
});
|
|
439
|
+
stringValuesToBigints(vkey.X_2);
|
|
440
|
+
const x2Point = curve.G2.fromObject(vkey.X_2);
|
|
441
|
+
const x2Uncompressed = curve.G2.toUncompressed(x2Point);
|
|
442
|
+
const x1 = x2Uncompressed.subarray(0, 48);
|
|
443
|
+
const x0 = x2Uncompressed.subarray(48, 96);
|
|
444
|
+
const y1 = x2Uncompressed.subarray(96, 144);
|
|
445
|
+
const y0 = x2Uncompressed.subarray(144, 192);
|
|
446
|
+
const x2Bytes = new Uint8Array(192);
|
|
447
|
+
x2Bytes.set(x0, 0);
|
|
448
|
+
x2Bytes.set(x1, 48);
|
|
449
|
+
x2Bytes.set(y0, 96);
|
|
450
|
+
x2Bytes.set(y1, 144);
|
|
451
|
+
return {
|
|
452
|
+
power: vkey.power,
|
|
453
|
+
nPublic: vkey.nPublic,
|
|
454
|
+
ql: vkey.QlBytes,
|
|
455
|
+
qr: vkey.QrBytes,
|
|
456
|
+
qo: vkey.QoBytes,
|
|
457
|
+
qm: vkey.QmBytes,
|
|
458
|
+
qc: vkey.QcBytes,
|
|
459
|
+
s1: vkey.S1Bytes,
|
|
460
|
+
s2: vkey.S2Bytes,
|
|
461
|
+
s3: vkey.S3Bytes,
|
|
462
|
+
k1: BigInt(vkey.k1),
|
|
463
|
+
k2: BigInt(vkey.k2),
|
|
464
|
+
x_2: x2Bytes
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
function encodeVk(vkey, appSpec) {
|
|
468
|
+
return getABIEncodedValue(vkey, "VerificationKey", appSpec.structs);
|
|
469
|
+
}
|
|
470
|
+
async function getProof(path, curve) {
|
|
471
|
+
const proof = JSON.parse(readFileSync(path, "utf8"));
|
|
472
|
+
return encodeProof(proof, curve);
|
|
473
|
+
}
|
|
474
|
+
function encodeProof(proof, curve) {
|
|
475
|
+
["A", "B", "C", "Z", "T1", "T2", "T3", "Wxi", "Wxiw"].forEach((p) => {
|
|
476
|
+
stringValuesToBigints(proof[p]);
|
|
477
|
+
const point = curve.G1.fromObject(proof[p]);
|
|
478
|
+
proof[`${p}Bytes`] = curve.G1.toUncompressed(point);
|
|
479
|
+
});
|
|
480
|
+
["eval_a", "eval_b", "eval_c", "eval_s1", "eval_s2", "eval_zw"].forEach(
|
|
481
|
+
(p) => {
|
|
482
|
+
proof[`${p}BigInt`] = BigInt(proof[p]);
|
|
483
|
+
}
|
|
484
|
+
);
|
|
485
|
+
return {
|
|
486
|
+
a: proof.ABytes,
|
|
487
|
+
b: proof.BBytes,
|
|
488
|
+
c: proof.CBytes,
|
|
489
|
+
z: proof.ZBytes,
|
|
490
|
+
t1: proof.T1Bytes,
|
|
491
|
+
t2: proof.T2Bytes,
|
|
492
|
+
t3: proof.T3Bytes,
|
|
493
|
+
wxi: proof.WxiBytes,
|
|
494
|
+
wxiw: proof.WxiwBytes,
|
|
495
|
+
evalA: proof.eval_aBigInt,
|
|
496
|
+
evalB: proof.eval_bBigInt,
|
|
497
|
+
evalC: proof.eval_cBigInt,
|
|
498
|
+
evalS1: proof.eval_s1BigInt,
|
|
499
|
+
evalS2: proof.eval_s2BigInt,
|
|
500
|
+
evalZw: proof.eval_zwBigInt
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
function encodeSignals(...inputs) {
|
|
504
|
+
return inputs.map((input) => {
|
|
505
|
+
return BigInt(input);
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
var AppVerifier = class {
|
|
509
|
+
constructor(algorand, zKey2, wasmProver) {
|
|
510
|
+
this.algorand = algorand;
|
|
511
|
+
this.zKey = zKey2;
|
|
512
|
+
this.wasmProver = wasmProver;
|
|
513
|
+
}
|
|
514
|
+
appClient;
|
|
515
|
+
curve;
|
|
516
|
+
async ensureCurveInstanttiation() {
|
|
517
|
+
if (!this.curve) {
|
|
518
|
+
this.curve = await snarkjs.curves.getCurveFromName("bls12381");
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
async deploy(params) {
|
|
522
|
+
if (this.appClient) {
|
|
523
|
+
throw new Error("AppVerifier already deployed");
|
|
524
|
+
}
|
|
525
|
+
const curve = await snarkjs.curves.getCurveFromName("bls12381");
|
|
526
|
+
const factory = new PlonkVerifierFactory({
|
|
527
|
+
algorand: this.algorand,
|
|
528
|
+
defaultSender: params.defaultSender
|
|
529
|
+
});
|
|
530
|
+
const vk = await getVkey(this.zKey, curve);
|
|
531
|
+
const vkBytes = encodeVk(vk, factory.appSpec);
|
|
532
|
+
const rootOfUnity = Buffer.from(
|
|
533
|
+
curve.Fr.toObject(curve.Fr.w[Number(vk.power)]).toString(16).padStart(64, "0"),
|
|
534
|
+
"hex"
|
|
535
|
+
);
|
|
536
|
+
const { appClient } = await factory.deploy({
|
|
537
|
+
...params,
|
|
538
|
+
deployTimeParams: {
|
|
539
|
+
VERIFICATION_KEY: vkBytes,
|
|
540
|
+
ROOT_OF_UNITY: rootOfUnity,
|
|
541
|
+
DEBUG_LOGGING: params.debugLogging ? 1 : 0
|
|
542
|
+
}
|
|
543
|
+
});
|
|
544
|
+
this.appClient = appClient;
|
|
545
|
+
return appClient;
|
|
546
|
+
}
|
|
547
|
+
async proofAndSignals(inputs) {
|
|
548
|
+
await this.ensureCurveInstanttiation();
|
|
549
|
+
const { proof: rawProof, publicSignals: rawSignals } = await snarkjs.plonk.fullProve(inputs, this.wasmProver, this.zKey);
|
|
550
|
+
const proof = encodeProof(rawProof, this.curve);
|
|
551
|
+
const signals = encodeSignals(...rawSignals);
|
|
552
|
+
return { proof, signals };
|
|
553
|
+
}
|
|
554
|
+
assertDeployed() {
|
|
555
|
+
if (!this.appClient) {
|
|
556
|
+
throw new Error("AppVerifier not deployed");
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
// Methods that take in proof and signals directly
|
|
560
|
+
async simulateVerificationWithProofAndSignals(proofAndSignals, simParams) {
|
|
561
|
+
this.assertDeployed();
|
|
562
|
+
return this.appClient.newGroup().verify({ args: proofAndSignals }).simulate(simParams ?? {});
|
|
563
|
+
}
|
|
564
|
+
async verifyTransactionFromProofAndSignals(proofAndSignals) {
|
|
565
|
+
this.assertDeployed();
|
|
566
|
+
return (await this.appClient.createTransaction.verify({
|
|
567
|
+
args: proofAndSignals
|
|
568
|
+
})).transactions[0];
|
|
569
|
+
}
|
|
570
|
+
async callVerifyFromProofAndSignals(proofAndSignals, callParams) {
|
|
571
|
+
this.assertDeployed();
|
|
572
|
+
return this.appClient.send.verify({ ...callParams, args: proofAndSignals });
|
|
573
|
+
}
|
|
574
|
+
// Methods that generate proof and signals internally
|
|
575
|
+
async simulateVerification(inputs, simParams) {
|
|
576
|
+
return this.simulateVerificationWithProofAndSignals(
|
|
577
|
+
await this.proofAndSignals(inputs),
|
|
578
|
+
simParams
|
|
579
|
+
);
|
|
580
|
+
}
|
|
581
|
+
async verifyTransaction(inputs) {
|
|
582
|
+
return this.verifyTransactionFromProofAndSignals(
|
|
583
|
+
await this.proofAndSignals(inputs)
|
|
584
|
+
);
|
|
585
|
+
}
|
|
586
|
+
async callVerify(inputs, callParams) {
|
|
587
|
+
return this.callVerifyFromProofAndSignals(
|
|
588
|
+
await this.proofAndSignals(inputs),
|
|
589
|
+
callParams
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
export {
|
|
594
|
+
AppVerifier,
|
|
595
|
+
PlonkVerifierClient,
|
|
596
|
+
encodeProof,
|
|
597
|
+
encodeSignals,
|
|
598
|
+
encodeVk,
|
|
599
|
+
getProof,
|
|
600
|
+
getVkey
|
|
601
|
+
};
|