diff --git a/README.md b/README.md index 87beeeb..76e8724 100644 --- a/README.md +++ b/README.md @@ -54,4 +54,5 @@ To re-generate contract-helper for correspondent step of Nova verification: python src/verifier/step1/step1-data-contract-gen.py compressed-snark.json > src/verifier/step1/Step1Data.sol python src/verifier/step2/step2-data-contract-gen.py verifier-key.json compressed-snark.json > src/verifier/step2/Step2Data.sol python src/verifier/step3/step3-data-contract-gen.py verifier-key.json compressed-snark.json > src/verifier/step3/Step3Data.sol +python src/verifier/step4/sumcheck-data-contract-gen.py verifier-key.json compressed-snark.json > src/verifier/step4/SumcheckData.sol ``` diff --git a/src/Polynomial.sol b/src/Polynomial.sol new file mode 100644 index 0000000..b3d3623 --- /dev/null +++ b/src/Polynomial.sol @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.16; + +import "src/verifier/step4/EqPolynomial.sol"; + +library PolyLib { + struct UniPoly { + uint256[] coeffs; + } + + struct CompressedUniPoly { + uint256[] coeffs_except_linear_term; + } + + struct SumcheckProof { + PolyLib.CompressedUniPoly[] compressed_polys; + } + + function degree(UniPoly memory poly) public pure returns (uint256) { + return poly.coeffs.length - 1; + } + + function evalAtZero(UniPoly memory poly) public pure returns (uint256) { + return poly.coeffs[0]; + } + + function evalAtOne(UniPoly memory poly, uint256 mod) public pure returns (uint256 result) { + for (uint256 i = 0; i < poly.coeffs.length; i++) { + // result += poly.coeffs[i]; + result = addmod(result, poly.coeffs[i], mod); + } + } + + function evaluate(UniPoly memory poly, uint256 r, uint256 mod) public pure returns (uint256) { + uint256 power = r; + uint256 result = poly.coeffs[0]; + for (uint256 i = 1; i < poly.coeffs.length; i++) { + // result += power * poly.coeffs[i]; + result = addmod(result, mulmod(power, poly.coeffs[i], mod), mod); + // power *= r; + power = mulmod(power, r, mod); + } + + return result; + } + + function negate(uint256 x, uint256 mod) internal pure returns (uint256) { + return mod - (x % mod); + } + + function decompress(CompressedUniPoly calldata poly, uint256 hint, uint256 mod) + public + pure + returns (UniPoly memory) + { + // uint256 linear_term = hint - poly.coeffs_except_linear_term[0] - poly.coeffs_except_linear_term[0]; + uint256 linear_term = addmod( + hint, negate(addmod(poly.coeffs_except_linear_term[0], poly.coeffs_except_linear_term[0], mod), mod), mod + ); + + for (uint256 i = 1; i < poly.coeffs_except_linear_term.length; i++) { + // linear_term -= poly.coeffs_except_linear_term[i]; + linear_term = addmod(linear_term, negate(poly.coeffs_except_linear_term[i], mod), mod); + } + + uint256 coeff_index = 0; + uint256[] memory coeffs = new uint256[]( + poly.coeffs_except_linear_term.length + 1 + ); + coeffs[coeff_index] = poly.coeffs_except_linear_term[0]; + coeff_index++; + coeffs[coeff_index] = linear_term; + coeff_index++; + + for (uint256 i = 1; i < poly.coeffs_except_linear_term.length; i++) { + coeffs[coeff_index] = poly.coeffs_except_linear_term[i]; + coeff_index++; + } + + return UniPoly(coeffs); + } + + function toUInt8Array(uint256 input) private pure returns (uint8[] memory) { + uint8[] memory result = new uint8[](32); + + bytes32 input_bytes = bytes32(input); + + for (uint256 i = 0; i < 32; i++) { + result[i] = uint8(input_bytes[31 - i]); + } + return result; + } + + function toTranscriptBytes(UniPoly memory poly) public pure returns (uint8[] memory) { + uint8[] memory result = new uint8[](32 * (poly.coeffs.length - 1)); + + uint256 offset; + uint8[] memory coeff_bytes = toUInt8Array(poly.coeffs[0]); + for (uint256 i = 0; i < 32; i++) { + result[i] = coeff_bytes[i]; + } + offset += 32; + + for (uint256 i = 2; i < poly.coeffs.length; i++) { + coeff_bytes = toUInt8Array(poly.coeffs[i]); + for (uint256 j = 0; j < 32; j++) { + result[offset + j] = coeff_bytes[j]; + } + offset += 32; + } + + return result; + } +} diff --git a/src/verifier/step4/KeccakTranscript.sol b/src/verifier/step4/KeccakTranscript.sol index 7ba0c10..52a4ee6 100644 --- a/src/verifier/step4/KeccakTranscript.sol +++ b/src/verifier/step4/KeccakTranscript.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.16; import "src/pasta/Vesta.sol"; import "src/pasta/Pallas.sol"; +import "src/Polynomial.sol"; library ScalarFromUniformLib { uint256 private constant SCALAR_UNIFORM_BYTE_SIZE = 64; @@ -325,7 +326,7 @@ library KeccakTranscriptLib { uint32 private constant DOM_SEP_TAG = 0x4e6f4453; uint8 private constant KECCAK256_PREFIX_CHALLENGE_LO = 0x00; uint8 private constant KECCAK256_PREFIX_CHALLENGE_HI = 0x01; - uint256 private constant KECCAK_TRANSCRIPT_STATE_BYTE_LEN = 64; + uint256 public constant KECCAK_TRANSCRIPT_STATE_BYTE_LEN = 64; struct KeccakTranscript { uint16 round; @@ -393,13 +394,12 @@ library KeccakTranscriptLib { return updatedState; } - function absorb(KeccakTranscript memory keccak, uint8[] memory label, uint256 input) + function absorb(KeccakTranscript memory keccak, uint8[] memory label, uint8[] memory input) public pure returns (KeccakTranscript memory) { - // uint256 input will always take 32 bytes - uint8[] memory transcript = new uint8[](keccak.transcript.length + label.length + 32); + uint8[] memory transcript = new uint8[](keccak.transcript.length + label.length + input.length); uint256 index = 0; // TODO think how to make it more efficient (without copying current transcript) // copy current transcript @@ -415,14 +415,115 @@ library KeccakTranscriptLib { index += label.length; // append input - for (uint256 i = 0; i < 32; i++) { - transcript[index + i] = uint8(bytes1(bytes32(input)[31 - i])); + for (uint256 i = 0; i < input.length; i++) { + transcript[index + i] = input[i]; } // TODO This should be workarounded by interacting with the blockchain, that holds the state return KeccakTranscript(keccak.round, keccak.state, transcript); } + function scalarToBytes(uint256 input) private pure returns (uint8[] memory) { + uint8[] memory input_bytes = new uint8[](32); + + for (uint256 i = 0; i < 32; i++) { + input_bytes[i] = uint8(bytes32(input)[31 - i]); + } + + return input_bytes; + } + + function absorb(KeccakTranscript memory keccak, uint8[] memory label, uint256 input) + public + pure + returns (KeccakTranscript memory) + { + uint8[] memory input_bytes = scalarToBytes(input); + return absorb(keccak, label, input_bytes); + } + + function absorb(KeccakTranscript memory keccak, uint8[] memory label, Pallas.PallasAffinePoint memory point) + public + pure + returns (KeccakTranscript memory) + { + uint8 is_infinity; + if (Pallas.isInfinity(point)) { + is_infinity = 0; + } else { + is_infinity = 1; + } + + uint8[] memory x_bytes = scalarToBytes(point.x); + uint8[] memory y_bytes = scalarToBytes(point.y); + + uint8[] memory input = new uint8[](x_bytes.length + y_bytes.length + 1); + + for (uint256 i = 0; i < x_bytes.length; i++) { + input[i] = x_bytes[i]; + } + for (uint256 i = 0; i < y_bytes.length; i++) { + input[x_bytes.length + i] = y_bytes[i]; + } + input[x_bytes.length + y_bytes.length] = is_infinity; + + return absorb(keccak, label, input); + } + + function absorb(KeccakTranscript memory keccak, uint8[] memory label, Vesta.VestaAffinePoint memory point) + public + pure + returns (KeccakTranscript memory) + { + uint8 is_infinity; + if (Vesta.isInfinity(point)) { + is_infinity = 0; + } else { + is_infinity = 1; + } + + uint8[] memory x_bytes = scalarToBytes(point.x); + uint8[] memory y_bytes = scalarToBytes(point.y); + + uint8[] memory input = new uint8[](x_bytes.length + y_bytes.length + 1); + + for (uint256 i = 0; i < x_bytes.length; i++) { + input[i] = x_bytes[i]; + } + for (uint256 i = 0; i < y_bytes.length; i++) { + input[x_bytes.length + i] = y_bytes[i]; + } + input[x_bytes.length + y_bytes.length] = is_infinity; + + return absorb(keccak, label, input); + } + + function absorb(KeccakTranscript memory keccak, uint8[] memory label, uint256[] memory inputs) + public + pure + returns (KeccakTranscript memory) + { + uint8[] memory input = new uint8[](32 * inputs.length); + + for (uint256 i = 0; i < inputs.length; i++) { + uint8[] memory input_bytes = scalarToBytes(inputs[i]); + + for (uint256 j = 0; j < 32; j++) { + input[32 * i + j] = input_bytes[j]; + } + } + + return absorb(keccak, label, input); + } + + function absorb(KeccakTranscript memory keccak, uint8[] memory label, PolyLib.UniPoly memory poly) + public + pure + returns (KeccakTranscript memory) + { + return absorb(keccak, label, PolyLib.toTranscriptBytes(poly)); + } + function squeeze(KeccakTranscript memory keccak, ScalarFromUniformLib.Curve curve, uint8[] memory label) public pure diff --git a/src/verifier/step4/SumcheckData.sol b/src/verifier/step4/SumcheckData.sol new file mode 100644 index 0000000..0b1c722 --- /dev/null +++ b/src/verifier/step4/SumcheckData.sol @@ -0,0 +1,592 @@ +// SPDX-License-Identifier: Apache-2.0 +// Do not change manually. This contract has been auto-generated by src/verifier/step4/sumcheck-data-contract-gen.py +pragma solidity ^0.8.16; + +import "src/Polynomial.sol"; +import "src/verifier/step4/SumcheckLogic.sol"; + +library SumcheckData { + // This function returns a SumcheckProof for the relevant corresponding field + function returnPrimaryOuterData() public pure returns (PolyLib.SumcheckProof memory) { + PolyLib.CompressedUniPoly[] memory proof_array = new PolyLib.CompressedUniPoly[](14); + uint256[] memory poly_array; + PolyLib.CompressedUniPoly memory poly; + poly_array = new uint256[](3); + poly_array[0] = 0x0000000000000000000000000000000000000000000000000000000000000000; + poly_array[1] = 0x3156ab3e1bea772559548817e8d23e4d60a57bc280baf032420e3c6133dd7e2f; + poly_array[2] = 0x1dff490409def9717737be07798dad2c3a6bc952eec88937c6076da01f9d9af0; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[0] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x2a0cd6f39b97ed92a45886a8e80a5944ed373498922050a3745f29c2ec6667ae; + poly_array[1] = 0x12fbd521f3fdb45f92e1bc9d045197000c74f40e67292ccac43f9b65f854b955; + poly_array[2] = 0x0bf922cb074481cf22bfe02c62561af632503238b4198aeb5e2bb5cf8dd0fac3; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[1] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x1a7160ebd6e443d51da504fa28e5168868012deaacfc8188014cde90744297bc; + poly_array[1] = 0x281222608e87d3d0d154e6621dbe68a181e5e646bbaab420859659a0e042dd4c; + poly_array[2] = 0x2ae2df351788ef2c603da9501a93ea6ea1080a1742c923a56e0daa7e0599cd1e; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[2] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x2cadc3a75b23fdebbcef67f3b2d193348ea927786e761d43406e4358d324c4d1; + poly_array[1] = 0x06d2d5a5f516f2734156ed7b78e9687e0a6a52c89456c09af0609fe5b27b1fca; + poly_array[2] = 0x0a1a4cee698d0bea9725c189f39509b1e3fb54dcbf0cfeb0ead4a679e30b6b97; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[3] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x21d36d5eeab44b9e1dab9a1941353a9b259b0e37f8130c97ac45e7ee1ee46e5d; + poly_array[1] = 0x09cd8f4b3cdb357a80b6d967f5c0f33335ba536e76092ed3ac9ce4b576777817; + poly_array[2] = 0x047de779ead5aef11c60969244ec4bdcf2ef7e7081f734a4239cfe4607768d6c; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[4] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x25291aac7c299b973f93613a17c13191037cb2fd01e2eccdf4697deaf0c9a04a; + poly_array[1] = 0x35f26c09cec10804a870e39ef1d192dd5609b1481229da10415680c367fce145; + poly_array[2] = 0x2b37031e0daac3039e35efc738ca354614b0263e45658a0c90de1dccd6735711; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[5] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x02563c53bdabeb954ec43901c61cb5ad9e81c2cb7dd31b9f46f80440078fd7fd; + poly_array[1] = 0x0807ce199363c83d6c6fbeb708cef45c4f96236b7e861812b879de1a205db161; + poly_array[2] = 0x32fcb855b9dd89717b27154af419b9389ad459a36f94730efe771b0f5940f633; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[6] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x2087b996187c4be4d5eb576a9b6d00d315ad25cee961c8f424621a41c6b0c971; + poly_array[1] = 0x1ef0832cd1a4ba98bf66682a990f9c56216fc31b39d2adecc94c5cc9b4031ab8; + poly_array[2] = 0x0b652696a88affcc0ab69d52903bcd3965f262ddf222c3fe2da3af2fa6a0f27a; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[7] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x36a3f10a14df17c5dde2ec64df992874659af5e22e4db23ad1ea73d66807c8ef; + poly_array[1] = 0x09c9b72ebe89f51aec378af41815f75964c4d8f993e5f9b1681e2b21a42385f9; + poly_array[2] = 0x1b75c4dd2c3cb3a62b90b02ea20c4051ca98c9d9c1424a2421f947c12c7d3eb7; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[8] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x2828a18fa8618435b512a4292b9fcea3b150859f50a3e74bb2a3ee15ae88da9c; + poly_array[1] = 0x1964a64964a1859af0d3d333762bbec3a22487ca091e6b89494ce72cef90130a; + poly_array[2] = 0x10e43d7966039b6cc7b1ced16fd886fe1ca375a8485b820f48611b822781226c; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[9] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x3eb95a4f74af56e31c0b35fe7498c938009c9bea670a61a8383dab0c4c429bfe; + poly_array[1] = 0x0dff761d89b94a2551136b0f4df357b400850910295952ad9ee5c2f85123e5e5; + poly_array[2] = 0x13e46518e76c51be58f3748832326568b0c2cd2e683ae9bb4b1ece9b93c56376; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[10] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x26592d33bfd615e40cfe4c9a0b8e56e88a2c8aa00c84f49b783b4f0c1c359706; + poly_array[1] = 0x29f1f0b13ba89df090f4d23bc74060929ca75281737b7200ec6ad66e94e3c1e2; + poly_array[2] = 0x36ede69bcd3a25e759a2b798f83b569a4906b688623ac23529b8cdc12355abc3; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[11] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x05d85babbee109ab6d627a03a8e8ea0d372d96cfa1929cee86ae5af797cb9657; + poly_array[1] = 0x2b9ce21b23851fcce3cc996e5c80da63f8818737d35957b31b0125bccfebe967; + poly_array[2] = 0x15f5eb776094fbed243e952d5c3512ec31b123db1af788fa9686b8b18b7d7168; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[12] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x07e180612d7bd63a41bd64c2e6c1b0c5edbe6fa6f318cba353edb77eecd59bac; + poly_array[1] = 0x1785c227874bcb2e816af7d0b1b39d6369dc3017b21cfdaccbbbdf3e9a63c9ca; + poly_array[2] = 0x3001d35ebe98119d070a55ea1544bcb729493df381bf7c80ffb0203b2956d7c9; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[13] = poly; + return PolyLib.SumcheckProof(proof_array); + } + + // This function returns a SumcheckProof for the relevant corresponding field + function returnPrimaryInnerData() public pure returns (PolyLib.SumcheckProof memory) { + PolyLib.CompressedUniPoly[] memory proof_array = new PolyLib.CompressedUniPoly[](15); + uint256[] memory poly_array; + PolyLib.CompressedUniPoly memory poly; + poly_array = new uint256[](2); + poly_array[0] = 0x1c4716f6500639b9ee9e0a493a76aa7c7aa8196dd10d4eeb40627f83ec901ab3; + poly_array[1] = 0x12ddcbfdc897aea3ddd931a65341be5be2cd518c188a73256a71b0b5d742f87a; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[0] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x1eacd6a8ccb244c64826baf09705d29d8ef995632ed1b70c7e7af712825d19e2; + poly_array[1] = 0x03ef3e2a0f4b278e998da912353b35a0c40e76e67f4d8b8213f2393d8f742b8d; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[1] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x3fec761f5f12b29c168cc1fe7b27254666e8fed9d0eefbc314e634e30ef07d92; + poly_array[1] = 0x1d16b757b0e8d062872b6d3c5958e93ce78bf3e31be62d1b7ebf4c35c93c21fe; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[2] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x069a0ee19958d15bfed6947ab0a689a0f6e4384f651407760e1045e363015b9b; + poly_array[1] = 0x1e154ecac18821ead0126f8a850c4a9fc7c06e9078af0eb02a5362c2ab19ddba; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[3] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x0960f1909773fd0cd0142c4f988a17be72b09d5542276c24b10ac96c9f964b88; + poly_array[1] = 0x004fdcee2f0b851cd672ea49de9760f69e56fb6d7fec59445daba272d849dc06; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[4] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x21b81234955853a2affe69496b2831035b90d5b31eefd3bda3fdad37974efeab; + poly_array[1] = 0x22f8ec817975e9313c8ee3a49b477633ad32819965e0a6e6d821691a510eeb0b; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[5] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x38a2603ead84692ace689ec57ebe7cec1a9453fd2919c650b048740c8a2c39e3; + poly_array[1] = 0x254b089648bcfb1ac112cf795a7189a93555820e2e9489d0eeee4513a166e793; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[6] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x178f3b3f5ff04fd87346830452d7b923df016a390bc502f6ffe557120744290e; + poly_array[1] = 0x1b849c9bb28d386b2b3adad7183f80dea1242964ccb38188937129ba5fbc3a7a; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[7] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x02d85bd61ed1849b2f3e7b9be14a86055723a97303f0df2b04a533bffa285c16; + poly_array[1] = 0x3b4bbb46b769c1725e934257a561e01248e8876d9c8197c8b4a4f62ff53cbd65; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[8] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x102abddb1ed3784b298cd43c10ffabfed2d649332fb82ab7027daef4c6e6f845; + poly_array[1] = 0x3d57a9cf5588852f198f874e37ea5db4dc46a684c2d9a9b2186fdf60c497ce6a; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[9] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x020391cbc46173b9e1908c9f90bfbbf44ccd3328112f1a42482099dd60eb822e; + poly_array[1] = 0x1b2f8805ccd6bb1855294ac62537075a102441b5743caca629a0de56dc3d0bae; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[10] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x1e1639b26e4bc45cacfe52d84ff1e5a9333ef770aa814dbe444ba16345b07b89; + poly_array[1] = 0x2136cf7fba716952ec0dbb672c7d3e9e8200ac6ef547dc06f0e87317ec8acd30; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[11] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x32ca14ba8af6c53fc1e8cd50dcd3d718fb444f16a3e4e832a26195285489a961; + poly_array[1] = 0x2c8f9603d754035cc3efe1af4a55c24e498bd10e4d289a9cf4ebde41c78bb63f; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[12] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x1fd16fb6bf71d9b5e27c81cc22ca308b6ecf227c279a540fb78435d9661a92d2; + poly_array[1] = 0x0e7136096c545edbeaca24dad44083385fe147980df8b0d4149ac693d483a66e; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[13] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x0df4439409c23205c94fff01fab2978f40f8aee927a2a97ff3168af0a5d28fc8; + poly_array[1] = 0x0144eebfcf46c4d529bd5875de0d23df56c65a2eb54d7000b68837f01eacd58e; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[14] = poly; + return PolyLib.SumcheckProof(proof_array); + } + + // This function returns a SumcheckProof for the relevant corresponding field + function returnPrimaryBatchData() public pure returns (PolyLib.SumcheckProof memory) { + PolyLib.CompressedUniPoly[] memory proof_array = new PolyLib.CompressedUniPoly[](14); + uint256[] memory poly_array; + PolyLib.CompressedUniPoly memory poly; + poly_array = new uint256[](2); + poly_array[0] = 0x2155c5a20f5a1194e2ac3f9177909cef926c05e32fb7e9d22ef0d77d28688763; + poly_array[1] = 0x27fad0f1b0d77c1f120661e1a815714a8dad8f5ff4a2310c450fa9ab2e742e54; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[0] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x1eed419f37fe888cd7019a630b689deea4d7ed62a38ee9ec6d369f8034c85b09; + poly_array[1] = 0x3b70d8d30df9e02f4f7adb9bf411f1011f0d92bb13be7e28fc751867a6fd033c; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[1] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x02c9849afed1c30df760be1f226a08a7ce3590ea9c3b65d2dcf5894627c9d152; + poly_array[1] = 0x2b6ea31acdb0372acf50cba700488af46ce8a93950a59c156fde310099e0322b; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[2] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x39765fa514c503853592b2f72c557234c2efafba9815111959b6463678b15c5e; + poly_array[1] = 0x33a7ff8c7d32efdfafdee39e62c74afa54d488dc72dfe1ca78d0744fdf308ee1; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[3] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x2c391fa31a4e5650852011c5f16ada3f59db9ba0b4dafaef57099430348801d6; + poly_array[1] = 0x197b3e0837694a8ebab6d966f4a920f05af65dd30833e7dc0e913bf85ad37225; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[4] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x2d7be88f517910bc0fac0392ee91efe8d85a3a97d6a0d61afa3a0cb41712fe76; + poly_array[1] = 0x32843e5549400578b03af5fe731709f0a21d1c415b45d5c4b14f9fd149e66c1e; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[5] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x330b20e3b08c055a68e60d46f6b7b108fd953bbc7cde6ce77f0810887e2474f8; + poly_array[1] = 0x3a2d7c73d3d387ec99c36e57269e60cdcb76e747db777519f0b428306656db34; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[6] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x3b6cf05c93b2ddce857281ab92c00820662ea883470eae0687fe528623881b2e; + poly_array[1] = 0x2bea6206030ca0310385056aab275eeb953faa84fe98143e6c450ca2bd914bfc; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[7] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x3427a9cac1fadf65a0ee155dbce8116cc074c1e610f07b4f5f1488cbc4a3e0b8; + poly_array[1] = 0x23a552df25fa8ac97bf3441e7b4db68043c76ed2525ff794a31bcde16fb3e40c; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[8] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x0f83b9b92c770da002d1a2f26ff04acd3cbb2e5fa74e5b4751563f6e0d09ae57; + poly_array[1] = 0x2d83e394e01194e288428b4c5dbc4c25239fe6ed91e24c5e72a8d6efd7fc390e; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[9] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x3f58d15471a50cb03e5ef99c687bc24c904dc825c944c528e267a8e0ca821806; + poly_array[1] = 0x0312eec0bd722003eaf7f6e00874f9770f2d3a988ec3f7fae804fab1d3269114; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[10] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x00c1c1243543a2e54373171f76be13e5942593734afef8b5b3c1a5bfb0bf2dc9; + poly_array[1] = 0x0bd82242c23980470f76eb13dfe88cf1ad2fc918f0cae76e63c9c34ff2dd58e2; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[11] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x0bec8b247b7b9aaa0f47ef1fa6e525878bf760049f601a4adeabb8d02223d171; + poly_array[1] = 0x1d4e02fdcd90b13c5b2bc528f50e11313a8e8b47f5177abd475c8bb23406510c; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[12] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x3b314367a784bbad47b57679d0c57345027fea6e2e8d44c1ca6746971670fbe0; + poly_array[1] = 0x10c1a4c0d36de5eb0b5e3f733eeb644f9d29f4069afa840606b7e0a33214dbec; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[13] = poly; + return PolyLib.SumcheckProof(proof_array); + } + + // This function returns a SumcheckProof for the relevant corresponding field + function returnSecondaryOuterData() public pure returns (PolyLib.SumcheckProof memory) { + PolyLib.CompressedUniPoly[] memory proof_array = new PolyLib.CompressedUniPoly[](14); + uint256[] memory poly_array; + PolyLib.CompressedUniPoly memory poly; + poly_array = new uint256[](3); + poly_array[0] = 0x0000000000000000000000000000000000000000000000000000000000000000; + poly_array[1] = 0x090796c2a029b81e4b30b65a449b8f943a1cd5a119a5d6ea1865efebcc515975; + poly_array[2] = 0x067c67d9f00d27334795d0b6587f7de9e8bbb3ae85a2aa0730e87eb038750fd3; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[0] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x35ab7e62b24329fc2784fd4ddf143a4919e7b06b7f101b94c23325707d972598; + poly_array[1] = 0x0368440836408ed96cdeeda474fa6d50ca5304bcd994a59b04a35ad5cb82988c; + poly_array[2] = 0x0cd794be4f0dcd1962d1c3b94abf4869362315cde53e76c54ca6e69ffbb54fd1; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[1] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x1ac92b883ac9222ed2f099dc01a9a8698fdd2a981dc515a2908c73ee0779d4ed; + poly_array[1] = 0x05fa19839ccd1d979f724185a504eadf564e8cb13a35c789dc4c97862a1ab43f; + poly_array[2] = 0x3161fbce7771ce913d815456b42b3c129a9c3c120d8694ad5ddc53135bd7957c; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[2] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x3f8bfb004ecbb634983b60395e025445d813d52e2038661f2c2611e0efe87bb9; + poly_array[1] = 0x02e1a31742c3893a5022e217bd46588e69f284a88a1aab7fa821e9ae309e35f1; + poly_array[2] = 0x3f5038f7aada98ba046b1677110fc20c2308af4a7d4248a0fc20abac09fad80e; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[3] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x31411873831a3d0f76b6e21c1f0d638332453d84f73e6e62f597ea16d318f98a; + poly_array[1] = 0x181254eb869f39f12708a854068abfcf4fed2aedd2ffc2e28dcd00477b3b408a; + poly_array[2] = 0x2a38ce34a893f57f46230dc86c278af06f38201d09a5aac25fff21a362c19503; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[4] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x3b390cebb5321a5d374cfdc02f36e268e57436648adeb4a6f374d687e3b83f80; + poly_array[1] = 0x372ef3614d501411ece142d48fd34cb9cb092066f1257d38601b69788ad2eb7c; + poly_array[2] = 0x00c12c5100c9064d735aed7b10cc0ab283747058decbbb18a5b741acb8124bcd; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[5] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x1a904ae3fa645c6a5085fdd7e6a32aa13156989ceb38b27bcb6d50b93b9f5e50; + poly_array[1] = 0x2040c55e383b83f0aee66f0507d8b8dbad9712d946f0af4bf8b44927cef92620; + poly_array[2] = 0x0821176e32ab95c32676b38d8b9ab811c957f1831c9b27ab1f370ece48b671c6; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[6] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x17290df24a694e928dd665c9d347d71c787503678da8b85d0e68459512116b9e; + poly_array[1] = 0x1f2fb1f39a8e22a3837735fb2f050de5fe9db26f7c75abf1381dea16a557dec1; + poly_array[2] = 0x36a1cbeb839a6959595764789ff67be0e8a74f007ca7e7805794fbd6bad88b68; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[7] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x265113405d948ad03ae371265f568532c6ad37c400c92d667aa0140cd32969ac; + poly_array[1] = 0x22641d41c810605b33f7c87487722d6f41dabf9b1ceb8c99e8269a1f5a8c8037; + poly_array[2] = 0x0ced61caaabe14bf7895a0bdf4b841441aee4d43b5a7c4733b3472574f0a983d; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[8] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x1efdf83fe07484106737f606fbd1e3c29417a4d88fcd0969f6bc8cdfde0eec46; + poly_array[1] = 0x1b17694bef0a2f6d89acf07e0a830eb8088f07b6c2cb24d1108a6d3d83657a54; + poly_array[2] = 0x219f36cf1c636cb8e8f23931d44a1af19b5422d992773a1276c4c4ad7aeb81e6; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[9] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x3b1eb16f9af3e92be52401f4bc1a72e8819c7dada4bcb7085a1e660c6cd3b32c; + poly_array[1] = 0x0776b65ef71b553ccc400eb387c8eb1a5ee7205ad30c0fe2438373fd6a1bb7da; + poly_array[2] = 0x2151dbbf153f7aab0338111f1dad8709dae12680167d12fc3fa48aa5729ce042; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[10] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x008cd96ec564a9908459113718ebe2061337339f37d3c008e57ef3e0ce4c06f2; + poly_array[1] = 0x094407f4448f79930c8326c88624b016b7f6439a61664d2a7796d190a74d30c6; + poly_array[2] = 0x1bbbbb0e733aa832acf78c89ecfae9da618df4ad0addb0096d79d8feeb74df89; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[11] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x2589f6fbbb4b1b0fb0b2470bbc28d6cbf47536bd8c26c8e31e2acc3a10a761f6; + poly_array[1] = 0x34af65ce9841e688d2bfdeca1c90fa613bd53ccdd6027ccdbeb4749b41637824; + poly_array[2] = 0x109e02018ce3cfff0b3cbab192ee2848ab1653edfe520a57966a37827bff815b; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[12] = poly; + poly_array = new uint256[](3); + poly_array[0] = 0x3914ef9f52080f298240bedac07f6a3fbfe78a4b78b2012a43af5b9fed3eb2ab; + poly_array[1] = 0x03150bd2bc4fc7a377d012ace84edf8f266494b2a45e9e658df389a7970598f9; + poly_array[2] = 0x0e1d558f115e7184052f3a1a689989506165b26e4bfbcdde9245d38dd4b47149; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[13] = poly; + return PolyLib.SumcheckProof(proof_array); + } + + // This function returns a SumcheckProof for the relevant corresponding field + function returnSecondaryInnerData() public pure returns (PolyLib.SumcheckProof memory) { + PolyLib.CompressedUniPoly[] memory proof_array = new PolyLib.CompressedUniPoly[](15); + uint256[] memory poly_array; + PolyLib.CompressedUniPoly memory poly; + poly_array = new uint256[](2); + poly_array[0] = 0x2c5ad28caf2a30723db06b0c5f2daf1bd489089b295bea581a34b87ac4c992c5; + poly_array[1] = 0x11c867d92fbfd8321e07fa9f7bade6ca1e6485378644fb3c81ec92f75cd0f138; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[0] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x38db06de76eda60bb2ba837d498b852235666824b6a4a34fd4f0542a07eaf83c; + poly_array[1] = 0x0bc76064c182c83bf55acd1ef18e78b3edc84ccf6fbdc7cc13ab541423f1d777; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[1] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x107dc161b518391d870ad4776828cdbd7c2aa856ca05db4bca3ccebeb40b3e79; + poly_array[1] = 0x02cdd0b15810133f2614e9c3db70cce5703ebfe1942dedea4f8e814cdee6e9b9; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[2] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x3acc1c97598f737e4f0a33c2a31448185bea391c46ca3c9a2d2f32b01cc00cfe; + poly_array[1] = 0x19159c6766b74f0cf6a164c5702700140c556041e42a9cd55f0395aaa3751d62; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[3] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x3ddcb7ecc9a8a9746f03ddab3e84d35f5c5687db7777d1024f99715a2a0cf5e9; + poly_array[1] = 0x0f386d55fa899a2f680448f082f4044e94b16c619c0e00dc161abb316f5f055c; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[4] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x02bb0cd20cd33767bb2ced0bd20cf59964347983eb7d627679a10fec348dd93c; + poly_array[1] = 0x308611d1239b841723ea46beedd4ad6c18256cd7abace7ade92daffb85d432f1; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[5] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x091533e2c27b3de8b92b136f00258e310c4be08bf4deee63f6c2106d17226535; + poly_array[1] = 0x394e426b7ce6acc45aadb1149582754723398a47af7a048cad8c965a4a23edac; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[6] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x27f986cec5aa415f5c4f55605025a76fd3a3680513eb8cf846c2b807a1133a88; + poly_array[1] = 0x21073e2efb597f693306bfa1e7a9d69dc5017a496ceb6c60d4e24597de7bf386; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[7] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x089c618c7dd2d0d4cd214509ee66c061400af394292d26ab986a6d245396e726; + poly_array[1] = 0x3fc835443a5dcfcd52e21e2267cc07bd422c66cfe6c689d058da4f489361bdaf; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[8] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x02cc3866a95d1134d02f44744d2b9b07b7986ec7b0b9a86310e613973756329d; + poly_array[1] = 0x2ecadda0e35901a6d5d4619df0d1704f5b471c7e7ad17ce073628bd2688cea7a; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[9] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x187f6facad361cd0cb88c8b74b75d47b9d861d7822bbf19fe53106388af01b59; + poly_array[1] = 0x11bdfe5683e46f19bb9fd7052534090aff4c107f43ab0d972596ea4790a5b6c4; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[10] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x1cb6de6208c78deb1857e9c6e17561ca0f1b89430f6e03b4a9ca5963a14f62c1; + poly_array[1] = 0x2ffddcf67dd8dc7425ab39f6c9846052dd12e60627d1d434cc1d4febc6f096f1; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[11] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x2c6f01df34d61c82e0240a814a361eabf531e35c4e92df971e2b6ee6f933e490; + poly_array[1] = 0x195499856700d4f79a24519ecde2beee9d62249d638380691cb11a15a3d51b0f; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[12] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x08360997dd7d4470e3caefefc6189a980515f68cbe583138e24ea7225d7d463f; + poly_array[1] = 0x0ab471e96ccc91e240ee9c324d755cbc5df9ae23b784cd1958178d8b79c9360f; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[13] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x20350438adcd696b8d02f7fc56c0b61ec52a701e50a20f6d11fe7ff80bb3600b; + poly_array[1] = 0x196579d55c1006d34fe99b580bf70f1ca34cd057d73726f018de41e3004aa5e7; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[14] = poly; + return PolyLib.SumcheckProof(proof_array); + } + + // This function returns a SumcheckProof for the relevant corresponding field + function returnSecondaryBatchData() public pure returns (PolyLib.SumcheckProof memory) { + PolyLib.CompressedUniPoly[] memory proof_array = new PolyLib.CompressedUniPoly[](14); + uint256[] memory poly_array; + PolyLib.CompressedUniPoly memory poly; + poly_array = new uint256[](2); + poly_array[0] = 0x3778dd47bff37eaa5f46f8cf0b8a83df26ab59e81d834880a62c98628dab18cb; + poly_array[1] = 0x36430699e436e3fd6d3a9d5c41285d72b43cbe9e7c0def5b430630beb883322e; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[0] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x23b2f8541fd8cca0087e7e772432296e6d5637b38694a0d3959dafec886a581d; + poly_array[1] = 0x380153e856d13c73bf6df99c746256f44790832f1b920537cb236e0700c41076; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[1] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x25264d4ca84b5fab52ed410c0b1edf4b73c283d36915442cdbf774b534d35b07; + poly_array[1] = 0x3bc4d96b1ff53b954914bf9695d6cae5dd7bd3857ff08cc9b44c525525d65e28; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[2] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x045c77586032794edc94fa6ef6baa4a1de0cae38cb0e50f292837e91a6c8da0f; + poly_array[1] = 0x3012c9f83f5d5897e253963d60f9e7764e5faefc3acdd2da0bc3357b77f56723; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[3] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x3552e33e401d19eb6efd85b828f4da62edb71c482ecb551e2731611f116b6b37; + poly_array[1] = 0x1d77f649e9c08c2b722b7ea57e2b862f9a92c923e0d4e0bc29bb0c21d4a514f3; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[4] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x228c5e1529107612f903bf0006d376d2183fc2abfbed7097f53945c2fb99a2b1; + poly_array[1] = 0x263b63e884d49ce6ef5693aa4f4cd64efcee6b7c5c149585048aa2036609c209; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[5] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x31baa5e08c957f55acf5392f4e98c8b02ec7dc9142b6d2442cad8875c8ad1ac1; + poly_array[1] = 0x2d526b31084c79c9ba271b4f9dec0641b18fa4aded4fe24fb58f9e2262c7836f; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[6] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x15260793e8c1ebcdd6c40e7da3c223b56d99dddbc7835a708915f5da392065bf; + poly_array[1] = 0x33e63541161ad8a8f215e76fa48516d1736caefe88b8398e273444a1e3e5335c; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[7] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x3499aef515afcad923dd687caac79e2d8759ac186fa6353cc9af2e53078b4450; + poly_array[1] = 0x2070daf5b2e65015ee0a1adbe3037a2ee5f52d7b0c1da1e04bac11fadfb9d2e4; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[8] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x0b89d997302a0eb3e2d636852d43df2b478413a640c845dccbc4a71b9a1930be; + poly_array[1] = 0x088218b57f51763066db38c08963d7dff1dc61b08442f85d8b1cffd4a67de019; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[9] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x24beaaa573677f834b463dbdcd3877069039cba9c4480c0af736addb9ec539d8; + poly_array[1] = 0x1b77b1f53662c3bae203b71fde3886eccfc6a542cee8fa4e4584c21f524891d2; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[10] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x22c71df97cecf7de4475f48b77ddab8b514a000d732485eb0001ce5addb5f83d; + poly_array[1] = 0x1d9d3928f0d029539b68648d9ab43fbbe53f9abcda7bfe8b7e3e66a0ea9c08c9; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[11] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x31978a8cb06be3b5eacaf8f6cb648285b08e0440691a7f7e6108724cc74c2d35; + poly_array[1] = 0x1964ce18e81e22fcff8c793b878295a37d8960d07d878682ce5b1ac12686c41a; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[12] = poly; + poly_array = new uint256[](2); + poly_array[0] = 0x15c712d36849a0762b953a465e8c044fd7ca946dcf04265c68cd652859f5f9b1; + poly_array[1] = 0x04d0d2dfc250cd724074c023f2f099ffa61313893e0e4f84b4d99964e2186c29; + poly = PolyLib.CompressedUniPoly(poly_array); + proof_array[13] = poly; + return PolyLib.SumcheckProof(proof_array); + } + + // This function returns R1CS structure digest as a uint8[] + function returnPrimaryTranscriptData() public pure returns (uint8[] memory) { + uint8[] memory digest = new uint8[](32); + digest[0] = 0x23; + digest[1] = 0xa9; + digest[2] = 0x65; + digest[3] = 0xae; + digest[4] = 0xf5; + digest[5] = 0x44; + digest[6] = 0x37; + digest[7] = 0x51; + digest[8] = 0x77; + digest[9] = 0xe0; + digest[10] = 0xae; + digest[11] = 0x37; + digest[12] = 0x26; + digest[13] = 0x8b; + digest[14] = 0x5b; + digest[15] = 0x32; + digest[16] = 0xca; + digest[17] = 0x91; + digest[18] = 0x55; + digest[19] = 0x28; + digest[20] = 0xac; + digest[21] = 0x3b; + digest[22] = 0x12; + digest[23] = 0x23; + digest[24] = 0xe5; + digest[25] = 0x68; + digest[26] = 0xfb; + digest[27] = 0x1c; + digest[28] = 0xef; + digest[29] = 0x6b; + digest[30] = 0x41; + digest[31] = 0x03; + + return digest; + } + // This function returns R1CS structure digest as a uint8[] + + function returnSecondaryTranscriptData() public pure returns (uint8[] memory) { + uint8[] memory digest = new uint8[](32); + digest[0] = 0x11; + digest[1] = 0x73; + digest[2] = 0x20; + digest[3] = 0xb4; + digest[4] = 0x29; + digest[5] = 0x57; + digest[6] = 0x30; + digest[7] = 0x8a; + digest[8] = 0x3a; + digest[9] = 0x95; + digest[10] = 0xd2; + digest[11] = 0x08; + digest[12] = 0x54; + digest[13] = 0x2d; + digest[14] = 0xaa; + digest[15] = 0x4c; + digest[16] = 0xc7; + digest[17] = 0xbf; + digest[18] = 0xd6; + digest[19] = 0x6d; + digest[20] = 0x70; + digest[21] = 0xfc; + digest[22] = 0xa6; + digest[23] = 0xce; + digest[24] = 0x14; + digest[25] = 0x9e; + digest[26] = 0xd4; + digest[27] = 0x51; + digest[28] = 0x7c; + digest[29] = 0x6d; + digest[30] = 0xc2; + digest[31] = 0x01; + + return digest; + } +} diff --git a/src/verifier/step4/SumcheckLogic.sol b/src/verifier/step4/SumcheckLogic.sol new file mode 100644 index 0000000..323677b --- /dev/null +++ b/src/verifier/step4/SumcheckLogic.sol @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.16; + +import "src/pasta/Pallas.sol"; +import "src/pasta/Vesta.sol"; +import "src/verifier/step4/KeccakTranscript.sol"; +import "src/verifier/step4/EqPolynomial.sol"; +import "src/Polynomial.sol"; + +library PrimarySumcheck { + function verify( + PolyLib.SumcheckProof calldata proof, + uint256 claim, + uint256 num_rounds, + uint256 degree_bound, + KeccakTranscriptLib.KeccakTranscript memory transcript + ) public pure returns (uint256, uint256[] memory, KeccakTranscriptLib.KeccakTranscript memory) { + uint256 e = claim; + uint256[] memory r = new uint256[](num_rounds); + + uint8[] memory label = new uint8[](1); + + require(proof.compressed_polys.length == num_rounds, "[PrimarySumcheck::verify] Wrong number of polynomials"); + + PolyLib.UniPoly memory poly; + + for (uint256 i = 0; i < num_rounds; i++) { + poly = PolyLib.decompress(proof.compressed_polys[i], e, Pallas.R_MOD); + + require(PolyLib.degree(poly) == degree_bound, "[PrimarySumcheck::verify] Polynomial has wrong degree"); + require( + addmod(PolyLib.evalAtZero(poly), PolyLib.evalAtOne(poly, Pallas.R_MOD), Pallas.R_MOD) == e, + "[PrimarySumcheck::verify] Polynomial decompression yields incorrect result" + ); + + label[0] = 112; // p_label[0] = 112; + + transcript = KeccakTranscriptLib.absorb(transcript, label, poly); + + uint256 r_i; + label[0] = 99; // c_label[0] = 99; + (transcript, r_i) = KeccakTranscriptLib.squeeze(transcript, ScalarFromUniformLib.curveVesta(), label); + + r[i] = r_i; + + e = PolyLib.evaluate(poly, r_i, Pallas.R_MOD); + } + + return (e, r, transcript); + } +} + +library SecondarySumcheck { + struct SumcheckProof { + PolyLib.CompressedUniPoly[] compressed_polys; + } + + function verify( + PolyLib.SumcheckProof calldata proof, + uint256 claim, + uint256 num_rounds, + uint256 degree_bound, + KeccakTranscriptLib.KeccakTranscript memory transcript + ) public pure returns (uint256, uint256[] memory, KeccakTranscriptLib.KeccakTranscript memory) { + uint256 e = claim; + uint256[] memory r = new uint256[](num_rounds); + + uint8[] memory label = new uint8[](1); + + require(proof.compressed_polys.length == num_rounds, "[SecondarySumcheck::verify] Wrong number of polynomials"); + + PolyLib.UniPoly memory poly; + + for (uint256 i = 0; i < num_rounds; i++) { + poly = PolyLib.decompress(proof.compressed_polys[i], e, Vesta.R_MOD); + + require(PolyLib.degree(poly) == degree_bound, "[SecondarySumcheck::verify] Polynomial has wrong degree"); + require( + addmod(PolyLib.evalAtZero(poly), PolyLib.evalAtOne(poly, Vesta.R_MOD), Vesta.R_MOD) == e, + "[SecondarySumcheck::verify] Polynomial decompression yields incorrect result" + ); + + label[0] = 112; // p_label[0] = 112; + + transcript = KeccakTranscriptLib.absorb(transcript, label, poly); + + uint256 r_i; + label[0] = 99; // c_label[0] = 99; + (transcript, r_i) = KeccakTranscriptLib.squeeze(transcript, ScalarFromUniformLib.curvePallas(), label); + + r[i] = r_i; + + e = PolyLib.evaluate(poly, r_i, Vesta.R_MOD); + } + + return (e, r, transcript); + } +} diff --git a/src/verifier/step4/sumcheck-data-contract-gen.py b/src/verifier/step4/sumcheck-data-contract-gen.py new file mode 100644 index 0000000..41abca1 --- /dev/null +++ b/src/verifier/step4/sumcheck-data-contract-gen.py @@ -0,0 +1,160 @@ +import json +import sys +import os +from enum import Enum + +class Version(Enum): + PRIMARY = "Primary" + SECONDARY = "Secondary" + + def get_curve(self) -> str: + match self: + case Version.PRIMARY: + return "Pallas" + case Version.SECONDARY: + return "Vesta" + +def h(s): + """ + Hexify a string + """ + return "0x" + s + +def reverse_bytes(val): + """ + Reverses the byte order of a hexdecimal number for ingest in Solidity contract + """ + ba = bytearray.fromhex(val) + ba.reverse() + return ba.hex() + +def sumcheck_data_contract_gen(data): + compressed_polynomials = data["compressed_polys"] + output = f"PolyLib.CompressedUniPoly[] memory proof_array = new PolyLib.CompressedUniPoly[]({len(compressed_polynomials)});\n" + output += "uint256[] memory poly_array;\n" + degree = len(compressed_polynomials[0]["coeffs_except_linear_term"]) + output += f"PolyLib.CompressedUniPoly memory poly;\n" + + for poly_idx, poly in enumerate(compressed_polynomials): + coeffs = poly["coeffs_except_linear_term"] + output += f"poly_array = new uint256[]({degree});\n" + for coeff_idx, coeff in enumerate(coeffs): + output += f"poly_array[{coeff_idx}] = {h(reverse_bytes(coeff))};\n" + output += f"poly = PolyLib.CompressedUniPoly(poly_array);\n" + output += f"proof_array[{poly_idx}] = poly;\n" + + output += f"return PolyLib.SumcheckProof(proof_array);\n" + return output + +def transcript_data_contract_gen(data): + output = f"uint8[] memory digest = new uint8[](32);\n" + for idx in range(32): + output += f"digest[{idx}] = {h(data[2*idx:2*(idx + 1)])};\n" + + output += "\nreturn digest;" + return output + +def function_decl(name: str) -> str: + output = f"function {name}()\n" + output += "public pure returns\n" + return output + +def sumcheck_function_return() -> str: + return f"(PolyLib.SumcheckProof memory)" + " {\n" + +vk_file = sys.argv[1] +if not os.path.exists(vk_file): + print("verifier-key (json) input file is missing") + exit(1) + +proof_file = sys.argv[2] +if not os.path.exists(proof_file): + print("compressed snark (json) input file is missing") + exit(1) + +proof_f = open(os.path.basename(proof_file)) +proof_data = json.load(proof_f) + +vk_f = open(os.path.basename(vk_file)) +vk_data = json.load(vk_f) + +header = "// SPDX-License-Identifier: Apache-2.0\n" +header += f"// Do not change manually. This contract has been auto-generated by {sys.argv[0]}\n" +header += "pragma solidity ^0.8.16;\n" +header += 'import "src/Polynomial.sol";\n' +header += 'import "src/verifier/step4/SumcheckLogic.sol";\n' + +sumcheck_function_doc = "// This function returns a SumcheckProof for the relevant corresponding field\n" + +primary_data = proof_data["f_W_snark_primary"] + +primary_outer_data_def = sumcheck_function_doc +primary_outer_data_def += function_decl("returnPrimaryOuterData") +primary_outer_data_def += sumcheck_function_return() +primary_outer_data_def += sumcheck_data_contract_gen(primary_data["sc_proof_outer"]) +primary_outer_data_def += "}\n\n" + +primary_inner_data_def = sumcheck_function_doc +primary_inner_data_def += function_decl("returnPrimaryInnerData") +primary_inner_data_def += sumcheck_function_return() +primary_inner_data_def += sumcheck_data_contract_gen(primary_data["sc_proof_inner"]) +primary_inner_data_def += "}\n\n" + +primary_batch_data_def = sumcheck_function_doc +primary_batch_data_def += function_decl("returnPrimaryBatchData") +primary_batch_data_def += sumcheck_function_return() +primary_batch_data_def += sumcheck_data_contract_gen(primary_data["sc_proof_batch"]) +primary_batch_data_def += "}\n\n" + +secondary_data = proof_data["f_W_snark_secondary"] + +secondary_outer_data_def = sumcheck_function_doc +secondary_outer_data_def += function_decl("returnSecondaryOuterData") +secondary_outer_data_def += sumcheck_function_return() +secondary_outer_data_def += sumcheck_data_contract_gen(secondary_data["sc_proof_outer"]) +secondary_outer_data_def += "}\n\n" + +secondary_inner_data_def = sumcheck_function_doc +secondary_inner_data_def += function_decl("returnSecondaryInnerData") +secondary_inner_data_def += sumcheck_function_return() +secondary_inner_data_def += sumcheck_data_contract_gen(secondary_data["sc_proof_inner"]) +secondary_inner_data_def += "}\n\n" + +secondary_batch_data_def = sumcheck_function_doc +secondary_batch_data_def += function_decl("returnSecondaryBatchData") +secondary_batch_data_def += sumcheck_function_return() +secondary_batch_data_def += sumcheck_data_contract_gen(secondary_data["sc_proof_batch"]) +secondary_batch_data_def += "}\n\n" + +transcript_function_doc = "// This function returns R1CS structure digest as a uint8[]\n" + +primary_transcript_data = vk_data["vk_primary"]["comm"]["S"]["digest"] + +primary_transcript_data_def = transcript_function_doc +primary_transcript_data_def += function_decl("returnPrimaryTranscriptData") +primary_transcript_data_def += "(uint8[] memory) {\n" +primary_transcript_data_def += transcript_data_contract_gen(primary_transcript_data) +primary_transcript_data_def += "}\n" + +secondary_transcript_data = vk_data["vk_secondary"]["comm"]["S"]["digest"] + +secondary_transcript_data_def = transcript_function_doc +secondary_transcript_data_def += function_decl("returnSecondaryTranscriptData") +secondary_transcript_data_def += "(uint8[] memory) {\n" +secondary_transcript_data_def += transcript_data_contract_gen(secondary_transcript_data) +secondary_transcript_data_def += "}\n" + +data_contract_body = "library SumcheckData {\n" +data_contract_body += primary_outer_data_def +data_contract_body += primary_inner_data_def +data_contract_body += primary_batch_data_def +data_contract_body += secondary_outer_data_def +data_contract_body += secondary_inner_data_def +data_contract_body += secondary_batch_data_def +data_contract_body += primary_transcript_data_def +data_contract_body += secondary_transcript_data_def + +data_contract_body += "}\n" + +print(header) +print(data_contract_body) diff --git a/test/nova-verifier-tests.t.sol b/test/nova-verifier-tests.t.sol index 5c43dbe..8183dbe 100644 --- a/test/nova-verifier-tests.t.sol +++ b/test/nova-verifier-tests.t.sol @@ -10,6 +10,10 @@ import "src/verifier/step3/Step3Logic.sol"; import "src/verifier/step3/Step3Data.sol"; import "src/poseidon/Sponge.sol"; import "src/verifier/step4/SubStep2.sol"; +import "src/verifier/step4/SumcheckLogic.sol"; +import "src/verifier/step4/SumcheckData.sol"; +import "src/pasta/Pallas.sol"; +import "src/pasta/Vesta.sol"; contract NovaVerifierContractTest is Test { function testVerificationStep1() public pure { @@ -235,4 +239,594 @@ contract NovaVerifierContractTest is Test { assertEq(result.X, expected_X); assertEq(result.u, expected_u); } + + function testSumcheckPrimary() public { + uint8[] memory input = new uint8[](16); // b"RelaxedR1CSSNARK" in Rust + input[0] = 0x52; + input[1] = 0x65; + input[2] = 0x6c; + input[3] = 0x61; + input[4] = 0x78; + input[5] = 0x65; + input[6] = 0x64; + input[7] = 0x52; + input[8] = 0x31; + input[9] = 0x43; + input[10] = 0x53; + input[11] = 0x53; + input[12] = 0x4e; + input[13] = 0x41; + input[14] = 0x52; + input[15] = 0x4b; + + KeccakTranscriptLib.KeccakTranscript memory transcript = KeccakTranscriptLib.instantiate(input); + + uint8[] memory vk_comm = SumcheckData.returnPrimaryTranscriptData(); + uint8[] memory vk_comm_label = new uint8[](1); + vk_comm_label[0] = 0x43; // b"C" + + uint8[] memory U = new uint8[](226); + U[0] = 0xab; + U[1] = 0xf4; + U[2] = 0xc0; + U[3] = 0x93; + U[4] = 0xd7; + U[5] = 0x1b; + U[6] = 0xd2; + U[7] = 0xab; + U[8] = 0x61; + U[9] = 0xa2; + U[10] = 0x84; + U[11] = 0x16; + U[12] = 0x3a; + U[13] = 0x36; + U[14] = 0xb2; + U[15] = 0x6c; + U[16] = 0x75; + U[17] = 0x42; + U[18] = 0x9c; + U[19] = 0x4e; + U[20] = 0x0a; + U[21] = 0xbe; + U[22] = 0x30; + U[23] = 0x25; + U[24] = 0x86; + U[25] = 0xb8; + U[26] = 0x75; + U[27] = 0x6f; + U[28] = 0x56; + U[29] = 0x1c; + U[30] = 0x3b; + U[31] = 0x22; + U[32] = 0x08; + U[33] = 0x4e; + U[34] = 0xc4; + U[35] = 0x00; + U[36] = 0xc1; + U[37] = 0xbc; + U[38] = 0x28; + U[39] = 0x22; + U[40] = 0x6d; + U[41] = 0xc7; + U[42] = 0x98; + U[43] = 0x66; + U[44] = 0x2a; + U[45] = 0x67; + U[46] = 0x8d; + U[47] = 0x47; + U[48] = 0xf0; + U[49] = 0x1e; + U[50] = 0x0c; + U[51] = 0x24; + U[52] = 0xee; + U[53] = 0xaa; + U[54] = 0x59; + U[55] = 0x69; + U[56] = 0xf7; + U[57] = 0xaa; + U[58] = 0xcf; + U[59] = 0x24; + U[60] = 0x19; + U[61] = 0x8c; + U[62] = 0x21; + U[63] = 0x05; + U[64] = 0x01; + U[65] = 0x94; + U[66] = 0x18; + U[67] = 0x0d; + U[68] = 0x05; + U[69] = 0x6f; + U[70] = 0xf8; + U[71] = 0x6d; + U[72] = 0xd8; + U[73] = 0xb2; + U[74] = 0x99; + U[75] = 0x7f; + U[76] = 0x5f; + U[77] = 0xd7; + U[78] = 0xe2; + U[79] = 0x53; + U[80] = 0xd4; + U[81] = 0x0d; + U[82] = 0xfb; + U[83] = 0xa2; + U[84] = 0x7a; + U[85] = 0x8b; + U[86] = 0x4c; + U[87] = 0xb9; + U[88] = 0x74; + U[89] = 0x62; + U[90] = 0xe6; + U[91] = 0xef; + U[92] = 0x3a; + U[93] = 0x52; + U[94] = 0x2b; + U[95] = 0xf0; + U[96] = 0x15; + U[97] = 0x78; + U[98] = 0x01; + U[99] = 0x35; + U[100] = 0x68; + U[101] = 0xf3; + U[102] = 0x63; + U[103] = 0x2c; + U[104] = 0x36; + U[105] = 0x67; + U[106] = 0x02; + U[107] = 0x01; + U[108] = 0xea; + U[109] = 0x3a; + U[110] = 0x89; + U[111] = 0x9f; + U[112] = 0x60; + U[113] = 0x25; + U[114] = 0x05; + U[115] = 0x1e; + U[116] = 0x74; + U[117] = 0xd3; + U[118] = 0x9a; + U[119] = 0x85; + U[120] = 0x6c; + U[121] = 0xf0; + U[122] = 0x96; + U[123] = 0x77; + U[124] = 0xff; + U[125] = 0xda; + U[126] = 0xea; + U[127] = 0x48; + U[128] = 0x34; + U[129] = 0x01; + U[130] = 0x30; + U[131] = 0x65; + U[132] = 0xfe; + U[133] = 0x20; + U[134] = 0x9d; + U[135] = 0x44; + U[136] = 0xbb; + U[137] = 0x99; + U[138] = 0x76; + U[139] = 0x58; + U[140] = 0x4c; + U[141] = 0xb4; + U[142] = 0xea; + U[143] = 0xd9; + U[144] = 0x89; + U[145] = 0xa3; + U[146] = 0x01; + U[147] = 0x00; + U[148] = 0x00; + U[149] = 0x00; + U[150] = 0x00; + U[151] = 0x00; + U[152] = 0x00; + U[153] = 0x00; + U[154] = 0x00; + U[155] = 0x00; + U[156] = 0x00; + U[157] = 0x00; + U[158] = 0x00; + U[159] = 0x00; + U[160] = 0x00; + U[161] = 0x00; + U[162] = 0x6a; + U[163] = 0xf4; + U[164] = 0x72; + U[165] = 0xae; + U[166] = 0x09; + U[167] = 0xba; + U[168] = 0x90; + U[169] = 0x21; + U[170] = 0xc5; + U[171] = 0xca; + U[172] = 0xd4; + U[173] = 0xa5; + U[174] = 0x3d; + U[175] = 0xe0; + U[176] = 0x18; + U[177] = 0x1f; + U[178] = 0x07; + U[179] = 0xd3; + U[180] = 0xd7; + U[181] = 0x18; + U[182] = 0xf7; + U[183] = 0x98; + U[184] = 0x27; + U[185] = 0xa1; + U[186] = 0x2b; + U[187] = 0x6f; + U[188] = 0xa6; + U[189] = 0x56; + U[190] = 0x0a; + U[191] = 0xd2; + U[192] = 0x56; + U[193] = 0x2e; + U[194] = 0xad; + U[195] = 0x9f; + U[196] = 0xa6; + U[197] = 0x2a; + U[198] = 0x1a; + U[199] = 0x9d; + U[200] = 0x69; + U[201] = 0x38; + U[202] = 0xce; + U[203] = 0x77; + U[204] = 0xa3; + U[205] = 0xd0; + U[206] = 0x4b; + U[207] = 0x90; + U[208] = 0xce; + U[209] = 0xf2; + U[210] = 0x2b; + U[211] = 0x0e; + U[212] = 0x8d; + U[213] = 0x05; + U[214] = 0x4b; + U[215] = 0x68; + U[216] = 0x8f; + U[217] = 0x47; + U[218] = 0x5b; + U[219] = 0x0c; + U[220] = 0xa6; + U[221] = 0xa1; + U[222] = 0x2b; + U[223] = 0xf5; + U[224] = 0x75; + U[225] = 0x28; + + uint8[] memory U_label = new uint8[](1); + U_label[0] = 0x55; // b"U" + + transcript = KeccakTranscriptLib.absorb(transcript, vk_comm_label, vk_comm); + transcript = KeccakTranscriptLib.absorb(transcript, U_label, U); + + ScalarFromUniformLib.Curve curve = ScalarFromUniformLib.curveVesta(); + + uint8[] memory t_label = new uint8[](1); + t_label[0] = 0x74; // b"t" + + for (uint256 idx = 0; idx < 14; idx++) { + (transcript,) = KeccakTranscriptLib.squeeze(transcript, curve, t_label); + } + + PolyLib.SumcheckProof memory outer_proof = SumcheckData.returnPrimaryOuterData(); + + uint256 claim_final; + uint256[] memory r_x = new uint256[](14); + + (claim_final, r_x, transcript) = PrimarySumcheck.verify(outer_proof, 0, 14, 3, transcript); + + uint256[] memory r_x_result = new uint256[](14); + r_x_result[0] = 0x265e1d73ee4ce9a23d98bf74a9807abd1c0bedf6368e8db884c05bd9336549bd; + r_x_result[1] = 0x3a009bec1c4dc776ba75c643de9e61b3070a4a6b3865b5751a3d6f517e483a4a; + r_x_result[2] = 0x3932891c1f17ba15d07baba47d6599058812a73225d11a554ced25ad00fd78dd; + r_x_result[3] = 0x140622b73b006b8470ed724172721f7d25f3efb2208f42c73e0658fbc493579b; + r_x_result[4] = 0x2516f6f6ccf854843d9319fad46a0dff2729c608af31c143590c347d0f0805c6; + r_x_result[5] = 0x28942f6ecc7b89c49bfaa569687a9b6902ace63343300e808e86d608eca3f9dc; + r_x_result[6] = 0x1ae6542e6085a0c42ae6e947813a6f701329263a1a59f823cb544e83dce0b9cf; + r_x_result[7] = 0x39979cf05d7d96da05aba4dd24e9f072d52e8efbf4740f1a857680a096193f8b; + r_x_result[8] = 0x2d887fae3954bcb89f20051c96f6812eb841ccc29c8b56e2879e445f74cb4331; + r_x_result[9] = 0x29fb4b14d5d53616b881719c4986e5aad92f7320fc1e6c89f301b8a81ab72896; + r_x_result[10] = 0x2d69fc2f360b3328cb723687589b065ff4250c414c817bd4f6b187583e103270; + r_x_result[11] = 0x06dc812740949078bc2487f020274042e7400e44f7a95d26c2cf6de8b7ba5099; + r_x_result[12] = 0x39ade5abede093bbb12d81f27c28cbc7149d1b1ad6e43c49424687fb4c29ae31; + r_x_result[13] = 0x3d764ae71118a8a3c653b58c534db9fae607dd9c316cdd3675de0d62e0882bf1; + + assertEq(claim_final, 0x346b738474d5b2cda8c002566f1a7004d06cab6b467303a2b7c4b04eaa6df733); + assertEq(r_x, r_x_result); + } + + function testSumcheckSecondary() public { + uint8[] memory input = new uint8[](16); // b"RelaxedR1CSSNARK" in Rust + input[0] = 0x52; + input[1] = 0x65; + input[2] = 0x6c; + input[3] = 0x61; + input[4] = 0x78; + input[5] = 0x65; + input[6] = 0x64; + input[7] = 0x52; + input[8] = 0x31; + input[9] = 0x43; + input[10] = 0x53; + input[11] = 0x53; + input[12] = 0x4e; + input[13] = 0x41; + input[14] = 0x52; + input[15] = 0x4b; + + KeccakTranscriptLib.KeccakTranscript memory transcript = KeccakTranscriptLib.instantiate(input); + + uint8[] memory vk_comm = SumcheckData.returnSecondaryTranscriptData(); + uint8[] memory vk_comm_label = new uint8[](1); + vk_comm_label[0] = 0x43; // b"C" + + uint8[] memory U = new uint8[](226); + U[0] = 0x58; + U[1] = 0x72; + U[2] = 0xeb; + U[3] = 0x4; + U[4] = 0x7; + U[5] = 0xd2; + U[6] = 0xe2; + U[7] = 0xeb; + U[8] = 0x41; + U[9] = 0x55; + U[10] = 0x85; + U[11] = 0xab; + U[12] = 0x31; + U[13] = 0xb1; + U[14] = 0x6a; + U[15] = 0xf7; + U[16] = 0xa7; + U[17] = 0xb0; + U[18] = 0xaa; + U[19] = 0x2a; + U[20] = 0x7e; + U[21] = 0xa9; + U[22] = 0x1f; + U[23] = 0x4d; + U[24] = 0x60; + U[25] = 0x85; + U[26] = 0x3; + U[27] = 0x58; + U[28] = 0xf3; + U[29] = 0xe9; + U[30] = 0xa4; + U[31] = 0x33; + U[32] = 0x23; + U[33] = 0x65; + U[34] = 0x80; + U[35] = 0xd; + U[36] = 0xf2; + U[37] = 0x4f; + U[38] = 0x9f; + U[39] = 0xc7; + U[40] = 0xb5; + U[41] = 0xa7; + U[42] = 0xc3; + U[43] = 0xa3; + U[44] = 0xb6; + U[45] = 0x2; + U[46] = 0x23; + U[47] = 0xc0; + U[48] = 0xe9; + U[49] = 0x95; + U[50] = 0x7c; + U[51] = 0x84; + U[52] = 0xd3; + U[53] = 0x1; + U[54] = 0xb5; + U[55] = 0xa0; + U[56] = 0x4c; + U[57] = 0x79; + U[58] = 0xd2; + U[59] = 0x65; + U[60] = 0x1; + U[61] = 0x3a; + U[62] = 0x84; + U[63] = 0x31; + U[64] = 0x1; + U[65] = 0xc; + U[66] = 0x74; + U[67] = 0x22; + U[68] = 0xf7; + U[69] = 0xea; + U[70] = 0xbb; + U[71] = 0x81; + U[72] = 0xb1; + U[73] = 0x86; + U[74] = 0x6c; + U[75] = 0xc; + U[76] = 0x6c; + U[77] = 0x7e; + U[78] = 0x9e; + U[79] = 0x6c; + U[80] = 0x43; + U[81] = 0x42; + U[82] = 0x5a; + U[83] = 0xa8; + U[84] = 0x84; + U[85] = 0x96; + U[86] = 0x38; + U[87] = 0x31; + U[88] = 0xfa; + U[89] = 0x89; + U[90] = 0x9e; + U[91] = 0x1c; + U[92] = 0x81; + U[93] = 0x10; + U[94] = 0xb3; + U[95] = 0x98; + U[96] = 0xf; + U[97] = 0xbb; + U[98] = 0x78; + U[99] = 0x40; + U[100] = 0x64; + U[101] = 0x89; + U[102] = 0x20; + U[103] = 0x96; + U[104] = 0xbc; + U[105] = 0x48; + U[106] = 0x82; + U[107] = 0x40; + U[108] = 0x7d; + U[109] = 0xef; + U[110] = 0xfb; + U[111] = 0x4b; + U[112] = 0x8c; + U[113] = 0xa4; + U[114] = 0xd9; + U[115] = 0x5e; + U[116] = 0xc6; + U[117] = 0xb4; + U[118] = 0x36; + U[119] = 0xbf; + U[120] = 0x55; + U[121] = 0xac; + U[122] = 0xa6; + U[123] = 0xc5; + U[124] = 0x10; + U[125] = 0xee; + U[126] = 0x7b; + U[127] = 0x54; + U[128] = 0x12; + U[129] = 0x1; + U[130] = 0x46; + U[131] = 0x6e; + U[132] = 0x7c; + U[133] = 0xef; + U[134] = 0xcd; + U[135] = 0x20; + U[136] = 0xa5; + U[137] = 0xe6; + U[138] = 0x88; + U[139] = 0xa7; + U[140] = 0x90; + U[141] = 0xfc; + U[142] = 0xce; + U[143] = 0x4e; + U[144] = 0x44; + U[145] = 0xe4; + U[146] = 0x1; + U[147] = 0x0; + U[148] = 0x0; + U[149] = 0x0; + U[150] = 0x0; + U[151] = 0x0; + U[152] = 0x0; + U[153] = 0x0; + U[154] = 0x0; + U[155] = 0x0; + U[156] = 0x0; + U[157] = 0x0; + U[158] = 0x0; + U[159] = 0x0; + U[160] = 0x0; + U[161] = 0x0; + U[162] = 0xee; + U[163] = 0xcb; + U[164] = 0x9f; + U[165] = 0xcf; + U[166] = 0x27; + U[167] = 0xb4; + U[168] = 0xd5; + U[169] = 0x3b; + U[170] = 0x82; + U[171] = 0xfc; + U[172] = 0xe0; + U[173] = 0x36; + U[174] = 0xa6; + U[175] = 0xd5; + U[176] = 0x1e; + U[177] = 0x26; + U[178] = 0xb0; + U[179] = 0xfd; + U[180] = 0x9e; + U[181] = 0xcc; + U[182] = 0x56; + U[183] = 0x9c; + U[184] = 0x9c; + U[185] = 0xb; + U[186] = 0x41; + U[187] = 0xbe; + U[188] = 0x4a; + U[189] = 0x58; + U[190] = 0x12; + U[191] = 0xd9; + U[192] = 0xd8; + U[193] = 0x32; + U[194] = 0x98; + U[195] = 0x1; + U[196] = 0x33; + U[197] = 0xb0; + U[198] = 0x59; + U[199] = 0x4c; + U[200] = 0x16; + U[201] = 0xf0; + U[202] = 0xcd; + U[203] = 0x89; + U[204] = 0xde; + U[205] = 0xb1; + U[206] = 0xfd; + U[207] = 0xef; + U[208] = 0xdf; + U[209] = 0x88; + U[210] = 0x26; + U[211] = 0x15; + U[212] = 0xea; + U[213] = 0xf1; + U[214] = 0xba; + U[215] = 0xec; + U[216] = 0x2b; + U[217] = 0x4f; + U[218] = 0x4b; + U[219] = 0x65; + U[220] = 0x43; + U[221] = 0x70; + U[222] = 0xf6; + U[223] = 0x6d; + U[224] = 0xb8; + U[225] = 0x25; + + uint8[] memory U_label = new uint8[](1); + U_label[0] = 0x55; // b"U" + + transcript = KeccakTranscriptLib.absorb(transcript, vk_comm_label, vk_comm); + transcript = KeccakTranscriptLib.absorb(transcript, U_label, U); + + ScalarFromUniformLib.Curve curve = ScalarFromUniformLib.curveVesta(); + + uint8[] memory t_label = new uint8[](1); + t_label[0] = 0x74; // b"t" + + for (uint256 idx = 0; idx < 14; idx++) { + (transcript,) = KeccakTranscriptLib.squeeze(transcript, curve, t_label); + } + + PolyLib.SumcheckProof memory outer_proof = SumcheckData.returnSecondaryOuterData(); + + uint256 claim_final; + uint256[] memory r_x = new uint256[](14); + + (claim_final, r_x, transcript) = SecondarySumcheck.verify(outer_proof, 0, 14, 3, transcript); + + uint256[] memory r_x_result = new uint256[](14); + r_x_result[0] = 0x0f165407419e8c2e7685d7d70bf99a758d8d7fbea89da907b3aeaa7bee833a56; + r_x_result[1] = 0x29560c2a6cfae551d9c4dca9c51099996b3d3c2bdd2498e787f046506ba52814; + r_x_result[2] = 0x362da2eabc9f9e7d98621f197a1302f443ce859376ef1855b994adeed58fe545; + r_x_result[3] = 0x3cca5c7ea86a6a28fe166886c9170d6c5c11c0c3a62ec3542461ab9d4570db8e; + r_x_result[4] = 0x011032bc2a262b1177be0d1a0819af301f07b2526b482a642c044e9f1fb235e0; + r_x_result[5] = 0x2457b45828d84cbec89fe251bf00eef3eef83c892343349798c252ddfa6ed892; + r_x_result[6] = 0x1e75806536a945babea5f7c8f9919c044ecac67b97598cb833253aebea65f43a; + r_x_result[7] = 0x26ffb40cd04ebeee0ef0534d2e0ab8f3bab0b7965896acc89e8ca6d73fb7998f; + r_x_result[8] = 0x0204eda144c122b0dd23f2730444b643873d2dfd24b3d9f6e4120699f8d67f17; + r_x_result[9] = 0x2a5748db09c9d1253f8accba25f25e6cf536baadf655939b25f762251b238433; + r_x_result[10] = 0x006775e2804bb5851a122fb8d1023ff427e3614f93b9dc201811638c88ce449b; + r_x_result[11] = 0x1ff82c34a25a9521840fe3fce05a08766cf8236f214871de953ffed41f5312ba; + r_x_result[12] = 0x070bb7c8b02abf2d75ef8b6b8fb3997745d1c041991e0d3af11d78b11f879920; + r_x_result[13] = 0x0218ba00634e903a39bd7ed1388141981ac7aaa0572ba61802aaf2b580667bf1; + + assertEq(claim_final, 0x157e00e739ad0d53d95e24c8ec0e97081a1f94bb9a4e94a4d198c5533aebc28b); + assertEq(r_x, r_x_result); + } } diff --git a/test/sumcheck-tests.t.sol b/test/sumcheck-tests.t.sol new file mode 100644 index 0000000..547ca22 --- /dev/null +++ b/test/sumcheck-tests.t.sol @@ -0,0 +1,554 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.16; + +import "@std/Test.sol"; +import "src/verifier/step4/KeccakTranscript.sol"; +import "src/verifier/step4/SumcheckLogic.sol"; + +contract SumcheckTest is Test { + function log2(uint256 x) public pure returns (uint256 y) { + assembly { + let arg := x + x := sub(x, 1) + x := or(x, div(x, 0x02)) + x := or(x, div(x, 0x04)) + x := or(x, div(x, 0x10)) + x := or(x, div(x, 0x100)) + x := or(x, div(x, 0x10000)) + x := or(x, div(x, 0x100000000)) + x := or(x, div(x, 0x10000000000000000)) + x := or(x, div(x, 0x100000000000000000000000000000000)) + x := add(x, 1) + let m := mload(0x40) + mstore(m, 0xf8f9cbfae6cc78fbefe7cdc3a1793dfcf4f0e8bbd8cec470b6a28a7a5a3e1efd) + mstore(add(m, 0x20), 0xf5ecf1b3e9debc68e1d9cfabc5997135bfb7a7a3938b7b606b5b4b3f2f1f0ffe) + mstore(add(m, 0x40), 0xf6e4ed9ff2d6b458eadcdf97bd91692de2d4da8fd2d0ac50c6ae9a8272523616) + mstore(add(m, 0x60), 0xc8c0b887b0a8a4489c948c7f847c6125746c645c544c444038302820181008ff) + mstore(add(m, 0x80), 0xf7cae577eec2a03cf3bad76fb589591debb2dd67e0aa9834bea6925f6a4a2e0e) + mstore(add(m, 0xa0), 0xe39ed557db96902cd38ed14fad815115c786af479b7e83247363534337271707) + mstore(add(m, 0xc0), 0xc976c13bb96e881cb166a933a55e490d9d56952b8d4e801485467d2362422606) + mstore(add(m, 0xe0), 0x753a6d1b65325d0c552a4d1345224105391a310b29122104190a110309020100) + mstore(0x40, add(m, 0x100)) + let magic := 0x818283848586878898a8b8c8d8e8f929395969799a9b9d9e9faaeb6bedeeff + let shift := 0x100000000000000000000000000000000000000000000000000000000000000 + let a := div(mul(x, magic), shift) + y := div(mload(add(m, sub(255, a))), shift) + y := add(y, mul(256, gt(arg, 0x8000000000000000000000000000000000000000000000000000000000000000))) + } + } + + function testComputeTauPrimary() public { + uint8[] memory input = new uint8[](16); // b"RelaxedR1CSSNARK" in Rust + input[0] = 0x52; + input[1] = 0x65; + input[2] = 0x6c; + input[3] = 0x61; + input[4] = 0x78; + input[5] = 0x65; + input[6] = 0x64; + input[7] = 0x52; + input[8] = 0x31; + input[9] = 0x43; + input[10] = 0x53; + input[11] = 0x53; + input[12] = 0x4e; + input[13] = 0x41; + input[14] = 0x52; + input[15] = 0x4b; + + KeccakTranscriptLib.KeccakTranscript memory transcript = KeccakTranscriptLib.instantiate(input); + + uint8[] memory vk_comm = new uint8[](32); + vk_comm[0] = 0x23; + vk_comm[1] = 0xa9; + vk_comm[2] = 0x65; + vk_comm[3] = 0xae; + vk_comm[4] = 0xf5; + vk_comm[5] = 0x44; + vk_comm[6] = 0x37; + vk_comm[7] = 0x51; + vk_comm[8] = 0x77; + vk_comm[9] = 0xe0; + vk_comm[10] = 0xae; + vk_comm[11] = 0x37; + vk_comm[12] = 0x26; + vk_comm[13] = 0x8b; + vk_comm[14] = 0x5b; + vk_comm[15] = 0x32; + vk_comm[16] = 0xca; + vk_comm[17] = 0x91; + vk_comm[18] = 0x55; + vk_comm[19] = 0x28; + vk_comm[20] = 0xac; + vk_comm[21] = 0x3b; + vk_comm[22] = 0x12; + vk_comm[23] = 0x23; + vk_comm[24] = 0xe5; + vk_comm[25] = 0x68; + vk_comm[26] = 0xfb; + vk_comm[27] = 0x1c; + vk_comm[28] = 0xef; + vk_comm[29] = 0x6b; + vk_comm[30] = 0x41; + vk_comm[31] = 0x03; + + uint8[] memory vk_comm_label = new uint8[](1); // b"C" in Rust + vk_comm_label[0] = 0x43; + + uint8[] memory U = new uint8[](226); + U[0] = 0xab; + U[1] = 0xf4; + U[2] = 0xc0; + U[3] = 0x93; + U[4] = 0xd7; + U[5] = 0x1b; + U[6] = 0xd2; + U[7] = 0xab; + U[8] = 0x61; + U[9] = 0xa2; + U[10] = 0x84; + U[11] = 0x16; + U[12] = 0x3a; + U[13] = 0x36; + U[14] = 0xb2; + U[15] = 0x6c; + U[16] = 0x75; + U[17] = 0x42; + U[18] = 0x9c; + U[19] = 0x4e; + U[20] = 0x0a; + U[21] = 0xbe; + U[22] = 0x30; + U[23] = 0x25; + U[24] = 0x86; + U[25] = 0xb8; + U[26] = 0x75; + U[27] = 0x6f; + U[28] = 0x56; + U[29] = 0x1c; + U[30] = 0x3b; + U[31] = 0x22; + U[32] = 0x08; + U[33] = 0x4e; + U[34] = 0xc4; + U[35] = 0x00; + U[36] = 0xc1; + U[37] = 0xbc; + U[38] = 0x28; + U[39] = 0x22; + U[40] = 0x6d; + U[41] = 0xc7; + U[42] = 0x98; + U[43] = 0x66; + U[44] = 0x2a; + U[45] = 0x67; + U[46] = 0x8d; + U[47] = 0x47; + U[48] = 0xf0; + U[49] = 0x1e; + U[50] = 0x0c; + U[51] = 0x24; + U[52] = 0xee; + U[53] = 0xaa; + U[54] = 0x59; + U[55] = 0x69; + U[56] = 0xf7; + U[57] = 0xaa; + U[58] = 0xcf; + U[59] = 0x24; + U[60] = 0x19; + U[61] = 0x8c; + U[62] = 0x21; + U[63] = 0x05; + U[64] = 0x01; + U[65] = 0x94; + U[66] = 0x18; + U[67] = 0x0d; + U[68] = 0x05; + U[69] = 0x6f; + U[70] = 0xf8; + U[71] = 0x6d; + U[72] = 0xd8; + U[73] = 0xb2; + U[74] = 0x99; + U[75] = 0x7f; + U[76] = 0x5f; + U[77] = 0xd7; + U[78] = 0xe2; + U[79] = 0x53; + U[80] = 0xd4; + U[81] = 0x0d; + U[82] = 0xfb; + U[83] = 0xa2; + U[84] = 0x7a; + U[85] = 0x8b; + U[86] = 0x4c; + U[87] = 0xb9; + U[88] = 0x74; + U[89] = 0x62; + U[90] = 0xe6; + U[91] = 0xef; + U[92] = 0x3a; + U[93] = 0x52; + U[94] = 0x2b; + U[95] = 0xf0; + U[96] = 0x15; + U[97] = 0x78; + U[98] = 0x01; + U[99] = 0x35; + U[100] = 0x68; + U[101] = 0xf3; + U[102] = 0x63; + U[103] = 0x2c; + U[104] = 0x36; + U[105] = 0x67; + U[106] = 0x02; + U[107] = 0x01; + U[108] = 0xea; + U[109] = 0x3a; + U[110] = 0x89; + U[111] = 0x9f; + U[112] = 0x60; + U[113] = 0x25; + U[114] = 0x05; + U[115] = 0x1e; + U[116] = 0x74; + U[117] = 0xd3; + U[118] = 0x9a; + U[119] = 0x85; + U[120] = 0x6c; + U[121] = 0xf0; + U[122] = 0x96; + U[123] = 0x77; + U[124] = 0xff; + U[125] = 0xda; + U[126] = 0xea; + U[127] = 0x48; + U[128] = 0x34; + U[129] = 0x01; + U[130] = 0x30; + U[131] = 0x65; + U[132] = 0xfe; + U[133] = 0x20; + U[134] = 0x9d; + U[135] = 0x44; + U[136] = 0xbb; + U[137] = 0x99; + U[138] = 0x76; + U[139] = 0x58; + U[140] = 0x4c; + U[141] = 0xb4; + U[142] = 0xea; + U[143] = 0xd9; + U[144] = 0x89; + U[145] = 0xa3; + U[146] = 0x01; + U[147] = 0x00; + U[148] = 0x00; + U[149] = 0x00; + U[150] = 0x00; + U[151] = 0x00; + U[152] = 0x00; + U[153] = 0x00; + U[154] = 0x00; + U[155] = 0x00; + U[156] = 0x00; + U[157] = 0x00; + U[158] = 0x00; + U[159] = 0x00; + U[160] = 0x00; + U[161] = 0x00; + U[162] = 0x6a; + U[163] = 0xf4; + U[164] = 0x72; + U[165] = 0xae; + U[166] = 0x09; + U[167] = 0xba; + U[168] = 0x90; + U[169] = 0x21; + U[170] = 0xc5; + U[171] = 0xca; + U[172] = 0xd4; + U[173] = 0xa5; + U[174] = 0x3d; + U[175] = 0xe0; + U[176] = 0x18; + U[177] = 0x1f; + U[178] = 0x07; + U[179] = 0xd3; + U[180] = 0xd7; + U[181] = 0x18; + U[182] = 0xf7; + U[183] = 0x98; + U[184] = 0x27; + U[185] = 0xa1; + U[186] = 0x2b; + U[187] = 0x6f; + U[188] = 0xa6; + U[189] = 0x56; + U[190] = 0x0a; + U[191] = 0xd2; + U[192] = 0x56; + U[193] = 0x2e; + U[194] = 0xad; + U[195] = 0x9f; + U[196] = 0xa6; + U[197] = 0x2a; + U[198] = 0x1a; + U[199] = 0x9d; + U[200] = 0x69; + U[201] = 0x38; + U[202] = 0xce; + U[203] = 0x77; + U[204] = 0xa3; + U[205] = 0xd0; + U[206] = 0x4b; + U[207] = 0x90; + U[208] = 0xce; + U[209] = 0xf2; + U[210] = 0x2b; + U[211] = 0x0e; + U[212] = 0x8d; + U[213] = 0x05; + U[214] = 0x4b; + U[215] = 0x68; + U[216] = 0x8f; + U[217] = 0x47; + U[218] = 0x5b; + U[219] = 0x0c; + U[220] = 0xa6; + U[221] = 0xa1; + U[222] = 0x2b; + U[223] = 0xf5; + U[224] = 0x75; + U[225] = 0x28; + + uint8[] memory U_label = new uint8[](1); // b"U" in Rust + U_label[0] = 0x55; + + transcript = KeccakTranscriptLib.absorb(transcript, vk_comm_label, vk_comm); + transcript = KeccakTranscriptLib.absorb(transcript, U_label, U); + + uint256 num_rounds_x = log2(16384); + //uint256 num_rounds_y = log2(16384) + 1; + + uint8[] memory squeezeLabel = new uint8[](1); // b"t" in Rust + squeezeLabel[0] = 0x74; + ScalarFromUniformLib.Curve curve = ScalarFromUniformLib.curveVesta(); + + uint256[] memory tau = new uint256[](num_rounds_x); + uint256 keccakOutput; + for (uint256 index = 0; index < tau.length; index++) { + (transcript, keccakOutput) = KeccakTranscriptLib.squeeze(transcript, curve, squeezeLabel); + tau[index] = keccakOutput; + } + + assertEq(tau[0], 0x327f4af4db96711d3192cee19b1946d5b9d3c61e78d6f352261e11af7cbed55a); + assertEq(tau[1], 0x2640290b59a25f849e020cb1b0063861e35a95a8c42a9cdd63928a4ea856adbf); + assertEq(tau[2], 0x11b72e2a69592c5545a794428674fd998d4e3fbd52f156eca4a66d54f09f775e); + assertEq(tau[3], 0x09b0dcdd3ebe153fea39180a0f6bf9546778ffd7e288088489529aa95097fcea); + assertEq(tau[4], 0x3757c49e53ce7f58203159e411db2fe38854df4fc7a93833f28e63960576202e); + assertEq(tau[5], 0x362681bac77a734c4b893a2a2ff2f3cfbff469319b1a1e851c139349f1f62232); + assertEq(tau[6], 0x3036e71d56b2ed7027b5e305dddbc94d3bae6c6afdfaec8bdcd7d05cd89fc4ef); + assertEq(tau[7], 0x33ebf2408bbe683a2516b6e3904d95f6a99da08c27843d425bb3e781b407f812); + assertEq(tau[8], 0x03b2369449d816527fe9f0ec97e4971a65a35f89762ae71610f06096337ea9f2); + assertEq(tau[9], 0x38ca25021f2193df59c755dcebe90a5efb52e97c0440597915d022e9a59357bd); + assertEq(tau[10], 0x240032a20ecb27257f7334b3f538d836f40783e9709b879bd5523f789aad0a63); + assertEq(tau[11], 0x364f7a4b101385305529e5d5237cb71e69950f2b4ed7b4f0b160b1aa3ac71c9a); + assertEq(tau[12], 0x3ffacadcc0e723b1fa45c1ad1b30612dc31924e6027171f0a5da6d8963671c5a); + assertEq(tau[13], 0x25ad865935043775d676da736cc400404b1060585df1386dd4f560de4c4680bc); + } + + function testPolyUncompress() public { + uint256 e = 0; + + uint256[] memory raw_poly; + PolyLib.CompressedUniPoly memory poly; + + raw_poly = new uint256[](3); + raw_poly[0] = 0x0000000000000000000000000000000000000000000000000000000000000000; + raw_poly[1] = 0x3156ab3e1bea772559548817e8d23e4d60a57bc280baf032420e3c6133dd7e2f; + raw_poly[2] = 0x1dff490409def9717737be07798dad2c3a6bc952eec88937c6076da01f9d9af0; + + poly = PolyLib.CompressedUniPoly(raw_poly); + + PolyLib.UniPoly memory uni_poly = PolyLib.decompress(poly, e, Pallas.R_MOD); + + assertEq(uni_poly.coeffs[0], 0x0000000000000000000000000000000000000000000000000000000000000000); + assertEq(uni_poly.coeffs[1], 0x30aa0bbdda368f692f73b9e09da01486a97bece2a3a5d85110782c40ac84e6e3); + assertEq(uni_poly.coeffs[2], 0x3156ab3e1bea772559548817e8d23e4d60a57bc280baf032420e3c6133dd7e2f); + assertEq(uni_poly.coeffs[3], 0x1dff490409def9717737be07798dad2c3a6bc952eec88937c6076da01f9d9af0); + } + + function testPolyEvalAtZero() public { + uint256[] memory coeffs = new uint256[](4); + coeffs[0] = 0x2a0cd6f39b97ed92a45886a8e80a5944ed373498922050a3745f29c2ec6667ae; + coeffs[1] = 0x15d1d88908637f82529915e409c52f24dfdd0f088857a2ff9721405cbac93e42; + coeffs[2] = 0x12fbd521f3fdb45f92e1bc9d045197000c74f40e67292ccac43f9b65f854b955; + coeffs[3] = 0x0bf922cb074481cf22bfe02c62561af632503238b4198aeb5e2bb5cf8dd0fac3; + + PolyLib.UniPoly memory uni_poly = PolyLib.UniPoly(coeffs); + + assertEq(PolyLib.evalAtZero(uni_poly), 0x2a0cd6f39b97ed92a45886a8e80a5944ed373498922050a3745f29c2ec6667ae); + } + + function testPolyEvalAtOne1() public { + uint256[] memory coeffs = new uint256[](4); + coeffs[0] = 0x0000000000000000000000000000000000000000000000000000000000000000; + coeffs[1] = 0x30aa0bbdda368f692f73b9e09da01486a97bece2a3a5d85110782c40ac84e6e3; + coeffs[2] = 0x3156ab3e1bea772559548817e8d23e4d60a57bc280baf032420e3c6133dd7e2f; + coeffs[3] = 0x1dff490409def9717737be07798dad2c3a6bc952eec88937c6076da01f9d9af0; + + PolyLib.UniPoly memory uni_poly = PolyLib.UniPoly(coeffs); + + assertEq( + PolyLib.evalAtOne(uni_poly, Pallas.R_MOD), + 0x0000000000000000000000000000000000000000000000000000000000000000 + ); + } + + function testPolyEvalAtOne2() public { + uint256[] memory coeffs = new uint256[](4); + coeffs[0] = 0x2a0cd6f39b97ed92a45886a8e80a5944ed373498922050a3745f29c2ec6667ae; + coeffs[1] = 0x15d1d88908637f82529915e409c52f24dfdd0f088857a2ff9721405cbac93e42; + coeffs[2] = 0x12fbd521f3fdb45f92e1bc9d045197000c74f40e67292ccac43f9b65f854b955; + coeffs[3] = 0x0bf922cb074481cf22bfe02c62561af632503238b4198aeb5e2bb5cf8dd0fac3; + + PolyLib.UniPoly memory uni_poly = PolyLib.UniPoly(coeffs); + + assertEq( + PolyLib.evalAtOne(uni_poly, Pallas.R_MOD), + 0x1ed3a7699f3da343ac93395658773a5fe992d0ec2c26027ba1a4d0342d555a07 + ); + } + + function testPolyEvalAtOne3() public { + uint256[] memory coeffs = new uint256[](4); + coeffs[0] = 0x1a7160ebd6e443d51da504fa28e5168868012deaacfc8188014cde90744297bc; + coeffs[1] = 0x00f74486c14ea32b0c2b2116f5bcb73950d525199ddbca495ad7685e96f22f76; + coeffs[2] = 0x281222608e87d3d0d154e6621dbe68a181e5e646bbaab420859659a0e042dd4c; + coeffs[3] = 0x2ae2df351788ef2c603da9501a93ea6ea1080a1742c923a56e0daa7e0599cd1e; + + PolyLib.UniPoly memory uni_poly = PolyLib.UniPoly(coeffs); + + assertEq( + PolyLib.evalAtOne(uni_poly, Pallas.R_MOD), + 0x2e5da7083e43a9fd5b62b5c356f420d1b97daa663fb77ab9c3815fecf111719b + ); + } + + function testPolyToTranscriptBytes() public { + uint256[] memory coeffs = new uint256[](4); + coeffs[0] = 0x07e180612d7bd63a41bd64c2e6c1b0c5edbe6fa6f318cba353edb77eecd59bac; + coeffs[1] = 0x3ebba32e8b1eb5338d437e0db1894ab6fb2c14725daeef4c6a361fce880ae0ed; + coeffs[2] = 0x1785c227874bcb2e816af7d0b1b39d6369dc3017b21cfdaccbbbdf3e9a63c9ca; + coeffs[3] = 0x3001d35ebe98119d070a55ea1544bcb729493df381bf7c80ffb0203b2956d7c9; + + PolyLib.UniPoly memory uni_poly = PolyLib.UniPoly(coeffs); + + uint8[] memory polyBytes = PolyLib.toTranscriptBytes(uni_poly); + + uint8[] memory expected = new uint8[](96); + expected[0] = 0xac; + expected[1] = 0x9b; + expected[2] = 0xd5; + expected[3] = 0xec; + expected[4] = 0x7e; + expected[5] = 0xb7; + expected[6] = 0xed; + expected[7] = 0x53; + expected[8] = 0xa3; + expected[9] = 0xcb; + expected[10] = 0x18; + expected[11] = 0xf3; + expected[12] = 0xa6; + expected[13] = 0x6f; + expected[14] = 0xbe; + expected[15] = 0xed; + expected[16] = 0xc5; + expected[17] = 0xb0; + expected[18] = 0xc1; + expected[19] = 0xe6; + expected[20] = 0xc2; + expected[21] = 0x64; + expected[22] = 0xbd; + expected[23] = 0x41; + expected[24] = 0x3a; + expected[25] = 0xd6; + expected[26] = 0x7b; + expected[27] = 0x2d; + expected[28] = 0x61; + expected[29] = 0x80; + expected[30] = 0xe1; + expected[31] = 0x07; + expected[32] = 0xca; + expected[33] = 0xc9; + expected[34] = 0x63; + expected[35] = 0x9a; + expected[36] = 0x3e; + expected[37] = 0xdf; + expected[38] = 0xbb; + expected[39] = 0xcb; + expected[40] = 0xac; + expected[41] = 0xfd; + expected[42] = 0x1c; + expected[43] = 0xb2; + expected[44] = 0x17; + expected[45] = 0x30; + expected[46] = 0xdc; + expected[47] = 0x69; + expected[48] = 0x63; + expected[49] = 0x9d; + expected[50] = 0xb3; + expected[51] = 0xb1; + expected[52] = 0xd0; + expected[53] = 0xf7; + expected[54] = 0x6a; + expected[55] = 0x81; + expected[56] = 0x2e; + expected[57] = 0xcb; + expected[58] = 0x4b; + expected[59] = 0x87; + expected[60] = 0x27; + expected[61] = 0xc2; + expected[62] = 0x85; + expected[63] = 0x17; + expected[64] = 0xc9; + expected[65] = 0xd7; + expected[66] = 0x56; + expected[67] = 0x29; + expected[68] = 0x3b; + expected[69] = 0x20; + expected[70] = 0xb0; + expected[71] = 0xff; + expected[72] = 0x80; + expected[73] = 0x7c; + expected[74] = 0xbf; + expected[75] = 0x81; + expected[76] = 0xf3; + expected[77] = 0x3d; + expected[78] = 0x49; + expected[79] = 0x29; + expected[80] = 0xb7; + expected[81] = 0xbc; + expected[82] = 0x44; + expected[83] = 0x15; + expected[84] = 0xea; + expected[85] = 0x55; + expected[86] = 0x0a; + expected[87] = 0x07; + expected[88] = 0x9d; + expected[89] = 0x11; + expected[90] = 0x98; + expected[91] = 0xbe; + expected[92] = 0x5e; + expected[93] = 0xd3; + expected[94] = 0x01; + expected[95] = 0x30; + + assertEq(polyBytes.length, expected.length); + for (uint256 index = 0; index < polyBytes.length; index++) { + assertEq(polyBytes[index], expected[index]); + } + } +}