Commit 31471987 authored by John Doe's avatar John Doe
Browse files

Initial commit message

parents
node_modules
artifacts
cache
typechain-types
proofs
build
target
bin
package-lock.json
Protocol.md
yarn.lock
\ No newline at end of file
[package]
authors = [""]
compiler_version = "0.1"
[dependencies]
\ No newline at end of file
tx_in = [
"0x14ce11999f658466af477da8d73f549c0bb83b2f4e3c5d020662d321c7be1235",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725"
]
amount_public_in = "0x0000000000000000000000000000000000000000000000000000000000000000"
amount_public_out = "0x00000000000000000000000000000000000000000000000006f05b59d3b20000"
commitment_out = [
"0x216acaebb8aad63b870a974e1f9e78ae404da0dd9f8a209c003546b4f1d4e309",
"0x0b122c7b56a6e8e66be64e88f83ec2dc4a92038d1823622a0b3fdcf5bf026ba7",
"0x0c919c72f9e1f4343745ed25a81d64eac9be1a985ed7bd76c522daa881bbe7f1",
"0x0409604341f7a16a202f780e01f6e4b920e699c42091c3bba80bbde4badff707",
"0x2790046cc3aef47a53fbfaf2afa9931a7ee7ac6d20e2e4345f97fcb82902f981",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725"
]
recipient = "0x0000000000000000000000003C44CdDdB6a900fa2b585dd299e03d12FA4293BC"
oracle = "0x03fdabb754f4f499c12406532fc924264db1b70702888a191683157056334d61"
old_root = "0x2a19cec67ca39baec7fe767faff4ccd1272d15272012cf7bcbd9f2efa1b13a91"
new_root = "0x1868e63dbe4383339f1c07733bcbfeedfdc21eee06bd38b5caa9e3bba39e30b0"
secrets = [
"0x23fc83b5dfd2360d08f81dbe4c70d7b5b23489ed503866689860634e8a860326",
"0x03e13dbfea1ed899d34adb68441eedbe2c67a0acb0d1fbf933509433277f2625",
"0x06754d76d406db4404aacc070291ca9dc79259f2e0f032aee3e23a31bf6813ce",
"0x0081f735d11cacbb1d7a3806cad4d42eefc8fe1c80a997c4ec7d9ce6dbd281c4",
"0x1b4bb44a0f675188fc4baaa1d25524d93153babc05fa510058374be53f6aad19",
"0x1f18b1674675a226918d5b94fda0c5581d1ffe90f9e45cac87b1efe760514159",
"0x2198283c1c1bed29c594369c5d3d4856354b1cdbcbff11e96788fea593c5b538",
"0x1781798ae6e7ce06838d71215a86390125a3cb56da9278ac2830f95ef3a737e4",
"0x3045d37ede6526594c5f9cc62eb6a8040467c798a110da93470a692945281fbf",
"0x0a0ce922b4c4712cf4aad081893c1079a234b41e4f96e24c70c3d77563935ed5",
"0",
"0",
"0",
"0",
"0",
"0"
]
utxo_in = [
"0x2c171c1c30b48bac02f4119bd345ea0a0779b7f3ba004c0ab2879c0b073595aa",
"0x000000000000000000000000000000000000000000000000016345785d8a0000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x249a3db9022a60b9906e697030320bfb3f11ab1e37b7d8041819618a019f1cef",
"0x000000000000000000000000000000000000000000000000016345785d8a0000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x26d0f5f1d5a84e400e4d10b8416e2d381451078e4283326f6c8bfd811bfd3721",
"0x000000000000000000000000000000000000000000000000016345785d8a0000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x093a0616767cd7fc9f848b8b2450a2f0375b463d2bd45e112918031130b78907",
"0x000000000000000000000000000000000000000000000000016345785d8a0000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x174ed83459a38ad3da6d77b12c098097246dc168d9a6048e40ac2d10c5d90c37",
"0x000000000000000000000000000000000000000000000000016345785d8a0000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x2b6eb0c9fc47fa33cb6dd9ff821e8454ddbbce2870f7935e651c073573ff35b9",
"0x000000000000000000000000000000000000000000000000016345785d8a0000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x2503b4f82a3856134466af1eaf8d4ec0de2239a3adbfaba73efcb5115d15f0e2",
"0x000000000000000000000000000000000000000000000000016345785d8a0000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x20dc9f0f1f666e3d8dcc15b92acee020b277f73cc57702680e35d625920789a6",
"0x000000000000000000000000000000000000000000000000016345785d8a0000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x1a5af16ad2676a76b85a9ac48e1905cb8b65743934d79ba9cfe379ed0c800550",
"0x000000000000000000000000000000000000000000000000016345785d8a0000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x1042b81c2620a2948a99af3cb0b9b4a3c30ccab56a57dfbc966541dfe3a9ae56",
"0x000000000000000000000000000000000000000000000000016345785d8a0000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0"
]
utxo_out = [
"0x145212c73489bde1b234e3af6006436a89e1842fb46a3cefb842bfe5028cd107",
"0x000000000000000000000000000000000000000000000000016345785d8a0000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x094c0bc425de7057471653f1316651da62d86f6ab489fc8e0108c8051d45cc7a",
"0x000000000000000000000000000000000000000000000000016345785d8a0000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x193faf6a13fbaf7a378247b32b82728465fdf00f00ef941d9de0cce1b5788c68",
"0x000000000000000000000000000000000000000000000000016345785d8a0000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x098ddedde45057fe109b0f54b548b7a4062a51bb329889119b5e8aebca923f4c",
"0x000000000000000000000000000000000000000000000000016345785d8a0000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x13a420922863e36fa7ac6350616ea6f64c85b5ef12e26eb3ef773ae040aa6763",
"0x000000000000000000000000000000000000000000000000016345785d8a0000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0"
]
roots = [
"0x01985d26e37bd06ce89c91e9c7a5e39fe7fc3006d6d1808f79782c68d82d70a9",
"0x175021ede49ef7ce6667e9d6300685001c0fc9e9b038e9bd0260126d929f4c6a",
"0x1146734be4e804a2e35454888902835fa3a16937ddb454b199b1cfba2903f2f3",
"0x26be9e4c32c33d944576516a3dc594421bc450255ddfb2219b337d7b5988014e",
"0x01985d26e37bd06ce89c91e9c7a5e39fe7fc3006d6d1808f79782c68d82d70a9",
"0x175021ede49ef7ce6667e9d6300685001c0fc9e9b038e9bd0260126d929f4c6a",
"0x1146734be4e804a2e35454888902835fa3a16937ddb454b199b1cfba2903f2f3",
"0x26be9e4c32c33d944576516a3dc594421bc450255ddfb2219b337d7b5988014e",
"0x01985d26e37bd06ce89c91e9c7a5e39fe7fc3006d6d1808f79782c68d82d70a9",
"0x175021ede49ef7ce6667e9d6300685001c0fc9e9b038e9bd0260126d929f4c6a",
"0x1146734be4e804a2e35454888902835fa3a16937ddb454b199b1cfba2903f2f3",
"0x26be9e4c32c33d944576516a3dc594421bc450255ddfb2219b337d7b5988014e",
"0x01985d26e37bd06ce89c91e9c7a5e39fe7fc3006d6d1808f79782c68d82d70a9",
"0x175021ede49ef7ce6667e9d6300685001c0fc9e9b038e9bd0260126d929f4c6a",
"0x1146734be4e804a2e35454888902835fa3a16937ddb454b199b1cfba2903f2f3",
"0x26be9e4c32c33d944576516a3dc594421bc450255ddfb2219b337d7b5988014e",
"0x01985d26e37bd06ce89c91e9c7a5e39fe7fc3006d6d1808f79782c68d82d70a9",
"0x175021ede49ef7ce6667e9d6300685001c0fc9e9b038e9bd0260126d929f4c6a",
"0x1146734be4e804a2e35454888902835fa3a16937ddb454b199b1cfba2903f2f3",
"0x26be9e4c32c33d944576516a3dc594421bc450255ddfb2219b337d7b5988014e",
"0x01985d26e37bd06ce89c91e9c7a5e39fe7fc3006d6d1808f79782c68d82d70a9",
"0x175021ede49ef7ce6667e9d6300685001c0fc9e9b038e9bd0260126d929f4c6a",
"0x1146734be4e804a2e35454888902835fa3a16937ddb454b199b1cfba2903f2f3",
"0x26be9e4c32c33d944576516a3dc594421bc450255ddfb2219b337d7b5988014e",
"0x01985d26e37bd06ce89c91e9c7a5e39fe7fc3006d6d1808f79782c68d82d70a9",
"0x175021ede49ef7ce6667e9d6300685001c0fc9e9b038e9bd0260126d929f4c6a",
"0x1146734be4e804a2e35454888902835fa3a16937ddb454b199b1cfba2903f2f3",
"0x26be9e4c32c33d944576516a3dc594421bc450255ddfb2219b337d7b5988014e",
"0x01985d26e37bd06ce89c91e9c7a5e39fe7fc3006d6d1808f79782c68d82d70a9",
"0x175021ede49ef7ce6667e9d6300685001c0fc9e9b038e9bd0260126d929f4c6a",
"0x1146734be4e804a2e35454888902835fa3a16937ddb454b199b1cfba2903f2f3",
"0x26be9e4c32c33d944576516a3dc594421bc450255ddfb2219b337d7b5988014e",
"0x01985d26e37bd06ce89c91e9c7a5e39fe7fc3006d6d1808f79782c68d82d70a9",
"0x175021ede49ef7ce6667e9d6300685001c0fc9e9b038e9bd0260126d929f4c6a",
"0x1146734be4e804a2e35454888902835fa3a16937ddb454b199b1cfba2903f2f3",
"0x26be9e4c32c33d944576516a3dc594421bc450255ddfb2219b337d7b5988014e",
"0x01985d26e37bd06ce89c91e9c7a5e39fe7fc3006d6d1808f79782c68d82d70a9",
"0x175021ede49ef7ce6667e9d6300685001c0fc9e9b038e9bd0260126d929f4c6a",
"0x1146734be4e804a2e35454888902835fa3a16937ddb454b199b1cfba2903f2f3",
"0x26be9e4c32c33d944576516a3dc594421bc450255ddfb2219b337d7b5988014e",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0"
]
leaves = [
"0x0a27a4e40a242026b9ff931e02979663a308cb61019ce834ea16054ec2b494b6",
"0x01985d26e37bd06ce89c91e9c7a5e39fe7fc3006d6d1808f79782c68d82d70a9",
"0x214c02e7a7ab0bba26a8514d9490548308c0cebb189aa9a294f8f2065cb3f9be",
"0x2a19cec67ca39baec7fe767faff4ccd1272d15272012cf7bcbd9f2efa1b13a91",
"0x26223cabc71a72f7de5c55241ecbc790dd04934c3152fd2a5ea104d15ceef917",
"0x01985d26e37bd06ce89c91e9c7a5e39fe7fc3006d6d1808f79782c68d82d70a9",
"0x214c02e7a7ab0bba26a8514d9490548308c0cebb189aa9a294f8f2065cb3f9be",
"0x2a19cec67ca39baec7fe767faff4ccd1272d15272012cf7bcbd9f2efa1b13a91",
"0x092b1b51fcb279ae4772ebea09885fd8e54d742ceac780a2be91fc0f8639d783",
"0x01985d26e37bd06ce89c91e9c7a5e39fe7fc3006d6d1808f79782c68d82d70a9",
"0x214c02e7a7ab0bba26a8514d9490548308c0cebb189aa9a294f8f2065cb3f9be",
"0x2a19cec67ca39baec7fe767faff4ccd1272d15272012cf7bcbd9f2efa1b13a91",
"0x09c1f70995dd83f65dff7824ef2b82743db6638244273814fd8f451036d1f212",
"0x01985d26e37bd06ce89c91e9c7a5e39fe7fc3006d6d1808f79782c68d82d70a9",
"0x214c02e7a7ab0bba26a8514d9490548308c0cebb189aa9a294f8f2065cb3f9be",
"0x2a19cec67ca39baec7fe767faff4ccd1272d15272012cf7bcbd9f2efa1b13a91",
"0x14c78490d28f579676aeb622e93649322ba9e579a85951eb1d074e1a982fb4c7",
"0x01985d26e37bd06ce89c91e9c7a5e39fe7fc3006d6d1808f79782c68d82d70a9",
"0x214c02e7a7ab0bba26a8514d9490548308c0cebb189aa9a294f8f2065cb3f9be",
"0x2a19cec67ca39baec7fe767faff4ccd1272d15272012cf7bcbd9f2efa1b13a91",
"0x1b8fba317360a2956821a61f20957682c6301cb47ef81a305d904874ef89ded5",
"0x01985d26e37bd06ce89c91e9c7a5e39fe7fc3006d6d1808f79782c68d82d70a9",
"0x214c02e7a7ab0bba26a8514d9490548308c0cebb189aa9a294f8f2065cb3f9be",
"0x2a19cec67ca39baec7fe767faff4ccd1272d15272012cf7bcbd9f2efa1b13a91",
"0x01f17b7ece6103dc60321f3f697ac2ed18d727cd3bbfa8076ad694cd6736f0c5",
"0x01985d26e37bd06ce89c91e9c7a5e39fe7fc3006d6d1808f79782c68d82d70a9",
"0x214c02e7a7ab0bba26a8514d9490548308c0cebb189aa9a294f8f2065cb3f9be",
"0x2a19cec67ca39baec7fe767faff4ccd1272d15272012cf7bcbd9f2efa1b13a91",
"0x1b3e22a48ff8d3210c3e88fffdd6106c21c45e98be006960ccc036c5534c1062",
"0x01985d26e37bd06ce89c91e9c7a5e39fe7fc3006d6d1808f79782c68d82d70a9",
"0x214c02e7a7ab0bba26a8514d9490548308c0cebb189aa9a294f8f2065cb3f9be",
"0x2a19cec67ca39baec7fe767faff4ccd1272d15272012cf7bcbd9f2efa1b13a91",
"0x218b9743f32a1905964cf6361ecb4ca0d1005b93cc72a5772f7f3da5b1a91376",
"0x01985d26e37bd06ce89c91e9c7a5e39fe7fc3006d6d1808f79782c68d82d70a9",
"0x214c02e7a7ab0bba26a8514d9490548308c0cebb189aa9a294f8f2065cb3f9be",
"0x2a19cec67ca39baec7fe767faff4ccd1272d15272012cf7bcbd9f2efa1b13a91",
"0x2f87b0b0c7029eb603fec590b876281adb655bd8becbb67cdcf93b899e649e4c",
"0x01985d26e37bd06ce89c91e9c7a5e39fe7fc3006d6d1808f79782c68d82d70a9",
"0x214c02e7a7ab0bba26a8514d9490548308c0cebb189aa9a294f8f2065cb3f9be",
"0x2a19cec67ca39baec7fe767faff4ccd1272d15272012cf7bcbd9f2efa1b13a91",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0"
]
indexes = [
"0",
"0",
"0",
"0",
"1",
"0",
"0",
"0",
"2",
"0",
"0",
"0",
"3",
"0",
"0",
"0",
"4",
"0",
"0",
"0",
"5",
"0",
"0",
"0",
"6",
"0",
"0",
"0",
"7",
"0",
"0",
"0",
"8",
"0",
"0",
"0",
"9",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0"
]
hash_path = [
"0x26223cabc71a72f7de5c55241ecbc790dd04934c3152fd2a5ea104d15ceef917",
"0x0b2b4a2f0c77fab3d7f75ce53e97a3732d543d8d1323130b099b105588c0d430",
"0x1904edbdbe313ffb928b9babad092b2d10b45766b6081f6f646e505f461d881d",
"0x1a92ad0c1b929248d262c3a8b464939bfce772f7e4c83b5ee36f81d5c7debf71",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0x1f52888a486099a7e05f4e3986fbca71a77edb7ce37be12536c895905de75307",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0x1f52888a486099a7e05f4e3986fbca71a77edb7ce37be12536c895905de75307",
"0x0a27a4e40a242026b9ff931e02979663a308cb61019ce834ea16054ec2b494b6",
"0x0b2b4a2f0c77fab3d7f75ce53e97a3732d543d8d1323130b099b105588c0d430",
"0x1904edbdbe313ffb928b9babad092b2d10b45766b6081f6f646e505f461d881d",
"0x1a92ad0c1b929248d262c3a8b464939bfce772f7e4c83b5ee36f81d5c7debf71",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0x1f52888a486099a7e05f4e3986fbca71a77edb7ce37be12536c895905de75307",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0x1f52888a486099a7e05f4e3986fbca71a77edb7ce37be12536c895905de75307",
"0x09c1f70995dd83f65dff7824ef2b82743db6638244273814fd8f451036d1f212",
"0x011a19c1fb96ef6a8882210b9ff8df53658275c192d0e282fa1cde60bffc28cf",
"0x1904edbdbe313ffb928b9babad092b2d10b45766b6081f6f646e505f461d881d",
"0x1a92ad0c1b929248d262c3a8b464939bfce772f7e4c83b5ee36f81d5c7debf71",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0x1f52888a486099a7e05f4e3986fbca71a77edb7ce37be12536c895905de75307",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0x1f52888a486099a7e05f4e3986fbca71a77edb7ce37be12536c895905de75307",
"0x092b1b51fcb279ae4772ebea09885fd8e54d742ceac780a2be91fc0f8639d783",
"0x011a19c1fb96ef6a8882210b9ff8df53658275c192d0e282fa1cde60bffc28cf",
"0x1904edbdbe313ffb928b9babad092b2d10b45766b6081f6f646e505f461d881d",
"0x1a92ad0c1b929248d262c3a8b464939bfce772f7e4c83b5ee36f81d5c7debf71",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0x1f52888a486099a7e05f4e3986fbca71a77edb7ce37be12536c895905de75307",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0x1f52888a486099a7e05f4e3986fbca71a77edb7ce37be12536c895905de75307",
"0x1b8fba317360a2956821a61f20957682c6301cb47ef81a305d904874ef89ded5",
"0x032e08de6ae4b4da4cdacd6d33f7080f61d8a31366063aaa717286b89416c6b0",
"0x2b4e0049039b7b6668295dd860957fc13dfd952131ac50aff57253b3c166cbdf",
"0x1a92ad0c1b929248d262c3a8b464939bfce772f7e4c83b5ee36f81d5c7debf71",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0x1f52888a486099a7e05f4e3986fbca71a77edb7ce37be12536c895905de75307",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0x1f52888a486099a7e05f4e3986fbca71a77edb7ce37be12536c895905de75307",
"0x14c78490d28f579676aeb622e93649322ba9e579a85951eb1d074e1a982fb4c7",
"0x032e08de6ae4b4da4cdacd6d33f7080f61d8a31366063aaa717286b89416c6b0",
"0x2b4e0049039b7b6668295dd860957fc13dfd952131ac50aff57253b3c166cbdf",
"0x1a92ad0c1b929248d262c3a8b464939bfce772f7e4c83b5ee36f81d5c7debf71",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0x1f52888a486099a7e05f4e3986fbca71a77edb7ce37be12536c895905de75307",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0x1f52888a486099a7e05f4e3986fbca71a77edb7ce37be12536c895905de75307",
"0x1b3e22a48ff8d3210c3e88fffdd6106c21c45e98be006960ccc036c5534c1062",
"0x1fc8d48307659b8e8a280b40001ed1598f71fdc1b7400d9fb4a6b757214eaace",
"0x2b4e0049039b7b6668295dd860957fc13dfd952131ac50aff57253b3c166cbdf",
"0x1a92ad0c1b929248d262c3a8b464939bfce772f7e4c83b5ee36f81d5c7debf71",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0x1f52888a486099a7e05f4e3986fbca71a77edb7ce37be12536c895905de75307",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0x1f52888a486099a7e05f4e3986fbca71a77edb7ce37be12536c895905de75307",
"0x01f17b7ece6103dc60321f3f697ac2ed18d727cd3bbfa8076ad694cd6736f0c5",
"0x1fc8d48307659b8e8a280b40001ed1598f71fdc1b7400d9fb4a6b757214eaace",
"0x2b4e0049039b7b6668295dd860957fc13dfd952131ac50aff57253b3c166cbdf",
"0x1a92ad0c1b929248d262c3a8b464939bfce772f7e4c83b5ee36f81d5c7debf71",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0x1f52888a486099a7e05f4e3986fbca71a77edb7ce37be12536c895905de75307",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0x1f52888a486099a7e05f4e3986fbca71a77edb7ce37be12536c895905de75307",
"0x2f87b0b0c7029eb603fec590b876281adb655bd8becbb67cdcf93b899e649e4c",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x071c0081674e77639ba67d5f406601b1973c781881f5f9640e3e9f686e87e3b5",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0x1f52888a486099a7e05f4e3986fbca71a77edb7ce37be12536c895905de75307",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0x1f52888a486099a7e05f4e3986fbca71a77edb7ce37be12536c895905de75307",
"0x218b9743f32a1905964cf6361ecb4ca0d1005b93cc72a5772f7f3da5b1a91376",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x071c0081674e77639ba67d5f406601b1973c781881f5f9640e3e9f686e87e3b5",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0x1f52888a486099a7e05f4e3986fbca71a77edb7ce37be12536c895905de75307",
"0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
"0x232362acc9586b6f897824acd644faaff178ee5b1646afa8e5dec5668bc2cda7",
"0x229a4089c30cbdc834c672fe9b9dd544fdcad369f7a6d3b6519c616753b09dae",
"0x26786561b86e7e52ed730f31ccda670db12cf02ef521eeb8316dda79f6f46099",
"0x1f52888a486099a7e05f4e3986fbca71a77edb7ce37be12536c895905de75307",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0"
]
nullifier_hashes = [
"0x0c5a9ce50ae597c75d30e0e1f3b254ae94befc38c6f0645e4f16e4d04c7617e2",
"0x2869a09c481fa55e08c7608e507cc4eba76109a65eb2d2f128c064cfcd93a793",
"0x00939e1afd608c33a5034c8dece5d623fe4a5d006e30de9da22e605b40cc7a52",
"0x0e4c5d00dae00ae4425d4cb525321543f1aff498675e6dece9480dff17cffe1f",
"0x1f8723a5d7deb47d5a08e9b62fc58542d6e9f61c75d564b9be5513325b43c6f3",
"0x13f6979d19548241f5a6a3e5ccd0ba6a22e8c77c92ff7f69adb516486de13140",
"0x119dd9cd1dedb274808bef71a3d41c1897e393c038745eac249fe6f123b37a52",
"0x10090f1824fdc4dfb613e2b768e5164a5b3940b754e5a7d8924028e9159bd51e",
"0x00f23f383d68fd7f815ecb54d38bc2abb0806f5d75b803d6a07d6c27a4f9ea3b",
"0x0c294f84ceb8efe846beadcd0c85318d3f2baa0d2414964a18f084b4f303a736",
"0",
"0",
"0",
"0",
"0",
"0"
]
\ No newline at end of file
# Momiji testnet
Set membership/state transition using batched proofs in Noir
## Requirements
- Noir is based upon [Rust](https://www.rust-lang.org/tools/install), and we will need to Noir's package manager `nargo` in order to compile our circuits. Further installation instructions for can be found [here](https://noir-lang.org/getting_started/nargo_installation).
- Note: This version of the testnet was built using nargo 0.9.0; this is highly likely to change in future releases as Noir continues to grow.
- The Javascript tests and contracts live within a hardhat project, where we use [yarn](https://classic.yarnpkg.com/lang/en/docs/install/) as the package manager.
## Development
This repository contains an application that generates proofs of valid state transition and set membership using Pedersen-hash Merkle trees. This walkthrough will allow you to perform test transfers on a local testnet instance using a Solidity verifier.
Start by installing all the packages specified in the `package.json`
```shell
yarn install
```
For the initial Momiji testnet release, you should use nargo 0.9.0. Check which version you are using.
```shell
nargo --version
```
If not 0.9.0, install it.
```shell
noirup --version 0.9.0
```
After installing nargo it should be placed in our path and can be called from inside the folder. We will then compile our circuit and verifier. The contract tests will also run this step if needed.
```shell
npm run compile
```
### Solidity Verifier
Once we have compiled our program, we can generate a Solidity verifier rather than having to use the verifier provided by `nargo`.
This Solidity verifier can also be generated by calling `nargo codegen-verifier`. This will produce a Solidity verifier inside of the Noir project which you can then move into the correct `contracts` folder.
It is important to note that if you change your circuit and want to verify proofs in Solidity you must also regenerate your Solidity verifier. The verifier is based upon the circuit and if the circuit changes any previous verifier will be out of date.
### Running tests
The tests use the method of compiling the circuit using `nargo`. The tests also show how to complete proof verification using the Solidity verifier.
```
npm run test
```
You will also notice inputs in `Prover.toml` that satisfy the specified circuit constraints. This toml file will be automatically populated by the tests. You can run `nargo prove main` followed by `nargo verify main` to prove and verify a circuit natively. More info on the `nargo` commands can be found in the Noir documentation linked above or by running: `nargo --help` in your command line.
amount_public_in = "0x0000000000000000000000000000000000000000000000000000000000000000"
amount_public_out = "0x00000000000000000000000000000000000000000000000006f05b59d3b20000"
commitment_out = ["0x216acaebb8aad63b870a974e1f9e78ae404da0dd9f8a209c003546b4f1d4e309", "0x0b122c7b56a6e8e66be64e88f83ec2dc4a92038d1823622a0b3fdcf5bf026ba7", "0x0c919c72f9e1f4343745ed25a81d64eac9be1a985ed7bd76c522daa881bbe7f1", "0x0409604341f7a16a202f780e01f6e4b920e699c42091c3bba80bbde4badff707", "0x2790046cc3aef47a53fbfaf2afa9931a7ee7ac6d20e2e4345f97fcb82902f981", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720"]
new_root = "0x1868e63dbe4383339f1c07733bcbfeedfdc21eee06bd38b5caa9e3bba39e30b0"
nullifier_hashes = ["0x0c5a9ce50ae597c75d30e0e1f3b254ae94befc38c6f0645e4f16e4d04c7617e2", "0x2869a09c481fa55e08c7608e507cc4eba76109a65eb2d2f128c064cfcd93a793", "0x00939e1afd608c33a5034c8dece5d623fe4a5d006e30de9da22e605b40cc7a52", "0x0e4c5d00dae00ae4425d4cb525321543f1aff498675e6dece9480dff17cffe1f", "0x1f8723a5d7deb47d5a08e9b62fc58542d6e9f61c75d564b9be5513325b43c6f3", "0x13f6979d19548241f5a6a3e5ccd0ba6a22e8c77c92ff7f69adb516486de13140", "0x119dd9cd1dedb274808bef71a3d41c1897e393c038745eac249fe6f123b37a52", "0x10090f1824fdc4dfb613e2b768e5164a5b3940b754e5a7d8924028e9159bd51e", "0x00f23f383d68fd7f815ecb54d38bc2abb0806f5d75b803d6a07d6c27a4f9ea3b", "0x0c294f84ceb8efe846beadcd0c85318d3f2baa0d2414964a18f084b4f303a736", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000"]
old_root = "0x2a19cec67ca39baec7fe767faff4ccd1272d15272012cf7bcbd9f2efa1b13a91"
oracle = "0x03fdabb754f4f499c12406532fc924264db1b70702888a191683157056334d61"
recipient = "0x0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc"
tx_in = ["0x14ce11999f658466af477da8d73f549c0bb83b2f4e3c5d020662d321c7be1235", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720", "0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720"]
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;
// import "./IElasticERC20.sol";
/*
Offshift PureL1Rollup State Contract
Technical Preview Testnet
*/
struct BatchPublicInputs {
bytes32[16] tx_in;
bytes32 amount_public_in;
bytes32 amount_public_out;
bytes32[16] commitment_out;
bytes32 recipient;
bytes32 oracle;
bytes32 old_root;
bytes32 new_root;
bytes32[16] nullifier_hashes;
}
interface IVerifier {
function verify(
bytes calldata,
bytes32[] calldata
) external view returns (bool);
}
contract TechnicalPreview {
// IElasticIERC20 public token;
IVerifier public verifier;
bytes32[] public utxo;
bytes32[] public validRoots; // Valid
mapping(bytes32 => bool) public nullifierHashes; // Spent UTXO hashes
mapping(bytes32 => bool) public commitments; // Individual commitments
bytes32 public merkleRoot =
0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720;
constructor(IVerifier _verifier) {
// , address _token) {
verifier = _verifier;
// token = IElasticERC20(_token);
}
function publish(
bytes calldata _proof,
BatchPublicInputs calldata _batch
) public payable {
require(uint256(_batch.old_root) == uint256(merkleRoot), "invalid root");
require(verifier.verify(_proof, flattenBatchPublicInputs(_batch)), "invalid proof");
for (uint256 i = 0; i < _batch.nullifier_hashes.length; i++) {
if (_batch.nullifier_hashes[i] == 0) continue;
assert(!nullifierHashes[_batch.nullifier_hashes[i]]);
nullifierHashes[_batch.nullifier_hashes[i]] = true;
}
// Publish UTXO set
for (uint256 i = 0; i < _batch.commitment_out.length; i++) {
utxo.push(_batch.commitment_out[i]);
}
// token.mint(_batch.recipient, _batch.amount_public_out); // Process withdraw
require(msg.value == uint256(_batch.amount_public_in), "Incorrect input amount");
validRoots.push(_batch.new_root); // Add to valid roots
merkleRoot = _batch.new_root; // Update the root
(bool sent, ) = address(uint160(uint256(_batch.recipient))).call{value: uint256(_batch.amount_public_out)}("");
require(sent, "unbalanced reserves or gas griefed");
}
function verifyProof(
bytes calldata _proof,
bytes32[] memory _publicInputs
) public view returns (bool) {
return verifier.verify(_proof, _publicInputs);
}
function flattenBatchPublicInputs(
BatchPublicInputs memory input
) public pure returns (bytes32[] memory) {
bytes32[] memory flatArray = new bytes32[](54);
uint256 idx = 0;
for (uint i = 0; i < 16; i++) {
flatArray[idx++] = input.tx_in[i];
}
flatArray[idx++] = input.amount_public_in;
flatArray[idx++] = input.amount_public_out;
for (uint i = 0; i < 16; i++) {
flatArray[idx++] = input.commitment_out[i];
}
flatArray[idx++] = input.recipient;
flatArray[idx++] = input.oracle;
flatArray[idx++] = input.old_root;
flatArray[idx++] = input.new_root;
for (uint i = 0; i < 16; i++) {
flatArray[idx++] = input.nullifier_hashes[i];
}
return flatArray;
}
}
// Verification Key Hash: 853111d0050bebc76ee61ac45bff4349ec9c30e05c476203f4ae99c9d0293712
// SPDX-License-Identifier: Apache-2.0
// Copyright 2022 Aztec
pragma solidity >=0.8.4;
library UltraVerificationKey {
function verificationKeyHash() internal pure returns(bytes32) {
return 0x853111d0050bebc76ee61ac45bff4349ec9c30e05c476203f4ae99c9d0293712;
}
function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure {
assembly {
mstore(add(_vk, 0x00), 0x0000000000000000000000000000000000000000000000000000000000020000) // vk.circuit_size
mstore(add(_vk, 0x20), 0x0000000000000000000000000000000000000000000000000000000000000036) // vk.num_inputs
mstore(add(_vk, 0x40), 0x1bf82deba7d74902c3708cc6e70e61f30512eca95655210e276e5858ce8f58e5) // vk.work_root
mstore(add(_vk, 0x60), 0x30643640b9f82f90e83b698e5ea6179c7c05542e859533b48b9953a2f5360801) // vk.domain_inverse
mstore(add(_vk, 0x80), 0x0cc1ff085d727fcbd37286ac775564f43ce63e7e453465787d0affbc14e1d71c) // vk.Q1.x
mstore(add(_vk, 0xa0), 0x1cd31dc8e30aaa9d1490c984d99755adfebab6d93c24b891318f3aef7f06125f) // vk.Q1.y
mstore(add(_vk, 0xc0), 0x20c4570f33b316d4873c8183eb591016cf3cadd4be0829b7d649802608a03ac2) // vk.Q2.x
mstore(add(_vk, 0xe0), 0x2b869571d594d2f0d055ab74c4be1cac2bf625259f692c9b0a92fa31fdbe59de) // vk.Q2.y
mstore(add(_vk, 0x100), 0x01c28a8123d79723164b3e395ba833f1c772b5d26b3dd7821e933a98bb4505f1) // vk.Q3.x
mstore(add(_vk, 0x120), 0x1b7a16c7cfe59d5be4791e63d6d69997dfe5de6e8bbd442d9a4deaf88acbbfb6) // vk.Q3.y
mstore(add(_vk, 0x140), 0x1103d2feaa9139c7ba8094f877f8f21cc65ff0cec724513259be27821df719de) // vk.Q4.x
mstore(add(_vk, 0x160), 0x2b400a1f2aa2cad8420a12370fe95c0c8a30b57b86ff09b1d014771fc633c279) // vk.Q4.y
mstore(add(_vk, 0x180), 0x1bb9d84ae98458c1a55ed3bdb6f5a35d12d0782c8c8421186f5c2e7094ec07a6) // vk.Q_M.x
mstore(add(_vk, 0x1a0), 0x0514dcbe76d1c6326d9fcd5a40ead1b90b4a6140fda1205b6af4ac1b9dcf7a4d) // vk.Q_M.y
mstore(add(_vk, 0x1c0), 0x20735609f22c821510b6626e5ee03ccf201443320d3215e17a6bee74ca23608c) // vk.Q_C.x
mstore(add(_vk, 0x1e0), 0x1f5a5e6acca00bb1c1bb96513c6410772429a630ea364ff90ba3f9597ffa0dbe) // vk.Q_C.y
mstore(add(_vk, 0x200), 0x2aa8d146eee083c6904dbb64f0b7c0da61893c22b3d74e129cbeb57d208fbf4a) // vk.Q_ARITHMETIC.x
mstore(add(_vk, 0x220), 0x0ccff3d9e3170e4f21a27cfe912e75dcddb35f93f8351ba0a22e0a93da2e4dc8) // vk.Q_ARITHMETIC.y
mstore(add(_vk, 0x240), 0x0276ceefae739e2b46af42163b62ca77b5688d19589f1fe0e4827730d9f531f1) // vk.QSORT.x
mstore(add(_vk, 0x260), 0x04f4d9c75d6785220633afd055acbf361ab8274c957944d8157f50429c087a8f) // vk.QSORT.y
mstore(add(_vk, 0x280), 0x1f118bec13e048d6f947187a9f32e450a49acc387c24cb179fe64746a97c7eb8) // vk.Q_ELLIPTIC.x
mstore(add(_vk, 0x2a0), 0x0528ea7d973d16eaa69e8c90f96657e262b74cb5b5bb3f1f606cbfc8b21e7182) // vk.Q_ELLIPTIC.y
mstore(add(_vk, 0x2c0), 0x1414af76247139fa9e8fef8b393a3e03227ee3a6fedb1e55f5db82cb2352782a) // vk.Q_AUX.x
mstore(add(_vk, 0x2e0), 0x2c7895a68d2fab5b2bce4d7703daebf9011e63d675bc6898c7f06087d6d83d99) // vk.Q_AUX.y
mstore(add(_vk, 0x300), 0x128b67bde4622986792bcadd0549584fc0526d06dcc07645388368296108df25) // vk.SIGMA1.x
mstore(add(_vk, 0x320), 0x04a0c746360e0ce46c49b7ec7b239d2f36151ea6f06486bec4c342ebec06c325) // vk.SIGMA1.y
mstore(add(_vk, 0x340), 0x1c1230b6dbe7aa2538340b41f69effcb68550e3d98c33cafae053e4f3a6cce9a) // vk.SIGMA2.x
mstore(add(_vk, 0x360), 0x2074f7e506d1b5c198eac5f0922d9075f4cb9272c54c4ecd37ee31bef438e7df) // vk.SIGMA2.y
mstore(add(_vk, 0x380), 0x02b7ef0de4c55968f91a5dc9fb91637c8fe229710649226b28c9dbfd825e7b42) // vk.SIGMA3.x
mstore(add(_vk, 0x3a0), 0x0bab1622f7687c5b3ceac99597cf265db85756b50e10a72e10f6889e706be7ae) // vk.SIGMA3.y
mstore(add(_vk, 0x3c0), 0x187f2c513b2b299e9bcc20763814486157f79d46b2a8a6c1b12a759b23035f55) // vk.SIGMA4.x
mstore(add(_vk, 0x3e0), 0x0cfe2030e14e57f0b08d254fe93478d48935eaf24f64a59e4b2edcd3df0cc269) // vk.SIGMA4.y
mstore(add(_vk, 0x400), 0x1f085b2095ee26145e167f353ef9a02dde005b3ba11bf60add10bdd9c00e7643) // vk.TABLE1.x
mstore(add(_vk, 0x420), 0x0748759c43af1624acf605b6a23ebba01173cd346730c934d5fb7edd48413f94) // vk.TABLE1.y
mstore(add(_vk, 0x440), 0x2c8d2b9623692ab46021a60209f7148458ecb2ccdbbd766251f463ca7c53489a) // vk.TABLE2.x
mstore(add(_vk, 0x460), 0x1aefa543256fc4b49dc193383f0156f7c331a2b89d0a0b5938a2fe2abe136d19) // vk.TABLE2.y
mstore(add(_vk, 0x480), 0x058ea36a362c899e3304278eca9a52fa74b07588d35cc5583278237cbbb53d68) // vk.TABLE3.x
mstore(add(_vk, 0x4a0), 0x2afc5a5c85ca7b8fdac8a2b082096621e184e5a00a5cf1d481e28ad8071a691a) // vk.TABLE3.y
mstore(add(_vk, 0x4c0), 0x14864cbfc194228094a325c4abf8260dbdca65e4883fce1425ec2933843b6737) // vk.TABLE4.x
mstore(add(_vk, 0x4e0), 0x1489390b9b42c540c675cfea8acb88ceebe8c678f21ee8e8bee12af884fc1c3d) // vk.TABLE4.y
mstore(add(_vk, 0x500), 0x163dbf577ee1c54e7c4d605acee747bbb385eaead5cefc6f0aad717abb4c979f) // vk.TABLE_TYPE.x
mstore(add(_vk, 0x520), 0x103462cf8a7f5e47c4ff97572259305a367367d627a8df0a88b43112b80acfce) // vk.TABLE_TYPE.y
mstore(add(_vk, 0x540), 0x2ef30ac2e4dee5800398991d6a5a44864a08e2d6f56a8e4a4137ab8663d2afff) // vk.ID1.x
mstore(add(_vk, 0x560), 0x18defb06fb5b23a6d64969163baee52f3a522a807a5bf2bc5476dde282338d3e) // vk.ID1.y
mstore(add(_vk, 0x580), 0x0b9b393a9eca77ab29d27548a923bc59acaebd06f7d5aa67c62eb7a6372204bc) // vk.ID2.x
mstore(add(_vk, 0x5a0), 0x066d66fde666b84994ef1d6dd2575699e5c170162ea917741754f3da1f8174e3) // vk.ID2.y
mstore(add(_vk, 0x5c0), 0x27c75ee262ac195255ca4b8d5333af42b61a36674f6c5b27fd9363799fbeb9d6) // vk.ID3.x
mstore(add(_vk, 0x5e0), 0x179ab56fecca1e5c93742b476315043fc8ee10c534ebea463b5580ea28424f71) // vk.ID3.y
mstore(add(_vk, 0x600), 0x28491b73d2cf57ee8461543270c6b5da24c3ddec7bc5f72341f5050d4ef3d291) // vk.ID4.x
mstore(add(_vk, 0x620), 0x2611771e3fa77836aefd6649e88774530315b2fbc14c27fe5701853bc8b147be) // vk.ID4.y
mstore(add(_vk, 0x640), 0x00) // vk.contains_recursive_proof
mstore(add(_vk, 0x660), 0) // vk.recursive_proof_public_input_indices
mstore(add(_vk, 0x680), 0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1) // vk.g2_x.X.c1
mstore(add(_vk, 0x6a0), 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0) // vk.g2_x.X.c0
mstore(add(_vk, 0x6c0), 0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4) // vk.g2_x.Y.c1
mstore(add(_vk, 0x6e0), 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) // vk.g2_x.Y.c0
mstore(_omegaInverseLoc, 0x244cf010c43ca87237d8b00bf9dd50c4c01c7f086bd4e8c920e75251d96f0d22) // vk.work_root_inverse
}
}
}
/**
* @title Ultra Plonk proof verification contract
* @dev Top level Plonk proof verification contract, which allows Plonk proof to be verified
*/
abstract contract BaseUltraVerifier {
// VERIFICATION KEY MEMORY LOCATIONS
uint256 internal constant N_LOC = 0x380;
uint256 internal constant NUM_INPUTS_LOC = 0x3a0;
uint256 internal constant OMEGA_LOC = 0x3c0;
uint256 internal constant DOMAIN_INVERSE_LOC = 0x3e0;
uint256 internal constant Q1_X_LOC = 0x400;
uint256 internal constant Q1_Y_LOC = 0x420;
uint256 internal constant Q2_X_LOC = 0x440;
uint256 internal constant Q2_Y_LOC = 0x460;
uint256 internal constant Q3_X_LOC = 0x480;
uint256 internal constant Q3_Y_LOC = 0x4a0;
uint256 internal constant Q4_X_LOC = 0x4c0;
uint256 internal constant Q4_Y_LOC = 0x4e0;
uint256 internal constant QM_X_LOC = 0x500;
uint256 internal constant QM_Y_LOC = 0x520;
uint256 internal constant QC_X_LOC = 0x540;
uint256 internal constant QC_Y_LOC = 0x560;
uint256 internal constant QARITH_X_LOC = 0x580;
uint256 internal constant QARITH_Y_LOC = 0x5a0;
uint256 internal constant QSORT_X_LOC = 0x5c0;
uint256 internal constant QSORT_Y_LOC = 0x5e0;
uint256 internal constant QELLIPTIC_X_LOC = 0x600;
uint256 internal constant QELLIPTIC_Y_LOC = 0x620;
uint256 internal constant QAUX_X_LOC = 0x640;
uint256 internal constant QAUX_Y_LOC = 0x660;
uint256 internal constant SIGMA1_X_LOC = 0x680;
uint256 internal constant SIGMA1_Y_LOC = 0x6a0;
uint256 internal constant SIGMA2_X_LOC = 0x6c0;
uint256 internal constant SIGMA2_Y_LOC = 0x6e0;
uint256 internal constant SIGMA3_X_LOC = 0x700;
uint256 internal constant SIGMA3_Y_LOC = 0x720;
uint256 internal constant SIGMA4_X_LOC = 0x740;
uint256 internal constant SIGMA4_Y_LOC = 0x760;
uint256 internal constant TABLE1_X_LOC = 0x780;
uint256 internal constant TABLE1_Y_LOC = 0x7a0;
uint256 internal constant TABLE2_X_LOC = 0x7c0;
uint256 internal constant TABLE2_Y_LOC = 0x7e0;
uint256 internal constant TABLE3_X_LOC = 0x800;
uint256 internal constant TABLE3_Y_LOC = 0x820;
uint256 internal constant TABLE4_X_LOC = 0x840;
uint256 internal constant TABLE4_Y_LOC = 0x860;
uint256 internal constant TABLE_TYPE_X_LOC = 0x880;
uint256 internal constant TABLE_TYPE_Y_LOC = 0x8a0;
uint256 internal constant ID1_X_LOC = 0x8c0;
uint256 internal constant ID1_Y_LOC = 0x8e0;
uint256 internal constant ID2_X_LOC = 0x900;
uint256 internal constant ID2_Y_LOC = 0x920;
uint256 internal constant ID3_X_LOC = 0x940;
uint256 internal constant ID3_Y_LOC = 0x960;
uint256 internal constant ID4_X_LOC = 0x980;
uint256 internal constant ID4_Y_LOC = 0x9a0;
uint256 internal constant CONTAINS_RECURSIVE_PROOF_LOC = 0x9c0;
uint256 internal constant RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC = 0x9e0;
uint256 internal constant G2X_X0_LOC = 0xa00;
uint256 internal constant G2X_X1_LOC = 0xa20;
uint256 internal constant G2X_Y0_LOC = 0xa40;
uint256 internal constant G2X_Y1_LOC = 0xa60;
// ### PROOF DATA MEMORY LOCATIONS
uint256 internal constant W1_X_LOC = 0x1200;
uint256 internal constant W1_Y_LOC = 0x1220;
uint256 internal constant W2_X_LOC = 0x1240;
uint256 internal constant W2_Y_LOC = 0x1260;
uint256 internal constant W3_X_LOC = 0x1280;
uint256 internal constant W3_Y_LOC = 0x12a0;
uint256 internal constant W4_X_LOC = 0x12c0;
uint256 internal constant W4_Y_LOC = 0x12e0;
uint256 internal constant S_X_LOC = 0x1300;
uint256 internal constant S_Y_LOC = 0x1320;
uint256 internal constant Z_X_LOC = 0x1340;
uint256 internal constant Z_Y_LOC = 0x1360;
uint256 internal constant Z_LOOKUP_X_LOC = 0x1380;
uint256 internal constant Z_LOOKUP_Y_LOC = 0x13a0;
uint256 internal constant T1_X_LOC = 0x13c0;
uint256 internal constant T1_Y_LOC = 0x13e0;
uint256 internal constant T2_X_LOC = 0x1400;
uint256 internal constant T2_Y_LOC = 0x1420;
uint256 internal constant T3_X_LOC = 0x1440;
uint256 internal constant T3_Y_LOC = 0x1460;
uint256 internal constant T4_X_LOC = 0x1480;
uint256 internal constant T4_Y_LOC = 0x14a0;
uint256 internal constant W1_EVAL_LOC = 0x1600;
uint256 internal constant W2_EVAL_LOC = 0x1620;
uint256 internal constant W3_EVAL_LOC = 0x1640;
uint256 internal constant W4_EVAL_LOC = 0x1660;
uint256 internal constant S_EVAL_LOC = 0x1680;
uint256 internal constant Z_EVAL_LOC = 0x16a0;
uint256 internal constant Z_LOOKUP_EVAL_LOC = 0x16c0;
uint256 internal constant Q1_EVAL_LOC = 0x16e0;
uint256 internal constant Q2_EVAL_LOC = 0x1700;
uint256 internal constant Q3_EVAL_LOC = 0x1720;
uint256 internal constant Q4_EVAL_LOC = 0x1740;
uint256 internal constant QM_EVAL_LOC = 0x1760;
uint256 internal constant QC_EVAL_LOC = 0x1780;
uint256 internal constant QARITH_EVAL_LOC = 0x17a0;
uint256 internal constant QSORT_EVAL_LOC = 0x17c0;
uint256 internal constant QELLIPTIC_EVAL_LOC = 0x17e0;
uint256 internal constant QAUX_EVAL_LOC = 0x1800;
uint256 internal constant TABLE1_EVAL_LOC = 0x1840;
uint256 internal constant TABLE2_EVAL_LOC = 0x1860;
uint256 internal constant TABLE3_EVAL_LOC = 0x1880;
uint256 internal constant TABLE4_EVAL_LOC = 0x18a0;
uint256 internal constant TABLE_TYPE_EVAL_LOC = 0x18c0;
uint256 internal constant ID1_EVAL_LOC = 0x18e0;
uint256 internal constant ID2_EVAL_LOC = 0x1900;
uint256 internal constant ID3_EVAL_LOC = 0x1920;
uint256 internal constant ID4_EVAL_LOC = 0x1940;
uint256 internal constant SIGMA1_EVAL_LOC = 0x1960;
uint256 internal constant SIGMA2_EVAL_LOC = 0x1980;
uint256 internal constant SIGMA3_EVAL_LOC = 0x19a0;
uint256 internal constant SIGMA4_EVAL_LOC = 0x19c0;
uint256 internal constant W1_OMEGA_EVAL_LOC = 0x19e0;
uint256 internal constant W2_OMEGA_EVAL_LOC = 0x2000;
uint256 internal constant W3_OMEGA_EVAL_LOC = 0x2020;
uint256 internal constant W4_OMEGA_EVAL_LOC = 0x2040;
uint256 internal constant S_OMEGA_EVAL_LOC = 0x2060;
uint256 internal constant Z_OMEGA_EVAL_LOC = 0x2080;
uint256 internal constant Z_LOOKUP_OMEGA_EVAL_LOC = 0x20a0;
uint256 internal constant TABLE1_OMEGA_EVAL_LOC = 0x20c0;
uint256 internal constant TABLE2_OMEGA_EVAL_LOC = 0x20e0;
uint256 internal constant TABLE3_OMEGA_EVAL_LOC = 0x2100;
uint256 internal constant TABLE4_OMEGA_EVAL_LOC = 0x2120;
uint256 internal constant PI_Z_X_LOC = 0x2300;
uint256 internal constant PI_Z_Y_LOC = 0x2320;
uint256 internal constant PI_Z_OMEGA_X_LOC = 0x2340;
uint256 internal constant PI_Z_OMEGA_Y_LOC = 0x2360;
// Used for elliptic widget. These are alias names for wire + shifted wire evaluations
uint256 internal constant X1_EVAL_LOC = W2_EVAL_LOC;
uint256 internal constant X2_EVAL_LOC = W1_OMEGA_EVAL_LOC;
uint256 internal constant X3_EVAL_LOC = W2_OMEGA_EVAL_LOC;
uint256 internal constant Y1_EVAL_LOC = W3_EVAL_LOC;
uint256 internal constant Y2_EVAL_LOC = W4_OMEGA_EVAL_LOC;
uint256 internal constant Y3_EVAL_LOC = W3_OMEGA_EVAL_LOC;
uint256 internal constant QBETA_LOC = Q3_EVAL_LOC;
uint256 internal constant QBETA_SQR_LOC = Q4_EVAL_LOC;
uint256 internal constant QSIGN_LOC = Q1_EVAL_LOC;
// ### CHALLENGES MEMORY OFFSETS
uint256 internal constant C_BETA_LOC = 0x2600;
uint256 internal constant C_GAMMA_LOC = 0x2620;
uint256 internal constant C_ALPHA_LOC = 0x2640;
uint256 internal constant C_ETA_LOC = 0x2660;
uint256 internal constant C_ETA_SQR_LOC = 0x2680;
uint256 internal constant C_ETA_CUBE_LOC = 0x26a0;
uint256 internal constant C_ZETA_LOC = 0x26c0;
uint256 internal constant C_CURRENT_LOC = 0x26e0;
uint256 internal constant C_V0_LOC = 0x2700;
uint256 internal constant C_V1_LOC = 0x2720;
uint256 internal constant C_V2_LOC = 0x2740;
uint256 internal constant C_V3_LOC = 0x2760;
uint256 internal constant C_V4_LOC = 0x2780;
uint256 internal constant C_V5_LOC = 0x27a0;
uint256 internal constant C_V6_LOC = 0x27c0;
uint256 internal constant C_V7_LOC = 0x27e0;
uint256 internal constant C_V8_LOC = 0x2800;
uint256 internal constant C_V9_LOC = 0x2820;
uint256 internal constant C_V10_LOC = 0x2840;
uint256 internal constant C_V11_LOC = 0x2860;
uint256 internal constant C_V12_LOC = 0x2880;
uint256 internal constant C_V13_LOC = 0x28a0;
uint256 internal constant C_V14_LOC = 0x28c0;
uint256 internal constant C_V15_LOC = 0x28e0;
uint256 internal constant C_V16_LOC = 0x2900;
uint256 internal constant C_V17_LOC = 0x2920;
uint256 internal constant C_V18_LOC = 0x2940;
uint256 internal constant C_V19_LOC = 0x2960;
uint256 internal constant C_V20_LOC = 0x2980;
uint256 internal constant C_V21_LOC = 0x29a0;
uint256 internal constant C_V22_LOC = 0x29c0;
uint256 internal constant C_V23_LOC = 0x29e0;
uint256 internal constant C_V24_LOC = 0x2a00;
uint256 internal constant C_V25_LOC = 0x2a20;
uint256 internal constant C_V26_LOC = 0x2a40;
uint256 internal constant C_V27_LOC = 0x2a60;
uint256 internal constant C_V28_LOC = 0x2a80;
uint256 internal constant C_V29_LOC = 0x2aa0;
uint256 internal constant C_V30_LOC = 0x2ac0;
uint256 internal constant C_U_LOC = 0x2b00;
// ### LOCAL VARIABLES MEMORY OFFSETS
uint256 internal constant DELTA_NUMERATOR_LOC = 0x3000;
uint256 internal constant DELTA_DENOMINATOR_LOC = 0x3020;
uint256 internal constant ZETA_POW_N_LOC = 0x3040;
uint256 internal constant PUBLIC_INPUT_DELTA_LOC = 0x3060;
uint256 internal constant ZERO_POLY_LOC = 0x3080;
uint256 internal constant L_START_LOC = 0x30a0;
uint256 internal constant L_END_LOC = 0x30c0;
uint256 internal constant R_ZERO_EVAL_LOC = 0x30e0;
uint256 internal constant PLOOKUP_DELTA_NUMERATOR_LOC = 0x3100;
uint256 internal constant PLOOKUP_DELTA_DENOMINATOR_LOC = 0x3120;
uint256 internal constant PLOOKUP_DELTA_LOC = 0x3140;
uint256 internal constant ACCUMULATOR_X_LOC = 0x3160;
uint256 internal constant ACCUMULATOR_Y_LOC = 0x3180;
uint256 internal constant ACCUMULATOR2_X_LOC = 0x31a0;
uint256 internal constant ACCUMULATOR2_Y_LOC = 0x31c0;
uint256 internal constant PAIRING_LHS_X_LOC = 0x31e0;
uint256 internal constant PAIRING_LHS_Y_LOC = 0x3200;
uint256 internal constant PAIRING_RHS_X_LOC = 0x3220;
uint256 internal constant PAIRING_RHS_Y_LOC = 0x3240;
// ### SUCCESS FLAG MEMORY LOCATIONS
uint256 internal constant GRAND_PRODUCT_SUCCESS_FLAG = 0x3300;
uint256 internal constant ARITHMETIC_TERM_SUCCESS_FLAG = 0x3020;
uint256 internal constant BATCH_OPENING_SUCCESS_FLAG = 0x3340;
uint256 internal constant OPENING_COMMITMENT_SUCCESS_FLAG = 0x3360;
uint256 internal constant PAIRING_PREAMBLE_SUCCESS_FLAG = 0x3380;
uint256 internal constant PAIRING_SUCCESS_FLAG = 0x33a0;
uint256 internal constant RESULT_FLAG = 0x33c0;
// misc stuff
uint256 internal constant OMEGA_INVERSE_LOC = 0x3400;
uint256 internal constant C_ALPHA_SQR_LOC = 0x3420;
uint256 internal constant C_ALPHA_CUBE_LOC = 0x3440;
uint256 internal constant C_ALPHA_QUAD_LOC = 0x3460;
uint256 internal constant C_ALPHA_BASE_LOC = 0x3480;
// ### RECURSION VARIABLE MEMORY LOCATIONS
uint256 internal constant RECURSIVE_P1_X_LOC = 0x3500;
uint256 internal constant RECURSIVE_P1_Y_LOC = 0x3520;
uint256 internal constant RECURSIVE_P2_X_LOC = 0x3540;
uint256 internal constant RECURSIVE_P2_Y_LOC = 0x3560;
uint256 internal constant PUBLIC_INPUTS_HASH_LOCATION = 0x3580;
// sub-identity storage
uint256 internal constant PERMUTATION_IDENTITY = 0x3600;
uint256 internal constant PLOOKUP_IDENTITY = 0x3620;
uint256 internal constant ARITHMETIC_IDENTITY = 0x3640;
uint256 internal constant SORT_IDENTITY = 0x3660;
uint256 internal constant ELLIPTIC_IDENTITY = 0x3680;
uint256 internal constant AUX_IDENTITY = 0x36a0;
uint256 internal constant AUX_NON_NATIVE_FIELD_EVALUATION = 0x36c0;
uint256 internal constant AUX_LIMB_ACCUMULATOR_EVALUATION = 0x36e0;
uint256 internal constant AUX_RAM_CONSISTENCY_EVALUATION = 0x3700;
uint256 internal constant AUX_ROM_CONSISTENCY_EVALUATION = 0x3720;
uint256 internal constant AUX_MEMORY_EVALUATION = 0x3740;
uint256 internal constant QUOTIENT_EVAL_LOC = 0x3760;
uint256 internal constant ZERO_POLY_INVERSE_LOC = 0x3780;
// when hashing public inputs we use memory at NU_CHALLENGE_INPUT_LOC_A, as the hash input size is unknown at compile time
uint256 internal constant NU_CHALLENGE_INPUT_LOC_A = 0x37a0;
uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x37c0;
uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x37e0;
bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6;
bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f;
bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc;
bytes4 internal constant EC_SCALAR_MUL_FAILURE_SELECTOR = 0xf755f369;
bytes4 internal constant PROOF_FAILURE_SELECTOR = 0x0711fcec;
uint256 internal constant ETA_INPUT_LENGTH = 0xc0; // W1, W2, W3 = 6 * 0x20 bytes
// We need to hash 41 field elements when generating the NU challenge
// w1, w2, w3, w4, s, z, z_lookup, q1, q2, q3, q4, qm, qc, qarith (14)
// qsort, qelliptic, qaux, sigma1, sigma2, sigma, sigma4, (7)
// table1, table2, table3, table4, tabletype, id1, id2, id3, id4, (9)
// w1_omega, w2_omega, w3_omega, w4_omega, s_omega, z_omega, z_lookup_omega, (7)
// table1_omega, table2_omega, table3_omega, table4_omega (4)
uint256 internal constant NU_INPUT_LENGTH = 0x520; // 0x520 = 41 * 0x20
// There are ELEVEN G1 group elements added into the transcript in the `beta` round, that we need to skip over
// W1, W2, W3, W4, S, Z, Z_LOOKUP, T1, T2, T3, T4
uint256 internal constant NU_CALLDATA_SKIP_LENGTH = 0x2c0; // 11 * 0x40 = 0x2c0
uint256 internal constant NEGATIVE_INVERSE_OF_2_MODULO_P =
0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000;
uint256 internal constant LIMB_SIZE = 0x100000000000000000; // 2<<68
uint256 internal constant SUBLIMB_SHIFT = 0x4000; // 2<<14
error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual);
error PUBLIC_INPUT_INVALID_BN128_G1_POINT();
error PUBLIC_INPUT_GE_P();
error MOD_EXP_FAILURE();
error EC_SCALAR_MUL_FAILURE();
error PROOF_FAILURE();
function getVerificationKeyHash() public pure virtual returns (bytes32);
function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual;
/**
* @notice Verify a Ultra Plonk proof
* @param _proof - The serialized proof
* @param _publicInputs - An array of the public inputs
* @return True if proof is valid, reverts otherwise
*/
function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) {
loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC);
uint256 requiredPublicInputCount;
assembly {
requiredPublicInputCount := mload(NUM_INPUTS_LOC)
}
if (requiredPublicInputCount != _publicInputs.length) {
revert PUBLIC_INPUT_COUNT_INVALID(requiredPublicInputCount, _publicInputs.length);
}
assembly {
let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order
let p := 21888242871839275222246405745257275088548364400416034343698204186575808495617 // Prime field order
/**
* LOAD PROOF FROM CALLDATA
*/
{
let data_ptr := add(calldataload(0x04), 0x24)
mstore(W1_Y_LOC, mod(calldataload(data_ptr), q))
mstore(W1_X_LOC, mod(calldataload(add(data_ptr, 0x20)), q))
mstore(W2_Y_LOC, mod(calldataload(add(data_ptr, 0x40)), q))
mstore(W2_X_LOC, mod(calldataload(add(data_ptr, 0x60)), q))
mstore(W3_Y_LOC, mod(calldataload(add(data_ptr, 0x80)), q))
mstore(W3_X_LOC, mod(calldataload(add(data_ptr, 0xa0)), q))
mstore(W4_Y_LOC, mod(calldataload(add(data_ptr, 0xc0)), q))
mstore(W4_X_LOC, mod(calldataload(add(data_ptr, 0xe0)), q))
mstore(S_Y_LOC, mod(calldataload(add(data_ptr, 0x100)), q))
mstore(S_X_LOC, mod(calldataload(add(data_ptr, 0x120)), q))
mstore(Z_Y_LOC, mod(calldataload(add(data_ptr, 0x140)), q))
mstore(Z_X_LOC, mod(calldataload(add(data_ptr, 0x160)), q))
mstore(Z_LOOKUP_Y_LOC, mod(calldataload(add(data_ptr, 0x180)), q))
mstore(Z_LOOKUP_X_LOC, mod(calldataload(add(data_ptr, 0x1a0)), q))
mstore(T1_Y_LOC, mod(calldataload(add(data_ptr, 0x1c0)), q))
mstore(T1_X_LOC, mod(calldataload(add(data_ptr, 0x1e0)), q))
mstore(T2_Y_LOC, mod(calldataload(add(data_ptr, 0x200)), q))
mstore(T2_X_LOC, mod(calldataload(add(data_ptr, 0x220)), q))
mstore(T3_Y_LOC, mod(calldataload(add(data_ptr, 0x240)), q))
mstore(T3_X_LOC, mod(calldataload(add(data_ptr, 0x260)), q))
mstore(T4_Y_LOC, mod(calldataload(add(data_ptr, 0x280)), q))
mstore(T4_X_LOC, mod(calldataload(add(data_ptr, 0x2a0)), q))
mstore(W1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2c0)), p))
mstore(W2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2e0)), p))
mstore(W3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x300)), p))
mstore(W4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x320)), p))
mstore(S_EVAL_LOC, mod(calldataload(add(data_ptr, 0x340)), p))
mstore(Z_EVAL_LOC, mod(calldataload(add(data_ptr, 0x360)), p))
mstore(Z_LOOKUP_EVAL_LOC, mod(calldataload(add(data_ptr, 0x380)), p))
mstore(Q1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3a0)), p))
mstore(Q2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3c0)), p))
mstore(Q3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3e0)), p))
mstore(Q4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x400)), p))
mstore(QM_EVAL_LOC, mod(calldataload(add(data_ptr, 0x420)), p))
mstore(QC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x440)), p))
mstore(QARITH_EVAL_LOC, mod(calldataload(add(data_ptr, 0x460)), p))
mstore(QSORT_EVAL_LOC, mod(calldataload(add(data_ptr, 0x480)), p))
mstore(QELLIPTIC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4a0)), p))
mstore(QAUX_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4c0)), p))
mstore(SIGMA1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4e0)), p))
mstore(SIGMA2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x500)), p))
mstore(SIGMA3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x520)), p))
mstore(SIGMA4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x540)), p))
mstore(TABLE1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x560)), p))
mstore(TABLE2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x580)), p))
mstore(TABLE3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5a0)), p))
mstore(TABLE4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5c0)), p))
mstore(TABLE_TYPE_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5e0)), p))
mstore(ID1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x600)), p))
mstore(ID2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x620)), p))
mstore(ID3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x640)), p))
mstore(ID4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x660)), p))
mstore(W1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x680)), p))
mstore(W2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6a0)), p))
mstore(W3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6c0)), p))
mstore(W4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6e0)), p))
mstore(S_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x700)), p))
mstore(Z_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x720)), p))
mstore(Z_LOOKUP_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x740)), p))
mstore(TABLE1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x760)), p))
mstore(TABLE2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x780)), p))
mstore(TABLE3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7a0)), p))
mstore(TABLE4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7c0)), p))
mstore(PI_Z_Y_LOC, mod(calldataload(add(data_ptr, 0x7e0)), q))
mstore(PI_Z_X_LOC, mod(calldataload(add(data_ptr, 0x800)), q))
mstore(PI_Z_OMEGA_Y_LOC, mod(calldataload(add(data_ptr, 0x820)), q))
mstore(PI_Z_OMEGA_X_LOC, mod(calldataload(add(data_ptr, 0x840)), q))
}
/**
* LOAD RECURSIVE PROOF INTO MEMORY
*/
{
if mload(CONTAINS_RECURSIVE_PROOF_LOC) {
let public_inputs_ptr := add(calldataload(0x24), 0x24)
let index_counter := add(shl(5, mload(RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC)), public_inputs_ptr)
let x0 := calldataload(index_counter)
x0 := add(x0, shl(68, calldataload(add(index_counter, 0x20))))
x0 := add(x0, shl(136, calldataload(add(index_counter, 0x40))))
x0 := add(x0, shl(204, calldataload(add(index_counter, 0x60))))
let y0 := calldataload(add(index_counter, 0x80))
y0 := add(y0, shl(68, calldataload(add(index_counter, 0xa0))))
y0 := add(y0, shl(136, calldataload(add(index_counter, 0xc0))))
y0 := add(y0, shl(204, calldataload(add(index_counter, 0xe0))))
let x1 := calldataload(add(index_counter, 0x100))
x1 := add(x1, shl(68, calldataload(add(index_counter, 0x120))))
x1 := add(x1, shl(136, calldataload(add(index_counter, 0x140))))
x1 := add(x1, shl(204, calldataload(add(index_counter, 0x160))))
let y1 := calldataload(add(index_counter, 0x180))
y1 := add(y1, shl(68, calldataload(add(index_counter, 0x1a0))))
y1 := add(y1, shl(136, calldataload(add(index_counter, 0x1c0))))
y1 := add(y1, shl(204, calldataload(add(index_counter, 0x1e0))))
mstore(RECURSIVE_P1_X_LOC, x0)
mstore(RECURSIVE_P1_Y_LOC, y0)
mstore(RECURSIVE_P2_X_LOC, x1)
mstore(RECURSIVE_P2_Y_LOC, y1)
// validate these are valid bn128 G1 points
if iszero(and(and(lt(x0, q), lt(x1, q)), and(lt(y0, q), lt(y1, q)))) {
mstore(0x00, PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR)
revert(0x00, 0x04)
}
}
}
{
/**
* Generate initial challenge
*/
mstore(0x00, shl(224, mload(N_LOC)))
mstore(0x04, shl(224, mload(NUM_INPUTS_LOC)))
let challenge := keccak256(0x00, 0x08)
/**
* Generate eta challenge
*/
mstore(PUBLIC_INPUTS_HASH_LOCATION, challenge)
// The public input location is stored at 0x24, we then add 0x24 to skip selector and the length of public inputs
let public_inputs_start := add(calldataload(0x24), 0x24)
// copy the public inputs over
let public_input_size := mul(mload(NUM_INPUTS_LOC), 0x20)
calldatacopy(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_inputs_start, public_input_size)
// copy W1, W2, W3 into challenge. Each point is 0x40 bytes, so load 0xc0 = 3 * 0x40 bytes (ETA input length)
let w_start := add(calldataload(0x04), 0x24)
calldatacopy(add(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_input_size), w_start, ETA_INPUT_LENGTH)
// Challenge is the old challenge + public inputs + W1, W2, W3 (0x20 + public_input_size + 0xc0)
let challenge_bytes_size := add(0x20, add(public_input_size, ETA_INPUT_LENGTH))
challenge := keccak256(PUBLIC_INPUTS_HASH_LOCATION, challenge_bytes_size)
{
let eta := mod(challenge, p)
mstore(C_ETA_LOC, eta)
mstore(C_ETA_SQR_LOC, mulmod(eta, eta, p))
mstore(C_ETA_CUBE_LOC, mulmod(mload(C_ETA_SQR_LOC), eta, p))
}
/**
* Generate beta challenge
*/
mstore(0x00, challenge)
mstore(0x20, mload(W4_Y_LOC))
mstore(0x40, mload(W4_X_LOC))
mstore(0x60, mload(S_Y_LOC))
mstore(0x80, mload(S_X_LOC))
challenge := keccak256(0x00, 0xa0)
mstore(C_BETA_LOC, mod(challenge, p))
/**
* Generate gamma challenge
*/
mstore(0x00, challenge)
mstore8(0x20, 0x01)
challenge := keccak256(0x00, 0x21)
mstore(C_GAMMA_LOC, mod(challenge, p))
/**
* Generate alpha challenge
*/
mstore(0x00, challenge)
mstore(0x20, mload(Z_Y_LOC))
mstore(0x40, mload(Z_X_LOC))
mstore(0x60, mload(Z_LOOKUP_Y_LOC))
mstore(0x80, mload(Z_LOOKUP_X_LOC))
challenge := keccak256(0x00, 0xa0)
mstore(C_ALPHA_LOC, mod(challenge, p))
/**
* Compute and store some powers of alpha for future computations
*/
let alpha := mload(C_ALPHA_LOC)
mstore(C_ALPHA_SQR_LOC, mulmod(alpha, alpha, p))
mstore(C_ALPHA_CUBE_LOC, mulmod(mload(C_ALPHA_SQR_LOC), alpha, p))
mstore(C_ALPHA_QUAD_LOC, mulmod(mload(C_ALPHA_CUBE_LOC), alpha, p))
mstore(C_ALPHA_BASE_LOC, alpha)
/**
* Generate zeta challenge
*/
mstore(0x00, challenge)
mstore(0x20, mload(T1_Y_LOC))
mstore(0x40, mload(T1_X_LOC))
mstore(0x60, mload(T2_Y_LOC))
mstore(0x80, mload(T2_X_LOC))
mstore(0xa0, mload(T3_Y_LOC))
mstore(0xc0, mload(T3_X_LOC))
mstore(0xe0, mload(T4_Y_LOC))
mstore(0x100, mload(T4_X_LOC))
challenge := keccak256(0x00, 0x120)
mstore(C_ZETA_LOC, mod(challenge, p))
mstore(C_CURRENT_LOC, challenge)
}
/**
* EVALUATE FIELD OPERATIONS
*/
/**
* COMPUTE PUBLIC INPUT DELTA
* ΔPI = ∏ᵢ∈ℓ(wᵢ + β σ(i) + γ) / ∏ᵢ∈ℓ(wᵢ + β σ'(i) + γ)
*/
{
let beta := mload(C_BETA_LOC) // β
let gamma := mload(C_GAMMA_LOC) // γ
let work_root := mload(OMEGA_LOC) // ω
let numerator_value := 1
let denominator_value := 1
let p_clone := p // move p to the front of the stack
let valid_inputs := true
// Load the starting point of the public inputs (jump over the selector and the length of public inputs [0x24])
let public_inputs_ptr := add(calldataload(0x24), 0x24)
// endpoint_ptr = public_inputs_ptr + num_inputs * 0x20. // every public input is 0x20 bytes
let endpoint_ptr := add(public_inputs_ptr, mul(mload(NUM_INPUTS_LOC), 0x20))
// root_1 = β * 0x05
let root_1 := mulmod(beta, 0x05, p_clone) // k1.β
// root_2 = β * 0x0c
let root_2 := mulmod(beta, 0x0c, p_clone)
// @note 0x05 + 0x07 == 0x0c == external coset generator
for {} lt(public_inputs_ptr, endpoint_ptr) { public_inputs_ptr := add(public_inputs_ptr, 0x20) } {
/**
* input = public_input[i]
* valid_inputs &= input < p
* temp = input + gamma
* numerator_value *= (β.σ(i) + wᵢ + γ) // σ(i) = 0x05.ωⁱ
* denominator_value *= (β.σ'(i) + wᵢ + γ) // σ'(i) = 0x0c.ωⁱ
* root_1 *= ω
* root_2 *= ω
*/
let input := calldataload(public_inputs_ptr)
valid_inputs := and(valid_inputs, lt(input, p_clone))
let temp := addmod(input, gamma, p_clone)
numerator_value := mulmod(numerator_value, add(root_1, temp), p_clone)
denominator_value := mulmod(denominator_value, add(root_2, temp), p_clone)
root_1 := mulmod(root_1, work_root, p_clone)
root_2 := mulmod(root_2, work_root, p_clone)
}
// Revert if not all public inputs are field elements (i.e. < p)
if iszero(valid_inputs) {
mstore(0x00, PUBLIC_INPUT_GE_P_SELECTOR)
revert(0x00, 0x04)
}
mstore(DELTA_NUMERATOR_LOC, numerator_value)
mstore(DELTA_DENOMINATOR_LOC, denominator_value)
}
/**
* Compute Plookup delta factor [γ(1 + β)]^{n-k}
* k = num roots cut out of Z_H = 4
*/
{
let delta_base := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p)
let delta_numerator := delta_base
{
let exponent := mload(N_LOC)
let count := 1
for {} lt(count, exponent) { count := add(count, count) } {
delta_numerator := mulmod(delta_numerator, delta_numerator, p)
}
}
mstore(PLOOKUP_DELTA_NUMERATOR_LOC, delta_numerator)
let delta_denominator := mulmod(delta_base, delta_base, p)
delta_denominator := mulmod(delta_denominator, delta_denominator, p)
mstore(PLOOKUP_DELTA_DENOMINATOR_LOC, delta_denominator)
}
/**
* Compute lagrange poly and vanishing poly fractions
*/
{
/**
* vanishing_numerator = zeta
* ZETA_POW_N = zeta^n
* vanishing_numerator -= 1
* accumulating_root = omega_inverse
* work_root = p - accumulating_root
* domain_inverse = domain_inverse
* vanishing_denominator = zeta + work_root
* work_root *= accumulating_root
* vanishing_denominator *= (zeta + work_root)
* work_root *= accumulating_root
* vanishing_denominator *= (zeta + work_root)
* vanishing_denominator *= (zeta + (zeta + accumulating_root))
* work_root = omega
* lagrange_numerator = vanishing_numerator * domain_inverse
* l_start_denominator = zeta - 1
* accumulating_root = work_root^2
* l_end_denominator = accumulating_root^2 * work_root * zeta - 1
* Note: l_end_denominator term contains a term \omega^5 to cut out 5 roots of unity from vanishing poly
*/
let zeta := mload(C_ZETA_LOC)
// compute zeta^n, where n is a power of 2
let vanishing_numerator := zeta
{
// pow_small
let exponent := mload(N_LOC)
let count := 1
for {} lt(count, exponent) { count := add(count, count) } {
vanishing_numerator := mulmod(vanishing_numerator, vanishing_numerator, p)
}
}
mstore(ZETA_POW_N_LOC, vanishing_numerator)
vanishing_numerator := addmod(vanishing_numerator, sub(p, 1), p)
let accumulating_root := mload(OMEGA_INVERSE_LOC)
let work_root := sub(p, accumulating_root)
let domain_inverse := mload(DOMAIN_INVERSE_LOC)
let vanishing_denominator := addmod(zeta, work_root, p)
work_root := mulmod(work_root, accumulating_root, p)
vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p)
work_root := mulmod(work_root, accumulating_root, p)
vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p)
vanishing_denominator :=
mulmod(vanishing_denominator, addmod(zeta, mulmod(work_root, accumulating_root, p), p), p)
work_root := mload(OMEGA_LOC)
let lagrange_numerator := mulmod(vanishing_numerator, domain_inverse, p)
let l_start_denominator := addmod(zeta, sub(p, 1), p)
accumulating_root := mulmod(work_root, work_root, p)
let l_end_denominator :=
addmod(
mulmod(mulmod(mulmod(accumulating_root, accumulating_root, p), work_root, p), zeta, p), sub(p, 1), p
)
/**
* Compute inversions using Montgomery's batch inversion trick
*/
let accumulator := mload(DELTA_DENOMINATOR_LOC)
let t0 := accumulator
accumulator := mulmod(accumulator, vanishing_denominator, p)
let t1 := accumulator
accumulator := mulmod(accumulator, vanishing_numerator, p)
let t2 := accumulator
accumulator := mulmod(accumulator, l_start_denominator, p)
let t3 := accumulator
accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p)
let t4 := accumulator
{
mstore(0, 0x20)
mstore(0x20, 0x20)
mstore(0x40, 0x20)
mstore(0x60, mulmod(accumulator, l_end_denominator, p))
mstore(0x80, sub(p, 2))
mstore(0xa0, p)
if iszero(staticcall(gas(), 0x05, 0x00, 0xc0, 0x00, 0x20)) {
mstore(0x0, MOD_EXP_FAILURE_SELECTOR)
revert(0x00, 0x04)
}
accumulator := mload(0x00)
}
t4 := mulmod(accumulator, t4, p)
accumulator := mulmod(accumulator, l_end_denominator, p)
t3 := mulmod(accumulator, t3, p)
accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p)
t2 := mulmod(accumulator, t2, p)
accumulator := mulmod(accumulator, l_start_denominator, p)
t1 := mulmod(accumulator, t1, p)
accumulator := mulmod(accumulator, vanishing_numerator, p)
t0 := mulmod(accumulator, t0, p)
accumulator := mulmod(accumulator, vanishing_denominator, p)
accumulator := mulmod(mulmod(accumulator, accumulator, p), mload(DELTA_DENOMINATOR_LOC), p)
mstore(PUBLIC_INPUT_DELTA_LOC, mulmod(mload(DELTA_NUMERATOR_LOC), accumulator, p))
mstore(ZERO_POLY_LOC, mulmod(vanishing_numerator, t0, p))
mstore(ZERO_POLY_INVERSE_LOC, mulmod(vanishing_denominator, t1, p))
mstore(L_START_LOC, mulmod(lagrange_numerator, t2, p))
mstore(PLOOKUP_DELTA_LOC, mulmod(mload(PLOOKUP_DELTA_NUMERATOR_LOC), t3, p))
mstore(L_END_LOC, mulmod(lagrange_numerator, t4, p))
}
/**
* UltraPlonk Widget Ordering:
*
* 1. Permutation widget
* 2. Plookup widget
* 3. Arithmetic widget
* 4. Fixed base widget (?)
* 5. GenPermSort widget
* 6. Elliptic widget
* 7. Auxiliary widget
*/
/**
* COMPUTE PERMUTATION WIDGET EVALUATION
*/
{
let alpha := mload(C_ALPHA_LOC)
let beta := mload(C_BETA_LOC)
let gamma := mload(C_GAMMA_LOC)
/**
* t1 = (W1 + gamma + beta * ID1) * (W2 + gamma + beta * ID2)
* t2 = (W3 + gamma + beta * ID3) * (W4 + gamma + beta * ID4)
* result = alpha_base * z_eval * t1 * t2
* t1 = (W1 + gamma + beta * sigma_1_eval) * (W2 + gamma + beta * sigma_2_eval)
* t2 = (W2 + gamma + beta * sigma_3_eval) * (W3 + gamma + beta * sigma_4_eval)
* result -= (alpha_base * z_omega_eval * t1 * t2)
*/
let t1 :=
mulmod(
add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(ID1_EVAL_LOC), p)),
add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(ID2_EVAL_LOC), p)),
p
)
let t2 :=
mulmod(
add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(ID3_EVAL_LOC), p)),
add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(ID4_EVAL_LOC), p)),
p
)
let result := mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_EVAL_LOC), mulmod(t1, t2, p), p), p)
t1 :=
mulmod(
add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA1_EVAL_LOC), p)),
add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA2_EVAL_LOC), p)),
p
)
t2 :=
mulmod(
add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA3_EVAL_LOC), p)),
add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA4_EVAL_LOC), p)),
p
)
result :=
addmod(
result,
sub(p, mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_OMEGA_EVAL_LOC), mulmod(t1, t2, p), p), p)),
p
)
/**
* alpha_base *= alpha
* result += alpha_base . (L_{n-k}(ʓ) . (z(ʓ.ω) - ∆_{PI}))
* alpha_base *= alpha
* result += alpha_base . (L_1(ʓ)(Z(ʓ) - 1))
* alpha_Base *= alpha
*/
mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p))
result :=
addmod(
result,
mulmod(
mload(C_ALPHA_BASE_LOC),
mulmod(
mload(L_END_LOC),
addmod(mload(Z_OMEGA_EVAL_LOC), sub(p, mload(PUBLIC_INPUT_DELTA_LOC)), p),
p
),
p
),
p
)
mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p))
mstore(
PERMUTATION_IDENTITY,
addmod(
result,
mulmod(
mload(C_ALPHA_BASE_LOC),
mulmod(mload(L_START_LOC), addmod(mload(Z_EVAL_LOC), sub(p, 1), p), p),
p
),
p
)
)
mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p))
}
/**
* COMPUTE PLOOKUP WIDGET EVALUATION
*/
{
/**
* Goal: f = (w1(z) + q2.w1(zω)) + η(w2(z) + qm.w2(zω)) + η²(w3(z) + qc.w_3(zω)) + q3(z).η³
* f = η.q3(z)
* f += (w3(z) + qc.w_3(zω))
* f *= η
* f += (w2(z) + qm.w2(zω))
* f *= η
* f += (w1(z) + q2.w1(zω))
*/
let f := mulmod(mload(C_ETA_LOC), mload(Q3_EVAL_LOC), p)
f :=
addmod(f, addmod(mload(W3_EVAL_LOC), mulmod(mload(QC_EVAL_LOC), mload(W3_OMEGA_EVAL_LOC), p), p), p)
f := mulmod(f, mload(C_ETA_LOC), p)
f :=
addmod(f, addmod(mload(W2_EVAL_LOC), mulmod(mload(QM_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p), p)
f := mulmod(f, mload(C_ETA_LOC), p)
f :=
addmod(f, addmod(mload(W1_EVAL_LOC), mulmod(mload(Q2_EVAL_LOC), mload(W1_OMEGA_EVAL_LOC), p), p), p)
// t(z) = table4(z).η³ + table3(z).η² + table2(z).η + table1(z)
let t :=
addmod(
addmod(
addmod(
mulmod(mload(TABLE4_EVAL_LOC), mload(C_ETA_CUBE_LOC), p),
mulmod(mload(TABLE3_EVAL_LOC), mload(C_ETA_SQR_LOC), p),
p
),
mulmod(mload(TABLE2_EVAL_LOC), mload(C_ETA_LOC), p),
p
),
mload(TABLE1_EVAL_LOC),
p
)
// t(zw) = table4(zw).η³ + table3(zw).η² + table2(zw).η + table1(zw)
let t_omega :=
addmod(
addmod(
addmod(
mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_ETA_CUBE_LOC), p),
mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_ETA_SQR_LOC), p),
p
),
mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p),
p
),
mload(TABLE1_OMEGA_EVAL_LOC),
p
)
/**
* Goal: numerator = (TABLE_TYPE_EVAL * f(z) + γ) * (t(z) + βt(zω) + γ(β + 1)) * (β + 1)
* gamma_beta_constant = γ(β + 1)
* numerator = f * TABLE_TYPE_EVAL + gamma
* temp0 = t(z) + t(zω) * β + gamma_beta_constant
* numerator *= temp0
* numerator *= (β + 1)
* temp0 = alpha * l_1
* numerator += temp0
* numerator *= z_lookup(z)
* numerator -= temp0
*/
let gamma_beta_constant := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p)
let numerator := addmod(mulmod(f, mload(TABLE_TYPE_EVAL_LOC), p), mload(C_GAMMA_LOC), p)
let temp0 := addmod(addmod(t, mulmod(t_omega, mload(C_BETA_LOC), p), p), gamma_beta_constant, p)
numerator := mulmod(numerator, temp0, p)
numerator := mulmod(numerator, addmod(mload(C_BETA_LOC), 1, p), p)
temp0 := mulmod(mload(C_ALPHA_LOC), mload(L_START_LOC), p)
numerator := addmod(numerator, temp0, p)
numerator := mulmod(numerator, mload(Z_LOOKUP_EVAL_LOC), p)
numerator := addmod(numerator, sub(p, temp0), p)
/**
* Goal: denominator = z_lookup(zω)*[s(z) + βs(zω) + γ(1 + β)] - [z_lookup(zω) - [γ(1 + β)]^{n-k}]*α²L_end(z)
* note: delta_factor = [γ(1 + β)]^{n-k}
* denominator = s(z) + βs(zω) + γ(β + 1)
* temp1 = α²L_end(z)
* denominator -= temp1
* denominator *= z_lookup(zω)
* denominator += temp1 * delta_factor
* PLOOKUP_IDENTITY = (numerator - denominator).alpha_base
* alpha_base *= alpha^3
*/
let denominator :=
addmod(
addmod(mload(S_EVAL_LOC), mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_BETA_LOC), p), p),
gamma_beta_constant,
p
)
let temp1 := mulmod(mload(C_ALPHA_SQR_LOC), mload(L_END_LOC), p)
denominator := addmod(denominator, sub(p, temp1), p)
denominator := mulmod(denominator, mload(Z_LOOKUP_OMEGA_EVAL_LOC), p)
denominator := addmod(denominator, mulmod(temp1, mload(PLOOKUP_DELTA_LOC), p), p)
mstore(PLOOKUP_IDENTITY, mulmod(addmod(numerator, sub(p, denominator), p), mload(C_ALPHA_BASE_LOC), p))
// update alpha
mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p))
}
/**
* COMPUTE ARITHMETIC WIDGET EVALUATION
*/
{
/**
* The basic arithmetic gate identity in standard plonk is as follows.
* (w_1 . w_2 . q_m) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c = 0
* However, for Ultraplonk, we extend this to support "passing" wires between rows (shown without alpha scaling below):
* q_arith * ( ( (-1/2) * (q_arith - 3) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c ) +
* (q_arith - 1)*( α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + w_4_omega) ) = 0
*
* This formula results in several cases depending on q_arith:
* 1. q_arith == 0: Arithmetic gate is completely disabled
*
* 2. q_arith == 1: Everything in the minigate on the right is disabled. The equation is just a standard plonk equation
* with extra wires: q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c = 0
*
* 3. q_arith == 2: The (w_1 + w_4 - ...) term is disabled. THe equation is:
* (1/2) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + w_4_omega = 0
* It allows defining w_4 at next index (w_4_omega) in terms of current wire values
*
* 4. q_arith == 3: The product of w_1 and w_2 is disabled, but a mini addition gate is enabled. α allows us to split
* the equation into two:
*
* q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + 2 * w_4_omega = 0
* and
* w_1 + w_4 - w_1_omega + q_m = 0 (we are reusing q_m here)
*
* 5. q_arith > 3: The product of w_1 and w_2 is scaled by (q_arith - 3), while the w_4_omega term is scaled by (q_arith - 1).
* The equation can be split into two:
*
* (q_arith - 3)* q_m * w_1 * w_ 2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + (q_arith - 1) * w_4_omega = 0
* and
* w_1 + w_4 - w_1_omega + q_m = 0
*
* The problem that q_m is used both in both equations can be dealt with by appropriately changing selector values at
* the next gate. Then we can treat (q_arith - 1) as a simulated q_6 selector and scale q_m to handle (q_arith - 3) at
* product.
*/
let w1q1 := mulmod(mload(W1_EVAL_LOC), mload(Q1_EVAL_LOC), p)
let w2q2 := mulmod(mload(W2_EVAL_LOC), mload(Q2_EVAL_LOC), p)
let w3q3 := mulmod(mload(W3_EVAL_LOC), mload(Q3_EVAL_LOC), p)
let w4q3 := mulmod(mload(W4_EVAL_LOC), mload(Q4_EVAL_LOC), p)
// @todo - Add a explicit test that hits QARITH == 3
// w1w2qm := (w_1 . w_2 . q_m . (QARITH_EVAL_LOC - 3)) / 2
let w1w2qm :=
mulmod(
mulmod(
mulmod(mulmod(mload(W1_EVAL_LOC), mload(W2_EVAL_LOC), p), mload(QM_EVAL_LOC), p),
addmod(mload(QARITH_EVAL_LOC), sub(p, 3), p),
p
),
NEGATIVE_INVERSE_OF_2_MODULO_P,
p
)
// (w_1 . w_2 . q_m . (q_arith - 3)) / -2) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c
let identity :=
addmod(
mload(QC_EVAL_LOC), addmod(w4q3, addmod(w3q3, addmod(w2q2, addmod(w1q1, w1w2qm, p), p), p), p), p
)
// if q_arith == 3 we evaluate an additional mini addition gate (on top of the regular one), where:
// w_1 + w_4 - w_1_omega + q_m = 0
// we use this gate to save an addition gate when adding or subtracting non-native field elements
// α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m)
let extra_small_addition_gate_identity :=
mulmod(
mload(C_ALPHA_LOC),
mulmod(
addmod(mload(QARITH_EVAL_LOC), sub(p, 2), p),
addmod(
mload(QM_EVAL_LOC),
addmod(
sub(p, mload(W1_OMEGA_EVAL_LOC)), addmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), p
),
p
),
p
),
p
)
// if q_arith == 2 OR q_arith == 3 we add the 4th wire of the NEXT gate into the arithmetic identity
// N.B. if q_arith > 2, this wire value will be scaled by (q_arith - 1) relative to the other gate wires!
// alpha_base * q_arith * (identity + (q_arith - 1) * (w_4_omega + extra_small_addition_gate_identity))
mstore(
ARITHMETIC_IDENTITY,
mulmod(
mload(C_ALPHA_BASE_LOC),
mulmod(
mload(QARITH_EVAL_LOC),
addmod(
identity,
mulmod(
addmod(mload(QARITH_EVAL_LOC), sub(p, 1), p),
addmod(mload(W4_OMEGA_EVAL_LOC), extra_small_addition_gate_identity, p),
p
),
p
),
p
),
p
)
)
// update alpha
mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p))
}
/**
* COMPUTE GENPERMSORT WIDGET EVALUATION
*/
{
/**
* D1 = (w2 - w1)
* D2 = (w3 - w2)
* D3 = (w4 - w3)
* D4 = (w1_omega - w4)
*
* α_a = alpha_base
* α_b = alpha_base * α
* α_c = alpha_base * α^2
* α_d = alpha_base * α^3
*
* range_accumulator = (
* D1(D1 - 1)(D1 - 2)(D1 - 3).α_a +
* D2(D2 - 1)(D2 - 2)(D2 - 3).α_b +
* D3(D3 - 1)(D3 - 2)(D3 - 3).α_c +
* D4(D4 - 1)(D4 - 2)(D4 - 3).α_d +
* ) . q_sort
*/
let minus_two := sub(p, 2)
let minus_three := sub(p, 3)
let d1 := addmod(mload(W2_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p)
let d2 := addmod(mload(W3_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p)
let d3 := addmod(mload(W4_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p)
let d4 := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p)
let range_accumulator :=
mulmod(
mulmod(
mulmod(addmod(mulmod(d1, d1, p), sub(p, d1), p), addmod(d1, minus_two, p), p),
addmod(d1, minus_three, p),
p
),
mload(C_ALPHA_BASE_LOC),
p
)
range_accumulator :=
addmod(
range_accumulator,
mulmod(
mulmod(
mulmod(addmod(mulmod(d2, d2, p), sub(p, d2), p), addmod(d2, minus_two, p), p),
addmod(d2, minus_three, p),
p
),
mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p),
p
),
p
)
range_accumulator :=
addmod(
range_accumulator,
mulmod(
mulmod(
mulmod(addmod(mulmod(d3, d3, p), sub(p, d3), p), addmod(d3, minus_two, p), p),
addmod(d3, minus_three, p),
p
),
mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p),
p
),
p
)
range_accumulator :=
addmod(
range_accumulator,
mulmod(
mulmod(
mulmod(addmod(mulmod(d4, d4, p), sub(p, d4), p), addmod(d4, minus_two, p), p),
addmod(d4, minus_three, p),
p
),
mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p),
p
),
p
)
range_accumulator := mulmod(range_accumulator, mload(QSORT_EVAL_LOC), p)
mstore(SORT_IDENTITY, range_accumulator)
// update alpha
mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p))
}
/**
* COMPUTE ELLIPTIC WIDGET EVALUATION
*/
{
/**
* endo_term = (-x_2) * x_1 * (x_3 * 2 + x_1) * q_beta
* endo_sqr_term = x_2^2
* endo_sqr_term *= (x_3 - x_1)
* endo_sqr_term *= q_beta^2
* leftovers = x_2^2
* leftovers *= x_2
* leftovers += x_1^2 * (x_3 + x_1) @follow-up Invalid comment in BB widget
* leftovers -= (y_2^2 + y_1^2)
* sign_term = y_2 * y_1
* sign_term += sign_term
* sign_term *= q_sign
*/
let endo_term :=
mulmod(
mulmod(
mulmod(sub(p, mload(X2_EVAL_LOC)), mload(X1_EVAL_LOC), p),
addmod(addmod(mload(X3_EVAL_LOC), mload(X3_EVAL_LOC), p), mload(X1_EVAL_LOC), p),
p
),
mload(QBETA_LOC),
p
)
let endo_sqr_term := mulmod(mload(X2_EVAL_LOC), mload(X2_EVAL_LOC), p)
endo_sqr_term := mulmod(endo_sqr_term, addmod(mload(X3_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p), p)
endo_sqr_term := mulmod(endo_sqr_term, mload(QBETA_SQR_LOC), p)
let leftovers := mulmod(mload(X2_EVAL_LOC), mload(X2_EVAL_LOC), p)
leftovers := mulmod(leftovers, mload(X2_EVAL_LOC), p)
leftovers :=
addmod(
leftovers,
mulmod(
mulmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p),
addmod(mload(X3_EVAL_LOC), mload(X1_EVAL_LOC), p),
p
),
p
)
leftovers :=
addmod(
leftovers,
sub(
p,
addmod(
mulmod(mload(Y2_EVAL_LOC), mload(Y2_EVAL_LOC), p),
mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p),
p
)
),
p
)
let sign_term := mulmod(mload(Y2_EVAL_LOC), mload(Y1_EVAL_LOC), p)
sign_term := addmod(sign_term, sign_term, p)
sign_term := mulmod(sign_term, mload(QSIGN_LOC), p)
/**
* x_identity = endo_term + endo_sqr_term + sign_term + leftovers
* x_identity *= alpha_base
* endo_term = (x_2 * q_beta) * (y_3 + y_1)
* sign_term = -((y2 * q_sign) * (x_1 + x_3))
* leftovers = - x1 * (y_3 + y_1) + y_1 * (x_1 - x_3)
* y_identity = (endo_term + sign_term + leftovers) * (alpha_base * α)
*/
let x_identity := addmod(addmod(endo_term, endo_sqr_term, p), addmod(sign_term, leftovers, p), p)
x_identity := mulmod(x_identity, mload(C_ALPHA_BASE_LOC), p)
endo_term :=
mulmod(
mulmod(mload(X2_EVAL_LOC), mload(QBETA_LOC), p),
addmod(mload(Y3_EVAL_LOC), mload(Y1_EVAL_LOC), p),
p
)
sign_term :=
sub(
p,
mulmod(
mulmod(mload(Y2_EVAL_LOC), mload(QSIGN_LOC), p),
addmod(mload(X1_EVAL_LOC), sub(p, mload(X3_EVAL_LOC)), p),
p
)
)
leftovers :=
addmod(
sub(p, mulmod(mload(X1_EVAL_LOC), addmod(mload(Y3_EVAL_LOC), mload(Y1_EVAL_LOC), p), p)),
mulmod(mload(Y1_EVAL_LOC), addmod(mload(X1_EVAL_LOC), sub(p, mload(X3_EVAL_LOC)), p), p),
p
)
let y_identity :=
mulmod(
addmod(addmod(endo_term, sign_term, p), leftovers, p),
mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p),
p
)
// ELLIPTIC_IDENTITY = (x_identity + y_identity) * Q_ELLIPTIC_EVAL
mstore(ELLIPTIC_IDENTITY, mulmod(addmod(x_identity, y_identity, p), mload(QELLIPTIC_EVAL_LOC), p))
// update alpha
// The paper says to use ALPHA^2, we use ALPHA^4 this is a small oversight in the prover protocol
mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p))
}
/**
* COMPUTE AUXILIARY WIDGET EVALUATION
*/
{
{
/**
* Non native field arithmetic gate 2
* _ _
* / _ _ _ 14 \
* q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 |
* \_ _/
*
* limb_subproduct = w_1 . w_2_omega + w_1_omega . w_2
* non_native_field_gate_2 = w_1 * w_4 + w_4 * w_3 - w_3_omega
* non_native_field_gate_2 = non_native_field_gate_2 * limb_size
* non_native_field_gate_2 -= w_4_omega
* non_native_field_gate_2 += limb_subproduct
* non_native_field_gate_2 *= q_4
* limb_subproduct *= limb_size
* limb_subproduct += w_1_omega * w_2_omega
* non_native_field_gate_1 = (limb_subproduct + w_3 + w_4) * q_3
* non_native_field_gate_3 = (limb_subproduct + w_4 - (w_3_omega + w_4_omega)) * q_m
* non_native_field_identity = (non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3) * q_2
*/
let limb_subproduct :=
addmod(
mulmod(mload(W1_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p),
mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_EVAL_LOC), p),
p
)
let non_native_field_gate_2 :=
addmod(
addmod(
mulmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p),
mulmod(mload(W2_EVAL_LOC), mload(W3_EVAL_LOC), p),
p
),
sub(p, mload(W3_OMEGA_EVAL_LOC)),
p
)
non_native_field_gate_2 := mulmod(non_native_field_gate_2, LIMB_SIZE, p)
non_native_field_gate_2 := addmod(non_native_field_gate_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p)
non_native_field_gate_2 := addmod(non_native_field_gate_2, limb_subproduct, p)
non_native_field_gate_2 := mulmod(non_native_field_gate_2, mload(Q4_EVAL_LOC), p)
limb_subproduct := mulmod(limb_subproduct, LIMB_SIZE, p)
limb_subproduct :=
addmod(limb_subproduct, mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p)
let non_native_field_gate_1 :=
mulmod(
addmod(limb_subproduct, sub(p, addmod(mload(W3_EVAL_LOC), mload(W4_EVAL_LOC), p)), p),
mload(Q3_EVAL_LOC),
p
)
let non_native_field_gate_3 :=
mulmod(
addmod(
addmod(limb_subproduct, mload(W4_EVAL_LOC), p),
sub(p, addmod(mload(W3_OMEGA_EVAL_LOC), mload(W4_OMEGA_EVAL_LOC), p)),
p
),
mload(QM_EVAL_LOC),
p
)
let non_native_field_identity :=
mulmod(
addmod(addmod(non_native_field_gate_1, non_native_field_gate_2, p), non_native_field_gate_3, p),
mload(Q2_EVAL_LOC),
p
)
mstore(AUX_NON_NATIVE_FIELD_EVALUATION, non_native_field_identity)
}
{
/**
* limb_accumulator_1 = w_2_omega;
* limb_accumulator_1 *= SUBLIMB_SHIFT;
* limb_accumulator_1 += w_1_omega;
* limb_accumulator_1 *= SUBLIMB_SHIFT;
* limb_accumulator_1 += w_3;
* limb_accumulator_1 *= SUBLIMB_SHIFT;
* limb_accumulator_1 += w_2;
* limb_accumulator_1 *= SUBLIMB_SHIFT;
* limb_accumulator_1 += w_1;
* limb_accumulator_1 -= w_4;
* limb_accumulator_1 *= q_4;
*/
let limb_accumulator_1 := mulmod(mload(W2_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p)
limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_OMEGA_EVAL_LOC), p)
limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p)
limb_accumulator_1 := addmod(limb_accumulator_1, mload(W3_EVAL_LOC), p)
limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p)
limb_accumulator_1 := addmod(limb_accumulator_1, mload(W2_EVAL_LOC), p)
limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p)
limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_EVAL_LOC), p)
limb_accumulator_1 := addmod(limb_accumulator_1, sub(p, mload(W4_EVAL_LOC)), p)
limb_accumulator_1 := mulmod(limb_accumulator_1, mload(Q4_EVAL_LOC), p)
/**
* limb_accumulator_2 = w_3_omega;
* limb_accumulator_2 *= SUBLIMB_SHIFT;
* limb_accumulator_2 += w_2_omega;
* limb_accumulator_2 *= SUBLIMB_SHIFT;
* limb_accumulator_2 += w_1_omega;
* limb_accumulator_2 *= SUBLIMB_SHIFT;
* limb_accumulator_2 += w_4;
* limb_accumulator_2 *= SUBLIMB_SHIFT;
* limb_accumulator_2 += w_3;
* limb_accumulator_2 -= w_4_omega;
* limb_accumulator_2 *= q_m;
*/
let limb_accumulator_2 := mulmod(mload(W3_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p)
limb_accumulator_2 := addmod(limb_accumulator_2, mload(W2_OMEGA_EVAL_LOC), p)
limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p)
limb_accumulator_2 := addmod(limb_accumulator_2, mload(W1_OMEGA_EVAL_LOC), p)
limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p)
limb_accumulator_2 := addmod(limb_accumulator_2, mload(W4_EVAL_LOC), p)
limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p)
limb_accumulator_2 := addmod(limb_accumulator_2, mload(W3_EVAL_LOC), p)
limb_accumulator_2 := addmod(limb_accumulator_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p)
limb_accumulator_2 := mulmod(limb_accumulator_2, mload(QM_EVAL_LOC), p)
mstore(
AUX_LIMB_ACCUMULATOR_EVALUATION,
mulmod(addmod(limb_accumulator_1, limb_accumulator_2, p), mload(Q3_EVAL_LOC), p)
)
}
{
/**
* memory_record_check = w_3;
* memory_record_check *= eta;
* memory_record_check += w_2;
* memory_record_check *= eta;
* memory_record_check += w_1;
* memory_record_check *= eta;
* memory_record_check += q_c;
*
* partial_record_check = memory_record_check;
*
* memory_record_check -= w_4;
*/
let memory_record_check := mulmod(mload(W3_EVAL_LOC), mload(C_ETA_LOC), p)
memory_record_check := addmod(memory_record_check, mload(W2_EVAL_LOC), p)
memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p)
memory_record_check := addmod(memory_record_check, mload(W1_EVAL_LOC), p)
memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p)
memory_record_check := addmod(memory_record_check, mload(QC_EVAL_LOC), p)
let partial_record_check := memory_record_check
memory_record_check := addmod(memory_record_check, sub(p, mload(W4_EVAL_LOC)), p)
mstore(AUX_MEMORY_EVALUATION, memory_record_check)
// index_delta = w_1_omega - w_1
let index_delta := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p)
// record_delta = w_4_omega - w_4
let record_delta := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p)
// index_is_monotonically_increasing = index_delta * (index_delta - 1)
let index_is_monotonically_increasing := mulmod(index_delta, addmod(index_delta, sub(p, 1), p), p)
// adjacent_values_match_if_adjacent_indices_match = record_delta * (1 - index_delta)
let adjacent_values_match_if_adjacent_indices_match :=
mulmod(record_delta, addmod(1, sub(p, index_delta), p), p)
// AUX_ROM_CONSISTENCY_EVALUATION = ((adjacent_values_match_if_adjacent_indices_match * alpha) + index_is_monotonically_increasing) * alpha + partial_record_check
mstore(
AUX_ROM_CONSISTENCY_EVALUATION,
addmod(
mulmod(
addmod(
mulmod(adjacent_values_match_if_adjacent_indices_match, mload(C_ALPHA_LOC), p),
index_is_monotonically_increasing,
p
),
mload(C_ALPHA_LOC),
p
),
memory_record_check,
p
)
)
{
/**
* next_gate_access_type = w_3_omega;
* next_gate_access_type *= eta;
* next_gate_access_type += w_2_omega;
* next_gate_access_type *= eta;
* next_gate_access_type += w_1_omega;
* next_gate_access_type *= eta;
* next_gate_access_type = w_4_omega - next_gate_access_type;
*/
let next_gate_access_type := mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p)
next_gate_access_type := addmod(next_gate_access_type, mload(W2_OMEGA_EVAL_LOC), p)
next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p)
next_gate_access_type := addmod(next_gate_access_type, mload(W1_OMEGA_EVAL_LOC), p)
next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p)
next_gate_access_type := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, next_gate_access_type), p)
// value_delta = w_3_omega - w_3
let value_delta := addmod(mload(W3_OMEGA_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p)
// adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = (1 - index_delta) * value_delta * (1 - next_gate_access_type);
let adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation :=
mulmod(
addmod(1, sub(p, index_delta), p),
mulmod(value_delta, addmod(1, sub(p, next_gate_access_type), p), p),
p
)
// AUX_RAM_CONSISTENCY_EVALUATION
/**
* access_type = w_4 - partial_record_check
* access_check = access_type^2 - access_type
* next_gate_access_type_is_boolean = next_gate_access_type^2 - next_gate_access_type
* RAM_consistency_check_identity = adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation;
* RAM_consistency_check_identity *= alpha;
* RAM_consistency_check_identity += index_is_monotonically_increasing;
* RAM_consistency_check_identity *= alpha;
* RAM_consistency_check_identity += next_gate_access_type_is_boolean;
* RAM_consistency_check_identity *= alpha;
* RAM_consistency_check_identity += access_check;
*/
let access_type := addmod(mload(W4_EVAL_LOC), sub(p, partial_record_check), p)
let access_check := mulmod(access_type, addmod(access_type, sub(p, 1), p), p)
let next_gate_access_type_is_boolean :=
mulmod(next_gate_access_type, addmod(next_gate_access_type, sub(p, 1), p), p)
let RAM_cci :=
mulmod(
adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation,
mload(C_ALPHA_LOC),
p
)
RAM_cci := addmod(RAM_cci, index_is_monotonically_increasing, p)
RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p)
RAM_cci := addmod(RAM_cci, next_gate_access_type_is_boolean, p)
RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p)
RAM_cci := addmod(RAM_cci, access_check, p)
mstore(AUX_RAM_CONSISTENCY_EVALUATION, RAM_cci)
}
{
// timestamp_delta = w_2_omega - w_2
let timestamp_delta := addmod(mload(W2_OMEGA_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p)
// RAM_timestamp_check_identity = (1 - index_delta) * timestamp_delta - w_3
let RAM_timestamp_check_identity :=
addmod(
mulmod(timestamp_delta, addmod(1, sub(p, index_delta), p), p), sub(p, mload(W3_EVAL_LOC)), p
)
/**
* memory_identity = ROM_consistency_check_identity * q_2;
* memory_identity += RAM_timestamp_check_identity * q_4;
* memory_identity += memory_record_check * q_m;
* memory_identity *= q_1;
* memory_identity += (RAM_consistency_check_identity * q_arith);
*
* auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity;
* auxiliary_identity *= q_aux;
* auxiliary_identity *= alpha_base;
*/
let memory_identity := mulmod(mload(AUX_ROM_CONSISTENCY_EVALUATION), mload(Q2_EVAL_LOC), p)
memory_identity :=
addmod(memory_identity, mulmod(RAM_timestamp_check_identity, mload(Q4_EVAL_LOC), p), p)
memory_identity :=
addmod(memory_identity, mulmod(mload(AUX_MEMORY_EVALUATION), mload(QM_EVAL_LOC), p), p)
memory_identity := mulmod(memory_identity, mload(Q1_EVAL_LOC), p)
memory_identity :=
addmod(
memory_identity, mulmod(mload(AUX_RAM_CONSISTENCY_EVALUATION), mload(QARITH_EVAL_LOC), p), p
)
let auxiliary_identity := addmod(memory_identity, mload(AUX_NON_NATIVE_FIELD_EVALUATION), p)
auxiliary_identity := addmod(auxiliary_identity, mload(AUX_LIMB_ACCUMULATOR_EVALUATION), p)
auxiliary_identity := mulmod(auxiliary_identity, mload(QAUX_EVAL_LOC), p)
auxiliary_identity := mulmod(auxiliary_identity, mload(C_ALPHA_BASE_LOC), p)
mstore(AUX_IDENTITY, auxiliary_identity)
// update alpha
mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p))
}
}
}
{
/**
* quotient = ARITHMETIC_IDENTITY
* quotient += PERMUTATION_IDENTITY
* quotient += PLOOKUP_IDENTITY
* quotient += SORT_IDENTITY
* quotient += ELLIPTIC_IDENTITY
* quotient += AUX_IDENTITY
* quotient *= ZERO_POLY_INVERSE
*/
mstore(
QUOTIENT_EVAL_LOC,
mulmod(
addmod(
addmod(
addmod(
addmod(
addmod(mload(PERMUTATION_IDENTITY), mload(PLOOKUP_IDENTITY), p),
mload(ARITHMETIC_IDENTITY),
p
),
mload(SORT_IDENTITY),
p
),
mload(ELLIPTIC_IDENTITY),
p
),
mload(AUX_IDENTITY),
p
),
mload(ZERO_POLY_INVERSE_LOC),
p
)
)
}
/**
* GENERATE NU AND SEPARATOR CHALLENGES
*/
{
let current_challenge := mload(C_CURRENT_LOC)
// get a calldata pointer that points to the start of the data we want to copy
let calldata_ptr := add(calldataload(0x04), 0x24)
calldata_ptr := add(calldata_ptr, NU_CALLDATA_SKIP_LENGTH)
mstore(NU_CHALLENGE_INPUT_LOC_A, current_challenge)
mstore(NU_CHALLENGE_INPUT_LOC_B, mload(QUOTIENT_EVAL_LOC))
calldatacopy(NU_CHALLENGE_INPUT_LOC_C, calldata_ptr, NU_INPUT_LENGTH)
// hash length = (0x20 + num field elements), we include the previous challenge in the hash
let challenge := keccak256(NU_CHALLENGE_INPUT_LOC_A, add(NU_INPUT_LENGTH, 0x40))
mstore(C_V0_LOC, mod(challenge, p))
// We need THIRTY-ONE independent nu challenges!
mstore(0x00, challenge)
mstore8(0x20, 0x01)
mstore(C_V1_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x02)
mstore(C_V2_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x03)
mstore(C_V3_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x04)
mstore(C_V4_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x05)
mstore(C_V5_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x06)
mstore(C_V6_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x07)
mstore(C_V7_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x08)
mstore(C_V8_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x09)
mstore(C_V9_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x0a)
mstore(C_V10_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x0b)
mstore(C_V11_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x0c)
mstore(C_V12_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x0d)
mstore(C_V13_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x0e)
mstore(C_V14_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x0f)
mstore(C_V15_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x10)
mstore(C_V16_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x11)
mstore(C_V17_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x12)
mstore(C_V18_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x13)
mstore(C_V19_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x14)
mstore(C_V20_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x15)
mstore(C_V21_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x16)
mstore(C_V22_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x17)
mstore(C_V23_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x18)
mstore(C_V24_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x19)
mstore(C_V25_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x1a)
mstore(C_V26_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x1b)
mstore(C_V27_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x1c)
mstore(C_V28_LOC, mod(keccak256(0x00, 0x21), p))
mstore8(0x20, 0x1d)
mstore(C_V29_LOC, mod(keccak256(0x00, 0x21), p))
// @follow-up - Why are both v29 and v30 using appending 0x1d to the prior challenge and hashing, should it not change?
mstore8(0x20, 0x1d)
challenge := keccak256(0x00, 0x21)
mstore(C_V30_LOC, mod(challenge, p))
// separator
mstore(0x00, challenge)
mstore(0x20, mload(PI_Z_Y_LOC))
mstore(0x40, mload(PI_Z_X_LOC))
mstore(0x60, mload(PI_Z_OMEGA_Y_LOC))
mstore(0x80, mload(PI_Z_OMEGA_X_LOC))
mstore(C_U_LOC, mod(keccak256(0x00, 0xa0), p))
}
let success := 0
// VALIDATE T1
{
let x := mload(T1_X_LOC)
let y := mload(T1_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))
mstore(ACCUMULATOR_X_LOC, x)
mstore(add(ACCUMULATOR_X_LOC, 0x20), y)
}
// VALIDATE T2
{
let x := mload(T2_X_LOC) // 0x1400
let y := mload(T2_Y_LOC) // 0x1420
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mload(ZETA_POW_N_LOC))
// accumulator_2 = [T2].zeta^n
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = [T1] + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE T3
{
let x := mload(T3_X_LOC)
let y := mload(T3_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p))
// accumulator_2 = [T3].zeta^{2n}
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE T4
{
let x := mload(T4_X_LOC)
let y := mload(T4_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mulmod(mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p), mload(ZETA_POW_N_LOC), p))
// accumulator_2 = [T4].zeta^{3n}
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE W1
{
let x := mload(W1_X_LOC)
let y := mload(W1_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V0_LOC), p))
// accumulator_2 = v0.(u + 1).[W1]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE W2
{
let x := mload(W2_X_LOC)
let y := mload(W2_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V1_LOC), p))
// accumulator_2 = v1.(u + 1).[W2]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE W3
{
let x := mload(W3_X_LOC)
let y := mload(W3_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V2_LOC), p))
// accumulator_2 = v2.(u + 1).[W3]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE W4
{
let x := mload(W4_X_LOC)
let y := mload(W4_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V3_LOC), p))
// accumulator_2 = v3.(u + 1).[W4]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE S
{
let x := mload(S_X_LOC)
let y := mload(S_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V4_LOC), p))
// accumulator_2 = v4.(u + 1).[S]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE Z
{
let x := mload(Z_X_LOC)
let y := mload(Z_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V5_LOC), p))
// accumulator_2 = v5.(u + 1).[Z]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE Z_LOOKUP
{
let x := mload(Z_LOOKUP_X_LOC)
let y := mload(Z_LOOKUP_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V6_LOC), p))
// accumulator_2 = v6.(u + 1).[Z_LOOKUP]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE Q1
{
let x := mload(Q1_X_LOC)
let y := mload(Q1_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mload(C_V7_LOC))
// accumulator_2 = v7.[Q1]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE Q2
{
let x := mload(Q2_X_LOC)
let y := mload(Q2_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mload(C_V8_LOC))
// accumulator_2 = v8.[Q2]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE Q3
{
let x := mload(Q3_X_LOC)
let y := mload(Q3_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mload(C_V9_LOC))
// accumulator_2 = v9.[Q3]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE Q4
{
let x := mload(Q4_X_LOC)
let y := mload(Q4_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mload(C_V10_LOC))
// accumulator_2 = v10.[Q4]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE QM
{
let x := mload(QM_X_LOC)
let y := mload(QM_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mload(C_V11_LOC))
// accumulator_2 = v11.[Q;]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE QC
{
let x := mload(QC_X_LOC)
let y := mload(QC_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mload(C_V12_LOC))
// accumulator_2 = v12.[QC]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE QARITH
{
let x := mload(QARITH_X_LOC)
let y := mload(QARITH_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mload(C_V13_LOC))
// accumulator_2 = v13.[QARITH]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE QSORT
{
let x := mload(QSORT_X_LOC)
let y := mload(QSORT_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mload(C_V14_LOC))
// accumulator_2 = v14.[QSORT]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE QELLIPTIC
{
let x := mload(QELLIPTIC_X_LOC)
let y := mload(QELLIPTIC_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mload(C_V15_LOC))
// accumulator_2 = v15.[QELLIPTIC]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE QAUX
{
let x := mload(QAUX_X_LOC)
let y := mload(QAUX_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mload(C_V16_LOC))
// accumulator_2 = v15.[Q_AUX]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE SIGMA1
{
let x := mload(SIGMA1_X_LOC)
let y := mload(SIGMA1_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mload(C_V17_LOC))
// accumulator_2 = v17.[sigma1]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE SIGMA2
{
let x := mload(SIGMA2_X_LOC)
let y := mload(SIGMA2_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mload(C_V18_LOC))
// accumulator_2 = v18.[sigma2]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE SIGMA3
{
let x := mload(SIGMA3_X_LOC)
let y := mload(SIGMA3_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mload(C_V19_LOC))
// accumulator_2 = v19.[sigma3]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE SIGMA4
{
let x := mload(SIGMA4_X_LOC)
let y := mload(SIGMA4_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mload(C_V20_LOC))
// accumulator_2 = v20.[sigma4]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE TABLE1
{
let x := mload(TABLE1_X_LOC)
let y := mload(TABLE1_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V21_LOC), p))
// accumulator_2 = u.[table1]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE TABLE2
{
let x := mload(TABLE2_X_LOC)
let y := mload(TABLE2_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V22_LOC), p))
// accumulator_2 = u.[table2]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE TABLE3
{
let x := mload(TABLE3_X_LOC)
let y := mload(TABLE3_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V23_LOC), p))
// accumulator_2 = u.[table3]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE TABLE4
{
let x := mload(TABLE4_X_LOC)
let y := mload(TABLE4_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V24_LOC), p))
// accumulator_2 = u.[table4]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE TABLE_TYPE
{
let x := mload(TABLE_TYPE_X_LOC)
let y := mload(TABLE_TYPE_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mload(C_V25_LOC))
// accumulator_2 = v25.[TableType]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE ID1
{
let x := mload(ID1_X_LOC)
let y := mload(ID1_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mload(C_V26_LOC))
// accumulator_2 = v26.[ID1]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE ID2
{
let x := mload(ID2_X_LOC)
let y := mload(ID2_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mload(C_V27_LOC))
// accumulator_2 = v27.[ID2]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE ID3
{
let x := mload(ID3_X_LOC)
let y := mload(ID3_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mload(C_V28_LOC))
// accumulator_2 = v28.[ID3]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE ID4
{
let x := mload(ID4_X_LOC)
let y := mload(ID4_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mload(C_V29_LOC))
// accumulator_2 = v29.[ID4]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
/**
* COMPUTE BATCH EVALUATION SCALAR MULTIPLIER
*/
{
/**
* batch_evaluation = v0 * (w_1_omega * u + w_1_eval)
* batch_evaluation += v1 * (w_2_omega * u + w_2_eval)
* batch_evaluation += v2 * (w_3_omega * u + w_3_eval)
* batch_evaluation += v3 * (w_4_omega * u + w_4_eval)
* batch_evaluation += v4 * (s_omega_eval * u + s_eval)
* batch_evaluation += v5 * (z_omega_eval * u + z_eval)
* batch_evaluation += v6 * (z_lookup_omega_eval * u + z_lookup_eval)
*/
let batch_evaluation :=
mulmod(
mload(C_V0_LOC),
addmod(mulmod(mload(W1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W1_EVAL_LOC), p),
p
)
batch_evaluation :=
addmod(
batch_evaluation,
mulmod(
mload(C_V1_LOC),
addmod(mulmod(mload(W2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W2_EVAL_LOC), p),
p
),
p
)
batch_evaluation :=
addmod(
batch_evaluation,
mulmod(
mload(C_V2_LOC),
addmod(mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W3_EVAL_LOC), p),
p
),
p
)
batch_evaluation :=
addmod(
batch_evaluation,
mulmod(
mload(C_V3_LOC),
addmod(mulmod(mload(W4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W4_EVAL_LOC), p),
p
),
p
)
batch_evaluation :=
addmod(
batch_evaluation,
mulmod(
mload(C_V4_LOC),
addmod(mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(S_EVAL_LOC), p),
p
),
p
)
batch_evaluation :=
addmod(
batch_evaluation,
mulmod(
mload(C_V5_LOC),
addmod(mulmod(mload(Z_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_EVAL_LOC), p),
p
),
p
)
batch_evaluation :=
addmod(
batch_evaluation,
mulmod(
mload(C_V6_LOC),
addmod(mulmod(mload(Z_LOOKUP_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_LOOKUP_EVAL_LOC), p),
p
),
p
)
/**
* batch_evaluation += v7 * Q1_EVAL
* batch_evaluation += v8 * Q2_EVAL
* batch_evaluation += v9 * Q3_EVAL
* batch_evaluation += v10 * Q4_EVAL
* batch_evaluation += v11 * QM_EVAL
* batch_evaluation += v12 * QC_EVAL
* batch_evaluation += v13 * QARITH_EVAL
* batch_evaluation += v14 * QSORT_EVAL_LOC
* batch_evaluation += v15 * QELLIPTIC_EVAL_LOC
* batch_evaluation += v16 * QAUX_EVAL_LOC
* batch_evaluation += v17 * SIGMA1_EVAL_LOC
* batch_evaluation += v18 * SIGMA2_EVAL_LOC
* batch_evaluation += v19 * SIGMA3_EVAL_LOC
* batch_evaluation += v20 * SIGMA4_EVAL_LOC
*/
batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V7_LOC), mload(Q1_EVAL_LOC), p), p)
batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V8_LOC), mload(Q2_EVAL_LOC), p), p)
batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V9_LOC), mload(Q3_EVAL_LOC), p), p)
batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V10_LOC), mload(Q4_EVAL_LOC), p), p)
batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V11_LOC), mload(QM_EVAL_LOC), p), p)
batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V12_LOC), mload(QC_EVAL_LOC), p), p)
batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V13_LOC), mload(QARITH_EVAL_LOC), p), p)
batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V14_LOC), mload(QSORT_EVAL_LOC), p), p)
batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V15_LOC), mload(QELLIPTIC_EVAL_LOC), p), p)
batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V16_LOC), mload(QAUX_EVAL_LOC), p), p)
batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V17_LOC), mload(SIGMA1_EVAL_LOC), p), p)
batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V18_LOC), mload(SIGMA2_EVAL_LOC), p), p)
batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V19_LOC), mload(SIGMA3_EVAL_LOC), p), p)
batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V20_LOC), mload(SIGMA4_EVAL_LOC), p), p)
/**
* batch_evaluation += v21 * (table1(zw) * u + table1(z))
* batch_evaluation += v22 * (table2(zw) * u + table2(z))
* batch_evaluation += v23 * (table3(zw) * u + table3(z))
* batch_evaluation += v24 * (table4(zw) * u + table4(z))
* batch_evaluation += v25 * table_type_eval
* batch_evaluation += v26 * id1_eval
* batch_evaluation += v27 * id2_eval
* batch_evaluation += v28 * id3_eval
* batch_evaluation += v29 * id4_eval
* batch_evaluation += quotient_eval
*/
batch_evaluation :=
addmod(
batch_evaluation,
mulmod(
mload(C_V21_LOC),
addmod(mulmod(mload(TABLE1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE1_EVAL_LOC), p),
p
),
p
)
batch_evaluation :=
addmod(
batch_evaluation,
mulmod(
mload(C_V22_LOC),
addmod(mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE2_EVAL_LOC), p),
p
),
p
)
batch_evaluation :=
addmod(
batch_evaluation,
mulmod(
mload(C_V23_LOC),
addmod(mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE3_EVAL_LOC), p),
p
),
p
)
batch_evaluation :=
addmod(
batch_evaluation,
mulmod(
mload(C_V24_LOC),
addmod(mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE4_EVAL_LOC), p),
p
),
p
)
batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V25_LOC), mload(TABLE_TYPE_EVAL_LOC), p), p)
batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V26_LOC), mload(ID1_EVAL_LOC), p), p)
batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V27_LOC), mload(ID2_EVAL_LOC), p), p)
batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V28_LOC), mload(ID3_EVAL_LOC), p), p)
batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V29_LOC), mload(ID4_EVAL_LOC), p), p)
batch_evaluation := addmod(batch_evaluation, mload(QUOTIENT_EVAL_LOC), p)
mstore(0x00, 0x01) // [1].x
mstore(0x20, 0x02) // [1].y
mstore(0x40, sub(p, batch_evaluation))
// accumulator_2 = -[1].(batch_evaluation)
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
mstore(OPENING_COMMITMENT_SUCCESS_FLAG, success)
}
/**
* PERFORM PAIRING PREAMBLE
*/
{
let u := mload(C_U_LOC)
let zeta := mload(C_ZETA_LOC)
// VALIDATE PI_Z
{
let x := mload(PI_Z_X_LOC)
let y := mload(PI_Z_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))
mstore(0x00, x)
mstore(0x20, y)
}
// compute zeta.[PI_Z] and add into accumulator
mstore(0x40, zeta)
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40))
// VALIDATE PI_Z_OMEGA
{
let x := mload(PI_Z_OMEGA_X_LOC)
let y := mload(PI_Z_OMEGA_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
mstore(0x40, mulmod(mulmod(u, zeta, p), mload(OMEGA_LOC), p))
// accumulator_2 = u.zeta.omega.[PI_Z_OMEGA]
success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40))
// PAIRING_RHS = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, PAIRING_RHS_X_LOC, 0x40))
mstore(0x00, mload(PI_Z_X_LOC))
mstore(0x20, mload(PI_Z_Y_LOC))
mstore(0x40, mload(PI_Z_OMEGA_X_LOC))
mstore(0x60, mload(PI_Z_OMEGA_Y_LOC))
mstore(0x80, u)
success := and(success, staticcall(gas(), 7, 0x40, 0x60, 0x40, 0x40))
// PAIRING_LHS = [PI_Z] + [PI_Z_OMEGA] * u
success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40))
// negate lhs y-coordinate
mstore(PAIRING_LHS_Y_LOC, sub(q, mload(PAIRING_LHS_Y_LOC)))
if mload(CONTAINS_RECURSIVE_PROOF_LOC) {
// VALIDATE RECURSIVE P1
{
let x := mload(RECURSIVE_P1_X_LOC)
let y := mload(RECURSIVE_P1_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
// compute u.u.[recursive_p1] and write into 0x60
mstore(0x40, mulmod(u, u, p))
success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x60, 0x40))
// VALIDATE RECURSIVE P2
{
let x := mload(RECURSIVE_P2_X_LOC)
let y := mload(RECURSIVE_P2_Y_LOC)
let xx := mulmod(x, x, q)
// validate on curve
success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)))
mstore(0x00, x)
mstore(0x20, y)
}
// compute u.u.[recursive_p2] and write into 0x00
// 0x40 still contains u*u
success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x00, 0x40))
// compute u.u.[recursiveP1] + rhs and write into rhs
mstore(0xa0, mload(PAIRING_RHS_X_LOC))
mstore(0xc0, mload(PAIRING_RHS_Y_LOC))
success := and(success, staticcall(gas(), 6, 0x60, 0x80, PAIRING_RHS_X_LOC, 0x40))
// compute u.u.[recursiveP2] + lhs and write into lhs
mstore(0x40, mload(PAIRING_LHS_X_LOC))
mstore(0x60, mload(PAIRING_LHS_Y_LOC))
success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40))
}
if iszero(success) {
mstore(0x0, EC_SCALAR_MUL_FAILURE_SELECTOR)
revert(0x00, 0x04)
}
mstore(PAIRING_PREAMBLE_SUCCESS_FLAG, success)
}
/**
* PERFORM PAIRING
*/
{
// rhs paired with [1]_2
// lhs paired with [x]_2
mstore(0x00, mload(PAIRING_RHS_X_LOC))
mstore(0x20, mload(PAIRING_RHS_Y_LOC))
mstore(0x40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) // this is [1]_2
mstore(0x60, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed)
mstore(0x80, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b)
mstore(0xa0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa)
mstore(0xc0, mload(PAIRING_LHS_X_LOC))
mstore(0xe0, mload(PAIRING_LHS_Y_LOC))
mstore(0x100, mload(G2X_X0_LOC))
mstore(0x120, mload(G2X_X1_LOC))
mstore(0x140, mload(G2X_Y0_LOC))
mstore(0x160, mload(G2X_Y1_LOC))
success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20)
mstore(PAIRING_SUCCESS_FLAG, success)
mstore(RESULT_FLAG, mload(0x00))
}
if iszero(
and(
and(and(mload(PAIRING_SUCCESS_FLAG), mload(RESULT_FLAG)), mload(PAIRING_PREAMBLE_SUCCESS_FLAG)),
mload(OPENING_COMMITMENT_SUCCESS_FLAG)
)
) {
mstore(0x0, PROOF_FAILURE_SELECTOR)
revert(0x00, 0x04)
}
{
mstore(0x00, 0x01)
return(0x00, 0x20) // Proof succeeded!
}
}
}
}
contract UltraVerifier is BaseUltraVerifier {
function getVerificationKeyHash() public pure override(BaseUltraVerifier) returns (bytes32) {
return UltraVerificationKey.verificationKeyHash();
}
function loadVerificationKey(uint256 vk, uint256 _omegaInverseLoc) internal pure virtual override(BaseUltraVerifier) {
UltraVerificationKey.loadVerificationKey(vk, _omegaInverseLoc);
}
}
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
const config: HardhatUserConfig = {
solidity: {
version: '0.8.10',
settings: {
evmVersion: 'london',
optimizer: { enabled: true, runs: 5000 },
},
},
networks: {
hardhat: {
blockGasLimit: 10000000,
gasPrice: 10,
hardfork: 'istanbul',
},
},
mocha: {
timeout: 200000
}
};
export default config;
\ No newline at end of file
{
"name": "momiji",
"version": "1.0.0",
"description": "",
"scripts": {
"windows-compile": "nargo check && nargo compile p && nargo codegen-verifier && copy .\\contract\\plonk_vk.sol ..\\..\\contracts\\plonk_vk.sol",
"compile": "nargo check && nargo compile main && nargo codegen-verifier && cp ./contract/plonk_vk.sol ./contracts/plonk_vk.sol",
"test": "npx hardhat test ./test/transfer.test.mjs"
},
"repository": {
"type": "git",
"url": "git+https://open.offshift.io"
},
"author": "",
"license": "MIT",
"homepage": "https://open.offshift.io/",
"devDependencies": {
"@ethersproject/abi": "^5.6.4",
"@ethersproject/providers": "^5.6.8",
"@nomicfoundation/hardhat-chai-matchers": "^1.0.2",
"@nomicfoundation/hardhat-network-helpers": "^1.0.3",
"@nomicfoundation/hardhat-toolbox": "^1.0.2",
"@nomiclabs/hardhat-ethers": "^2.2.2",
"@nomiclabs/hardhat-etherscan": "^3.1.0",
"@openzeppelin/hardhat-upgrades": "^1.19.1",
"@typechain/hardhat": "^6.1.2",
"@types/memdown": "^3.0.0",
"@types/mocha": "^9.1.1",
"chai": "^4.3.6",
"ethers": "^5.6.9",
"hardhat": "^2.10.1",
"hardhat-gas-reporter": "^1.0.8",
"snarkjs": "^0.4.24",
"solidity-coverage": "^0.7.21",
"ts-node": "^10.9.1",
"typechain": "^8.1.0",
"typescript": "^4.7.4"
},
"dependencies": {
"@aztec/bb.js": "0.3.3",
"@chainlink/contracts": "^0.6.1",
"@openzeppelin/contracts": "^4.7.1",
"@typechain/ethers-v5": "^10.1.0",
"@uniswap/v3-core": "^1.0.1",
"bigint-buffer": "^1.1.5",
"circomlibjs": "^0.1.7",
"keccak256": "^1.0.6",
"sequelize": "^6.32.0",
"sqlite3": "^5.1.6"
}
}
use dep::std;
fn main(
tx_in: pub [Field; 16],
amount_public_in: pub Field,
amount_public_out: pub Field,
commitment_out: pub [Field; 16],
recipient: pub Field,
oracle: pub Field,
old_root: pub Field,
new_root: pub Field,
nullifier_hashes: pub [Field; 16],
secrets: [Field; 16],
utxo_in: [Field; 48],
utxo_out: [Field; 48],
roots: [Field; 64],
leaves: [Field; 64],
indexes: [Field; 64],
hash_path: [Field; 288],
) {
let trees: Field = 4;
let mut sum_in: Field = amount_public_in;
let mut sum_out: Field = amount_public_out;
for i in 0..16 {
if (utxo_in[i*3 + 1] != 0) {
let owner = std::hash::pedersen([secrets[i]]);
assert(owner[0] == utxo_in[i*3 + 0]);
assert(nullifier_hashes[i] == std::hash::pedersen([secrets[i], secrets[i]])[0]);
let commitment_in = std::hash::pedersen([utxo_in[i*3 + 0], utxo_in[i*3 + 1], utxo_in[i*3 + 2]])[0];
let mut hash_path_utxo: [Field; 4] = [0; 4];
let mut hash_path_tx: [Field; 4] = [0; 4];
let mut hash_path_batch: [Field; 5] = [0; 5];
let mut hash_path_historic: [Field; 5] = [0; 5];
for j in 0..4 {
hash_path_utxo[j] = hash_path[18*i + 0 + j];
hash_path_tx[j] = hash_path[18*i + 4 + j];
}
for l in 0..5 {
hash_path_batch[l] = hash_path[18*i + 8 + l];
hash_path_historic[l] = hash_path[18*i + 13 + l];
}
let leaf_tx = leaves[trees * i + 1];
let leaf_batch = leaves[trees * i + 2];
let leaf_historic = leaves[trees * i + 3];
let index_utxo = indexes[trees * i + 0];
let index_tx = indexes[trees * i + 1];
let index_batch = indexes[trees * i + 2];
let index_historic = indexes[trees * i + 3];
let root_tx = roots[trees * i + 1];
let root_batch = roots[trees * i + 2];
let root_historic = roots[trees * i + 3];
let utxo_root = std::merkle::compute_merkle_root(
commitment_in,
index_utxo,
hash_path_utxo
);
assert(utxo_root == leaf_tx);
let tx_root = std::merkle::compute_merkle_root(
leaf_tx,
index_tx,
hash_path_tx
);
assert(tx_root == root_tx);
let batch_root = std::merkle::compute_merkle_root(
leaf_batch,
index_batch,
hash_path_batch
);
assert(batch_root == root_batch);
let historic_root = std::merkle::compute_merkle_root(
leaf_historic,
index_historic,
hash_path_historic
);
assert(historic_root == root_historic);
sum_in += utxo_in[i*3 + 1];
}
}
for k in 0..16 {
if (utxo_out[k*3 + 1] != 0) {
let commitment_out_calc = std::hash::pedersen([utxo_out[k*3 + 0], utxo_out[k*3 + 1], utxo_out[k*3 + 2]]);
assert(commitment_out_calc[0] == commitment_out[k]);
sum_out += utxo_out[k*3 + 1];
}
else {
let zero_hash = 0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725 as Field;
assert(commitment_out[k] == zero_hash);
}
}
let utxo_root_calc: Field = pedersen_tree_four(commitment_out);
assert(tx_in[0] == utxo_root_calc);
let tx_root_calc: Field = pedersen_tree_four(tx_in);
assert(oracle == std::hash::pedersen([0])[0]);
let batch_root_calc: Field = std::hash::pedersen([tx_root_calc, oracle])[0];
let new_root_calc: Field = std::hash::pedersen([batch_root_calc, old_root])[0];
assert(new_root == new_root_calc);
assert(sum_in == sum_out);
assert(recipient == recipient);
}
fn pedersen_tree_four(leaves: [Field; 16]) -> Field {
let mut tx_tree: [Field; 16] = leaves;
for l in 0..8 {
tx_tree[l] = std::hash::pedersen([tx_tree[2*l], tx_tree[2*l + 1]])[0];
}
for l in 0..4 {
tx_tree[l] = std::hash::pedersen([tx_tree[2*l], tx_tree[2*l + 1]])[0];
}
for l in 0..2 {
tx_tree[l] = std::hash::pedersen([tx_tree[2*l], tx_tree[2*l + 1]])[0];
}
std::hash::pedersen([tx_tree[0], tx_tree[1]])[0]
}
import pkg from 'hardhat';
const { ethers } = pkg;
const { provider } = ethers;
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
import { newBarretenbergApiSync } from '@aztec/bb.js/dest/index.js';
import { BigNumber } from "ethers";
import { expect } from "chai";
import path from 'path';
import { execSync } from 'child_process';
import { MerkleTree } from "../utils/MerkleTree.mjs";
import { generateUTXO, generateTestTransaction, generateTestPublish, generateDataToml, randomBytesFr, generateTreeProof } from '../utils/test_helpers.mjs';
import fs from "fs"
describe('It compiles circuit.', () => {
let verifierContract;
before(async () => {
execSync(`nargo check`)
execSync(`nargo compile main`)
if (!fs.existsSync('./contracts/plonk_vk.sol')) {
execSync(`nargo codegen-verifier && cp ./contract/plonk_vk.sol ./contracts/plonk_vk.sol`)
}
});
before('Deploy contract', async () => {
console.log('Deploying verifier contract...')
execSync('npx hardhat compile', { cwd: path.join(__dirname, '../contracts') });
const Verifier = await ethers.getContractFactory('UltraVerifier');
verifierContract = await Verifier.deploy();
const verifierAddr = await verifierContract.deployed();
console.log(`Verifier deployed to ${verifierAddr.address}`);
});
});
let signers;
let recipient, recipient_new;
const api = await newBarretenbergApiSync();
let trees = {
utxo_tree: new MerkleTree(4, api),
tx_tree: new MerkleTree(4, api),
batch_tree: new MerkleTree(5, api),
historic_tree: new MerkleTree(5, api),
utxoTreeOld: new MerkleTree(4, api),
txTreeOld: new MerkleTree(4, api),
batchLeaf: "",
newHistoricRoot: ""
}
let utxoIn = []
let utxoOut = []
let treeProof = []
let data = generateDataToml("0", "0", api)
let amountPublic = {
amountIn: BigInt(0),
amountOut: BigInt(0)
}
before(async () => {
signers = await ethers.getSigners();
recipient = signers[1].address;
recipient = `0x`+ recipient.slice(2).padStart(64, "0")
recipient_new = signers[2].address;
recipient_new = `0x` + recipient_new.slice(2).padStart(64, "0")
});
describe("Private Transfer works with Solidity verifier", () => {
let Verifier, verifierContract, TechnicalPreview, technicalPreviewContract;
before("Set up Verifier contract", async () => {
TechnicalPreview = await ethers.getContractFactory("TechnicalPreview");
Verifier = await ethers.getContractFactory("UltraVerifier");
verifierContract = await Verifier.deploy();
technicalPreviewContract = await TechnicalPreview.deploy(verifierContract.address);
})
it("Deposit works using Solidity verifier", async () => {
console.log("** Generating Test Batch **")
let batchSize0 = 10
let secret0 = []
for (let s = 0; s < batchSize0; s++) {
secret0.push(randomBytesFr(32))
}
let amountsOutUTXO = new Array(10).fill(BigInt(1e17))
utxoOut = generateUTXO(batchSize0, amountsOutUTXO, secret0, api);
amountPublic.amountIn = BigInt(1e18)
generateTestTransaction(utxoIn, utxoOut, trees, treeProof, amountPublic, data, recipient, api)
console.log("** Generating Transaction Proof #1 (Deposit) **")
generateTestPublish(trees, data, api)
execSync(`nargo prove main`)
let proof = fs.readFileSync('./proofs/main.proof').toString()
proof = `0x`+ proof
let amount_public_in,
amount_public_out,
commitment_out,
new_root,
nullifier_hashes,
old_root,
oracle,
tx_in;
eval(fs.readFileSync('./Verifier.toml').toString());
let public_inputs = [
tx_in,
amount_public_in,
amount_public_out,
commitment_out,
recipient,
oracle,
old_root,
new_root,
nullifier_hashes
]
const before = await provider.getBalance(signers[1].address);
const technicalPreviewSigner = technicalPreviewContract.connect(signers[1]);
await technicalPreviewSigner.publish(proof, public_inputs, {value: amount_public_in, gasPrice: '0'});
const after = await provider.getBalance(signers[1].address);
expect(before.sub(after)).to.equal(BigNumber.from(amount_public_in));
utxoIn = utxoOut;
});
it("Private transfer works using Solidity verifier", async () => {
console.log("** Generating Transaction Proof #2 (Withdraw/Transfer) **")
let amountsOutUTXO = new Array(5).fill(BigInt(1e17))
treeProof = generateTreeProof(utxoIn, trees, api)
let batchSize1 = 5
let secret1 = []
for (let s = 0; s < batchSize1; s++) {
secret1.push(randomBytesFr(32))
}
utxoOut = generateUTXO(batchSize1, amountsOutUTXO, secret1, api);
amountPublic.amountIn = BigInt(0);
amountPublic.amountOut = BigInt(5e17);
let oldRoot = data.old_root
let newRoot = data.new_root
data = generateDataToml(oldRoot, newRoot, api)
const before = await provider.getBalance(signers[2].address);
generateTestTransaction(utxoIn, utxoOut, trees, treeProof, amountPublic, data, recipient_new, api)
generateTestPublish(trees, data, api)
execSync(`nargo prove main`)
let proof = fs.readFileSync('./proofs/main.proof').toString()
proof = `0x`+ proof
let amount_public_in,
amount_public_out,
commitment_out,
new_root,
nullifier_hashes,
old_root,
oracle,
tx_in;
eval(fs.readFileSync('./Verifier.toml').toString());
let public_inputs = [
tx_in,
amount_public_in,
amount_public_out,
commitment_out,
recipient_new,
oracle,
old_root,
new_root,
nullifier_hashes
]
await technicalPreviewContract.publish(proof, public_inputs)
const after = await provider.getBalance(signers[2].address);
expect(after.sub(before)).to.equal(BigNumber.from(amount_public_out));
});
});
{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"moduleResolution": "node",
},
"include": ["./test", "./utils"],
"files": ["hardhat.config.ts"]
}
\ No newline at end of file
// @ts-ignore -- no types
import { Fr } from '@aztec/bb.js/dest/types/index.js';
// @ts-ignore -- no types
export function pedersenLeftRight(
barretenberg,
left,
right) {
let leftBuffer = Fr.fromBufferReduce(Buffer.from(left.slice(2), 'hex'));
let rightBuffer = Fr.fromBufferReduce(Buffer.from(right.slice(2), 'hex'));
let hashRes = barretenberg.pedersenPlookupCompressFields(leftBuffer, rightBuffer);
return hashRes.toString('hex')
}
export class MerkleTree {
zeroValue = "0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725"; // sha256("Momiji")
levels;
hashLeftRight;
storage;
zeros;
totalLeaves;
barretenberg;
constructor(
levels,
barretenberg,
defaultLeaves = [],
hashLeftRight = pedersenLeftRight) {
this.levels = levels;
this.hashLeftRight = hashLeftRight;
this.storage = new Map();
this.zeros = [];
this.totalLeaves = 0;
this.barretenberg = barretenberg;
// build zeros depends on tree levels
let currentZero = this.zeroValue;
this.zeros.push(currentZero);
for (let i = 0; i < levels; i++) {
currentZero = this.hashLeftRight(barretenberg, currentZero, currentZero);
this.zeros.push(currentZero);
}
if (defaultLeaves.length > 0) {
this.totalLeaves = defaultLeaves.length;
// store leaves with key value pair
let level = 0;
defaultLeaves.forEach((leaf, index) => {
this.storage.set(MerkleTree.indexToKey(level, index), leaf);
});
// build tree with initial leaves
level++;
let numberOfNodesInLevel = Math.ceil(this.totalLeaves / 2);
for (level; level <= this.levels; level++) {
for (let i = 0; i < numberOfNodesInLevel; i++) {
const leftKey = MerkleTree.indexToKey(level - 1, 2 * i);
const rightKey = MerkleTree.indexToKey(level - 1, 2 * i + 1);
const left = this.storage.get(leftKey);
const right = this.storage.get(rightKey) || this.zeros[level - 1];
if (!left) throw new Error("leftKey not found");
const node = this.hashLeftRight(barretenberg, left, right);
this.storage.set(MerkleTree.indexToKey(level, i), node);
}
numberOfNodesInLevel = Math.ceil(numberOfNodesInLevel / 2);
}
}
}
static indexToKey(level, index) {
return `${level}-${index}`;
}
getIndex(leaf) {
for (const [key, value] of this.storage) {
if (value === leaf) {
return Number(key.split("-")[1]);
}
}
return -1;
}
root() {
return this.storage.get(MerkleTree.indexToKey(this.levels, 0)) || this.zeros[this.levels];
}
proof(indexOfLeaf) {
let pathElements = [];
let pathIndices = [];
const leaf = this.storage.get(MerkleTree.indexToKey(0, indexOfLeaf));
if (!leaf) throw new Error("leaf not found");
// store sibling into pathElements and target's indices into pathIndices
const handleIndex = (level, currentIndex, siblingIndex) => {
const siblingValue = this.storage.get(MerkleTree.indexToKey(level, siblingIndex)) || this.zeros[level];
pathElements.push(siblingValue);
pathIndices.push(currentIndex % 2);
};
this.traverse(indexOfLeaf, handleIndex);
return {
root: this.root(),
pathElements,
pathIndices,
leaf: leaf,
};
}
insert(leaf) {
const index = this.totalLeaves;
this.update(index, leaf, true);
this.totalLeaves++;
}
update(index, newLeaf, isInsert = false) {
if (!isInsert && index >= this.totalLeaves) {
throw Error("Use insert method for new elements.");
} else if (isInsert && index < this.totalLeaves) {
throw Error("Use update method for existing elements.");
}
let keyValueToStore = [];
let currentElement = newLeaf;
const handleIndex = (level, currentIndex, siblingIndex) => {
const siblingElement = this.storage.get(MerkleTree.indexToKey(level, siblingIndex)) || this.zeros[level];
let left;
let right;
if (currentIndex % 2 === 0) {
left = currentElement;
right = siblingElement;
} else {
left = siblingElement;
right = currentElement;
}
keyValueToStore.push({
key: MerkleTree.indexToKey(level, currentIndex),
value: currentElement,
});
currentElement = this.hashLeftRight(this.barretenberg, left, right);
};
this.traverse(index, handleIndex);
// push root to the end
keyValueToStore.push({
key: MerkleTree.indexToKey(this.levels, 0),
value: currentElement,
});
keyValueToStore.forEach(o => {
this.storage.set(o.key, o.value);
});
}
// traverse from leaf to root with handler for target node and sibling node
traverse(indexOfLeaf, handler) {
let currentIndex = indexOfLeaf;
for (let i = 0; i < this.levels; i++) {
let siblingIndex;
if (currentIndex % 2 === 0) {
siblingIndex = currentIndex + 1;
} else {
siblingIndex = currentIndex - 1;
}
handler(i, currentIndex, siblingIndex);
currentIndex = Math.floor(currentIndex / 2);
}
}
}
\ No newline at end of file
import { randomBytes } from 'crypto'
import { readFileSync } from 'fs';
import { Fr } from '@aztec/bb.js/dest/types/index.js';
import { MerkleTree } from './MerkleTree.mjs';
import { keccak256 } from "@ethersproject/keccak256/lib/index.js";
import fs from 'fs'
export function randomBytesFr(numBytes) {
const bytes = randomBytes(numBytes)
const bytesFr = Fr.fromBufferReduce(bytes)
return bytesFr
}
export const format = (data) => {
if (data.length === 0) return "[]"
return `[\n "${data.join('",\n "')}"\n]`;
}
export const dumpToml = (data) => {
data =
`
tx_in = ${format(data.tx_in)}
amount_public_in = "${data.amount_public_in}"
amount_public_out = "${data.amount_public_out}"
commitment_out = ${format(data.commitment_out)}
recipient = "${data.recipient}"
oracle = "${data.oracle}"
old_root = "${data.old_root}"
new_root = "${data.new_root}"
secrets = ${format(data.secrets)}
utxo_in = ${format(data.utxo_in)}
utxo_out = ${format(data.utxo_out)}
roots = ${format(data.roots)}
leaves = ${format(data.leaves)}
indexes = ${format(data.indexes)}
hash_path = ${format(data.hash_path)}
nullifier_hashes = ${format(data.nullifiers)}
`
fs.writeFileSync('./Prover.toml', data);
}
export function path_to_uint8array(path) {
let buffer = readFileSync(path);
return new Uint8Array(buffer);
}
const toFixedHex = (number, pad0x, length = 32) => {
let hexString = number.toString(16).padStart(length * 2, '0');
return (pad0x ? `0x` + hexString : hexString);
}
export function getSolidityHash(asset) {
// Flatten the object
asset = 0;
return keccak256(asset);
}
export function generateHashPathInput(hash_path) {
let hash_path_input = [];
for (var i = 0; i < hash_path.length; i++) {
hash_path_input.push(`0x` + hash_path[i]);
}
return hash_path_input;
}
export function generateUTXO(batchSize, amounts, _secrets, BarretenbergApi) {
let utxos = []
for (let i = 0; i < batchSize; i++) {
let amountBN = amounts[i]
let utxo = {
secret: _secrets[i],
owner: BarretenbergApi.pedersenPlookupCompress([_secrets[i]]),
amountBN: amountBN,
amount: Fr.fromString(toFixedHex(Number(amountBN.toString()), true)),
assetType: Fr.fromBufferReduce(Buffer.from(getSolidityHash(0), 'hex')),
}
utxos.push(utxo)
}
return utxos
}
export function generateTreeProof(utxoIn, trees, BarretenbergApi) {
let treeProof = []
for (let i = 0; i < utxoIn.length; i++) {
let commitment = BarretenbergApi.pedersenPlookupCompress(
[utxoIn[i].owner, utxoIn[i].amount, utxoIn[i].assetType]
).toString()
let proofs = {
utxo: {
leaf: commitment,
index: trees.utxoTreeOld.getIndex(commitment),
root: trees.utxoTreeOld.root(),
hash_path: trees.utxoTreeOld.proof(
trees.utxoTreeOld.getIndex(commitment)
).pathElements
},
tx: {
leaf: trees.utxoTreeOld.root(),
index: trees.txTreeOld.getIndex(trees.utxoTreeOld.root()),
root: trees.txTreeOld.root(),
hash_path: trees.txTreeOld.proof(
trees.txTreeOld.getIndex(trees.utxoTreeOld.root())
).pathElements
},
batch: {
leaf: trees.batchLeaf,
index: trees.batch_tree.getIndex(trees.batchLeaf),
root: trees.batch_tree.root(),
hash_path: trees.batch_tree.proof(
trees.batch_tree.getIndex(trees.batchLeaf)
).pathElements
},
historic: {
leaf: trees.newHistoricRoot,
index: trees.historic_tree.getIndex(trees.newHistoricRoot),
root: trees.historic_tree.root(),
hash_path: trees.historic_tree.proof(
trees.historic_tree.getIndex(trees.newHistoricRoot)
).pathElements
}
}
treeProof.push(proofs)
}
return treeProof
}
export function generateDataToml(oldRoot, newRoot, api) {
let zeroHash = api.pedersenPlookupCompress([Fr.fromString(toFixedHex(0, true))])
const data = {
tx_in: new Array(16).fill('0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725'),
secrets: new Array(16).fill('0'),
utxo_in: new Array(48).fill('0'),
utxo_out: new Array(48).fill('0'),
oracle: zeroHash.toString(),
old_root: "0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
new_root: "0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725",
roots: new Array(64).fill('0'),
leaves: new Array(64).fill('0'),
indexes: new Array(64).fill('0'),
hash_path: new Array(288).fill('0'),
commitment_out: new Array(16).fill('0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725'),
amount_public_in: "0",
amount_public_out: "0",
nullifiers: new Array(16).fill('0'),
recipient: Fr.fromString(toFixedHex(0, true)).toString()
}
if (oldRoot !== "0") data.old_root = oldRoot;
if (newRoot !== "0") data.new_root = newRoot;
return data
}
export function generateTestTransaction(utxoIn, utxoOut, trees, treeProof, amountPublic, data, recipient, BarretenbergApi) {
let utxoInLen = utxoIn.length
let utxoOutLen = utxoOut.length
// UTXOs being spent
for (let i = 0; i < utxoInLen; i++) {
let ownerHex = utxoIn[i].owner.toString();
let amountHex = utxoIn[i].amount.toString();
let assetTypeHex = utxoIn[i].assetType.toString();
let note_commitment = BarretenbergApi.pedersenPlookupCompress([utxoIn[i].owner, utxoIn[i].amount, utxoIn[i].assetType]);
let utxoLeaf = note_commitment.toString()
data.secrets[i] = utxoIn[i].secret
data.nullifiers[i] = BarretenbergApi.pedersenPlookupCompressFields(utxoIn[i].secret, utxoIn[i].secret)
data.utxo_in[i*3 + 0] = ownerHex
data.utxo_in[i*3 + 1] = amountHex
data.utxo_in[i*3 + 2] = assetTypeHex
data.leaves[i*4 + 0] = utxoLeaf
data.leaves[i*4 + 1] = treeProof[i].tx.leaf
data.leaves[i*4 + 2] = treeProof[i].batch.leaf
data.leaves[i*4 + 3] = treeProof[i].historic.leaf
data.indexes[i*4 + 0] = treeProof[i].utxo.index
data.indexes[i*4 + 1] = treeProof[i].tx.index
data.indexes[i*4 + 2] = treeProof[i].batch.index
data.indexes[i*4 + 3] = treeProof[i].historic.index
data.roots[i*4 + 0] = treeProof[i].utxo.root
data.roots[i*4 + 1] = treeProof[i].tx.root
data.roots[i*4 + 2] = treeProof[i].batch.root
data.roots[i*4 + 3] = treeProof[i].historic.root
let utxoPath = treeProof[i].utxo.hash_path
let txPath = treeProof[i].tx.hash_path
let batchPath = treeProof[i].batch.hash_path
let historicPath = treeProof[i].historic.hash_path
for (let j = 0; j < utxoPath.length; j++) {
data.hash_path[i*18 + 0 + j] = utxoPath[j]
data.hash_path[i*18 + 4 + j] = txPath[j]
}
for (let k = 0; k < batchPath.length; k++) {
data.hash_path[i*18 + 8 + k] = batchPath[k]
data.hash_path[i*18 + 13 + k] = historicPath[k]
}
}
// UTXOs being generated
for (let i = 0; i < utxoOutLen; i++) {
let ownerHex = utxoOut[i].owner.toString();
let amountHex = utxoOut[i].amount.toString();
let assetTypeHex = utxoOut[i].assetType.toString();
let note_commitment = BarretenbergApi.pedersenPlookupCompress([utxoOut[i].owner, utxoOut[i].amount, utxoOut[i].assetType]);
let utxoLeaf = note_commitment.toString()
trees.utxo_tree.insert(utxoLeaf)
data.utxo_out[i*3 + 0] = ownerHex
data.utxo_out[i*3 + 1] = amountHex
data.utxo_out[i*3 + 2] = assetTypeHex
data.commitment_out[i] = utxoLeaf
}
data.tx_in[0] = trees.utxo_tree.root()
data.amount_public_in = toFixedHex(Number(amountPublic.amountIn.toString()), true)
data.amount_public_out = toFixedHex(Number(amountPublic.amountOut.toString()), true)
data.recipient = recipient
dumpToml(data)
}
export function generateTestPublish(trees, data, api) {
// Publish our local set of test txs
let utxoTree = trees.utxo_tree
let txTree = trees.tx_tree
let batchTree = trees.batch_tree
let historicTree = trees.historic_tree
let utxoRoot = utxoTree.root()
txTree.insert(utxoRoot)
let txRoot = txTree.root()
let txRootFr = Fr.fromBufferReduce(Buffer.from(txRoot.slice(2), 'hex'))
let oracleFr = Fr.fromBufferReduce(toFixedHex(0, true))
let oracleHash = api.pedersenPlookupCompress([oracleFr])
let batch = api.pedersenPlookupCompressFields(txRootFr, oracleHash)
let batchHex = batch.toString()
batchTree.insert(batchHex)
let oldHistoricRoot = Fr.fromBufferReduce(Buffer.from(data.new_root.slice(2), 'hex'))
let newHistoricRoot = api.pedersenPlookupCompress([batch, oldHistoricRoot])
let newHistoricRootHex = newHistoricRoot.toString()
historicTree.insert(newHistoricRootHex)
data.old_root = oldHistoricRoot.toString()
data.new_root = newHistoricRootHex
// Clearing the utxo tree for the next batch
// Saving the old tree for proofs
trees.utxoTreeOld = trees.utxo_tree
trees.txTreeOld = trees.tx_tree
trees.batchLeaf = batchHex
trees.newHistoricRoot = newHistoricRootHex
trees.utxo_tree = new MerkleTree(4, api)
trees.tx_tree = new MerkleTree(4, api)
dumpToml(data)
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment