Submit proof as Groth16Proof struct

This commit is contained in:
Mark Spanbroek 2024-01-18 13:50:54 +01:00 committed by markspanbroek
parent ae03690d51
commit e6a918fed9
6 changed files with 53 additions and 33 deletions

18
contracts/Groth16.sol Normal file
View File

@ -0,0 +1,18 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
struct G1Point {
uint x;
uint y;
}
struct G2Point {
uint[2] x;
uint[2] y;
}
struct Groth16Proof {
G1Point a;
G2Point b;
G1Point c;
}

View File

@ -9,6 +9,7 @@ import "./Requests.sol";
import "./Proofs.sol"; import "./Proofs.sol";
import "./StateRetrieval.sol"; import "./StateRetrieval.sol";
import "./Verifier.sol"; import "./Verifier.sol";
import "./Groth16.sol";
contract Marketplace is Proofs, StateRetrieval { contract Marketplace is Proofs, StateRetrieval {
using EnumerableSet for EnumerableSet.Bytes32Set; using EnumerableSet for EnumerableSet.Bytes32Set;
@ -100,7 +101,7 @@ contract Marketplace is Proofs, StateRetrieval {
function fillSlot( function fillSlot(
RequestId requestId, RequestId requestId,
uint256 slotIndex, uint256 slotIndex,
uint256[8] calldata proof Groth16Proof calldata proof
) public requestIsKnown(requestId) { ) public requestIsKnown(requestId) {
Request storage request = _requests[requestId]; Request storage request = _requests[requestId];
require(slotIndex < request.ask.slots, "Invalid slot"); require(slotIndex < request.ask.slots, "Invalid slot");

View File

@ -5,6 +5,7 @@ import "./Configuration.sol";
import "./Requests.sol"; import "./Requests.sol";
import "./Periods.sol"; import "./Periods.sol";
import "./Verifier.sol"; import "./Verifier.sol";
import "./Groth16.sol";
abstract contract Proofs is Periods { abstract contract Proofs is Periods {
ProofConfig private _config; ProofConfig private _config;
@ -108,19 +109,8 @@ abstract contract Proofs is Periods {
return isRequired && pointer < _config.downtime; return isRequired && pointer < _config.downtime;
} }
function submitProof(SlotId id, uint256[8] calldata proof) public { function submitProof(SlotId id, Groth16Proof calldata proof) public {
require(!_received[id][_blockPeriod()], "Proof already submitted"); require(!_received[id][_blockPeriod()], "Proof already submitted");
uint256[2] memory a;
uint256[2][2] memory b;
uint256[2] memory c;
a[0] = proof[0];
a[1] = proof[1];
b[0][0] = proof[2];
b[0][1] = proof[3];
b[1][0] = proof[4];
b[1][1] = proof[5];
c[0] = proof[6];
c[1] = proof[7];
// TODO: The `pubSignals` should be constructed from information that we already know: // TODO: The `pubSignals` should be constructed from information that we already know:
// - external entropy (for example some fresh ethereum block header) - this gives us the unbiased randomness we use to sample which cells to prove // - external entropy (for example some fresh ethereum block header) - this gives us the unbiased randomness we use to sample which cells to prove
@ -133,7 +123,15 @@ abstract contract Proofs is Periods {
] = 16074246370508166450132968585287196391860062495017081813239200574579640171677; ] = 16074246370508166450132968585287196391860062495017081813239200574579640171677;
pubSignals[2] = 3; pubSignals[2] = 3;
require(_verifier.verifyProof(a, b, c, pubSignals), "Invalid proof"); require(
_verifier.verifyProof(
[proof.a.x, proof.a.y],
[proof.b.x, proof.b.y],
[proof.c.x, proof.c.y],
pubSignals
),
"Invalid proof"
);
_received[id][_blockPeriod()] = true; _received[id][_blockPeriod()] = true;
emit ProofSubmitted(id); emit ProofSubmitted(id);
} }

View File

@ -14,6 +14,7 @@ const { periodic } = require("./time")
const { loadProof } = require("./proof") const { loadProof } = require("./proof")
const { SlotState } = require("./requests") const { SlotState } = require("./requests")
const binomialTest = require("@stdlib/stats-binomial-test") const binomialTest = require("@stdlib/stats-binomial-test")
const { exampleProof } = require("./examples")
describe("Proofs", function () { describe("Proofs", function () {
const slotId = hexlify(randomBytes(32)) const slotId = hexlify(randomBytes(32))
@ -204,8 +205,7 @@ describe("Proofs", function () {
}) })
it("fails proof submission when proof is incorrect", async function () { it("fails proof submission when proof is incorrect", async function () {
let invalid = new Uint8Array(proof) let invalid = exampleProof()
invalid[42] = 42
await expect(proofs.submitProof(slotId, invalid)).to.be.reverted await expect(proofs.submitProof(slotId, invalid)).to.be.reverted
}) })

View File

@ -39,6 +39,10 @@ const exampleRequest = async () => {
} }
} }
const exampleProof = () => ([1, 2, 3, 4, 5, 6, 7, 8]) const exampleProof = () => ({
a: { x: 1, y: 2 },
b: { x: [3, 4], y: [5, 6]},
c: { x: 7, y: 8 }
})
module.exports = { exampleConfiguration, exampleRequest, exampleProof } module.exports = { exampleConfiguration, exampleRequest, exampleProof }

View File

@ -5,30 +5,29 @@ const { BigNumber } = ethers
const BASE_PATH = __dirname + "/../verifier/networks" const BASE_PATH = __dirname + "/../verifier/networks"
const PROOF_FILE_NAME = "example-proof/proof.json" const PROOF_FILE_NAME = "example-proof/proof.json"
function G1ToUInts(point) { function G1ToStruct(point) {
return [ return {
point[0], x: point[0],
point[1] y: point[1]
] }
} }
function G2ToUInts(point) { function G2ToStruct(point) {
return [ return {
point[0][1], x: [ point[0][1], point[0][0] ],
point[0][0], y: [ point[1][1], point[1][0] ]
point[1][1], }
point[1][0]
]
} }
function loadProof(name) { function loadProof(name) {
const proof = JSON.parse( const proof = JSON.parse(
fs.readFileSync(`${BASE_PATH}/${name}/${PROOF_FILE_NAME}`) fs.readFileSync(`${BASE_PATH}/${name}/${PROOF_FILE_NAME}`)
) )
return [] return {
.concat(G1ToUInts(proof['pi_a'])) a: G1ToStruct(proof['pi_a']),
.concat(G2ToUInts(proof['pi_b'])) b: G2ToStruct(proof['pi_b']),
.concat(G1ToUInts(proof['pi_c'])) c: G1ToStruct(proof['pi_c'])
}
} }
module.exports = { loadProof } module.exports = { loadProof }