diff --git a/Cargo.toml b/Cargo.toml index 047d115..e91c75e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ members = [ "shuffle/wasm", "matchmaking", "c-uzkge", + "wasm", ] resolver = "2" @@ -54,6 +55,7 @@ sha3 = "0.10" structopt = "0.3" tera = "1.19" thiserror = "1.0" +ethabi = "18.0.0" # wasm getrandom = { version = "0.2", features = ["js"] } diff --git a/wasm/Cargo.toml b/wasm/Cargo.toml new file mode 100644 index 0000000..eb7105a --- /dev/null +++ b/wasm/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "wasm" +description = "WASM SDK for encrypt and shuffle cards" +version.workspace = true +edition.workspace = true +authors.workspace = true +homepage.workspace = true +repository.workspace = true +categories.workspace = true +license.workspace = true + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +zshuffle.workspace = true +zmatchmaking.workspace = true +uzkge = { workspace = true, features = ["shuffle"] } + +ark-ec.workspace = true +ark-ff.workspace = true +ark-bn254.workspace = true +ark-serialize.workspace = true +ark-ed-on-bn254.workspace = true +bincode.workspace = true +hex.workspace = true +wasm-bindgen.workspace = true +serde-wasm-bindgen.workspace = true +rand_chacha = { workspace = true } +ethabi.workspace = true +getrandom = { version = "0.2", features = ["js"] } diff --git a/wasm/demo.js b/wasm/demo.js new file mode 100644 index 0000000..571f6a7 --- /dev/null +++ b/wasm/demo.js @@ -0,0 +1,68 @@ +// Call 'wasm-pack build --target nodejs' to build from this directory for this command to work +const wasm = require('./pkg/wasm.js'); +{ + let f1 = "0x2f8dd1f1a7583c42c4e12a44e110404c73ca6c94813f85835da4fb7bb1301d4a"; + let f2 = "0x1ee678a0470a75a6eaa8fe837060498ba828a3703b311d0f77f010424afeb025"; + let f3 = "0x2042a587a90c187b0a087c03e29c968b950b1db26d5c82d666905a6895790c0a"; + + let ret = wasm.anemoi_hash([f1, f2, f3]); + console.log(ret) +} +{ + let x1 = "0x0d52c3aa573af39845660735de0d3d9efb481a112cf00623ab22546122d4e16a"; + let y1 = "0x0e7e20b3cb30785b64cd6972e2ddf919db64d03d6cf01456243c5ef2fb766a65"; + let x2 = "0x242cbada3ae8d6e90056e73e4941eeccee72cb99945a194f754205b3678bd769"; + let y2 = "0x2d7690deeaa77c9d89b0ceb3c25f7bb09c44f40b4b8cf5d6fcb512c7be8fcba9"; + + let ret = wasm.point_add(x1, y1, x2, y2); + console.log(ret) +} +{ + let s = "0x008d7a42a4dde1d8f8bcacddcae9bc78b1480eb547d4a490d9cfa5c268a076c7"; + let x = "0x1738fd301654d891e32235d03a64b7ebe0c3f37df67db0b798f2664783b1bac9"; + let y = "0x22a689a1c0aebf70ceee76fe7891729002e072ceb7ba94a32b1fce79f8c009d9"; + + let ret = wasm.scalar_mul(s, x, y); + console.log(ret) +} + +{ + let verifier_params = wasm.verifier_matchmaking_params(); + let rng_seed = "0x0000000000000000000000000000000000000000000000000000000000000000"; + let inputs = ["0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000002", "0000000000000000000000000000000000000000000000000000000000000003", "0000000000000000000000000000000000000000000000000000000000000004", "0000000000000000000000000000000000000000000000000000000000000005", "0000000000000000000000000000000000000000000000000000000000000006", "0000000000000000000000000000000000000000000000000000000000000007", "0000000000000000000000000000000000000000000000000000000000000008", "0000000000000000000000000000000000000000000000000000000000000009", "000000000000000000000000000000000000000000000000000000000000000a", "000000000000000000000000000000000000000000000000000000000000000b", "000000000000000000000000000000000000000000000000000000000000000c", "000000000000000000000000000000000000000000000000000000000000000d", "000000000000000000000000000000000000000000000000000000000000000e", "000000000000000000000000000000000000000000000000000000000000000f", "0000000000000000000000000000000000000000000000000000000000000010", "0000000000000000000000000000000000000000000000000000000000000011", "0000000000000000000000000000000000000000000000000000000000000012", "0000000000000000000000000000000000000000000000000000000000000013", "0000000000000000000000000000000000000000000000000000000000000014", "0000000000000000000000000000000000000000000000000000000000000015", "0000000000000000000000000000000000000000000000000000000000000016", "0000000000000000000000000000000000000000000000000000000000000017", "0000000000000000000000000000000000000000000000000000000000000018", "0000000000000000000000000000000000000000000000000000000000000019", "000000000000000000000000000000000000000000000000000000000000001a", "000000000000000000000000000000000000000000000000000000000000001b", "000000000000000000000000000000000000000000000000000000000000001c", "000000000000000000000000000000000000000000000000000000000000001d", "000000000000000000000000000000000000000000000000000000000000001e", "000000000000000000000000000000000000000000000000000000000000001f", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000021", "0000000000000000000000000000000000000000000000000000000000000022", "0000000000000000000000000000000000000000000000000000000000000023", "0000000000000000000000000000000000000000000000000000000000000024", "0000000000000000000000000000000000000000000000000000000000000025", "0000000000000000000000000000000000000000000000000000000000000026", "0000000000000000000000000000000000000000000000000000000000000027", "0000000000000000000000000000000000000000000000000000000000000028", "0000000000000000000000000000000000000000000000000000000000000029", "000000000000000000000000000000000000000000000000000000000000002a", "000000000000000000000000000000000000000000000000000000000000002b", "000000000000000000000000000000000000000000000000000000000000002c", "000000000000000000000000000000000000000000000000000000000000002d", "000000000000000000000000000000000000000000000000000000000000002e", "000000000000000000000000000000000000000000000000000000000000002f", "0000000000000000000000000000000000000000000000000000000000000030", "0000000000000000000000000000000000000000000000000000000000000031", "0000000000000000000000000000000000000000000000000000000000000032"]; + let committed_seed = "0x2f8dd1f1a7583c42c4e12a44e110404c73ca6c94813f85835da4fb7bb1301d4a" + let random_number = "0x1ee678a0470a75a6eaa8fe837060498ba828a3703b311d0f77f010424afeb025"; + let ret = wasm.generate_matchmaking_proof(verifier_params, rng_seed, inputs, committed_seed, random_number); + console.log(ret) +} + +{ + let verifier_params = "0x28000000000000000100000000000000010000000000000000000000000000000000000000000000000000000000000088000000000000000200000000000000edf692d95cbdde46ddda5ef7d422436779445c5e66006a42761e1f12efde0018c212f3aeb785e49712e7a9353349aaf1255dfb31b7bf60723a480d9293938e19b0838893ec1f237e8b07323b0744599f4e97b598b3b589bcc2bc37b8d5c41801c18393c0fa30fe4e8b038e357ad851eae8de9107584effe7c7f1f651b2010e2608000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000800000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000800000000000000000000000000000080030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008b170000000000000020000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000108000000000000000000000000000000080000000000000020000000000000000260ee740b651909f3cb74b09f59504451ce08cd35949536dd54821719818f0720000000000000001d28434ab9c603dded2ce30fdb4928eff827bdcd25d2241244b0c77d2b038911200000000000000008b3ce07c205066e5343e88519d15ba413daad11ee4bac047ced5a5e1d1b84092000000000000000410e3151d6f536710cb198f2a66e54e1a8036d4f5469a2041b7044a54d2bcc2d2000000000000000b64ffe48a346f28353c47cffd273d3cf4152715fbbf476cb57ef25bb01d3089c20000000000000009d34cc541129c06a4b5aa47d72e3faab4bdd3a2896c787ab629367d6721c392720000000000000005cf8bb81f5d71685a47765692ba8c9fad33b6159799449beb81c11ceda85d3ad2000000000000000f36f4559f19be743feb6275d5a449e54d8503b646f89881d22f0b55e1c3c280105000000000000002000000000000000e7b108b86cbd1443e553e9f0557254627995fcfb8e37c6ea9683f427150369a62000000000000000a5541363d37a591a1f0d833acfd62b1fd397864a1e91a385178c925b44bc8b272000000000000000d88d2b725e6ba107efcebc80de5836dd3538da2a09f863edaf2d2fc79e1340ac2000000000000000715b5fc7975b98218df2aa8fdfedd9a4332461bdf1d8a890c5e144a5351c751c20000000000000007a4a4d157a71da65c485331b4987fcfe564660e26ab562dd0e8b9e855bbc49a32000000000000000da71775af617443dabe80db760ac8d3ab55a96ce04cf6f7a321f32138b04169204000000000000002000000000000000418499fc987e0a0c408e681cdd2d071161b51b850a29c1a180e78375959bd8a42000000000000000e347edc7dfc6df186b064c2268574e6ef155612387f9f40dec4832feb9b383972000000000000000c8e2224c62d0e2c52d24cd3bcdfb6f924d04cbeabcdc9820fd328a03484147992000000000000000898fe63f147802ee6bd953d58f8b01b03b926af95647ba790c37b6c7aa864090200000000000000000000000000000000000000000000000000000000000000000000000000000400c000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000000000000000000040200000000000000000000000000000000000000000000000000000000000000000000000000000402000000000000000000000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000000000000000000040200000000000000000000000000000000000000000000000000000000000000000000000000000402000000000000000000000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000000000000000000040200000000000000000000000000000000000000000000000000000000000000000000000000000402000000000000000000000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000000000000000000040200000000000000000000000000000000000000000000000000000000000000000000000000000400c00000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000402000000000000000000000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000000000000000000040200000000000000000000000000000000000000000000000000000000000000000000000000000402000000000000000000000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000000000000000000040200000000000000000000000000000000000000000000000000000000000000000000000000000402000000000000000000000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000000000000000000040200000000000000000000000000000000000000000000000000000000000000000000000000000402000000000000000000000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000000000000000000040200000000000000005000000000000000000000000000000000000000000000000000000000000002000000000000000676666c6d4fbf3e7062d4acae95caea98b56cd337cb5b949aad9135a94525b13a800000000000000050000000000000001000000000000000000000000000000000000000000000000000000000000004a1d30b17bfba45d83853f81946cca734c4010e1442ae1c4423c58a7f1d18d2f0a0c7995685a9066d6825c6db21d0b958b969ce2037c080a7b180ca987a5422060498e759b9e52bf33a7dc60a15f3bd732f36f793407eff03ce3e6134e94b42d462fd253005d048b4542010411e314a65ad0d7c68d1325992d0501af4a3a9e1d2000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000006600000000000000f213000000000000f313000000000000f413000000000000f513000000000000f613000000000000f713000000000000f813000000000000f913000000000000fa13000000000000fb13000000000000fc13000000000000fd13000000000000fe13000000000000ff1300000000000000140000000000000114000000000000021400000000000003140000000000000414000000000000051400000000000006140000000000000714000000000000081400000000000009140000000000000a140000000000000b140000000000000c140000000000000d140000000000000e140000000000000f1400000000000010140000000000001114000000000000121400000000000013140000000000001414000000000000151400000000000016140000000000001714000000000000181400000000000019140000000000001a140000000000001b140000000000001c140000000000001d140000000000001e140000000000001f1400000000000020140000000000002114000000000000221400000000000023140000000000002414000000000000251400000000000026140000000000002714000000000000281400000000000029140000000000002a140000000000002b140000000000002c140000000000002d140000000000002e140000000000002f1400000000000030140000000000003114000000000000321400000000000033140000000000003414000000000000351400000000000036140000000000003714000000000000381400000000000039140000000000003a140000000000003b140000000000003c140000000000003d140000000000003e140000000000003f1400000000000040140000000000004114000000000000421400000000000043140000000000004414000000000000451400000000000046140000000000004714000000000000481400000000000049140000000000004a140000000000004b140000000000004c140000000000004d140000000000004e140000000000004f1400000000000050140000000000005114000000000000521400000000000053140000000000005414000000000000551400000000000056140000000000005714000000000000c80c000000000000660000000000000059f5d5d00810ace0f7e6671b68d785cd004a6fee99ea60edff5060a51b43ec02ba8bed21ab60c4fbd34ca72a11c26844f7cb427d461a8565ba2d09011136692d06c7fe7e8f5db4d70b219b208a450e920fed5953a6e87e91fa4306efeea2921c7fdbc665c2e9be3568d46c387d6205afde6d01978c08571c486d902e4bdf75264d0b18e78744faf861a6d67dab795e01943b9b086d65daf09ad9ed765c3461009bff9aa41584f9a5f57ff18bdca2c7d6d052029a73bd3a2e479eee0acc1d622a6a6abadde7637ab325757f37deca3607f293d23bab1e41f0ca0f5024a9f7a8050c3b3375a4aa5e5ec61d7f53f5e2cb6cda916487e0cae9bf0c8289ef12dcdb010953486fa0cbb157840132474ab171a2e052b8d8303859f05a0e5a574447de2bd40816db62f4bd337a37ee50e5dea6fee6dfec71dd5d64e586fca66a0cab2422ce294c91a8271ea35153e24eb67e91aae9986825dc4101439ed127b9d8eb590e40e6d2bd39e15bbe85237dc3b8f3d9a7f62f48cb1f00b67d747ba881f48b00239feb06e6aed83f52ec3e26b6e5287625f360ce26062b4a0b2d3228940166c01262b6ee321a9f5342f7504139607f090036383824a7e267b5f78cb0376034f20916f26996a3b95e2492fecc7851e69e50b992f201951d954a9d06958f29411e2e7061446d0425bcff7438f58c0415ba41114189fbf2caf68436a066c5f16d66206ef08da16fe41d7fb3ba53f455aa181d60ed0d72936378c863694944e9fa6c03078a6266fd3ed766366bdf8c83d8bbc5bbdd98e68ec87e55552bf7426d326c19e8f9166b9e227aedf7c5ca31766bbb2581f30f8c0ba789362c6ccdf6150be81887e06a4480bcd50581e5b25f9c757a0abbbcd6eda87c2b9e1e894b0c0b9b6b11f0d2cb4bb21bcfe4dbcc92a451d59678eb78832f4059ecbbd227ecc08fa61a2c937a18de3822b020b30bda83094c8496a435f24191e659ca54bedd56cfa9932985c39a3b5cafcb0f8d3ebacf64ca9252d8eacf08bfa39216cba10ed9c923402978d9782bd0240be6dccc132eea8e557586d371d4265ee9380d45cf2afea38d1ef9c5c77d9e9ea8562ee0a5df1b274ea90429a1be5f23054044d05c5fa895ab12d33b6740b3bf02c46ef72e597ce0f9525172ac6a652145598116195f6f31c32a863fb7b67714d4d961017a45fb88398959a8adc13204e7f263da963073bb02080f4f84f6dc199903b8280ba215186d355956dafcc1932190c20966f4bc266030136053e45901f995378ba0694a842eae13b8ca671200d860fb4e3a1827fc071e093c0e6587f9d605c45e985b786e1a3a35d285660075bd245d5e6fb4dee5b80efaef1515c18e27f9223716e0446bf463a22a6e2ebc08afc582820e051a0a0326f2f9255a84e030e461f6288049ed5cd2de1347ec66649b02b7be86e26dc4fd06c7854872329b9fb6868055a2d86d663b3c65d6483304742e2d3879a32543001107d0d31f634128e8f217bb9eed11646ec293dc03e5e6a2e49a360bca40e05d20ba81aa9a57f7d0ab5b6218b28ccc55a9986206cddd23391278edc221bd4d9f088fed90bb3947edee49e8bfae62fdd1853ed54ae717a8abe990496fb574aa1c12bf5619c310a9db060ddbf8de2d52de934aefc25468ef8bf28cd69959fb526a1d9485be22fc5c1e25e20498be8ee2515ff04894000ea2be9e9c14edabd06d532717c0b630d9148306ec86e797b9c465280cc0532986b7f86e1467b5220772920cd2255bb059154072b375089467be0fd1c045b27e8277f5f7f18841366b24de2d27d109dcea448269648bb94ab32bdfe1e5b46708f27e75b98cb98cd6f3903107afaca82735af404fa981cbd84248258d08fc00f11585b728f14b6655d623032ce15cdb7464b611ee7fca38a256dd10929b661628a960f41557c8d42610219d1afab6b041b3cc393b29e7e9f36c104af54f9cbfa233fbf4c61342d71120de06193c8005069eda9fbea9aeebc73f3996568a5ecd0654eb965638b4e0c6cea515020553f9178983eef840d1a7edd0984057781d753c814dffa874ef222955475b10a44c083f823cb4e3c7caa713745e9429c134485e622d1ae65d9588ed4770ef0b98d123571a233f586c89490d513ceeae7229975298092dab7848164dcf60be21f93ee2c36fd65498889fc3f2fc454cf6ea24dba7ab00627c53ee7036d88dbe07de82adaa8b8f26cb2d7b4b2b1bb1769c0e9c6b9096ec2d3ff9eed5946081db02f24fcb23381b67a8b199a093d1e9ae60f429affab22c0f63cd6d47b0def6130bcca9a76a2ef4f1b713ea960244fb296f5c63a4d9f7c4ce032d6b3e49fcbe1c26f2d36e880df6853d8260a27f68fe4c0caf0b1038731446d29f190432f8213421fc7d94ee4c227214522c57f9a3c4c0be5f974dde11b23fb4aa85bb67a260df1d36f3fb6abea33ec19b9e72be917f6c2b393b009f8b2bae1608223c286340761ed97fe68a5e4dfa15872c2e80772a2b3d26f34d7607ce7869b254aa527285651323d03673fee57c1bf4bea8451fedd0d48310066661885c6b342776f227d93521c3775505fc1f68a181cb5676ede58ad73f4264982cd75c899802ff76fe3b2019f5971c084845a3bfc1d8c31a4ab7847db95d887e2d6269461544929834f23c2ebf925b25dfe15946d3f04befcc32eee1cd54528c5202a9c57b2255a9fb35ea2bea36c662483d49dde5e9bea9d48245c60256fb2d3c5c0e64b31ad65321d6591485fe9c7ade1282c5ff60c0ff180c205a12c9f894f849063002fd1023ade6a825983e24dad0e18f8a960141c260d63f0a7e47f64f60c7306f28883cd9c40d801fe4a80666a2e7654f8fe292c5dd626b8d258957ab755e33d92031335324c9c213fe33d0875095a54b17b954c45408139ccec23f6daf9762273d31ba1935d2952ef5f2367e1abbec442dfd736e4a27b5c7686242d49ff4d1dea43a50c0293b8f191e92cf71419afe72179376c78fd17e6c4034043f726de6c696563200dd06840fc5edca24dc19ba68fefcf19ccd586300923b94c7d5afb0148431738cc8b4060e5f2248532919cdf853fbff90d4d9ed4652d1f98bf2aa61cfc7afae05c2bb601a909352b0db6aac147272ecbf43df88545925bbe624479fff4ebc2022595bc70be8322e0f3a7002b06496778a02d01af7e64870e58fcc69c969e2af6d7d170d2748dea0bb9c16aecc5dfb79d6f09e94891de809ad824ee58c550341b7563a9408e69b3b9056cb4c77ca21714cc611e68c8726b161d0380477d754b774acdbc523e1594c5f1255b4e2bfef000ea27368e689f7cd8c72d579dda295761983455804716e3d0936663bd26cd373f62741d7afe4adbbeba987aee874d38ebc4c4d961e5674adaf95da50a96b6e8e7bb36487db377259df2114278b5166e746761c9e2594d11639ed6378dd10b8b7927fe1f6b5047996cf144b6b66d5d5b10d4b2818083a3fac7081714b4f4179f310defe2ceb7d156872a6dc801586200d4a9e28ab18d7f93a4c35e5c552812548d06106ad5eea75d883a97b994569a23aeff931e3255438dc412de63c750e79dcecaa06d209f2051d63564b74151c85ab58c2c5a2262f80f30f94fbe24cac408bf74d6147d5abfb5d085429c797f90e9b4968d1211b50bd5d4b9af17e0bcfeacd4e5df139a2a08b85d3c233479028e86258bda82724719bb5bac556155a6cb9ac2535d571ebd9374bbece61d3c41363401a481317041db6fcfb63972a6e154e73cb528cf0d25414c5561961d17de0d6f745e92f592cddbb3e6d680bea1220d105e17145d8425e44803e5b839c3dedeb2542c6fd240aa6dbe2486b398ed59b381747d3c92b1a6cddf38200c697fc18265453ab75b908d5a80f8ee92fc1772463378f2399b7ac2c7dc996c599aa874d09eff5e8703003578e568b09af47d9354e21fd3339ac4279a62651891e8ee766708d150d08c0146edf4d2c54eb361a6f0832911f1e6d07084d2e6e8d2b0e71856f8896f507cb0a18564a2335ad0fe5515d0b9024384658114adefbd5c49622b6735ca8a2d915275da783bd36dcd91ce88b03aadccd717975023282553f83817885025023e0301cb64fecc1bb79426f79f5fd0a72289ad0efa01b7d7e03ec8daf3d1178b1731103cf6f5863b85b27cdb0c935bd797b6eb1a5849cc8100bdd5a5f7dea23c7428011708f8dff53e463e588b692344aef565fd412e60b51c8d74511e06aac4dc3b3267fa0f85043308c8a30b93ed52e689f5762d6a603d4aaf63662107ee3e20bd306193e8e13a24270caf97bbca85d311a6eee38aad372e7af1ea99438322bde342f6cf7048ad2f755e298bbec9d6a240800fd60dfc9a1a89ce699dcaac1d71d9b2c4c49cca5c532b9968ae3e269b47d213863a0f8b4a8075ec14180f87d6c144113c533256ad9cf4f1a55ba9de4111bde5d5cd88dc4422ad6f520fe70dd5c7ab61b6ea00a3a3293366fd14c3cfc6e818ef9de3bac985f6b7825ce398eefd201cb2bc13e4751e886d0c2d5c7b5341d273c773579afb6a2d2a70bff8c00abb2729f2816118e9342863289c1c96e7be556e5583efa79e6fd6b6d3db19e2dffeeb36315"; + let inputs = ["0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000002", "0000000000000000000000000000000000000000000000000000000000000003", "0000000000000000000000000000000000000000000000000000000000000004", "0000000000000000000000000000000000000000000000000000000000000005", "0000000000000000000000000000000000000000000000000000000000000006", "0000000000000000000000000000000000000000000000000000000000000007", "0000000000000000000000000000000000000000000000000000000000000008", "0000000000000000000000000000000000000000000000000000000000000009", "000000000000000000000000000000000000000000000000000000000000000a", "000000000000000000000000000000000000000000000000000000000000000b", "000000000000000000000000000000000000000000000000000000000000000c", "000000000000000000000000000000000000000000000000000000000000000d", "000000000000000000000000000000000000000000000000000000000000000e", "000000000000000000000000000000000000000000000000000000000000000f", "0000000000000000000000000000000000000000000000000000000000000010", "0000000000000000000000000000000000000000000000000000000000000011", "0000000000000000000000000000000000000000000000000000000000000012", "0000000000000000000000000000000000000000000000000000000000000013", "0000000000000000000000000000000000000000000000000000000000000014", "0000000000000000000000000000000000000000000000000000000000000015", "0000000000000000000000000000000000000000000000000000000000000016", "0000000000000000000000000000000000000000000000000000000000000017", "0000000000000000000000000000000000000000000000000000000000000018", "0000000000000000000000000000000000000000000000000000000000000019", "000000000000000000000000000000000000000000000000000000000000001a", "000000000000000000000000000000000000000000000000000000000000001b", "000000000000000000000000000000000000000000000000000000000000001c", "000000000000000000000000000000000000000000000000000000000000001d", "000000000000000000000000000000000000000000000000000000000000001e", "000000000000000000000000000000000000000000000000000000000000001f", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000021", "0000000000000000000000000000000000000000000000000000000000000022", "0000000000000000000000000000000000000000000000000000000000000023", "0000000000000000000000000000000000000000000000000000000000000024", "0000000000000000000000000000000000000000000000000000000000000025", "0000000000000000000000000000000000000000000000000000000000000026", "0000000000000000000000000000000000000000000000000000000000000027", "0000000000000000000000000000000000000000000000000000000000000028", "0000000000000000000000000000000000000000000000000000000000000029", "000000000000000000000000000000000000000000000000000000000000002a", "000000000000000000000000000000000000000000000000000000000000002b", "000000000000000000000000000000000000000000000000000000000000002c", "000000000000000000000000000000000000000000000000000000000000002d", "000000000000000000000000000000000000000000000000000000000000002e", "000000000000000000000000000000000000000000000000000000000000002f", "0000000000000000000000000000000000000000000000000000000000000030", "0000000000000000000000000000000000000000000000000000000000000031", "0000000000000000000000000000000000000000000000000000000000000032"]; + let outputs = ["0000000000000000000000000000000000000000000000000000000000000011", "000000000000000000000000000000000000000000000000000000000000000f", "0000000000000000000000000000000000000000000000000000000000000019", "0000000000000000000000000000000000000000000000000000000000000002", "0000000000000000000000000000000000000000000000000000000000000022", "000000000000000000000000000000000000000000000000000000000000001d", "0000000000000000000000000000000000000000000000000000000000000030", "000000000000000000000000000000000000000000000000000000000000002f", "0000000000000000000000000000000000000000000000000000000000000001", "000000000000000000000000000000000000000000000000000000000000001a", "0000000000000000000000000000000000000000000000000000000000000024", "0000000000000000000000000000000000000000000000000000000000000014", "0000000000000000000000000000000000000000000000000000000000000013", "0000000000000000000000000000000000000000000000000000000000000005", "0000000000000000000000000000000000000000000000000000000000000003", "0000000000000000000000000000000000000000000000000000000000000028", "0000000000000000000000000000000000000000000000000000000000000015", "0000000000000000000000000000000000000000000000000000000000000004", "0000000000000000000000000000000000000000000000000000000000000026", "000000000000000000000000000000000000000000000000000000000000001b", "0000000000000000000000000000000000000000000000000000000000000027", "000000000000000000000000000000000000000000000000000000000000000b", "0000000000000000000000000000000000000000000000000000000000000017", "0000000000000000000000000000000000000000000000000000000000000010", "0000000000000000000000000000000000000000000000000000000000000031", "0000000000000000000000000000000000000000000000000000000000000006", "0000000000000000000000000000000000000000000000000000000000000023", "000000000000000000000000000000000000000000000000000000000000002a", "0000000000000000000000000000000000000000000000000000000000000021", "0000000000000000000000000000000000000000000000000000000000000018", "0000000000000000000000000000000000000000000000000000000000000007", "0000000000000000000000000000000000000000000000000000000000000012", "000000000000000000000000000000000000000000000000000000000000002d", "000000000000000000000000000000000000000000000000000000000000002b", "000000000000000000000000000000000000000000000000000000000000000d", "0000000000000000000000000000000000000000000000000000000000000025", "000000000000000000000000000000000000000000000000000000000000001f", "0000000000000000000000000000000000000000000000000000000000000029", "0000000000000000000000000000000000000000000000000000000000000008", "000000000000000000000000000000000000000000000000000000000000002c", "0000000000000000000000000000000000000000000000000000000000000016", "000000000000000000000000000000000000000000000000000000000000000a", "0000000000000000000000000000000000000000000000000000000000000020", "000000000000000000000000000000000000000000000000000000000000000e", "000000000000000000000000000000000000000000000000000000000000001c", "0000000000000000000000000000000000000000000000000000000000000009", "000000000000000000000000000000000000000000000000000000000000002e", "000000000000000000000000000000000000000000000000000000000000001e", "000000000000000000000000000000000000000000000000000000000000000c", "0000000000000000000000000000000000000000000000000000000000000032"]; + let commitment = "0x0b41654c6dcf28870852e8bf532bb7ec52f868cc106694cc4043802b429af9e4"; + let random_number = "0x1ee678a0470a75a6eaa8fe837060498ba828a3703b311d0f77f010424afeb025"; + let proof = "0x050000000000000020000000000000008ce6907688f4ef9607e90ef4b25a3107bf525a65f235498fe4a05768c7a48d982000000000000000127a248e987755fee6cd2c97c3af1d88c48179d9f0fbf619515375731dd74a292000000000000000f6a1a9865a1692db8c1f0a302f4b7058e82f6e7f2315f9f777df3cb2ddf2102820000000000000004516004a0474aa63341735d8e8abd841d717588c15d40b72142ac3e93486ea2e2000000000000000ae3310be43dce0c9154c188ba8f19835db402554e142431e244e3ba5ea2fe89c030000000000000020000000000000004e03867209865883e6f11a6669600a15d5c04ed137e41e36a22801340372151920000000000000004b71f6b9a082267e35892886fb159c4e48b88e5d3366f00042fa0c1942f9d12c2000000000000000c1fdbe434c9b49647bd4eeb6beacb6b3e3fec638994b482f8a9f87158fc46aa105000000000000002000000000000000e3db6c667fc3c5acfcdbf57583a8ea8fa37e4d9c1a33acb7577454407dfb4297200000000000000019fbc2d5f5f5d7e0876db499b7bbcfc4163a8c04c9b6908a1ddb5bb14eb99ca22000000000000000267ec7270dfc71fc6c78eba6f5ec72fe57be7e42ceac1fa60e3dbea334263d90200000000000000067e5db00ed06d30e58ac8b1b9c10eec7dd3650f7c143b5abfadd868c0a78e02b2000000000000000a7c5a60e87cc4987ef3b7dbf00b73ea44340afd78c802f596ac9e5d9055e0d2a20000000000000004ba588f2e6345d5e1377281c6bc694490a7e83eae305766808a09adc30eb81a5200000000000000092e70ad0cdb8ed344fd89918ed40648e0e254fa7073991911cc63fe199382d0f2000000000000000ce2bb32bb1b06961b37e98c029b452bf57a1ddd595b0de691f63b4dd2c1d8a0ba8000000000000000500000000000000048cf6bfe97ae077709b8b87b179d5c7dd636a4b0475d2b49d0b5bb2e01e7616f33aafe122703efa8243a68206a4d3084bdce32ee78a78f0c4fe906194a9d229207f1d68245aca2bce9aa66f98c6b5822a43a73c39743cffdb82433a04e7b3252ca65b8f4d40d19b1a18da5dddb0e1b518e577ad2173c9b70f6cab0794348c120a0977bf11058be0cd019608645069c495a14f1919f90f34f19db6edf2870404680000000000000003000000000000002822b3766521a48a4ff8f02c1b2367a4984f7e3f11aa47b4f84e2fc01ea41f09da1566f52352f53c96f8efd49544f92d392793bf388524ee3bcbbf720ffe1d154d5d3f7ff4cf494ac69fe66bf3af20f9982aaa73c7b5c2c0bdaeefbd9d8a6e0d2000000000000000bfc7e5ca4a840836d7e55abba5496e272935f05993b33542a3963305aa6a450c880000000000000004000000000000006c64628c2d7a25d1f45af9f3b8a64272a8b504bce4bc70354e4f7df74b739322e0c962af5fc276cd83d58f9ce7603e55462e5d77f2cc0ca26c764940cf018e1e822787a5307936aff20a37e87230f12835bb277f35e2abbc0762b57eeb66cd2bde24ac270f12128b2d2fa7bfcd82f005ca0c0660e984d9a6099f70a27630c41f20000000000000000000000000000000000000000000000000000000000000000000000000000000680000000000000003000000000000001de988bc4f4f9e609077f01084bfa40a8ca3c94dc6b7c0984da631e892a975237b07134e1144d99a7ed8e1fa8802d8b42fcf05e41b6525c39050125a6bc92e0f1a03b554ac0bb7f6bda9d1092e6219db014ec0ba392b3fedb9af590a400f1c23200000000000000053905d0b3ac0e049273be80125c743f5f068337ecdb1bfb9cba0ebfaff6cf29a2000000000000000c39895e1f83e77bec684c5455ff480199e3f93695415c6a2e73104f6e339442d"; + + let ret = wasm.plonk_verify_matchmaking(verifier_params, inputs, outputs, commitment, random_number, proof); + console.log(ret) +} + +{ + let rng_seed = "0x0000000000000000000000000000000000000000000000000000000000000000"; + let pk = "0x1030d8e2a7051bb3cd9b4b29c5380e024ce5ff8ecd9f99c098f24fc468b99608"; + let inputs = [["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0c1f4041eb684a665139056704f81f70bd0525c04da6d011b0f77f8e4e6b4258", "26c2402040d6ee0a837d84e8875e2c594cc5a9de7448b42ff747ddc467a818ce"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "2efb83d07f0552e5daf4398e79808c3c251a35ca5de00e262de70e870535bf7a", "1d7734a26f97cba8f8963a85a0a9720438ad66c77c2c46650272c94d3ea91dca"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "02edae02b825ec84b1e84e581750707777ba4bca183b6091851baa47ed086b3a", "0761b84578cc1b71c6a6a5b4dc03d1f3cd66478332f6b889706040954728d454"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0e0bb9034177de8f0216df1d23af469bc1df4c9b580182ce0fbe99bc67a12f2c", "21f0fc0eccebf2538e6af70f104fec9ea5e4da4d11ebbd5b9622132b60bf9158"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "26c7fb6b501288f13983e6167008fbfed383074ac2d9b540dd9e62b56c50229d", "136cf96499b6b6a72900ad6ac70a8ac108904e2ea76c1e56eba814e9ff59acde"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "25de3143398d7e27b71b632af47a9d7759d7b71addd055df33a30dd7be499263", "2a95c8a23364d905088a73032353e9f36a5bed9b76025a7b65b7a0559404ce03"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "2fececabb753e97837635b3f9ec0df48c80363011ef13c0424069123f2cc48dc", "303b59721324a38bacc8b2fd1d521732876b71d2aa25bb916b9df2369760cf3b"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "08f4f837bc57327057d409beef531f242d541161ee3a015fe1b84bf10f959063", "26c46e9b0678c6aacf9953e25468a1496430c90aae4dbcd87175d5bfda16a874"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "20022a02fb059fc9f929f8e15aeba122f27863231e58d38ed48e88e9efb9addb", "2d6a8c5a508e689754a6a5ed5b86dd8a907d6663909bc6744a9c515e7e935e58"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "1e0ac850115a2a4d261653b305b6ec4d4e339290ddb0094d4c71e05b9c361dda", "301138f7dbc40a5b8574022f6817d3472f506b4de0bec81224ae2de8edba3819"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "1cc5d987f445fba0e2f4ca9dd327f51cb906e65922423dd9cf507ee63c2ff379", "1fd589b9cc670e690046d1bd578207fff55beae706a74b8f56cbbb62edbcf008"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "211c3a15b96d53bb74ae5d9af6d572d489a583f793f35567f8b6cd46156bb5d9", "092aca168ca72104b0e22d844b38a05df02c4efbcac8e22d8e46252995d74a9d"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "036c648de83fe65fa998fddd62ba9f8629a2596f877658f5b8022a29a7937691", "078cad33ff44271dc9183c1fe16a93e3cdcf963fa0467c66b4f69d3a81932e97"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "1611d647796a4fb4b2bf0bbf6bf924607b75bcfdb1331628db6d6db29a9d9be7", "2244c681c89d010f4a457a06f97cc3f439ae242d817ba0c890f0d3cc59c6bf80"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0be580c59270c9f1cd03ad8e4da20f8476981b502eff3f311009fce26b23a275", "1fd36f025490572e77987ed62bd28345bab7589ce7bfccd72b0cfeae28fcae72"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "1918ef16c01ab4b298f0de1c3b335b36aa0e6f596803619727cac51cc0fb0b55", "201cdc86bfeee8edd11cb48fe1ee12045e6f0312995ab05fd244f163023b6287"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "03ca4005924fe4e0ecffef80c6c40fcf49dea696778fa55d9b888a063e46f803", "26b1b6f70bee7895e6d53177b4360e5a10c7d5ae193ebde536e98d0a095d8fbb"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "227685e026f81829d446d300ccb071732a842b9b285d4e0ef3e71354e932b2bc", "047795ae29557cf6cbcd89fad7d6476cf084713553fe13ec4f78dab25352934e"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0a3bf805a96b3a51f78be077353ae6cd21345e60aa13d8ff70263eecfb2c257f", "2bcb84e0353fad12a9db98bf9f5c5a2667d234c3614c09f6cc890478d48f4ec9"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0ed187006a3c0e403efd667755467bd2d8e54beb070c86513d2b341d0b3f7b6d", "1ecd8eb92f6018a0ccf7faed1a6a3d9cc2e242b9d8518ead34767de3f3e51cc6"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "26597f3a8e37c4d2aa768b13d96d43c3c798a158ff0f1ab04d4485523ec73ea4", "1676a04d9bbd7e4375813702ccbe7724faa33a95718ad886e68cf6742f84afe8"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "157b262172fa8ec0e6372d70edb0ed3be4d8b165be84b28c5bdd97561ca56258", "301587397731e972182b798d262b61ac303fc9d5eca5458d93ee45a4dbbd8d14"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "1642bc9e3d8614280b6084e60d2a70f6a5b9b7928bcb53d956b66291d488a073", "15ba2c326aa948e06260ea41a0bdfb517a3e6737fd7c3f50c64185e93ba9fbc9"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "1f70c6f5bfb236d1be621658896bdda0f2592b4a8814271a1b6b5785adfccb3b", "2c8be1a79e32231c47492cbb7bb4602ffd6186701aa1efeebc73582bd2c23621"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0961857e5a09255c5d36cc4ab004d2b37e84e85e012b63135ecc9eb6d30bad71", "06688697e7e5ccdc9199d2075279bf97de0a3d183455b5dd4270f156a21f3927"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "269363cc3502b8e9e20a6d8994cd044a3d5169a173001b8c827e642db6ca2981", "2a51563d9218c243e51140ab658fe300a2c93f747bfdc9521a2230309a1d1f93"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "09f0763a8b400d1524d935a42d46d0920091d28981cedaf0ad654f06567ed87a", "18b9544f8c20fc7f596ef474eee540dc32f58b53c3a09649f06cb77501cbc84b"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "15f5869e9caa1bc89ef20ab548af90bc0c36964c42ec45f14cea00389f246199", "119df87b5c48dd570d54f067cc8c0649c10f5ec88058a21228fa8cf54f03dcc9"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0a2ca3dfcfe3efdd1098ec0df56d3877541c6590a840a52042600ba871c6b600", "01a74f041e65e8ae0f5007cd88150133880ac970cfa83a9b1f80c83770eb94c1"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "2a13bc2ee33088a6412029bc0bc6e0fcc72b7dbae397f8313986e03d2fbc3cc8", "2c3e4563f82a00b26bd47d550958f056daa82d7bf88776e9e02da8e794df9ba2"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "2068c2adcf22f0f69c135ac4bfc6895d0c3b885885eaa0036aef0c441085d3f0", "2069b1a32ae5f75c9415ca26ee0033eabe125858741e2c190e2e6429c03843e1"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "04ad427df3ae73e4bcd4b40a497e59fd4aa6676791a21cfb45aaf9aa42ca40d8", "0f878f73e7cbf21184f0db084584bbb4969ed1dcbb1c5fb5ede68842fb9356e8"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0139a6e4e03674b2224d8a8d62fde5aec1a82eda46315608b24aea0e1ca4a902", "2e867257ec3f84a310220014033ddef96a06d5b5fcbfd496025a89c05e02d5ed"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "23f926e1e17bf3f7ff9045d915b1b25ca28cb05e5963ff6410483840c0aca082", "02ebb06b27703a1670134757c43169ed39dad7cf0bba07016749fc7697b46ed5"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "026a5e2422807ae244c932bd3b7cc215c90b6c39150dcfb0ac90890ace3654db", "2af55218392ae3ee06308e0248079a62e2651a7a4e62b7666de1d00ccef5cffc"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "22acbe88a73965792a2afc50749638b948eb46855bba1566259da5b0d23423e8", "2aaf05bddefb0ea6ca5e9ef58c1ecaff0548f08f516c5630581663458086fad8"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "04b2cd8fb17d2ea4aca2663e60588a7eb0e792a3adee4817f080eb77f5ea2d33", "1bb916c75ad626d50c97189100aa1d65999224c6bf1dc6f300eafb3a48ad8393"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "045d773b71bc062b2cbf47f4350802c4923e26499fa462eafaea89ad4809d8db", "09a379f47c8c8899c8afa502dbbacd6ebb30bc10b623fdfddcceee439afc2ae2"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "1fc30390d4056e9771ed699114605e620212f92753dc3a840039a284e0402a3e", "0039401832fee31cb09f74e6197d5ca3b12d396957847322d00f771ab49c7ebb"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0771677b78336f2b4e0e02ec4dc890e833350ea383a9032b56c5d5d10cb25541", "260097e05932f595399f980603c9bc678eaae6a46d45441cf519034623300d43"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "2c4ec71b517fb80382de6a1c9dfdcf4a48712659c09f4ea2f30a9e84c4889ccb", "18deb6b7314047bd4428d0a23d8dd88f1d4dbabf23fd4986e1746128e95df0f8"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "29e767b1caa0bba037cf24fc3fbf8921c4426233f7f8e78855e8ccddbeb71cd3", "1f30d424b62044ad88f7e2c644f61e55e6ff8ddcff543b83e26d96b8f9834100"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "04903f78a904faffa28065cb248451abe13f212e4100ceea416affbd4fb9e72c", "27d3673d46d5864ecd9308530fae5df595b10b6ed76d55dcc6386527ecbb199a"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0aef2b9b9fa5a58f55771f05b83e234868fec29dfa259a5c2681464f9040f8e5", "19b3ddac40f2ab7718e082d321cb84dcca22b88d6129c442684cc6e346e962ca"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "071086055a2e8a5983147215ea46f61ef099e7afa6d7dc26e1e95ea6d1852768", "25124d252c723d5a7bc75db24f7448ed99b905f4158ad899f60fb7e9b89d62d3"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "018858692e3f19bb79030e8c4bc968175ca7f578017790ab82b8aca671cbfd4c", "05ea75e1c59fb90e317ffc513865a666f6856b85e1c1c773b0331c337dd45bac"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "21f7a63ca80f2d8860abe6ce9692d24086d7a0cd4a53ca6adc4e4b12d7757bff", "1ff25d86d49426d3f8e7481045162dbae5bf02c136088802612484e3c0f0d8e2"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "23d8bae48c11b19f7896ce5eb2abb98fc70d7ba66181764009b193f66a3dcd12", "145a1f31426a262ae1ecc613ca4c769726853278d3aafad901568af2860de99c"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "18d09fcf2ed230be980a9aea911e71d7f29036d896807c2e9f36c953e2d3b1b8", "21ef56d684a5e0504f0e3b80234b1e52cb67b5d1266cf71c6415af12e9fee8af"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0affdd25976e7d0ad70afc82dedb0148dc8e00c75ac052c40b6bd0bcb0220618", "0270e7beb0de05754a1c96619fa0bcaa8d946755bc4153692c081c5f0ef66b49"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "28b363bce048704773acf5275ba9a80b6566c9d7808a1854c5c8951639e14c5f", "17b24750b52e823911773b0b42b170d657f11ee98b94e82696587491d6124098"], ["2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "1af9bba3eed2f4031d6aa978ab856a2c43419ad8967718d9278473bbee1a41d6", "1cf9c8775217233aa1f624a5b299bee256d0445b0cb67b5bb4a4064e1951c7e2"]]; + let n_cards = 52; + let ret = wasm.generate_shuffle_proof(rng_seed, pk, inputs, n_cards); + console.log(ret) +} + +{ + let verifier_params = "0x28000000000000000100000000000000010000000000000000000000000000000000000000000000000000000000000088000000000000000200000000000000edf692d95cbdde46ddda5ef7d422436779445c5e66006a42761e1f12efde0018c212f3aeb785e49712e7a9353349aaf1255dfb31b7bf60723a480d9293938e19b0838893ec1f237e8b07323b0744599f4e97b598b3b589bcc2bc37b8d5c41801c18393c0fa30fe4e8b038e357ad851eae8de9107584effe7c7f1f651b2010e260800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000800000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000008003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005400000000000000627300000000000000400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000001080000000000000000000000000000000800000000000000200000000000000098e9b385d5601361777c067b33a182a6ca29f1799a62de539d54fd4859a0c5282000000000000000f495a2bdc33ed33b52d3b9c4afa01ab994b6a3116c3c48f506eff370ce82741e20000000000000006a74f3f17a0c4cd5d4fb262122ba132a9107839f510c8a74a8ff992c546006902000000000000000f211d022dbea4456dd2dadb29fbd98a199617123ca67de8074900ba2b725d2ac20000000000000000d59d6edc24935b760e914158b073e45e2f57d968967ce9caff5e63a21e6e68320000000000000000d59d6edc24935b760e914158b073e45e2f57d968967ce9caff5e63a21e6e68320000000000000005bb1e0ecada184c908a069c4b42f42204a4ca8664dd8c58470ef38d17e08928d200000000000000087cfea507eceedca8740d940794baac730ac2d31198087e4f0cb37074585e3ac05000000000000002000000000000000c791bc9b9c619aa0404dd746401860078666123da8e4f9dc70c73ea0204ec2a620000000000000008c7fa0e166825df4da3ea6845ab25267b6eac040131971c692cd928c03f565a120000000000000000632523393c799f52ffaf5a155fc359d41af878ae964034395146d0d383ba1052000000000000000bb88cc59afc5714e58596f8562de31221501c92a9ddb9574cae8dde45854f327200000000000000018b3cdc3b43508e0ab7126ecad0c3b682130c2fafc89c0313da195094716039920000000000000004594f1837bef039042b351311738e8d2add21dc8b5aca2fcf523777555e806220400000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000402000000000000000000000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000000000000000000040200000000000000000000000000000000000000000000000000000000000000000000000000000402000000000000000201a6bf0b0548b6cd794365260ef6131dc03cd1141f98774bf9b4e48da75bb0e0c00000000000000200000000000000066077d81d0de480b5af7b7fa2955b68dce1395e6281a75a990f81af355e691a82000000000000000dc54efee8a19392900dc2d3faa2ef18b06d990474d4626f5913ecd2a071f7dae2000000000000000ff58d290e4622c38bf5554ce8f7d9574ae8a981a5035c31f788a9da08b4161002000000000000000cc23a7456de785cc94bb9e876aa0aa1d322880aa57b9a366bfb32609414d55132000000000000000c322e3c8d32c6084b3b8993f529b53b3cf6d7b706f49ef1dbe1f6c30c16fb7a52000000000000000ed3d03778c4d50782d514793f1fbcb01eb2ddba0acc54e8eeaacfa652715159e20000000000000009cd59b9d652b623712c8ab58a827368a03a02a35cc660b557016170ef5100e14200000000000000084b3e786cbc536344090fba5ab5c062015fb2bd0578002670d28247cb9fd22a62000000000000000df22e27e5523738dc1dea49d5f1afdaca7c3877ad759350e6c9d2f02a97c4e2520000000000000004e208f93342beed75abd9afd0836e9b270ff07f1eaeba121db30a1a19bd1522620000000000000003b9c1d83066200ec3d6779e7715c524290dd2abaf07fe5df2542d8421657b62e2000000000000000387ba12529900bed2d3f49e568ce2e7780e5ee62f0453f0b83566d2b6aac97070c0000000000000020000000000000002d7f64592af8f40ed47bbf2fd30ed0db6056275f679575aa517c4ded152af6942000000000000000491c8be8a5d0eec53d53e4ec719eab1aa34eed94c08a1dc26006308cfbc02d022000000000000000826ea70dda32a9b72087d8638660d27869e6cc1541ad123df231a32704152a112000000000000000a3122f2d3f16a83cd6fbc239171509615171f56e26376ea45118939d4939cb2b20000000000000005b9c7d395508329a215ced026825bfcb7f734b97730b412bc81eb6b64394112b2000000000000000ead28ae0ce2e06f8b12887ae34ebfcf791e42088698a8061459575f2a0cb4e1b20000000000000008d94b273f19c2521bf3cdfacb832f7f52d0fe81b2cf06067ae5a44b266258e012000000000000000ddb031b8d98c6e3c7a6b17be2aec8620ed0f3aafcdf14e7f04b52f51f879dc1c20000000000000009561435e7f538460ee1851e4f530dd4d8b25e419212710fe7e8780977b8a08142000000000000000482882b55cfbe5af2805ff4413868af854c3be95357208605dbdea3402069f12200000000000000017dd4f32588f6fbf999c7107e411bc3bec82efcde108aac9d0ad51b4c833da8020000000000000001a25941d776141817d3620cd1cd1a2e87b2f05d65391dfeaed7d275a189c6d2a2000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000a800000000000000050000000000000001000000000000000000000000000000000000000000000000000000000000004a1d30b17bfba45d83853f81946cca734c4010e1442ae1c4423c58a7f1d18d2f0a0c7995685a9066d6825c6db21d0b958b969ce2037c080a7b180ca987a5422060498e759b9e52bf33a7dc60a15f3bd732f36f793407eff03ce3e6134e94b42d462fd253005d048b4542010411e314a65ad0d7c68d1325992d0501af4a3a9e1d200000000000000001000000000000000000000000000000000000000000000000000000000000000040000000000000a00100000000000002000000000000000300000000000000040000000000000005000000000000005b000000000000005c000000000000005d000000000000005e00000000000000b400000000000000b500000000000000b600000000000000b7000000000000000d010000000000000e010000000000000f0100000000000010010000000000006601000000000000670100000000000068010000000000006901000000000000bf01000000000000c001000000000000c101000000000000c201000000000000180200000000000019020000000000001a020000000000001b020000000000007102000000000000720200000000000073020000000000007402000000000000ca02000000000000cb02000000000000cc02000000000000cd0200000000000023030000000000002403000000000000250300000000000026030000000000007c030000000000007d030000000000007e030000000000007f03000000000000d503000000000000d603000000000000d703000000000000d8030000000000002e040000000000002f04000000000000300400000000000031040000000000008704000000000000880400000000000089040000000000008a04000000000000e004000000000000e104000000000000e204000000000000e30400000000000039050000000000003a050000000000003b050000000000003c050000000000009205000000000000930500000000000094050000000000009505000000000000eb05000000000000ec05000000000000ed05000000000000ee0500000000000044060000000000004506000000000000460600000000000047060000000000009d060000000000009e060000000000009f06000000000000a006000000000000f606000000000000f706000000000000f806000000000000f9060000000000004f07000000000000500700000000000051070000000000005207000000000000a807000000000000a907000000000000aa07000000000000ab0700000000000001080000000000000208000000000000030800000000000004080000000000005a080000000000005b080000000000005c080000000000005d08000000000000b308000000000000b408000000000000b508000000000000b6080000000000000c090000000000000d090000000000000e090000000000000f090000000000006509000000000000660900000000000067090000000000006809000000000000be09000000000000bf09000000000000c009000000000000c109000000000000170a000000000000180a000000000000190a0000000000001a0a000000000000700a000000000000710a000000000000720a000000000000730a000000000000c90a000000000000ca0a000000000000cb0a000000000000cc0a000000000000220b000000000000230b000000000000240b000000000000250b0000000000007b0b0000000000007c0b0000000000007d0b0000000000007e0b000000000000d40b000000000000d50b000000000000d60b000000000000d70b0000000000002d0c0000000000002e0c0000000000002f0c000000000000300c000000000000860c000000000000870c000000000000880c000000000000890c000000000000df0c000000000000e00c000000000000e10c000000000000e20c000000000000380d000000000000390d0000000000003a0d0000000000003b0d000000000000910d000000000000920d000000000000930d000000000000940d000000000000ea0d000000000000eb0d000000000000ec0d000000000000ed0d000000000000430e000000000000440e000000000000450e000000000000460e0000000000009c0e0000000000009d0e0000000000009e0e0000000000009f0e000000000000f50e000000000000f60e000000000000f70e000000000000f80e0000000000004e0f0000000000004f0f000000000000500f000000000000510f000000000000a70f000000000000a80f000000000000a90f000000000000aa0f000000000000001000000000000001100000000000000210000000000000031000000000000059100000000000005a100000000000005b100000000000005c10000000000000b210000000000000b310000000000000b410000000000000b5100000000000000b110000000000000c110000000000000d110000000000000e110000000000006411000000000000651100000000000066110000000000006711000000000000bd11000000000000be11000000000000bf11000000000000c0110000000000003e360000000000003f3600000000000040360000000000004136000000000000423600000000000043360000000000004436000000000000453600000000000046360000000000004736000000000000483600000000000049360000000000004a360000000000004b360000000000004c360000000000004d360000000000004e360000000000004f3600000000000050360000000000005136000000000000523600000000000053360000000000005436000000000000553600000000000056360000000000005736000000000000583600000000000059360000000000005a360000000000005b360000000000005c360000000000005d360000000000005e360000000000005f3600000000000060360000000000006136000000000000623600000000000063360000000000006436000000000000653600000000000066360000000000006736000000000000683600000000000069360000000000006a360000000000006b360000000000006c360000000000006d360000000000006e360000000000006f3600000000000070360000000000007136000000000000723600000000000073360000000000007436000000000000753600000000000076360000000000007736000000000000783600000000000079360000000000007a360000000000007b360000000000007c360000000000007d360000000000007e360000000000007f3600000000000080360000000000008136000000000000823600000000000083360000000000008436000000000000853600000000000086360000000000008736000000000000883600000000000089360000000000008a360000000000008b360000000000008c360000000000008d360000000000008e360000000000008f3600000000000090360000000000009136000000000000923600000000000093360000000000009436000000000000953600000000000096360000000000009736000000000000983600000000000099360000000000009a360000000000009b360000000000009c360000000000009d360000000000009e360000000000009f36000000000000a036000000000000a136000000000000a236000000000000a336000000000000a436000000000000a536000000000000a636000000000000a736000000000000a836000000000000a936000000000000aa36000000000000ab36000000000000ac36000000000000ad36000000000000ae36000000000000af36000000000000b036000000000000b136000000000000b236000000000000b336000000000000b436000000000000b536000000000000b636000000000000b736000000000000b836000000000000b936000000000000ba36000000000000bb36000000000000bc36000000000000bd36000000000000be36000000000000bf36000000000000c036000000000000c136000000000000c236000000000000c336000000000000c436000000000000c536000000000000c636000000000000c736000000000000c836000000000000c936000000000000ca36000000000000cb36000000000000cc36000000000000cd36000000000000ce36000000000000cf36000000000000d036000000000000d136000000000000d236000000000000d336000000000000d436000000000000d536000000000000d636000000000000d736000000000000d836000000000000d936000000000000da36000000000000db36000000000000dc36000000000000dd36000000000000de36000000000000df36000000000000e036000000000000e136000000000000e236000000000000e336000000000000e436000000000000e536000000000000e636000000000000e736000000000000e836000000000000e936000000000000ea36000000000000eb36000000000000ec36000000000000ed36000000000000ee36000000000000ef36000000000000f036000000000000f136000000000000f236000000000000f336000000000000f436000000000000f536000000000000f636000000000000f736000000000000f836000000000000f936000000000000fa36000000000000fb36000000000000fc36000000000000fd36000000000000fe36000000000000ff3600000000000000370000000000000137000000000000023700000000000003370000000000000437000000000000053700000000000006370000000000000737000000000000083700000000000009370000000000000a370000000000000b370000000000000c370000000000000d370000000000000834000000000000a001000000000000f86efa0dc11243b5b22d02b3c8bee902957490906a5db204dc79c5d6d36ffa21f5d8b53d2909fd36c84ce1abc0dd81f80ebd20373f1028c1697a259b197dba120c81b6fc2c45ea4964e91ef96c1cdd39f284738da52e24cde2811139cf3f19218c71f77bbd0629fb658d3b77bb8de94c623bb0432c6290f652fab8548dc54128730d801a94a4bae45b91560d7db983dae29dd1efa8bdbcecd6049d1c8183bf06db6e7ef8f01b38d4a2c2df0c5b3904508667e7c13453c5761b4a1a9feffd6325a712289db79c30c26aebfdc5f70ff78364432dd681ff2c261b0d2740647b17297b7f3c2fe8c3916fdd830401890d452908838599860890ad2477c24851f82a12447f49fc232e5b2f4730f854132e95e58dffcfd6280aef3a46d5d15c2ba1cd05f2a45ed793aa44409b429a6709b84b592b29090376764d51efe3475c5675ac0402419887842edce1025ab62844dca0e3a3c1e31c8a8d5740dffcf8715fccce0dbd451b50be10d9e5fd0f906943231c44cbc2e26ad71c068eff7e129585c394068958a1da3a270aec6f030b54b87d0fbc594a2d5f5b8873840562e5a152ed7613c95bc862a23e7317d9b9ba965301b1fd113839bd1081648d0cf7e621e13c35220c9003b6a03038bb060b44c77dcae2a894e253f19abc053c985279227ee72c1b600b4ca680bef068ff0bdc109b57730850a49878bc9456eafc7570dd9ff5b607aef323e64cbcaf29bd6b2a8c7714ac1de92346bcb9327bcc8b7168d19d99292aa2db8f774c7c2b567a1314975f909b27934d63d9cda9dbfb9b3cd44cc60d3107e0c119963c5be3699fed2ab24d62c6a067e772e51e4c5ba4232f7130793bf715a2e98f647b0703fd782eb8c9a54f93c8df40f6c9ffaa844226f8d594a057a72834a62794a2fe685712230d0c549598de62a4831efa1c1ef6630509111eb1e22df49f54785074178fa66fb2f2403032a9cae33c0d0ebbdee815e0973eeed14f191a66a200915d4f43df2fc87178a5f2f6c4ea8c288735c5e768c69fe2386ddd1b44d8a8ee0decb5983cf377f7b48936406e3441a7afb9fee3cdbdb213abd887113dc0ba13f29b8f38b85460c958987c23fd069ccd1ce107b7605abdcd068b021cabe5d99088803cf2794c2828a4e48b6c6ec96c6aa88808ce63c7a3747275f2158e5974ea082c4114a7ca5e237d07127113e262d2fd2228504166bf676a4c640632f50d728419da68e71e04a51cd83ce28dfdd07cb475ac4eb5847580ad36be08f2352342079177f90a43919006712a258b131f7ebc4a13d5ad084a992eba8020b7c6972bbc9289d023af8408ade508821c64de60631f2261a50f46244c91e613aef3891f17bc2f0b5682f51c8f20bd2000a3af7779d159b80f6169e2c590e3191061583af976ac064bda62512456860b6ad3cf51d879ac7a02710ef659daf909f8add015d365156cd62a42a192900dc7cc202d1f10581f4875981c71daa7a50f587ca2ba69647b17991949a57ac29001b35e0417244f3c6626aed40b3624370073d4df5cbb5fd755de06077f46553a89178fefab19771867c51c2e5839eaab187780a56f80b45b9567a33b9ffd1fa91ccfeacd673da29ad67b83473eb9605d0fe1e6c3b244f8444949e48d69ee3576e03a117051cbbc2e8e2ee9965654539d1796fbe751bcd9b67bae57e58aa29d088ce7be34872047149aa7e060706a8c0c08bd90730081492933dfa5c7993261a4c9c09fd8a50d5eb1c271c2231fa580b927f2b047269676df0eb8b9df5eddd93390cfbf1acba4eae81128f6b98b7b2d011c8669847362be7e958d7fe265e14d93c0bc5132d757f37e4f72158e2f58c1121d62b722e71afc893e304daeb3ed318d769dae22f9f25551e9c92414c290e50f13e7b7518077542b5742c44ffccf02bbd93172508a86aa575b4695d79bdf8f93144979a2b39d1392681c14d039e8dda85407064843bfcd57ea95becb79497d33007bf1cbadd2d4d2b23f9c7461e905afa7af370ddb144a3edc2c224708b5300a1316bdd479cf194fcf4d8efbbce4d4813173ec5cd3bb75031e7df1ed45dea35b16f01ed16bde00b27c3baeeb8abbe149943b6080d90a719d3e37748f33f83c6b0da531325731e8fe38d01e38661d8b930f4e4072fd5abcb60adc2fcbe3775eda1b8326d09eb73fc037ae35d48549cd88082030b8e268e18f8ac27e3a0ec1ee0207ba1142e1ac3021f9d0e79d2217d29964f26d507b827909c94fdf0b0679ab2b23a5646ece4eb7fbd45a50025a25c5677a1c283a57aeb693d63876856e4d1d8d2d496338cbb733a6fcd91472642644a1ca164027ee311e69021b96363179c13400d8165d4e6e59896d15b0e87b11ba5b11da18c0c3573c7ba7c2a7bc3c8fa1ce2ad9712e81e4c77753471e4a4dbc48f21b79c459ef1997398c4f6c6af31b91e815f501afad220d28e8f0b35bdb18b437c9252f8337547bf5692536f90ae9e74118f6b65ae7a100961df22d0ae5d7e038068075511823d5adadfc7226fc774c4727ee75fb83a588d9828a2c7e0a6d3708c79de412d92c125c57e010267de53a7e1c52df6ed5a3b8f2ec468852cc37a142ca8dac03c0540d171d59890aad5732d50654b0950281fe6f8b28e9e6b1bf51eb0d78ca9ff931ce21e11ecc67b570ebd618d03d0e419549ba7db4138bc51a0fd2ba2de301b585cea73fde4a0e1771e7d02f6103da6e0c77a4713bb0194a5b44e03a2b691ff8c450bd1bd1d8066a7dc9e505838fab6374c872edadd433250823edf90126921dfea03822c8fb90d0c7c8b62bc0252282772c9848eb82c1d77c0f41d186d5375245655a6a8f60dc63f0e9610502ce2b2c9f1dc7604e1c4330342b1dd53b888d7acfbbd737e644686a50f97307eb01db148c39508ece74135de1cd8aa0906ecee6fcd68681cabe5ee18f71dc1295b2e899f220bd0b62820a58e15654c8df5e3d345a559e719209de7cb75a4b10e7ca0f5b766cd2bb8cdbf65ecbd416fc4de565084601fd72e3a61b794a42fe24641df6d5fde7a72e3e46d171011e14b6e1f2e644c10620c672b026c841c38522c57a826ddf2d0edf0550867483be3a1b994c842822fc18ae9552911b528e9e16821ea7f405ca1df785aa188e5b4db80a8828691ae7d780a80646dd7cbf228616f7278382b88eeeaff2c9795c7e081aaae5b43ba1a236dae149d2d66b3e731f0fbacdd998c208d918b90035393ec02482f0f66ff0a843ff131ba46c78b4634c1f273a1c053029c269bfb278ca5a2c4aa2d9eaba8572527911d1bf4b455a82412baf6948e4e3dae1fc764c0b3bdf86dbbcec5acd66a80c3d36c66fbfd4fc24192f7e50671361f7e108be166d76ae5f453db633e4a9c75c6f020cd8e2a27178ce09a4f22945f427441bd955fc8024f190956cb62c8ee02c319ff07d30b0ceb8cf0b9bd3676d4cdce833728146fd94bade114ca2c7e95cd8ac09e413065332b2e51adde865584509579b686fc367e82ae5e1e8433888202c13f0e5a84020e2cb780bda1cfa326a597008a3421df0d9b285703201228e4f55442f9ce316434fb4c913ce4d43215090d5b1e2aa7ca343162bb62b2e4428397fb7201075f2b25e220f27229000c144110d0da486125bc6749ec0e8c4e0f495d0a999dd5c6a31b13dde0cdae3db1104c41a6cd4b192469ce176624801dbad64f895f9c16e5325c204b12f27bf56a029ac4e08e3865d07728db880eb690ca03fcf8aba604e2b32c9d5e415d2a724b311a4a5bbe787c230c865bd8edd38cf0b5a003954129771f0c6242221642a10459590918ccc38334f551d7f971a900c83ebd76adc7373660d4f407912a57e2576aec4ba3f2247497d17d699bc3f2028d25ade03863c1abf7ada38b11e81cfb84b2c18a851b1f2d26c1da248085a634eb68c7ede223cbf2f8e0203ff0cb3b79d699b46ca21e735c10aed1d00dfc4e4eb21d5e50e7552ec9872e4204d032542eeac9b0ff26f0839aed59feb411e47144b9490afc07bd7967b5f2e3099263634436c6c351f8d2a25062ae77709e75adadb9d8a34dc3eef45797c2ef19e0e0c985e3c3284021bcbbe5f42ad1eed770fdff56972d7b62462baaa2a0a7c2107e91e0d90726fb8f3ed0cf2b151db50b29d97ad7e16276d6fb9150d3257eeba1eb70c2b79355f8973d69394638a76b7484477cf7dac621addb654de49d879a81849cf5db911e303c456d43e33c6dd5687d4b7bc033de0d4750e507efe79173120dffbc8d37707b8c179294cd73a30d0adb5d54e44dc54222f2ff9c9bb3d142027ca07391f5c03538437938f7f1d93a719ad617ac8ec1314d477eb0c3ffed0ad2ea1365265da09c4fedebf36c5bdda22a3c78197fab1a153f9d63eee9b3b0c3d0252a9ba348a031fb4711bb7baf9c7427607353ce414e389bb5812eea6c4f1e7128ce49cbeef563d559efbd924de2611c55bad836a98174906d0924637626337264babb0e43fcf805853020ded9d21cf30038564ab985eacd21393be7a2bf93819d6e32831e1f5b38141151d7d0a2a69d45325a353f423d9c9086050eabeb0b0216a36340b3afa6764e1dbc70eac4dd6748a0cc3224445a40ae62132c10d634818d44cf61d91e74a5c180bd4b41d0b3f09342bcf7061f6835a5910df81d7591c283402ff0337140ef956ffbc26fe2e2dbf8f2c8cc943d488a016a4a54b6ef72a1c77f82d3b6a230676e7786cbf413d68f5d46d40a5b211aa821455fd4247785e09ca304c3f82762103adc5ecfe88f32d8cb483021f20a4fecd31d10a0f95939c199260db4fb76fe69f542891c77c3a9d37f042ec842dcba8ca00331363dcaff5140c020f4e73ebd7d8565be9bed0d52f6a8b8434be89b90792bcb60cf78c633a09bd4271de0d6bc5f2d9cfc36573c6d3ab0b0be98ccc1fc68771ec889ffd0ef427a14fe72824cd18e0323e6f066e56bd5d03d61efe700f044ee749245c5fecaa1b9e363a4be5cda6431e47dd726e4ba87c3d90e9e844c25681cfedd85f747f782bd68a57db803f50e54c785b91a573340d1a15082f79396dec4af07c321c78b2232837fe25af8f321372e07f7b71a8cd91c326f77b741f6a6fca8e9fcbf4b0d922097d2e268e68419514c44665f66e033067eab5fd83bde47650a3df5ef91df7095f4fffd4bc3b085da4e3b8531f3c061604d9b051ce677e2144a838e0a2fa6e07101f696bd1d41e2edf6202640b6ee124092a6401a774ea229cc865ddb51a4306bc714a185932c0d73aeba665ecff7065b0da8db8a04f0c6e3c6d106a9e1ca2298ac92176b0d65529a048f4a026b76ff40b528cdb85d0e4d22a0287857df05f04ebb77c88a7542553cc31a70f58d891c9eb18ac12277abfd04498e0ec51079f0233da198ca23de4b10cb06d2e646e255838a0d09f84a7d59f0f824c372ef052144c7e7e6c8608eef6cac4469731fb99820edcd4e9b89dad4f84b458401e704a0a2bf64b18107abae09d1ade38bbd5595555bf1d7cca4354ae409dc70d01c4f118ad4b87023fb467dc33dceab2f09c934b8941821790153af78a159712f3447827e884c44c6aa7b9b2bf5b508d66a3e2b98cecbb6f410cfb4e4cbfe9605ee24604a06c39858241f24d04a6f06d59e498ef19f691b9dab1c4b61327a6daa5f374122bec486992fe80c4df096b8ed39cc96aac813a564a35211003772f100c3137160f429812956ec0304562c874d15e62afeb551f6123eda0f18993f6aef17e7c2633eba18b9b4da26fc0a2920a8d2f9ea252fc9ff73d9c7d87e26c6d16938fe72dddf09037845e572dd26350b6edf445de0f47737e00dee5ac735b6843cc88a82f312d488ee8288d6f42866deada5106bf1d73796545434531cc984197ae9ca207efed52f9478a5c587144d38b3a0955b0a0091b1b06dd48444e981dd6554b0024fcb69fbb2591fabd685332fe12c695ef879956858ea1056031dc28c3e8cadc248e39cce5d19745a259c9df640a567a24da3b5242144d6ea6747242c7e9c80615d40e6dfaf2b900f8f897e9d79d39ba3c7ce554896851599fe0bf5dbdf566da022d5514a792ce1b3c6d8e1a1abceeda7fe3f4edfee3825ca0058b82ca05cb542ed3916abbdf894d6bb89cb023f1bf1042d5c5507ff706affa4edbc6baaf9e851219207efffef9718e664a43abe6575369bca9ee5a73d40ddba4ddf6d1148adc06b93d2a4cee8f758bd2e519200832a3cc74dbc01aa6793fd1deb24e6d6ba72b2a436958955ec9596930d2ee69fd06d3ecfd31871f34b0a93af6153d4546cf961957c81a2fc496e9aa90cfb5a0b2b8d5b13cf19bd8868bdc8df642d873f6f1d12037a109d0ae3a180cf4fc050c50b57726bc16e91a88732c2673633e32d3fa510947d2418a5f9a14326245b942a24f43a5556404f7b24889c2ab7a993bb7162d067168ead86eac2cc1eaa0594355aaffe9bdcc3e752e4a2ffe0289ca7aac6323181c07c40b676253dff9ad2c816768adc202b787fe61450bf8c5d763af2a190706a1acdfacfcf9932ace9734868c52616c4528f79f48683de1784dbd4c752811040f2b557947688ba55998985f8c8d45673640d2a643f779b7a930caf42c57d60b0c6628dbb2094eeecc2affd3309c763ecaecc427f95f731aa3d1bd02c1dd152527f2b3a81dda2ff3463e12346afbe875d76a2ecf3f4272ccd7c3137ef269d21441bbd6feb8e16f2a6b31a889951cd406bf51eed1486f03040b54b0a9425f1b1a0fa28a972ba840fcf072cfdc365e33f1f5ecd59b49256a551919f44092c8f72a7baf3f3254241a23c4ee051e3d6c255dd49c9e554bff846693b4086a14dd5b161cb808c7a5f182936c2814d7e6035e57f25852b305bfd9a2b8c4b22194b4f41c223da9d928fdcb0fe9b8180f593be9efb8c15088ba87e76ab3eb9230cf167b19ed6f335335ada0e39cbe037fae841b9d36158b8b35a49c100b8a59f656f54911e5fa6b373180bf792a2a170e99e8512dfc6a12bced424f6b91fbb85c6b9c2311312c27470d30e79eebd16160538b81baa9c1b2da17fdbc0cf6147d9529dbc80f94cd5ec3ef1df063521423b1321ffc8b7c6b54ec3ff162acf11b9939627c952769761b62d943613abafb7607659867df7115a4b10bd793ceb2df283f0ec23d27358faeb106935e8470fc1d0cf602148d6311016d3a0e9999bccf1d8e136cae21a0ca1cc112ecb42afe3e1fb9d23db03cd2a9aaa0a04f90386722738b111aa2226d6516d2abd883104914ca6238ab179002c81d32e908019a71411cd9fe4e0c28b4a6d041f97722ccaa8d0f71ffcefd5a7788990fdd0c157b80e92ef3cd4c8c07894181702684f0b4368a7ff807a4d6078c3146afaf161e7aac397dc9784e7f0d7ee531e8f0b4f41a3003b0b753fbe235a8f034ee441e090625b4f9cb356529243aba357487947dbfc5c9c6102afddc3494752d6ced3cf72a69594e0e0604c22c23eaa3cff3a9b6ee2b583e0a3f53f1e80e5542b9621bb38b9d2ae76901592d00cc44e3409b2ddf97ea54c45580e8d588d70a1a4f47609d560949f8692bc26a2d494b61ed36d7259b4c49b315a711074e877013b19c32cc6c682894f0fe65ed2c297da03436a17c2f91f6e1855618ad1d1e6b01a4ca53d4dbe03f1f6552323416f4a7bef9441d7e27c12f6e1a60b83149e9a41172599ea2002d3ca3664eb8d913185a4f53af9cd805f7845a4abf477a0ec1870e3664fd39eeab0b96388ff29e1dd9a2be15ac6d4a47e199aacd36b925cecdb71d51835a74f213d27b59ca2c661a2d507e5e64f95b8e55cb8f3b5d9959cf3f4b9c13d8b3aadfdf5eb36e4eaa97014781ddecb0f48c286d5fae40fb3fbd7695e5c3ebac78cf391d19b6c99ea0a11aa0bf88992e65355e88b837eb34bfc07171f7d1df423b97bfe88a675010d618186a4e2673252709b51ca864e0123ac8f94712cbe6404dd6671639fe60c5204a131ac9776e3740b422e17bca434fe5ce1a8f5e495ff24d38e49b6e62b1121b281f70d3473bd4c04158e1b9f6e8b8dc83b0684c9c5c7fa0e9be9e91c57f35dae01b963a248184ccad68019aaf3b5ca82364c328ffa4d5c7df8cce7ca46c187b3c17757c8bb4eb372145200a7e3caf197eda07573230e5261df3905c6800f2e2461235a7eb4bd906333e5ae0f92b0c11f371edc3a4e5166f59347acdb5b407afdd1ad89c1c7539bc078ff1245ecc539889fb6e4b819e65579fe6533c9a6391ab650017beb179b547dc332ae636045d5b2489400bc113aa13dedaaa14de27cb047f13dd99ec7ecd0c9d8b3f7f2eb76071023b44ce19d9000f74b02b68bfc43229632bc1bd6ffaff93ba67ed3abae927a4bf030df0a36a57193de2ed430dfc309967075f7038fb7a7296dc389ae2521afc87398ad2202df09b2f7fa3186327dc3633176992fd78db925b874bd0071dbd13f1244bd7276eef192cda41a231f078e1a005bd3d73dac6fcf6794171d8566f954eccce2d91f653944ff4097297a7652ecb144a21a4bcb1e0795d1f4deae21812d7d8afefe6ec6e95ff54de32403385a2112b8dafa9b6f6ad944d15def43b9e427c7122f60eb31407a8029edb1231fc899d00c5874d038b3d28015fd259054b14f11676ffa417a302136ca566f1a76fc56d19629c7e176541283c445658725560fe27a8d7505e302128264059854e6e628e0d8f0bb52c782ee1a5881d5f7b20f779ceed6a8cb96d46ddd4c1bd6ae177f7aa0b8450e582cc85cd2caf836bb3ed0d968703196a87d93add695e64527a08d56808a5085cf48d63f9cf4b2e60c47aa292af676e385ff5834096c7b7a5784a16da1ed7eac26f6f05e32d31b55fc9e6b9619f764f2abbb747256a2d60d16f60832907f30b35243de560af173a00b23fb5233bba50b8ed548688d4c74adee95813fc2c7d02a662a3bf3cbf459728298ce7589e829ee01ba463791262e0c0e9c5189c2dacade1107a2e0090f13b39b47de445e992375d758b13811ea0067f8b9cd403022eec791889f550af03599ce4b2c34ed540f8922ab8314a80fecb831cf0d501057c1359aa8ea73e0c692e0c960b2f2dc40dd7984802352f00aa213415e233780007ecc578eec3744f8fd6342f7a03e7d2addebef1f9475e6608ccbd46e184571ef75d47b4ffa64cbaded4e9f82ac5da62faf01f372747660edfa0600c075a681a0641f4b6e94bcd54c5543e57ec9c24cefa2ff13da8a556486e00289caba2c919450fc089b81a1cf3a4c3052d7f3d6e97a8e8b42a8b50e57d72c94b4de907de2a3e77f56b84b4cf1f6b815792adddab87e38344f4882bc056c0827dcf959e8e284244efdc979ef013d6aa0767055ba698dcf8b2b7d145672703b2a100bb4d4d0735993b91f81e5ab03f125fc1a6a5fe1b80c0a35ab463a57489d0fc3e89ee2421bcd24a01b2253d566739f3536112339705c3c594ad7f76240c1766b3176af70fee395c858a5435f99ee5f54ea8f7f1ee39008a4d5fdb57b15dd38b223754dd22dd0ff057f56ea21379dfa4efa9733f5e61dbaf2e0a219724047730f8adf33319c524eedd83c6bdaf3981458ce8d8bd66c5b2ec092794937a6a166475177b77151b7f457b6a190de8a78e19b65a462826674e56b23ac2f258d6757cf7734aca1d26e8e537534351a10b5c71493295a54e966f83e5cb751b6d151f870212f3b51d2f580805c98090486ebbe205695dcb72eff118aa9c8c5f4f56fc29ea8f3f5e29f7405dd2e873c00c8878af211135233852b6e3414d037e279dd7da48a55b4318c8bf9385a8f0fa6150b4c9c828a59bb106dd038dac6a3ac30580f3773b337e1bdde8305f771ec0ca8949793781a55bac288465f6fddae925e59b04c8a65583246d33b39706208db859d17d2c17a6b245d76d7c5decf8f2e68619e23dab68b4237871905009366a40e7d0f2272f0bcf7ec95a384066a884a293358b67c4da0300722ffc3bee2dba6c17aac3c64ba030a4296d74642c10b2312b0ef96d6b15130979f7feef67658ccd2471c4814033ccca4f4a3512b307f55b4f25d29885e21527f2328eb6b4558f8c8ecd7eb9d03272e7ffe2ea41df8ff1910e96bb4dace8182780a16adc934c973c4bb11ebdcf924c321acbeda1af2c34c0671a4e99134e83117e116cb2914a8080b9d5a0a08deca0f6c513cb33c30c4942cd0faf7f2b9da616756d61df0458bae331ad09d2adb6c243b1ad6c2749b16e84729ddd5e2d1b54148cbf4e37063bfa1fddd958ffd5cea0befb449001cc77b47a856220429cb12b1029617127daa4a75daa425211b863c78cd58ce2fda1a7c37787248caf08a2831ca17255934347160d449e144a0333d0a4ca441fa429e573b254ff83c825266d0d2071a083ce3b9b273feca7581b135c81f08c4b5411208bc1c0f3998434e4831f91c459c3d008ab4fbcf52c902fa2f0e935ec7d5d5e39a9ec7dfa00283530252ebffa95237fc3efb7f778ef472b20339b382598818232df0888d166476727960c2ab3a46d9cd4526fda1446a464bcb5c466cf10f3e0f98165b8579107051a3c233b9f60f417bb765a730fb4df38270f31c951d8c2d370ebc97dd3f157edf6d9227cfcf08cc3395c90229a21dae4b4b02ce3eb7ab5a5e915bfd8382912fac8f317184d89dc303a070d8f49ff434a8f689d426118526fdd866a418c727b4e75820a680263c97771527a6465b4dcf76aa0f06a3411b70e18e5a5e981b1719f7a33038b126c732f7a418c9a5b753a4181405570ec43d3709bc43b4bc31ecdedb46501ca674d1c5a6e5222e97ae984440a817472b61cce4acd942d19ce7fd007c8930a2a5bc906670239112e0f3fbe1ad183d4ebd0da1dec66a457eb87ecf9646d8915560b006b0dd734b53cd923a2449f1b488befdb1c1a1d258345c7d5b59c1f3125faf1b4b42a7e22454eb273bb45c14ce8b6c4cf33407d940ca57007eeb7f3dd2bcf7ca6380b112a828fb84621a7be49f2e78de4892cc05e4b1ac6ac88a7ebd9240af81bb6094e71f5f29c149e4b1c3fc0a0ad3c53cf1c0ca9c2fb3f81eb230a18f58376f0109c36924aad5428a63d94f576795fbeee85c3da402888b3816cf2075c3c4c4fe669db6636445ee311a9bbac54a19077c6c923bdd4a67e11f5f2e52662a2b61fc775fd3a02227c75b6bf1f56b13a13f9a0921644b6334d65b364ae2cc46c3fe1e009cf3cb358210b82f747ec9d17fe56191fae607afae0e9df880020d35b3095bb4c235922b1613a146d1f4693f645cb7a814bde163bdf153f769e2a476293904c4c996667fff66c2a93b215a3bebab42761d2982ff74fb3243dd9138545b46cd65ab1526a7c47424b8063489404feb398b7887401127fc1a3ed80073d2eca7b8dea014a8a5adcc943427a72e4e14817fb5578145e84f73005326722cb51173f00a9431a33c5ada6d489aba1a3d88b2955c66dc9de438a8f8289b0196a630b89764eb2054e125702da1ee1f7a2295dcefbfb016f590bfb93ec6ce429844d55e1ef3430e3409b86c07189fd1863f24b5f7800ad9a690ac6ad135c30016ca2780be80a23155b16b3d297f942e27de9288a5b3b13e961d332165b5280166c1b396a543d785a76f1cd01fde98e20c0e99b498f5a3dd561d49870e5eebc142adf0236c92b78525db7d70572f7b82e93236d0e86ec2d37e9ee15ee7ae15322d46752cc8a62d86d2ef7cf9b75a1360d5569c0f94d6e5f5a6461d8bbee99951ee2338bc2f829047de07e77bfc263d4d6fa6394b3a9fa75bb44bd88753bde831ae523cc063de33c1cca373c4b8ce192238c6c55b4d4527b6b8dfcd37051a4611c3823cf28ed40897b9ccb6265bc04fb237bbee739250cf8059719145d7d92a22910163f502a25d797083cc72389847dfb6bfd4082b3536f8c9b95ef47d6d3880144cc9cefca24c1b70aed1e6af56bff280f6b3004a410844a4537fee61629fd12acbd9ba35c3c26691eade19376c3a3a255c9c57229a2f8b47dcb956d89b44e04820433163ffca190ae1d1f3e1ff91bb34033a28660e4192ca69fdddce7f4be1569fcb9775761bf53143257da617dc10cfabf9d14e4a7d676282848f689182f0816fd65bd55af31282913bda43b6833100ece98ffa1e1b36fd905bad9cbfb901519984ae24f42bd897656e2d51182f26bc7740925199c82481f3eeded1bb6a60fcc66ec4c230287f6cdf88cd9cf51e01ed518e07c177b3fc5f30c66465bbe1e2d13154824d1de2383ac400d5e1307e99d2b64a8ea59ab5d1ebea17c18c829f9087a4dd9f5e4c68a595cd9f8e08a182886e338df1409dce5c3d26ca6abb47439164971323ada13330ae94345dddb0575a018855f610a75714f053df9f01a59ba03870fb1a9456f06020f996916741dfd742a3d13a0c85f9ed19ea5f6748e55e8042fdb7c09dc7e5bd30f6a697ec0b5ec631334f141d7acfa315b8e75bee893fa0521695250d76b5d9cb9c9dbfe13de3ff959e44bb5b7b3f5cb3e2f34fed3ec7217d4de93f3084cec4557b655307e3acb329b8f752ce40cb86e88e6bc17bf11521c78a86e4cf83754f73393247e660e6a084c0f94cfd45b9c5f5a9db7931986f82e74c92edbdf597ac57f0cc07c9535a162de4a8c75a0cb6894a4f528e35905381a0773713218ad380d6c65290c35c5f906a97641122ee7d51f28d8a4382cfe142d04026644213359b0d7e42b9628343d17805b5259a40929265efee7b08541a927a2964a2cfc9922811179379fe3b2ae103b66787bebece503ed61243a8b9ed51baa59bd83c23ce49504d7259f6940ed8b6cd391b4d46d25d173be74b143b4c61d398d1bcd7c14b47436822e826e9098d34e67f51b27490613962b0cf016f44e130ba90de93ac3099679f495dc18aaaedcb71810010ec4809c4b70fd4b7ca7a0107546a6b7b7b3f358f9ca31e36a5709420f4a93486948d12aa7c9b70346edbd238fc438fe0d0b42ac9b25b859bdff7702cdedf06932501041086ae8f313e63d0f5f50d89c8a762976a545ea1d9c8d1e21026afd8556b655b0b4e83cf80cfacc0b20a9daf0ac55a290757b01be92c68c0a194370666737de8128af9c99d9f0c80206b8887afcceacadf7e5621f9a8d38e1ed1ad9e1b9bdc23ce5257f62c4506f2e0c7da2c55c07a7f1509457735ad368cd0dd74fdc49625b06d26f62722cc94e0d29841662b43a5780bfa6dda34e46d0d04b630500c68d7c161f85c7cb246f1b00918b4d073556e00ff8e395f20b932862c765b22f864b459bc67d19fbe6f30a103f68693ffda3ab9f8f866cbe3fdcd039ac795b7631e33b44f47d156c62cae212daacd231dbf517c7893a1d40181e82577ace9e4d6be8ea225c26685a33c8ee10570b328bf111a3cb314ec6537be6a29466cacf42365bce0c199a36b3cb081e110a26135d5f049e0f89903490b66190f1aaff7a223ce767aaa4c14371a61c322d866826cdc12990c0cf21ec7e855fad60b4424e2dbcaf99f4c55a33c8a28b5f2a1063e1b07a76f85a5d785522590f6c6c0b530628eb7bffc25e290f4cc8c8451465f5115c11bdc368cfba5a9ecb5cb87bde465d6ee33da38c3b0266265bccdb18658e66b70c691692e48bd1a303d4dc648ac5545a168f8d9f090f9c1a7c77c107de75d811e2f38b1b32cdce690d961143d98f829338edd4d800cb0d9752fbb71c4f8a53f393e7d4516c9c46e1059be8824f62d39d046104da5ae7d12cf89d042783403b398ecbd8cb37850907ec9680b655946996f3b91cde194c22428d85042c2cd4b01fa47aea806217e9c6ab24fa60dc1c2aabaf040a3bacbafdee0f74b42c33d4e54147be2e6e4b62ab1fda7764c938cf8b7e9c075065771f686aa7b6a90f56e0e5f7c777e0aa432c148ae3559243825fcb407f3965400765f859683787221f4497a35c716bc4a99e45207a8488ddeeb2ffa96bd482ccc76b229994818818ac149604394f76003315ec7d5dcbd58f11136c366b025523eb73a6cd365cb40a23ca75baaa87edadff01b2e22026557aabaa72c7ab931c691c39ede1882c3b16c08386bd3e4efa48bc1347ad1826f3b46062801cc5a2dd27f93f84e8a4ac8f0dcb5d0017f12fd8cc1d89f190bf216b4b5285b5e402e9c5ab7cbc01bc6d15ef181c7b816ef14b5e289bce65790c5b8c0bf535ad41d17fa23ad1f66fbd0d88ce0d81e363c2ce097a6755e8a3f916313330fe97b31fb108499ca54c806cfc06991dc551f8b5c9a822e87433ad883f7b899a08d46d2a9eb8cb955044bdc848be9500672b37a8529ec92e44bcaed9a3be14f7f056059dd6fc7a477a71e3b0af073615d3ce0ff8fec38d4b71f2f0f47f57b9ba3ec069127f4617a21ae34e7777b5e9240037ee249c87cdf1d923fe1a672cddaed5890867c2aff080f324bb81e3899110310f9e7cfb346c082799cc9f583de6ee738250726a219706aab3c1d992663000e89227ce1f78a4ca6053a5fcf0f8e221717ead2a0a035e086626e6b87f4a1b2e6e838a21e663ce647ad06342c883b3a8574c5315cd311891e3dddc0255aefb214d32a02a3370691becdb7bb5e4b2923c9086757b72ca21246d3d340b33b7052c41c855ff289662f3c248a197d0da850fb519ad798fb9b224e4430116f547cd026190556c04b1c678a438e4cb5b84f871d959233c1c9a192d152993e1ad88cc25e6a70abf2448dd525fc0fb829f64b890064d46e0d37bebb6dbd693ddca287f2e9ccbda96f4b7bedff52cf3ddd42c814c012e18ab03e2389a67ee20edaaee30224098d46f1bf81bbad3fa275a37903ccc2c0c871241bc7e2dd8a6f8a440dc7d29f83af753433edff11afa82b334d6ecb6ef5aa045d84fa2bb9d6fe0017940db11af107fbb0921b796f11a4c18b4232863bcb609cb3a26b1f20ff362e3f6128a14d9a698fe9e40ffc817404376e147ab07eee5ef310a6f78c4704aa2a193a12218f101a8b54c4472ea78ef1992a2935d3c475daf2271f84ee8fbab63f318f9650eb58705886be390163d979cdf0174dcf7b260eef02da5326fecd8db324bc9541d29ec1c80be61ece079dbb19269939478d1221847eb70ff0a6b826b252c83ee268c6d007c2d19f1b1f44f23d7acd9cf48c75ba6f35885be0ae89c3656b8558b0adc2939769b4964630c56f9cb2ca0a4a607345ac3eb3a1cfb23fffc38e391ea29512feb6e27a2528c9382aa25f30a270b0154405cab938f36a1da583f795d34241785f135f33ec6037b0b2056678eb02fcb78950f578f716c0246ad290cb347052eda1e119407852d65d4c2ad25e7f1e9cbf981649356ff1a97ac3ac57dd835057901ebb1840ed3791591b2f24ff536257470a4b07f9bcbb93b1f079fbf5e0f0e69dcbebf969aad3d503ab603602b06a9b575c978a11eeddbb37f0b507de7cf1b1199365a024858212970c7506de180c84a77cd18797a83154bf2907420cb32091e374d280545364c290f8c4a0f19304b071386ed4b519cd06b1a33fab146ca061a0039c87e613c39364aa3aa38e10be7e649d31f661f4b61c7253c5104f09c274989672ae9062a6d9084a90c5e67a9d11d0e97dc6a395314159758ea1efb4a2ecc4c0e0c97139279b678a3c6c18996b9cc7e78d08c855af9ec2fcc3a4044ba2d328ea46b46dcd10edcbb7a18d6fae70cdf185ece77de5de74a677e1ce596b32fb9c290fb3b553a7f9476edf8a71ec48881781ab72ca3d49eab12564829f766016ebfc01ae409e85a24e3fb2423c27ab57259dc9178c24bfa75d28466339077213dd1c1ed45146191aaa21a45b8c273177bb1d953af3518c9dfc26ee40d45df28015932ba17a68cc4e1fed522168314673966b0a2aa24ddfd9dac2e86c6b7581aae6159bc745d084a30811664ee65fdeda3a0ae4b6c239840f0f42d1b03b2540cd93fd55fe3bf8cde5b9ad650e041a0bd240cb0c5c84c3ba24a8baec6d71a112d84d35e5a3926cbe0bc54c817707dae6c5e5470443bfe66e28ffc7dc0b2de99217468a2d9b05611ee5a5f7fe09a0604746180946feef74600bdda0c30fc5f902ddb78fae3ce749e90e505002011e95c0398dea237e536c0c04f4543cbc6f0d22cd707afac4249ea489014e5d8b391ca7f51a631c633582890e45317bf6751a424a93cfe64894e5b553879bba36ee7c511bbe3903034ba9f673e1d1297632dd50b3f0f4e794cb69bbeb5ca07854531fc9e7d34089e50e16d2117507675873f1914c628b800e7db6b679bf5b40bb13d3a8aa0487e69ae014f94e7408f928671291d3a2798c4ff05124c267d0ff90b3722a9df689cc9525f86e7c96d6d86bc53621bd9c9851f3684dc645f96daac2b91f4179f78541463579c3f410828957462fc27a6ac7d82a9e3909a5390a9d4280fc1ac94c56143e1747afab5e4bfacf64ebe168af3b9bceac749ff9d933c5b7d9abf207102000938b96f4a9f1dd1a184dbd02739769773fdfefa81b2ac1f46b19f77c1a31ce1a7a238176c1433ced8c3dcc2004036f02d38456f64f20955b0abdf6152f5e54ba5e006029e28613db4228b321172f06606186cfb4e595b63b4ae37c9dbf2ca8ab8f1cac9a3688e024b89cfe52033fa413b792429cb297ed1814e6ad5d08dde7111b38ed898575019765db42c152efa2942360bb0046d084f41b012b29ba744b7313b07067e7573afca077bff2a973375a0d42e2d75ba505adfa2672ecbc52851bb7971cfae66bc10a860532a24f980842321f21f7a1172fcebb1350bf484ad4cc772cddf2f9ac7fd9e88fee719a03e231f71365376f26eeeda02e673f3dcf509d7d844e67fb422cd17c0c7ac2a9da3ed568254ebb35f263b6868846bbe93c45bc0342203998e4bbcad942fa60326a70058154698329d07ab1e21bb73bc5dd897fee8920260fa8b2cc134aed124c22454452ffee7ed1859b2da9cefee4c9a13817d1ab9a6dc775b34a1f0ff181aa15d26f336a11caca4871b50a0739a7bd943df579a660b0d8ca3944f45ea4113c47258637c915257360722cfeda8c3de6bf84e52d38810cf6e11d4a392c1051d3d3ac8d621032c49997eb779b2c996dfc3993ced4bc34a8c0e6ecbcada6fa813e9f4894d147f1f795a2a176f5a50730a2b7ed79e5a270449a23bc0b6ec3bbb221fe9e99ee9aef948e87ade1cca4d3e61c21533ab610cdde8c2e0a1bbbf8767295066d6e986d657e5f0b8880b4c3a1642d9aa60c009fbdaea448fca18bc80af1673d4e79e8c35a28aaaa5cf8caf3bcb21d876746c8c683bc0d0251bf5b1f7f314fbc9df9b472e514c69d5db4c78c87e8d037d3bc9510c720452c7a66944d71f13f838e81f2edc28c152bbb77759cf1b500698a01ec0761347626c6b912d48cc122fb696734c38d135f66c840f69c699f8dce4ba574ba69a3bf51e1dd73658fe1015eec7c1d0123e0370e8bde54d39875f2d9556ea230676affb28422bb6eb67282b919502b087a1b3fbcabdc53253a9ddea8083542297883d49d0e1666e062309f833b2d487af8f6444e04cd564e7f41cdaf27847af3c11b501213386f3583319d7afb0279fc13f0f4fa4d6ea23f8a6aa617c50283d83db2520d3daac7199a3255cf8f655e7891ff8769f1d65cb0440ab468a9c6b730e5b2ef7e570b499c2ad0e61b72222ff69ec83fa5e9996f5c83d13b9b8a509c2748c27b1255ab16cb0651330c160cdfacd1b62b2b98bb8f6178b607fadc40c059e2fcb2c1b35a43dc65d0cde53aa2e61e8eac9204391c7d1b5f16576b57365716cd01bb17ac156ce7f5a1404711e2fff17f25a787ecdef05fd310685cac3f4273297174c28f22b9b92de23d87d7e68e79e7436653d18b331a80cb3f087ff35d29e27426bdea61c6cb45b0db85b6490937163248a9396db571b0e55b9f0daeddb48e8dd00d1c620f90c5c21f09a2219f7ec01bc32e1f631c80c06a56e63cb3a58c263c9cfbef967811a252f18fb55839fe784cdbad5d9ef3957602f03b4ee436b17a89392c393929208aa20684e6fad20052db825ad4d5be03ad546e4e310b8661d050e5522e48181ed8a13d97fb150e7e20519e17ac88b2fd8258294379ba9125da245c122ec522ffc722f1e871f0174562ee3a79e145e9cb0afcf1f444309ac4aa1b268f6ac2ab40133293f7f109a54a707404c36fc1caf21caada5252ff7051892bc47b3db165a49061f7322cb15a5419b1541e88dc471a272fb88b0ef4818eed7369a4c39dac39dea23f00cddc470979a69b3caeb9919840d016f87f5e2e69ee71a62f1ad5d99c59e1c62e1f55201b732dde0c4f1f74788da8a2f17bdb70576cc33a375897287025917599c7697ee633eb55e26d71d02504ba4d80c7da29935bc6b64ad959572d75a171c71d5162cb3e0fb732cf06139a9572362e80abadc399d0f717aebd096fbcf135b73d15fceb0edce4cff87171970929eeb7504733f2930e729d30aca8e84fd2349593f10d42d2a9b1c3db9e9372cf8970ec388215eb9aaeacf2a0495461cd813ae28675ea400c933d248e86f9d320435b55e4e625eaec494dba02924b204802184def18ac18497db9dcffe80f6fbac52ec78276c0c2bde0af4a59034b7955b1ecac590752bd2438f2eea8159b536197a410f7652b34d80c7c2bfdd4bd091d10b383c28ad12a3e93cf6a4c769d0e61edcf0e0634bb5fcda539910a2aab1eeb3203813b2ba7f088e4e271c6c200d63b3c780d9800907b8b402974805be8640f90eb3a16160b98d520c02b09409b10406950b679c0fd97026dba68acc0ec0187c27a536a8de25d412126b46f91cc3269630d9b046e6f980be2f9b0b86b3aa78b02b862d466ee645922dc9a39649110c106dfa41688132b3ab1d14646d871e4b8e1f"; + let inputs = [["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x0139a6e4e03674b2224d8a8d62fde5aec1a82eda46315608b24aea0e1ca4a902", "0x2e867257ec3f84a310220014033ddef96a06d5b5fcbfd496025a89c05e02d5ed"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x04b2cd8fb17d2ea4aca2663e60588a7eb0e792a3adee4817f080eb77f5ea2d33", "0x1bb916c75ad626d50c97189100aa1d65999224c6bf1dc6f300eafb3a48ad8393"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x08f4f837bc57327057d409beef531f242d541161ee3a015fe1b84bf10f959063", "0x26c46e9b0678c6aacf9953e25468a1496430c90aae4dbcd87175d5bfda16a874"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x04903f78a904faffa28065cb248451abe13f212e4100ceea416affbd4fb9e72c", "0x27d3673d46d5864ecd9308530fae5df595b10b6ed76d55dcc6386527ecbb199a"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x0771677b78336f2b4e0e02ec4dc890e833350ea383a9032b56c5d5d10cb25541", "0x260097e05932f595399f980603c9bc678eaae6a46d45441cf519034623300d43"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x0be580c59270c9f1cd03ad8e4da20f8476981b502eff3f311009fce26b23a275", "0x1fd36f025490572e77987ed62bd28345bab7589ce7bfccd72b0cfeae28fcae72"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x02edae02b825ec84b1e84e581750707777ba4bca183b6091851baa47ed086b3a", "0x0761b84578cc1b71c6a6a5b4dc03d1f3cd66478332f6b889706040954728d454"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x1af9bba3eed2f4031d6aa978ab856a2c43419ad8967718d9278473bbee1a41d6", "0x1cf9c8775217233aa1f624a5b299bee256d0445b0cb67b5bb4a4064e1951c7e2"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x0961857e5a09255c5d36cc4ab004d2b37e84e85e012b63135ecc9eb6d30bad71", "0x06688697e7e5ccdc9199d2075279bf97de0a3d183455b5dd4270f156a21f3927"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x2fececabb753e97837635b3f9ec0df48c80363011ef13c0424069123f2cc48dc", "0x303b59721324a38bacc8b2fd1d521732876b71d2aa25bb916b9df2369760cf3b"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x09f0763a8b400d1524d935a42d46d0920091d28981cedaf0ad654f06567ed87a", "0x18b9544f8c20fc7f596ef474eee540dc32f58b53c3a09649f06cb77501cbc84b"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x1611d647796a4fb4b2bf0bbf6bf924607b75bcfdb1331628db6d6db29a9d9be7", "0x2244c681c89d010f4a457a06f97cc3f439ae242d817ba0c890f0d3cc59c6bf80"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x03ca4005924fe4e0ecffef80c6c40fcf49dea696778fa55d9b888a063e46f803", "0x26b1b6f70bee7895e6d53177b4360e5a10c7d5ae193ebde536e98d0a095d8fbb"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x0e0bb9034177de8f0216df1d23af469bc1df4c9b580182ce0fbe99bc67a12f2c", "0x21f0fc0eccebf2538e6af70f104fec9ea5e4da4d11ebbd5b9622132b60bf9158"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x227685e026f81829d446d300ccb071732a842b9b285d4e0ef3e71354e932b2bc", "0x047795ae29557cf6cbcd89fad7d6476cf084713553fe13ec4f78dab25352934e"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x1f70c6f5bfb236d1be621658896bdda0f2592b4a8814271a1b6b5785adfccb3b", "0x2c8be1a79e32231c47492cbb7bb4602ffd6186701aa1efeebc73582bd2c23621"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x0a2ca3dfcfe3efdd1098ec0df56d3877541c6590a840a52042600ba871c6b600", "0x01a74f041e65e8ae0f5007cd88150133880ac970cfa83a9b1f80c83770eb94c1"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x23f926e1e17bf3f7ff9045d915b1b25ca28cb05e5963ff6410483840c0aca082", "0x02ebb06b27703a1670134757c43169ed39dad7cf0bba07016749fc7697b46ed5"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x28b363bce048704773acf5275ba9a80b6566c9d7808a1854c5c8951639e14c5f", "0x17b24750b52e823911773b0b42b170d657f11ee98b94e82696587491d6124098"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x269363cc3502b8e9e20a6d8994cd044a3d5169a173001b8c827e642db6ca2981", "0x2a51563d9218c243e51140ab658fe300a2c93f747bfdc9521a2230309a1d1f93"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x0a3bf805a96b3a51f78be077353ae6cd21345e60aa13d8ff70263eecfb2c257f", "0x2bcb84e0353fad12a9db98bf9f5c5a2667d234c3614c09f6cc890478d48f4ec9"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x026a5e2422807ae244c932bd3b7cc215c90b6c39150dcfb0ac90890ace3654db", "0x2af55218392ae3ee06308e0248079a62e2651a7a4e62b7666de1d00ccef5cffc"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x21f7a63ca80f2d8860abe6ce9692d24086d7a0cd4a53ca6adc4e4b12d7757bff", "0x1ff25d86d49426d3f8e7481045162dbae5bf02c136088802612484e3c0f0d8e2"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x1cc5d987f445fba0e2f4ca9dd327f51cb906e65922423dd9cf507ee63c2ff379", "0x1fd589b9cc670e690046d1bd578207fff55beae706a74b8f56cbbb62edbcf008"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x23d8bae48c11b19f7896ce5eb2abb98fc70d7ba66181764009b193f66a3dcd12", "0x145a1f31426a262ae1ecc613ca4c769726853278d3aafad901568af2860de99c"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x157b262172fa8ec0e6372d70edb0ed3be4d8b165be84b28c5bdd97561ca56258", "0x301587397731e972182b798d262b61ac303fc9d5eca5458d93ee45a4dbbd8d14"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x22acbe88a73965792a2afc50749638b948eb46855bba1566259da5b0d23423e8", "0x2aaf05bddefb0ea6ca5e9ef58c1ecaff0548f08f516c5630581663458086fad8"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x25de3143398d7e27b71b632af47a9d7759d7b71addd055df33a30dd7be499263", "0x2a95c8a23364d905088a73032353e9f36a5bed9b76025a7b65b7a0559404ce03"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x0ed187006a3c0e403efd667755467bd2d8e54beb070c86513d2b341d0b3f7b6d", "0x1ecd8eb92f6018a0ccf7faed1a6a3d9cc2e242b9d8518ead34767de3f3e51cc6"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x045d773b71bc062b2cbf47f4350802c4923e26499fa462eafaea89ad4809d8db", "0x09a379f47c8c8899c8afa502dbbacd6ebb30bc10b623fdfddcceee439afc2ae2"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x1642bc9e3d8614280b6084e60d2a70f6a5b9b7928bcb53d956b66291d488a073", "0x15ba2c326aa948e06260ea41a0bdfb517a3e6737fd7c3f50c64185e93ba9fbc9"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x1fc30390d4056e9771ed699114605e620212f92753dc3a840039a284e0402a3e", "0x0039401832fee31cb09f74e6197d5ca3b12d396957847322d00f771ab49c7ebb"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x071086055a2e8a5983147215ea46f61ef099e7afa6d7dc26e1e95ea6d1852768", "0x25124d252c723d5a7bc75db24f7448ed99b905f4158ad899f60fb7e9b89d62d3"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x04ad427df3ae73e4bcd4b40a497e59fd4aa6676791a21cfb45aaf9aa42ca40d8", "0x0f878f73e7cbf21184f0db084584bbb4969ed1dcbb1c5fb5ede68842fb9356e8"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x2efb83d07f0552e5daf4398e79808c3c251a35ca5de00e262de70e870535bf7a", "0x1d7734a26f97cba8f8963a85a0a9720438ad66c77c2c46650272c94d3ea91dca"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x29e767b1caa0bba037cf24fc3fbf8921c4426233f7f8e78855e8ccddbeb71cd3", "0x1f30d424b62044ad88f7e2c644f61e55e6ff8ddcff543b83e26d96b8f9834100"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x2a13bc2ee33088a6412029bc0bc6e0fcc72b7dbae397f8313986e03d2fbc3cc8", "0x2c3e4563f82a00b26bd47d550958f056daa82d7bf88776e9e02da8e794df9ba2"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x0affdd25976e7d0ad70afc82dedb0148dc8e00c75ac052c40b6bd0bcb0220618", "0x0270e7beb0de05754a1c96619fa0bcaa8d946755bc4153692c081c5f0ef66b49"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x26c7fb6b501288f13983e6167008fbfed383074ac2d9b540dd9e62b56c50229d", "0x136cf96499b6b6a72900ad6ac70a8ac108904e2ea76c1e56eba814e9ff59acde"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x1e0ac850115a2a4d261653b305b6ec4d4e339290ddb0094d4c71e05b9c361dda", "0x301138f7dbc40a5b8574022f6817d3472f506b4de0bec81224ae2de8edba3819"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x20022a02fb059fc9f929f8e15aeba122f27863231e58d38ed48e88e9efb9addb", "0x2d6a8c5a508e689754a6a5ed5b86dd8a907d6663909bc6744a9c515e7e935e58"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x15f5869e9caa1bc89ef20ab548af90bc0c36964c42ec45f14cea00389f246199", "0x119df87b5c48dd570d54f067cc8c0649c10f5ec88058a21228fa8cf54f03dcc9"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x26597f3a8e37c4d2aa768b13d96d43c3c798a158ff0f1ab04d4485523ec73ea4", "0x1676a04d9bbd7e4375813702ccbe7724faa33a95718ad886e68cf6742f84afe8"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x036c648de83fe65fa998fddd62ba9f8629a2596f877658f5b8022a29a7937691", "0x078cad33ff44271dc9183c1fe16a93e3cdcf963fa0467c66b4f69d3a81932e97"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x211c3a15b96d53bb74ae5d9af6d572d489a583f793f35567f8b6cd46156bb5d9", "0x092aca168ca72104b0e22d844b38a05df02c4efbcac8e22d8e46252995d74a9d"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x0c1f4041eb684a665139056704f81f70bd0525c04da6d011b0f77f8e4e6b4258", "0x26c2402040d6ee0a837d84e8875e2c594cc5a9de7448b42ff747ddc467a818ce"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x1918ef16c01ab4b298f0de1c3b335b36aa0e6f596803619727cac51cc0fb0b55", "0x201cdc86bfeee8edd11cb48fe1ee12045e6f0312995ab05fd244f163023b6287"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x0aef2b9b9fa5a58f55771f05b83e234868fec29dfa259a5c2681464f9040f8e5", "0x19b3ddac40f2ab7718e082d321cb84dcca22b88d6129c442684cc6e346e962ca"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x2068c2adcf22f0f69c135ac4bfc6895d0c3b885885eaa0036aef0c441085d3f0", "0x2069b1a32ae5f75c9415ca26ee0033eabe125858741e2c190e2e6429c03843e1"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x18d09fcf2ed230be980a9aea911e71d7f29036d896807c2e9f36c953e2d3b1b8", "0x21ef56d684a5e0504f0e3b80234b1e52cb67b5d1266cf71c6415af12e9fee8af"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x2c4ec71b517fb80382de6a1c9dfdcf4a48712659c09f4ea2f30a9e84c4889ccb", "0x18deb6b7314047bd4428d0a23d8dd88f1d4dbabf23fd4986e1746128e95df0f8"], ["0x2b8cfd91b905cae31d41e7dedf4a927ee3bc429aad7e344d59d2810d82876c32", "0x2aaa6c24a758209e90aced1f10277b762a7c1115dbc0e16ac276fc2c671a861f", "0x018858692e3f19bb79030e8c4bc968175ca7f578017790ab82b8aca671cbfd4c", "0x05ea75e1c59fb90e317ffc513865a666f6856b85e1c1c773b0331c337dd45bac"]]; + let outputs = [["0x1befaea19227f5deaaadca57a56967d9ec8ccdb0bc444a2ea99626288595ec37", "0x277e8d4ca5672e7109d2cac9357d3c4da323ea6e3bd419b617ecb45c0fc32bdb", "0x2a6feb4a13237ad8671d374eca3b0dbc608eff31f6a44e985b3a82d50daa64b3", "0x064aeb8344edefd0dd13b0ba407c1e5847febfb1f20f279af45a9ff814876978"], ["0x255d11d1b991d0c912b7ff928e57b088087076f815a17819535a09acabdf72fc", "0x1825ccd2a6015d2b42da5bfe0e9df0b05457646cb0c28d7a210da2d4407e5b97", "0x1167ff60deea8fc695a5f537c891c0c3befef11f6b789f504173667844c58dd9", "0x175bfb757b90e3b2f016e1bc3b6ee7068e354f321579f2580017ac3ba020434f"], ["0x1c6b9a51d9238ca45f800dba0c09ae93eae30cd46f9af041d5261828253c20ee", "0x008d2014c9d68b071a33fe1ae12d1122c80ede1b0e49360763fcaacbb562c546", "0x03ef44084c34180283a05cc1d6cf5af697cf2efde2e92f40d8be651a6ca5c8d7", "0x2ca0e965a171fca714172e2459cb8af75bb9c5c8a1e39333e0736dae6f7ed61a"], ["0x1fe403a8498153f7571a4d06c24408121a4c176e7ecaef0f2e33591daad4259d", "0x00c05e98e1ef58212353a6612c8babbc2614d900362887c62e99d52056a64a6d", "0x29930104c3ed2dbed9f071bb08a30fbbe37e685957fcbf1153583b225b2c5fe0", "0x0c0965ea8f26e4893783bb08f4cdddd8169e71debfefb01c8e91be73d3d7ffc0"], ["0x300b32aa167a66004a6bfe9456125e750a27761305233fb0f7e64ed1505a1844", "0x2512603e908de0fc660540f05539f65a312e652330f954343199b547ed16c371", "0x2ada0127f84c28241e50fb1990d3a8930af5ea4e9c0a94e6435b2bf407da1224", "0x05418dd9a7e9c982d347e473af25ec40bf786568663195765c60157976b778d9"], ["0x2e3259228d8e6a250653cff599c393d7c774b6d407217eae36624c0405c5ba28", "0x013e7ce2cd499c34d8a8fd74c7d590d61a3e06257b2920c99f7587b6f9942501", "0x06becaee68eeba242b1cfabb082bb4bb1f0554a4acfa30da30405bfbcfa67f2d", "0x07ac2d15ca9d430b1da411e13e87811f6d9ec156fc06a0d6f814d6024b3e44fd"], ["0x1dc484810bce510ae3a96afcc8c1a28c3ebecac091d8e83e8c182e2143bd4e89", "0x025ea48483394d4bc7a5772cca24c6d09b2d200c4243b670ba0948c62ba8df77", "0x1c89f806144e15e6a0be541886dfef2d64748348e3b444cd2a0314fc8bbb425e", "0x164e075b8249534ed13f93d83ea66b8b5ed618d2f7180cf1026b2d79992214c0"], ["0x1cd9085a69ed8869d284ae259b0db043312bdc9e50021566d049b426c195da1f", "0x2dd2ddb5fb6140244554e352d48268d23d5977bdb8e066b49b5ef0c8703a5fed", "0x269824c363c06bcb6801105bd4d6a4b8685178c870d7c7da80bbeef61294aa1e", "0x274848e51d2a5fb2442df75c7543642cb35b1d8dfd93a6058855dfebd8ad2ff7"], ["0x042aee12383fea647f4490073a5ae26379163833fcc0558e68522de6b9dd25b7", "0x1a94322c47290561abe8f317ee86d0fc73b5704baf1228b1a87a5d8dbc6ad0de", "0x2cfcfe5160df95c3429601cd3156aa886e58d1d9bc71cf239d4972b0b7d12dd7", "0x159c3a9fd91e5f9c51f3f6f4b003d9f1431580fe9f111febecce49ec583a2087"], ["0x0b3dc5cb7a9261abfa984a86feb30c335c5832d37e3f0f66e60163d6ad116074", "0x2934c6c7cbf9d00719013a8dffc355292d9acf4b67b9a6dd18ad307ecb80da20", "0x2659c9536f248dc10d7a8dce41b0bf39f20efe8b7881f63955b63dd84d3b6e96", "0x14af931a2a082cbb55eab90b35da2d4687086388225624f20b1ecefa7c1e19fc"], ["0x2cec2718018b08717455769f4710d8d2ec58565d73bc16ae7a76012915d5d9d4", "0x188be8a79bfbb7900a4eec8bb8baaf4b6ce1ac1845aad50ebfa59c40bdd9118a", "0x2f9083be6b0feb3bd2eefb6a733fb83b612fe10fef85a2f4bbbd4cd4d577e20e", "0x1741796d65c7ca4e702f5156c45a0197ec6fdca44f8e2aee3b7887fa91eb7da9"], ["0x093ef3df6214631e627cbe4fc8ae92e14f914483069ed0d6bfbce150f6fed027", "0x1beca248e806646c8e51e9e8d4a764c8658bda9e8e49a5ccfc58bc915d1dc5e5", "0x12d9ad7c5b3db1a634ebe90978df1ee05e54d89e9afbfd93d1aa131bc258cd58", "0x068675a8008e12a8bd7b6d7a8fe40da89ed13b74ef46471a1dc476da9cecc9bb"], ["0x28cd421aa486b5bd2ac80a9c443b147cfb6b02659441344f7913a1f8ef366b20", "0x1511bd75cb8b294bf74a39e7978b2e390499047c3bfc381524708e7dbd40d149", "0x09b971e7c47a3ff91d20ed56c60f361fc111fcf3c47949f776b7cea3171a17a3", "0x04dfb38bf58bb41bf2360ce892e5898776d4b1cdbd2811b97443579ba7bd868b"], ["0x169cf4c25ebce6d6e2a4e7c4f6b9030100c50bb35ba609fb9eae86570be7ccf0", "0x10f656bc66cf20b0e17b04cafba7be7bdf05b4dd09244eee55c830a1c091790f", "0x23e34ca17b28e3ca3f09181a5c10b7aa70af5ed1486da24607f9de1c18ab5a4c", "0x155b71e341f772ad0be274f78f4da3db0aa19cd5a8a433a96e94bdd9a0c23709"], ["0x089ceb359fd7f38c29338093b57c36c13b87b6ef7c287b5810941ba5a62690f8", "0x20628e27b85d3c993b33679929d2054980606bb3fc6fd1aa6ccc9fd84b3c0ec9", "0x03edc5ff26b3b5c35f28d1f3e28a4bf9f3c11b63de1d58631d994d7214a78f45", "0x06eaa868b905438cd0bf4a81004cb2be3cf46c2659bbb6dc679eb9c05fdba2bd"], ["0x087bb45e7e1211900b78c5a2b6087959b9aa938c9d88e79f770627136003f1c5", "0x240d43a03ec5061c5c9c0813be789629d61109a696a62bb99054e22c67c607f3", "0x178716e727f47ff8c0389e416cfe1b90ce9027b1ec3b178c0c2d7bf68c04eff5", "0x03beeceb0c4ecd13846ecd8df9b8af45e79a91b5d28aece180996b9e10e54dc4"], ["0x0e531c54d0c4cbd454440a2ab79ef78e5a87f07c48a9adcbdf832892e730809b", "0x24d81c8df76e528d29de20fef6dcc0af05509eac88f97c2ebbcbea53bfcc2b9b", "0x238f4ea0e40bae3964f04a2a68af661e9aee604abd709d55242ed7667a64c9fc", "0x0a60c3bf3c06b29819073a34f49fd09a95f03029d155ccc5c1a30c93d18fdfaa"], ["0x12b62126c29dcf6b48c47056cd62b37af58abbf9f820cae5868bc17393e015e7", "0x2d9119ff604658073084c7cfb84b8be341c70a140eaadb9e638fa857e33a0f99", "0x2d77473af63245f73ab98c15ed4495e9a5102fa13c9175c3f71f60d96fc6cf46", "0x28447624369b6c02be46c688016517ce21dbe7019e2c1ef75db45d9ae503607f"], ["0x20cda6c60afa4689387c5c6ff0bcc5f96668b54af4371cc851b2064ae6096e70", "0x2253e521e08dcd14f6059c0af0a3d52eb7a4306244cde1937a907af8df4aa6c8", "0x249fa0b8353591e04e47505e6d6b3b78e271483cfee891299207338f9a0172c4", "0x1aac696a382b516ead0190ee4c70e95c9928d01a4779e9a1a9a2b1a42c3e4857"], ["0x18e72dcde5ebb8c18f1384edbeeb284e8aa7b55c5a027c5504e62645b2221859", "0x02ff99a2d6c83b88f36d84504f213aa43ae6f5f1c456a9ce8fc01c1406bf1e37", "0x0703f9887adf2d3affdc0fb7aaffb9e26a3f28a91d4d120e0e38cd5f94f0d88b", "0x167f0ff729f26789a2e613e1a25beda89f0c8c08df42b75e16e9580699b08e59"], ["0x003b58eee8c62d4d70195615e84ed72c7b165e0d33fc54e89cd2679d9eaa3a18", "0x2699a9feaa2c33673c3150f56ef15575bb2230c11e98002d19331e0df6faa947", "0x256b26875d8f57f1d931f7145335af146db19fc0bdf5c2d0412768d99a1d2240", "0x2e19f831093dd129acbcf048a36788475bca22b85975f04a766b7a86e5619a42"], ["0x073050869a621b7bd4ff2994e27777d98dede1efe306e30502800561733886d5", "0x301771de9d9f0e4551b965d915b63cf972e098ac7485be610101f4318c132af5", "0x06f61a75c49e58952a227e729e8bb7896966440e54d77a1c09787ec2df54e283", "0x2d6e00a7c21fb0ee1384c047b3596c6f90bb6b80d3bd0db2bf22e4c088eb0b94"], ["0x18cf0b3a7197809bd0f8d16f874709113a06bba41abfe0969497bd8886eaae23", "0x0e9455da71a6cb0bcec23ad86049c42a83be9d4345670a0a4b7867fdae7ed881", "0x2e4e969e97187dd8bb1e9d85adb53bd80876ee41e2175ebb9d2189a9809a3ce0", "0x0e72231fd0b9993e6339825a960d9e15d01cf395e8c77cc4d2dee6d69dcb4918"], ["0x1f5f7de52a340023ec23c1c6fc5eb175cc36b9d0625cb43cbb3f6c716d92e66c", "0x0b87c8a495cb4bcfd12977fc116921b1526caa34899b6d8e58e1ae2e251e74a9", "0x0d29d82c2efe8f29537a93742485a3670799a4fb5cc051d79bad08a5d15d2a1e", "0x1578608531a1c38fcfb9e966aa030628bfbae53ac5b0d3dcdc65d316a56c298a"], ["0x1561cf3bbe92124bf8c10029c23a5f65965c4d0339eb4be02e6b4cfe64581ff5", "0x07f6a08aa7260844144c94793acc44f8c721c7260ce6441aba30773244560cef", "0x113148e2a13cfe9fdeddb43e14cf79c39e53a916b488996b8a0cee95322b3d36", "0x0100cf3e852acbf6c5e72109ed48f80fbbb5946a0beb8b72a82c0bd6ef6a3992"], ["0x03bab889122a1a63b239063f45765efc8eb4432badcfa351059440204590bc71", "0x0f5b154715228a1f597cee92f7420245a13ef700aa9cd2b47347d19a3d933b91", "0x2a0897eed6208018b6f290fea5ef16c6750df1ca189b66920f45fead701ebb11", "0x28378628158a4b21653d50d8588d9a1ab30bd90e418cd13e8270f184461fb7c9"], ["0x017724205d1fdb1e224c1d62ca8a6b749094f319293e919a88b67471e7bdabd0", "0x201f460dde3dec47e4aeff5fca06b76de2dec3c41d3ba4eb8b446687988a0fde", "0x21adc1eb9fb19742fef763265cbd4e71bbce1193d471e6399042d17f785311c8", "0x2e4a8b2435bc1203d9c43c22697fdddef230adada4d475606914402e3dd65ed1"], ["0x0edc8e6a1a9148ae3bb8097ba353eebf73d66f71d79687bbc758f02a45649fd2", "0x2844a89978d227a7b4b7805447a878dcec0fa75193746c60fa4cb56abc9cb918", "0x2631d1a859a8d184421366a3559f63667d276c1091a6961a4e829a8fc11b1ac9", "0x196a3f5f38ca09e9124deec43a6d49dbdd292352e55cbae972acf149cf642f1a"], ["0x2cd6bbd57b46ded48af6e34bc0cb2cc4e252f057e8fe9ef2678b73a135895504", "0x2452dd77124f7c8ff90ff2bfae0f09b5762d5ff61cd8a83f420ac3e8b1a2909f", "0x08ad0ec1cb20cd102474da6bce930395928e0e135439050e10496e3594d63a05", "0x183d92e2000118fbe33ba8b083b0e4fbc8be09a0a33c505eadb3a7befe75715f"], ["0x1ba83d9159344392d4f17f8ad68c32259497bf8c2a8df6669fcfd43e5fcbc3b0", "0x18e3ea5b0bd68e53d68f04e21c6fb57372ef829692a91db5f19de6346bb283ec", "0x0fa49d6f20fe68b7e6d0cecd319c0a730b0d214878dea0ef562aec186366763b", "0x0e906750c916d7996144a62d444041c011103ca76a923a3744d5bf6b4e287f4b"], ["0x000b1a91198c694db8b414dbdeafb67486d3afa2c0394e6abff60e0746927562", "0x27fe1b4c75a9dac82c606570527b5920ce7bffae3b306ea6779ce19532c21ec5", "0x07f9829956222ccd2381cf88668710ea1235524f02e999dca1731392157cdbc6", "0x0d0f068760f21a9794c6cc90d4fe9823a52092ef4515f568e68464b258a46eb0"], ["0x20bf3ed06320ee26382b1adfdd3667ceaa035d03b7893c1dede278ebf1f96e81", "0x1b8c03581a86b273ab84ad938ea7042452d03ffd5b68e0da6da1a90471ef9d50", "0x07bca100b64374003b625623176e4fe184693ed7e14a10bd176ef3bc50a217fe", "0x1ca3a1df1ef188782da268627dc9d4e3f858f204251495b62f79b76365e7c26d"], ["0x0c4c30343cf2771682bcbe7845702b04f490d8b9a1a35a2c88939be3b6c4a3d1", "0x04cff500129faa96e09ee211ab64d18891facd5a910dfd29852c287d08956bda", "0x30333ee3ec227760f97e4a8bfdfd2d5664e21598576441fbe715eede77bfc714", "0x0403bf872d17cabee103042e7a6c13de774d766bde0ef829cf2e806a3ec54ba9"], ["0x2fb9efbb218191655fbfd50d4f4355d14f188d672b426f311d7973d2ba2c5699", "0x2145f998769fdfb2ebf9931d86fd21f57a2b0b03e2b552ae5b5a02f46badd956", "0x0c8dca356e97e52eff724957b7d982335a17d9c88dd6087749c5b42a5d884dcb", "0x082880525191a025f3f566f1932cf72fe8e9c43d1bdca2b1e3130dd40eaf8041"], ["0x013295dc6ca5a2a7f25496a21458acfd19c8f17865250c48c987bc19ce7d77c9", "0x263c2436e794f08da03d919c863206b63ef385134e59712b6eaf5f2a054f24fb", "0x23672ce99f39c9dcc9c542757abadbecc55a0adf044d8df1bbc641e185240d0c", "0x2b843a9b20c79380add0d58ed783395d186e9df18269d6dd3e76bfbc09d13b12"], ["0x09aeb6c26d738b4a58d37f26c29e57414db75a4c86d18aab25ed26ce39ff480e", "0x268ce04d9f936ac2ad0141bddbd7a01a6c57d1d0928135b6fbf1e19466e653eb", "0x046e2f72ba0f7abffc2ed8a94a110a49a7569da45a712831186def0c9ddfec83", "0x1e6b88c1396c2e28253b14af0ee0a0ca125a237aa2b932742f3301103e070588"], ["0x229dad6d2855d944d19b501820852e38efb2f7808eb95f15c9568f898f848643", "0x2354dd74f307d4ccbc0841c84fcbad19f8540bc9e2e4029b91543e45b6bab820", "0x21a76233168dc21bf4f50d06b4bd9a5a03738fd68a9b9ff38c2c6ce4dadb0a36", "0x11058234793d07cf5c955d2c7650655e84cfd977c1dc4b57a66a648f0e31239f"], ["0x1014bd40ff89667c44d8a595605b38a356df627868058a1e8af5138e3a72ab8a", "0x263c3c87ea6fd61d1342aef64433c6e4b41bbd18e5d080c368ae4a75e52294e5", "0x2f3f0598b1515936a2264142b9604aa265af34d6ca01d4f7681730e3596de282", "0x259d2cc2070ef1e119dd360cff634596dcec0eac491255b179e3f60f061851ed"], ["0x08c0faa717e61123d4a3ad0db6393d1ed693d9cf00dad4abc4b6142ccf0ab8c1", "0x00ea39a2eb2110e5d35078254e1f78ad0264536724a138c73dc1ad82baddc9b0", "0x088ea7cd57f54ec021ab9ec44eded1ebf632074a263a4582e0eb9c3a8d61015d", "0x13781090eefc71f8866014f596ce8b19ca2c1bec14b0febae94afaefa61abcda"], ["0x1de326c668b974416df94eb1cbd52ca3382d01b2a99f5c7a66f02a06bd914e5b", "0x012f770fb714ee936301fa5985fa455a9515b4a3653d4704c565c065550eba73", "0x1905966363ee081741d42c57e6e32d1edaf66dbe7ad2ef5209d93f22cc5bea26", "0x2e231d8a973b5e1aaa031bcad78d78422a554a9b222260a298f5c9cadc28f055"], ["0x0d658d1c02a33baf64772aeb4d742bea4ee1cf48927bdbab7aefe0305b429882", "0x091189aa1b18d2b9630fae7d78b8f35521f363cdf2156e7205028d4382bcf21c", "0x060e9aa7379aee6e8237e4ac4667dbc0b4ab21474f3917098f3668320ebac4ca", "0x18a4babbb5a29f0c9c7a3103d0a6ae74c0f200f94f8c3fafa555d414221810cc"], ["0x25829e78bca68b27ccbd50b939663bb824ddc769b5ade103f47981d498e611f4", "0x04be4e130ee5c50b67008ee822e749b1ebfbd27e4e130ae4e057b5c3ca3af1e2", "0x1e58e9fb6e34e85f07ece0f0291a1146aafcee7cadb5f5d07afed0be5083414c", "0x1cd9b82db8bef6e9d9723cc08f091c05d12c5ac53b34338d410f64b121248f24"], ["0x00438514138dd94466d1eeaf5c3a37dd328d4d6c53f0dd840098d389cc3b9935", "0x0f1ddababb76186f73ace58bbad9f04f03f7cef79a0ca8cfc351f75538e03d34", "0x161496532a6013a097eadff233e5b1e991c714e10ce30f225fbf067600857fe2", "0x2b7647dba6bd214bdc9cad774707a3412f95a42d0a0909203f01582011e108f7"], ["0x14b2078c71e734a5453dffae534e839ae093a2f76fd7000850026c74eb88aaf9", "0x112d8e93712df54fbfdb32e28accf835b98e1c977f356a83f6cc8d2d6aa8b35d", "0x105d39db1fb96a2dd632c5a324b7b0bb5e408c1058629b56a83e9e0670141f26", "0x03b5e2b56aa8bb807f06206990bd057261fbdc92dd77c9c94794191fe6191296"], ["0x094314f054c74804985dc9abe471453c606b4d61713ceab1d91b733ff2620f73", "0x04d1a25ea657a35d3ee8310f9e89eb616761e683967132016c869ee7c9d952f1", "0x2742d4264abd9ccf915df77546f58ad148e4ad5bc85dd378f059de5f777bf0a8", "0x14211b61db9ec1a196eb5aa943d825e7518df61acb0da88daaae42c38687ed9d"], ["0x07d58315572a13d53dde17de6c036c1db1fd2d617d6624c0ab8cf52c7d86ceeb", "0x28ce6b9b39f8f8bb56b83d695c781c0f384861615cfcfc6cba9cdc628ddf4379", "0x1a2f86f697642ad7344423e3c3b804a537029e0d6b35ad71159501d7abd1ddca", "0x19508c062e87866acf7ae4538a813ec72aa46cd2418773e21f1f4357c68aa64e"], ["0x151f175740db13dd04cf0dc5b7c31d7a63c62658d6c271b39e45ca4203a83717", "0x179f6ef310d00351671bd2d45694a4e4ecb6d851013093a1d71aea902bbf0fe0", "0x23bb58e43cc3aab0d9551d8a3aaa738e7dbfe18ecdf9e1547d9ebba7eb857b00", "0x12808109138b430f3c95babedcc06d9405f733e99e59555f269bbe362cf02d05"], ["0x29f9bccf95a239e904d930143e30814c2da6c54488e041281878c0dddc4d80a9", "0x0417e51dc9a2edb93d4178283281bb61cbcd1dd18664480db42aa7d0ea775e9f", "0x253d9a0c2778726fec94ab4fc9fbb366925f5e4b743f3f0dfba6f8bad023d597", "0x00de918bff40042413388c2fba6ef6e49981c223de46ece9deea6e9d4c05b90a"], ["0x2dc2448faa02c72ca4681d6e242b03e45f6d79d0b17793c06b69c8506b9ad664", "0x02730f6dfe24f3dbf3b546453940bee81e84857b6b6925779f5c3bfc0528ee78", "0x0b4676cf9fab73bf4888ff665c8034a4bafdb66f7f9ed7a9b869d81d8f1c482a", "0x0dc2e27c2deb9dfd5c56dc3e5f57cb708c53aa78a05a493433c478488d36ab5d"], ["0x26c22c0079d4d6d5782764b09c498da4fbcbb82ddd7ee248b87d2253ac635e78", "0x27d24bfceaede42bb91cef44ebeca2cb713316522c820d408139cc2644449439", "0x2223371942b24e38094401ad87615b2cbff197fd6eea7f5fa03e0541d3de1c77", "0x0561f0732711c9ae78c037eb3e64737e173908f1207b7b4b43183865321d9fd3"], ["0x167b60855de3b89a296fc1b807a11fa006e07695fa029620266cb9e19d78e9d5", "0x2ea7363dac1aa94e8ac783866ec854c34659178b9cedf09261233715357fd85f", "0x28f74de7b7fa7600fcf803c6f6269d215a011fc0dc5bfc62ac5d169d7462a81f", "0x1a77c70fa8141a5fb5fa4f70059fb15a5611a28f73d20c27b965ffbd37fe8271"], ["0x0fe24a67410f52062c5357e1962148bc265ab9276805f52ec3ae0f8d5aec1d7d", "0x08499ff3e2c0646b42482a8a2158481354d619b424f1e5aa9a4e55dfad1bfcb8", "0x2fbc166d5d041d81974cf469f19515df9656698aad3dfe860bd77813e73ed75a", "0x16e1fc0d2d5ab9ffb40ead1457c6f21c1130abf2d1a5b70aae01a8c39a379bf2"]]; + let proof = "0x21af6dfb2b29dd048284622fbed6f639af85c4ac3af74cc6fb133edccfec00d221c6f12a978300d8e0940ce6a70be2a975f85f919b256cdad8af39dfbb2e5633262a511846d7c36813e8fd93ddb4d5dce0fa674ee8e0d2d8a3610dad077c2d01181ad527c13670663fbbcebc45ebbdc26db1c1b966bb2b1daa30aa0ee8822d751fe3cb769450068b2ba8b278a67219120bead661f7e1e3436d8ffb1593ae1b781b5231958b5679c3e606c0a45fed53bd238970fa2a29b3de36c66cde2387532c20dfb9e9f96a4132ff64e4be0ef0e2cd8a297b6bbfcfbf30f259f30cd09c8812199d4ef1f2eacccde0615888d5cd6ffb4e9fd7f926965b45b5374e4453c9d6a41247dbde4ccf7d6a0cab5904bdc280887fc4986effe5a7870c03b6981379cddf2ff5194c0f6051a35f261edc122ba1af871ebeb26d218a2e90f615c2476842a401860b7a14d494f3bf8a978a94e7ba33c228a557b0d8a68134104f26d7d5e28727de1aeacfd27f036a55e27671dfab0f23e91224e49e20f321f92fd71c1db14125a2d758b5904b770a04a2108882806276eb66ed53fdf447a14db947962f18e806314c0054cbc63fe7f09be1f3bb12d51f88c929d3427be228b429862d05e47a0f8a79fcf2f42dac01d6c3e2e11ebb10a7b968d4cf4381a6a8441d72e06c63c22609775b3632c585a3c8bbfc196b61c67647c8d99bf8a231b5a63631f7d6905d02b8058ed98e7ced80a197584deeaaa7eec71faae86597c8af28b89881f2ae48291b2a2910c5fdc55d8c3b32550c2c8b2521b79b2b8d1c72fd7944fae406fbd41161395eb22165021abe8a2de678ef762fe7472c2b2ca2ddd1c56a1d3ce96e5f0341908e5e60235f35d9c2878b5a85f3cab9a47b995e9fe2d620347757550e2826a62781769705aab2bb43d8f48caa9e240c139e42f19e09e975ae2dfff14ea402b2d60620ef454df798f75c774d8d0c600c7971d26fb8bfe1c3ac3c70b1518e07369abc80f24fa43eb0cd727dfeb447951cd145783a5d5e408cc1a957d06bc200814b7b560ff68b446ed771ce0e546a99cf90c4b986e092cbce62274f2daed52ba401a4998506c297994222b1c7ef46710b478716e12826a554d9135e77bba811c97422c9d6ffcd0840142b31aeefbf4606ac82ef0c1de3c92a80ade977827c042be1d2b71bc6a26cb562c2cab235e3151a6f558f8b2a3c36057e7ca156c0d01ab71f936dadda8d07b3b6097ef7897a8dc8ced1b3ca389f80226e150ed81c89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b2826784994700a83b1fd1fa9305a2c94a5ee07b574dd147ff33734940a8e501f9d4b0a044a12a4d54c67f95c82df26a305ae34db93df5bb31a9aff16eab4e7168608c85a0739677a84d3e7a3d349e896d7ebb8e187f6fec0e56cacaef1e42b2f9f9b42d8c4ad7d9218ceea187ea44b9345d9807d1f939e01de2629345f4b6123b3e1d44a95d45af0db23379a5ce4a6fdcdbefcfb2513d0d8dcb1d74a583a371150ac2893138b7abb1988643ca711eb04bd7c70dc2d8bd1e101a44b213c10072acb4b5ac3eafa1ede3658baa7ad8630905b1835043e34ae2b2fb0443237b979071df42ff1c3de6c8cf3fb0b60d5686743dcd6b2ac58df7c5f5673f73e0f8f5f02f3105b4dd216e35906b92cd7c739246fa224ef45e9f6f6deb8c7243a8516611747e2abebd7d76b038e28b23ee4fa32ce6339ee16e56aeeb35b9c071966d51118e9944866ed2f38e0ba90110f95bce39e7302aa1ada45818cbdece24b11f5e116122ccb089124bcbd7bf17c3b4204235cd82c4fac82504312398d1fa3e379921f5183d00b4118efc35ac57f8c9f7c19b3715413cc55164ff38c772279bcfe8204be58add7c374b7eb036b2dedcfe8c3888bd3bddc794e668d375d173668b3c70024d6e637cac554d85b090ea92e72dd0e47168df6ec9ba2ca977541266e63790709851223f603e57004bbaa63fa4299b8a5bd38de3a10cbc0f363d993c9262f11fb8ebb31fccbc5dd56cba701b2f503edddc15f4ac9e8a128850f2674996e1516f80de5d724d914fdfeabb137a9468b4ce430fee114998254d6021eeef132832554ddf326c8f2c92f0ec1100497347f47adcf0656e2dcb531736e6ebd136ddc0a0080e1787b638b7d08d552830d4357b7535db7e91f431f3e29817611a92e42119f44a6b76a48d73ee79f5bcd5420a2d1a6eff6e0f7bb2a5a491367727adbf4"; + + let ret = wasm.plonk_verify_shuffle(verifier_params, inputs, outputs, proof); + console.log(ret) +} \ No newline at end of file diff --git a/wasm/src/anemoi.rs b/wasm/src/anemoi.rs new file mode 100644 index 0000000..e237923 --- /dev/null +++ b/wasm/src/anemoi.rs @@ -0,0 +1,20 @@ +use alloc::{string::String, vec::Vec}; +use ark_bn254::Fr; +use ark_ff::{BigInteger, PrimeField}; +use uzkge::anemoi::{AnemoiJive, AnemoiJive254}; +use wasm_bindgen::prelude::wasm_bindgen; + +#[wasm_bindgen] +pub fn anemoi_hash(datas: Vec) -> String { + let mut inputs: Vec = Vec::new(); + for data in datas { + let input = + hex::decode(data.strip_prefix("0x").unwrap_or(&data)).expect("hex decode data error"); + let input = Fr::from_be_bytes_mod_order(&input); + inputs.push(input); + } + + let res = AnemoiJive254::eval_variable_length_hash(&inputs); + + format!("0x{}", hex::encode(res.into_bigint().to_bytes_be())) +} diff --git a/wasm/src/ed_on_bn254.rs b/wasm/src/ed_on_bn254.rs new file mode 100644 index 0000000..73bc60a --- /dev/null +++ b/wasm/src/ed_on_bn254.rs @@ -0,0 +1,53 @@ +use alloc::string::String; +use ark_ec::{AffineRepr, CurveGroup}; +use ark_ed_on_bn254::{EdwardsAffine, Fq, Fr}; +use ark_ff::{BigInteger, PrimeField}; +use wasm_bindgen::prelude::wasm_bindgen; + +#[wasm_bindgen] +pub fn point_add(x1: String, y1: String, x2: String, y2: String) -> String { + let x1 = hex::decode(x1.strip_prefix("0x").unwrap_or(&x1)).expect("hex decode x1 error"); + let x_1 = Fq::from_be_bytes_mod_order(&x1); + + let y1 = hex::decode(y1.strip_prefix("0x").unwrap_or(&y1)).expect("hex decode y1 error"); + let y_1 = Fq::from_be_bytes_mod_order(&y1); + + let x2 = hex::decode(x2.strip_prefix("0x").unwrap_or(&x2)).expect("hex decode x2 error"); + let x_2 = Fq::from_be_bytes_mod_order(&x2); + + let y2 = hex::decode(y2.strip_prefix("0x").unwrap_or(&y2)).expect("hex decode y2 error"); + let y_2 = Fq::from_be_bytes_mod_order(&y2); + + let mut ret = [0u8; 64]; + let p1 = EdwardsAffine::new(x_1, y_1); + let p2 = EdwardsAffine::new(x_2, y_2); + let p3 = p1 + p2; + + if let Some((r_x, r_y)) = p3.into_affine().xy() { + ret[0..32].copy_from_slice(&r_x.into_bigint().to_bytes_be()); + ret[32..64].copy_from_slice(&r_y.into_bigint().to_bytes_be()); + } + format!("0x{}", hex::encode(ret.to_vec())) +} + +#[wasm_bindgen] +pub fn scalar_mul(s: String, x: String, y: String) -> String { + let s = hex::decode(s.strip_prefix("0x").unwrap_or(&s)).expect("hex decode s error"); + let s = Fr::from_be_bytes_mod_order(&s); + + let x = hex::decode(x.strip_prefix("0x").unwrap_or(&x)).expect("hex decode s error"); + let x = Fq::from_be_bytes_mod_order(&x); + + let y = hex::decode(y.strip_prefix("0x").unwrap_or(&y)).expect("hex decode s error"); + let y = Fq::from_be_bytes_mod_order(&y); + + let mut ret = [0u8; 64]; + let p = EdwardsAffine::new(x, y); + let p2 = p * s; + + if let Some((r_x, r_y)) = p2.into_affine().xy() { + ret[0..32].copy_from_slice(&r_x.into_bigint().to_bytes_be()); + ret[32..64].copy_from_slice(&r_y.into_bigint().to_bytes_be()); + } + format!("0x{}", hex::encode(ret.to_vec())) +} diff --git a/wasm/src/lib.rs b/wasm/src/lib.rs new file mode 100644 index 0000000..82ea1a4 --- /dev/null +++ b/wasm/src/lib.rs @@ -0,0 +1,9 @@ +extern crate alloc; + +pub mod ed_on_bn254; + +pub mod anemoi; + +pub mod shuffle; + +pub mod matchmaking; diff --git a/wasm/src/matchmaking.rs b/wasm/src/matchmaking.rs new file mode 100644 index 0000000..8d736ca --- /dev/null +++ b/wasm/src/matchmaking.rs @@ -0,0 +1,164 @@ +use alloc::{format, string::String, vec::Vec}; +use ark_bn254::Fr; +use ark_ff::{BigInteger, PrimeField}; +use ethabi::Token; +use rand_chacha::{rand_core::SeedableRng, ChaChaRng}; +use uzkge::{ + anemoi::{AnemoiJive, AnemoiJive254}, + gen_params::VerifierParams, +}; +use wasm_bindgen::prelude::wasm_bindgen; +use zmatchmaking::{ + build_cs::{prove_matchmaking, verify_matchmaking, Proof}, + gen_params::{gen_prover_params, get_verifier_params}, +}; + +#[wasm_bindgen] +pub fn verifier_matchmaking_params() -> String { + let param = get_verifier_params().unwrap(); + + format!("0x{}", hex::encode(bincode::serialize(¶m).unwrap())) +} + +#[wasm_bindgen] +pub fn generate_matchmaking_proof( + verifier_params: String, + rng_seed: String, + inputs: Vec, + committed_seed: String, + random_number: String, +) -> String { + let verifier_params = { + hex::decode( + verifier_params + .strip_prefix("0x") + .unwrap_or(&verifier_params), + ) + .expect("hex decode verifier_params error") + }; + + let rng_seed = { + hex::decode(rng_seed.strip_prefix("0x").unwrap_or(&rng_seed)) + .expect("hex decode rng_seed error") + .try_into() + .unwrap() + }; + let mut rng = ChaChaRng::from_seed(rng_seed); + + let mut input_param = Vec::new(); + for (index, input) in inputs.iter().enumerate() { + let data = hex::decode(input.strip_prefix("0x").unwrap_or(&input)) + .expect(&format!("hex decode {} input error", index)); + let input = Fr::from_be_bytes_mod_order(&data); + input_param.push(input) + } + + let committed_seed = { + let data = hex::decode(committed_seed.strip_prefix("0x").unwrap_or(&committed_seed)) + .expect("hex decode committed_seed error"); + Fr::from_be_bytes_mod_order(&data) + }; + + let committment = AnemoiJive254::eval_variable_length_hash(&[committed_seed]); + + let random_number = { + let data = hex::decode(random_number.strip_prefix("0x").unwrap_or(&random_number)) + .expect("hex decode random_number error"); + Fr::from_be_bytes_mod_order(&data) + }; + + let (proof, outputs) = prove_matchmaking( + &mut rng, + &input_param, + &committed_seed, + &random_number, + &gen_prover_params().unwrap(), + ) + .unwrap(); + + let proof = bincode::serialize(&proof).unwrap(); + + let data = ethabi::encode(&[ + Token::Bytes(verifier_params), + Token::Array( + input_param + .iter() + .map(|v| Token::Bytes(v.into_bigint().to_bytes_be())) + .collect::>(), + ), + Token::Array( + outputs + .iter() + .map(|v| Token::Bytes(v.into_bigint().to_bytes_be())) + .collect::>(), + ), + Token::Bytes(committment.into_bigint().to_bytes_be()), + Token::Bytes(random_number.into_bigint().to_bytes_be()), + Token::Bytes(proof), + ]); + format!("0x{}", hex::encode(data)) +} + +#[wasm_bindgen] +pub fn plonk_verify_matchmaking( + verifier_params: String, + inputs: Vec, + outputs: Vec, + commitment: String, + random_number: String, + proof: String, +) -> bool { + let verifier_params: VerifierParams = { + let data = hex::decode( + verifier_params + .strip_prefix("0x") + .unwrap_or(&verifier_params), + ) + .expect("hex decode verifier_params error"); + bincode::deserialize(&data).expect("bincode deserialize verifier_params error") + }; + + let mut input_param = Vec::new(); + for (index, input) in inputs.iter().enumerate() { + let data = hex::decode(input.strip_prefix("0x").unwrap_or(&input)) + .expect(&format!("hex decode {} input error", index)); + let input = Fr::from_be_bytes_mod_order(&data); + input_param.push(input) + } + + let mut output_param = Vec::new(); + for (index, output) in outputs.iter().enumerate() { + let data = hex::decode(output.strip_prefix("0x").unwrap_or(&output)) + .expect(&format!("hex decode {} output error", index)); + let output = Fr::from_be_bytes_mod_order(&data); + output_param.push(output) + } + + let commitment = { + let data = hex::decode(commitment.strip_prefix("0x").unwrap_or(&commitment)) + .expect("hex decode commitment error"); + Fr::from_be_bytes_mod_order(&data) + }; + + let random_number = { + let data = hex::decode(random_number.strip_prefix("0x").unwrap_or(&random_number)) + .expect("hex decode random_number error"); + Fr::from_be_bytes_mod_order(&data) + }; + + let proof: Proof = { + let data = hex::decode(proof.strip_prefix("0x").unwrap_or(&proof)) + .expect("hex decode proof error"); + bincode::deserialize(&data).expect("bincode deserialize proof error") + }; + + verify_matchmaking( + &verifier_params, + &input_param, + &output_param, + &commitment, + &random_number, + &proof, + ) + .is_ok() +} diff --git a/wasm/src/shuffle.rs b/wasm/src/shuffle.rs new file mode 100644 index 0000000..69faa7a --- /dev/null +++ b/wasm/src/shuffle.rs @@ -0,0 +1,188 @@ +use alloc::{format, string::String, vec::Vec}; +use ark_ec::{AffineRepr, CurveGroup}; +use ark_ed_on_bn254::{EdwardsAffine, EdwardsProjective, Fq}; +use ark_ff::{BigInteger, PrimeField}; +use ark_serialize::{CanonicalDeserialize, Compress, Validate}; +use ethabi::Token; +use rand_chacha::{rand_core::SeedableRng, ChaChaRng}; +use uzkge::gen_params::VerifierParams; +use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; +use zshuffle::{ + build_cs::{prove_shuffle, verify_shuffle, ShuffleProof, TurboCS}, + gen_params::{ + gen_shuffle_prover_params, get_shuffle_verifier_params, refresh_prover_params_public_key, + }, + keygen::PublicKey, + MaskedCard, +}; + +fn bytes_2_masked_card(cards: &[Vec]) -> Option { + let e1: EdwardsProjective = { + let x = Fq::from_be_bytes_mod_order(cards.first()?); + let y = Fq::from_be_bytes_mod_order(cards.get(1)?); + let affine = EdwardsAffine::new(x, y); + affine.into() + }; + + let e2: EdwardsProjective = { + let x = Fq::from_be_bytes_mod_order(cards.get(2)?); + let y = Fq::from_be_bytes_mod_order(cards.get(3)?); + let affine = EdwardsAffine::new(x, y); + affine.into() + }; + Some(MaskedCard { e1, e2 }) +} + +pub fn point_to_uncompress>( + point: &G, +) -> (Vec, Vec) { + let affine = G::Affine::from(*point); + let (x, y) = affine.xy().unwrap(); + (x.into_bigint().to_bytes_be(), y.into_bigint().to_bytes_be()) +} + +#[wasm_bindgen] +pub fn generate_shuffle_proof( + rng_seed: String, + pk: String, + inputs: Vec, + n_cards: u32, +) -> String { + let rng_seed = { + hex::decode(rng_seed.strip_prefix("0x").unwrap_or(&rng_seed)) + .expect("hex decode rng_seed error") + .try_into() + .unwrap() + }; + let mut rng = ChaChaRng::from_seed(rng_seed); + + let pk = { + let pk = hex::decode(pk.strip_prefix("0x").unwrap_or(&pk)).unwrap(); + PublicKey::deserialize_with_mode(&pk[..], Compress::Yes, Validate::Yes).unwrap() + }; + + let mut inputs_cards = Vec::new(); + for (i, cards) in inputs.iter().enumerate() { + let cards: Vec = serde_wasm_bindgen::from_value(cards.clone()).unwrap(); + let mut card_param = Vec::new(); + for (j, card) in cards.iter().enumerate() { + let data = hex::decode(card.strip_prefix("0x").unwrap_or(&card)) + .expect(&format!("hex decode {} {} input error", i, j)); + card_param.push(data) + } + let input = + bytes_2_masked_card(&card_param).expect(&format!("hex decode {} input error", i)); + inputs_cards.push(input) + } + + let mut prover_params = gen_shuffle_prover_params(n_cards as usize).unwrap(); + + refresh_prover_params_public_key(&mut prover_params, &pk).unwrap(); + + let mut verifier_params = get_shuffle_verifier_params(n_cards as usize).unwrap(); + verifier_params.verifier_params = prover_params.prover_params.verifier_params.clone(); + + // Alice, start shuffling. + let (proof, output_cards) = + prove_shuffle(&mut rng, &pk, &inputs_cards, &prover_params).unwrap(); + + let proof = proof.to_bytes_be(); + + let verifier_params = bincode::serialize(&verifier_params).unwrap(); + let deck = { + let mut ret = Vec::new(); + for it in inputs_cards.iter() { + let mut tmp = Vec::new(); + + let (x, y) = point_to_uncompress(&it.e1); + tmp.push(Token::Bytes(x)); + tmp.push(Token::Bytes(y)); + + let (x, y) = point_to_uncompress(&it.e2); + tmp.push(Token::Bytes(x)); + tmp.push(Token::Bytes(y)); + ret.push(Token::Array(tmp)) + } + ret + }; + + let alice_shuffle_deck = { + let mut ret = Vec::new(); + for it in output_cards.iter() { + let mut tmp = Vec::new(); + + let (x, y) = point_to_uncompress(&it.e1); + tmp.push(Token::Bytes(x)); + tmp.push(Token::Bytes(y)); + + let (x, y) = point_to_uncompress(&it.e2); + tmp.push(Token::Bytes(x)); + tmp.push(Token::Bytes(y)); + ret.push(Token::Array(tmp)) + } + ret + }; + + let data = ethabi::encode(&[ + Token::Bytes(verifier_params), + Token::Array(deck), + Token::Array(alice_shuffle_deck), + Token::Bytes(proof), + ]); + format!("0x{}", hex::encode(data)) +} + +#[wasm_bindgen] +pub fn plonk_verify_shuffle( + verifier_params: String, + inputs: Vec, + outputs: Vec, + proof: String, +) -> bool { + let verifier_params: VerifierParams = { + let data = hex::decode( + verifier_params + .strip_prefix("0x") + .unwrap_or(&verifier_params), + ) + .expect("hex decode verifier_params error"); + bincode::deserialize(&data).expect("bincode deserialize verifier_params error") + }; + + let mut input_param = Vec::new(); + for (i, cards) in inputs.iter().enumerate() { + let cards: Vec = serde_wasm_bindgen::from_value(cards.clone()).unwrap(); + let mut card_param = Vec::new(); + for (j, card) in cards.iter().enumerate() { + let data = hex::decode(card.strip_prefix("0x").unwrap_or(&card)) + .expect(&format!("hex decode {} {} input error", i, j)); + card_param.push(data) + } + let input = + bytes_2_masked_card(&card_param).expect(&format!("hex decode {} input error", i)); + input_param.push(input) + } + + let mut output_param = Vec::new(); + for (i, cards) in outputs.iter().enumerate() { + let cards: Vec = serde_wasm_bindgen::from_value(cards.clone()).unwrap(); + + let mut card_param = Vec::new(); + for (j, card) in cards.iter().enumerate() { + let data = hex::decode(card.strip_prefix("0x").unwrap_or(&card)) + .expect(&format!("hex decode {} {} output error", i, j)); + card_param.push(data) + } + let output = + bytes_2_masked_card(&card_param).expect(&format!("hex decode {} output error", i)); + output_param.push(output) + } + + let proof: ShuffleProof = { + let data = hex::decode(proof.strip_prefix("0x").unwrap_or(&proof)) + .expect("hex decode proof error"); + ShuffleProof::from_bytes_be::(&data).expect("ShuffleProof from_bytes_be error") + }; + + verify_shuffle(&verifier_params, &input_param, &output_param, &proof).is_ok() +} diff --git a/wasm/tests/web.rs b/wasm/tests/web.rs new file mode 100644 index 0000000..57a0f0a --- /dev/null +++ b/wasm/tests/web.rs @@ -0,0 +1,67 @@ +//! Test suite for the Web and headless browsers. + +#![cfg(target_arch = "wasm32")] + +extern crate wasm_bindgen_test; +use wasm_bindgen_test::*; +use web_sys::console::log_1; +use zshuffle_wasm::*; + +const CARD_NUM: i32 = 20; + +#[wasm_bindgen_test] +fn pass() { + init_prover_key(CARD_NUM); + + let key1 = generate_key().unwrap(); + let key2 = generate_key().unwrap(); + let key3 = generate_key().unwrap(); + let key4 = generate_key().unwrap(); + let key1: Keypair = serde_wasm_bindgen::from_value(key1).unwrap(); + let key2: Keypair = serde_wasm_bindgen::from_value(key2).unwrap(); + let key3: Keypair = serde_wasm_bindgen::from_value(key3).unwrap(); + let key4: Keypair = serde_wasm_bindgen::from_value(key4).unwrap(); + + let joint = [key1.public, key2.public, key3.public, key4.public]; + let joint_values = serde_wasm_bindgen::to_value(&joint).unwrap(); + let joint_pk = aggregate_keys(joint_values).unwrap(); + + // must do it before prov & verify. + // when joint pk changed, must do it again !!! + let pkc = refresh_joint_key(joint_pk.clone(), CARD_NUM).unwrap(); + + let init_deck = init_masked_cards(joint_pk.clone(), CARD_NUM).unwrap(); + let decks: Vec = serde_wasm_bindgen::from_value(init_deck).unwrap(); + let deck_cards: Vec = decks.iter().map(|v| v.card.clone()).collect(); + let first_deck = serde_wasm_bindgen::to_value(&deck_cards).unwrap(); + + let proof = shuffle_cards(joint_pk.clone(), first_deck.clone()).unwrap(); + let proof: ShuffledCardsWithProof = serde_wasm_bindgen::from_value(proof).unwrap(); + let cards = serde_wasm_bindgen::to_value(&proof.cards).unwrap(); + let res = + verify_shuffled_cards(first_deck.clone(), cards.clone(), proof.proof.clone()).unwrap(); + assert_eq!(res, true); + + log_1(&"PROOF:".into()); + log_1(&proof.proof.into()); + log_1(&"DECK1:".into()); + let deck1_v: Vec = serde_wasm_bindgen::from_value(first_deck).unwrap(); + for d in deck1_v { + log_1(&format!("\"{}\",", d.0).into()); + log_1(&format!("\"{}\",", d.1).into()); + log_1(&format!("\"{}\",", d.2).into()); + log_1(&format!("\"{}\",", d.3).into()); + } + log_1(&"DECK2:".into()); + let deck2_v: Vec = serde_wasm_bindgen::from_value(cards).unwrap(); + for d in deck2_v { + log_1(&format!("\"{}\",", d.0).into()); + log_1(&format!("\"{}\",", d.1).into()); + log_1(&format!("\"{}\",", d.2).into()); + log_1(&format!("\"{}\",", d.3).into()); + } + log_1(&"PKC:".into()); + for p in pkc { + log_1(&format!("\"{}\",", p).into()); + } +}