feat: verifier integration
This commit is contained in:
parent
b5f33992b6
commit
0d9b67bb31
|
@ -8,7 +8,8 @@ contract FuzzMarketplace is Marketplace {
|
||||||
constructor()
|
constructor()
|
||||||
Marketplace(
|
Marketplace(
|
||||||
new TestToken(),
|
new TestToken(),
|
||||||
MarketplaceConfig(CollateralConfig(10, 5, 3, 10), ProofConfig(10, 5, 64))
|
MarketplaceConfig(CollateralConfig(10, 5, 3, 10), ProofConfig(10, 5, 64)),
|
||||||
|
address(0)
|
||||||
)
|
)
|
||||||
// solhint-disable-next-line no-empty-blocks
|
// solhint-disable-next-line no-empty-blocks
|
||||||
{
|
{
|
||||||
|
|
|
@ -56,8 +56,9 @@ contract Marketplace is Proofs, StateRetrieval {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
IERC20 token_,
|
IERC20 token_,
|
||||||
MarketplaceConfig memory configuration
|
MarketplaceConfig memory configuration,
|
||||||
) Proofs(configuration.proofs) {
|
address verifierAddress
|
||||||
|
) Proofs(configuration.proofs, verifierAddress) {
|
||||||
token = token_;
|
token = token_;
|
||||||
|
|
||||||
require(
|
require(
|
||||||
|
@ -114,7 +115,8 @@ contract Marketplace is Proofs, StateRetrieval {
|
||||||
require(slotState(slotId) == SlotState.Free, "Slot is not free");
|
require(slotState(slotId) == SlotState.Free, "Slot is not free");
|
||||||
|
|
||||||
_startRequiringProofs(slotId, request.ask.proofProbability);
|
_startRequiringProofs(slotId, request.ask.proofProbability);
|
||||||
submitProof(slotId, proof);
|
// TODO: Update call signature
|
||||||
|
// submitProof(slotId, proof);
|
||||||
|
|
||||||
slot.host = msg.sender;
|
slot.host = msg.sender;
|
||||||
slot.state = SlotState.Filled;
|
slot.state = SlotState.Filled;
|
||||||
|
|
|
@ -5,12 +5,18 @@ import "./Configuration.sol";
|
||||||
import "./Requests.sol";
|
import "./Requests.sol";
|
||||||
import "./Periods.sol";
|
import "./Periods.sol";
|
||||||
|
|
||||||
|
interface IVerifier {
|
||||||
|
function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[3] calldata _pubSignals) external view returns (bool);
|
||||||
|
}
|
||||||
|
|
||||||
abstract contract Proofs is Periods {
|
abstract contract Proofs is Periods {
|
||||||
ProofConfig private _config;
|
ProofConfig private _config;
|
||||||
|
IVerifier private _verifier;
|
||||||
|
|
||||||
constructor(ProofConfig memory config) Periods(config.period) {
|
constructor(ProofConfig memory config, address verifierAddress) Periods(config.period) {
|
||||||
require(block.number > 256, "Insufficient block height");
|
require(block.number > 256, "Insufficient block height");
|
||||||
_config = config;
|
_config = config;
|
||||||
|
_verifier = IVerifier(verifierAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
mapping(SlotId => uint256) private _slotStarts;
|
mapping(SlotId => uint256) private _slotStarts;
|
||||||
|
@ -102,11 +108,15 @@ abstract contract Proofs is Periods {
|
||||||
return isRequired && pointer < _config.downtime;
|
return isRequired && pointer < _config.downtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
function submitProof(SlotId id, bytes calldata proof) public {
|
// TODO: The `pubSignals` should be constructed from information that we already know:
|
||||||
require(proof.length > 0, "Invalid proof"); // TODO: replace by actual check
|
// - external entropy (for example some fresh ethereum block header) - this gives us the unbiased randomness we use to sample which cells to prove
|
||||||
|
// - the dataset root (which dataset we prove)
|
||||||
|
// - and the slot index (which slot out of that dataset we prove)
|
||||||
|
function submitProof(SlotId id, uint[2] calldata pA, uint[2][2] calldata pB, uint[2] calldata pC, uint[3] calldata pubSignals) public {
|
||||||
require(!_received[id][_blockPeriod()], "Proof already submitted");
|
require(!_received[id][_blockPeriod()], "Proof already submitted");
|
||||||
|
require(_verifier.verifyProof(pA, pB, pC, pubSignals), "Invalid proof");
|
||||||
_received[id][_blockPeriod()] = true;
|
_received[id][_blockPeriod()] = true;
|
||||||
emit ProofSubmitted(id, proof);
|
emit ProofSubmitted(id, bytes("")); // TODO: Rework ProofSubmitted with the new call signature
|
||||||
}
|
}
|
||||||
|
|
||||||
function _markProofAsMissing(SlotId id, Period missedPeriod) internal {
|
function _markProofAsMissing(SlotId id, Period missedPeriod) internal {
|
||||||
|
|
|
@ -7,9 +7,10 @@ import "./Marketplace.sol";
|
||||||
contract TestMarketplace is Marketplace {
|
contract TestMarketplace is Marketplace {
|
||||||
constructor(
|
constructor(
|
||||||
IERC20 token,
|
IERC20 token,
|
||||||
MarketplaceConfig memory config
|
MarketplaceConfig memory config,
|
||||||
|
address verifierAddress
|
||||||
)
|
)
|
||||||
Marketplace(token, config) // solhint-disable-next-line no-empty-blocks
|
Marketplace(token, config, verifierAddress) // solhint-disable-next-line no-empty-blocks
|
||||||
{}
|
{}
|
||||||
|
|
||||||
function forciblyFreeSlot(SlotId slotId) public {
|
function forciblyFreeSlot(SlotId slotId) public {
|
||||||
|
|
|
@ -8,7 +8,7 @@ contract TestProofs is Proofs {
|
||||||
mapping(SlotId => SlotState) private _states;
|
mapping(SlotId => SlotState) private _states;
|
||||||
|
|
||||||
// solhint-disable-next-line no-empty-blocks
|
// solhint-disable-next-line no-empty-blocks
|
||||||
constructor(ProofConfig memory config) Proofs(config) {}
|
constructor(ProofConfig memory config, address verifierAddress) Proofs(config, verifierAddress) {}
|
||||||
|
|
||||||
function slotState(SlotId slotId) public view override returns (SlotState) {
|
function slotState(SlotId slotId) public view override returns (SlotState) {
|
||||||
return _states[slotId];
|
return _states[slotId];
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"pi_a": [
|
||||||
|
"12575931798333091286325232720222610208857693569302057808885252947429216447180",
|
||||||
|
"16549473200179311181194191095131663560815201508441791825123921223678935560766",
|
||||||
|
"1"
|
||||||
|
],
|
||||||
|
"pi_b": [
|
||||||
|
[
|
||||||
|
"10539735118221868154517125926361767140470515908908074935137601194792761800171",
|
||||||
|
"82933007286657251580767357783340888344421112063684410243727242770275681544"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"12783061468979995595204827460841361850250217151383589736164479836366818492603",
|
||||||
|
"14029329025815586221542089598302928160626432109838714917216872595944862705134"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"1",
|
||||||
|
"0"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"pi_c": [
|
||||||
|
"13431392674314693403054162903564691589030062102064045494372006369097976531644",
|
||||||
|
"14766632196294836790840495714548165339030519379498058874034063314395047727400",
|
||||||
|
"1"
|
||||||
|
],
|
||||||
|
"protocol": "groth16",
|
||||||
|
"curve": "bn128"
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
[
|
||||||
|
"7410779170",
|
||||||
|
"16074246370508166450132968585287196391860062495017081813239200574579640171677",
|
||||||
|
"3"
|
||||||
|
]
|
|
@ -0,0 +1,180 @@
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
/*
|
||||||
|
Copyright 2021 0KIMS association.
|
||||||
|
|
||||||
|
This file is generated with [snarkJS](https://github.com/iden3/snarkjs).
|
||||||
|
|
||||||
|
snarkJS is a free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity >=0.7.0 <0.9.0;
|
||||||
|
|
||||||
|
contract Groth16Verifier {
|
||||||
|
// Scalar field size
|
||||||
|
uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
|
||||||
|
// Base field size
|
||||||
|
uint256 constant q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
|
||||||
|
|
||||||
|
// Verification Key data
|
||||||
|
uint256 constant alphax = 20491192805390485299153009773594534940189261866228447918068658471970481763042;
|
||||||
|
uint256 constant alphay = 9383485363053290200918347156157836566562967994039712273449902621266178545958;
|
||||||
|
uint256 constant betax1 = 4252822878758300859123897981450591353533073413197771768651442665752259397132;
|
||||||
|
uint256 constant betax2 = 6375614351688725206403948262868962793625744043794305715222011528459656738731;
|
||||||
|
uint256 constant betay1 = 21847035105528745403288232691147584728191162732299865338377159692350059136679;
|
||||||
|
uint256 constant betay2 = 10505242626370262277552901082094356697409835680220590971873171140371331206856;
|
||||||
|
uint256 constant gammax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
|
||||||
|
uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
|
||||||
|
uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
|
||||||
|
uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
|
||||||
|
uint256 constant deltax1 = 13712868925708658085847556664366075488044104377560666483004097971457124593853;
|
||||||
|
uint256 constant deltax2 = 10641155327113821350709388160714981167756198765458730005846188297891779189493;
|
||||||
|
uint256 constant deltay1 = 17764386955997045623322956974738840392389044888308308825307170058332555991668;
|
||||||
|
uint256 constant deltay2 = 11545289596289529089490468468326982998415255475081847246298663415914281403462;
|
||||||
|
|
||||||
|
|
||||||
|
uint256 constant IC0x = 2685717341061384289974985759706305556965509240536260442727245444252129889599;
|
||||||
|
uint256 constant IC0y = 21827535600902499280458695057256182457185285685995970634461174274051979800815;
|
||||||
|
|
||||||
|
uint256 constant IC1x = 13158415194355348546090070151711085027834066488127676886518524272551654481129;
|
||||||
|
uint256 constant IC1y = 18831701962118195025265682681702066674741422770850028135520336928884612556978;
|
||||||
|
|
||||||
|
uint256 constant IC2x = 20882269691461568155321689204947751047717828445545223718893788782534717197527;
|
||||||
|
uint256 constant IC2y = 11996193054822748526485644723594571195813487505803351159052936325857690315211;
|
||||||
|
|
||||||
|
uint256 constant IC3x = 18155166643053044822201627105588517913195535693446564472247126736722594445000;
|
||||||
|
uint256 constant IC3y = 13816319482622393060406816684195314200198627617641073470088058848129378231754;
|
||||||
|
|
||||||
|
// Memory data
|
||||||
|
uint16 constant pVk = 0;
|
||||||
|
uint16 constant pPairing = 128;
|
||||||
|
|
||||||
|
uint16 constant pLastMem = 896;
|
||||||
|
|
||||||
|
function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[3] calldata _pubSignals) public view returns (bool) {
|
||||||
|
assembly {
|
||||||
|
function checkField(v) {
|
||||||
|
if iszero(lt(v, q)) {
|
||||||
|
mstore(0, 0)
|
||||||
|
return (0, 0x20)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// G1 function to multiply a G1 value(x,y) to value in an address
|
||||||
|
function g1_mulAccC(pR, x, y, s) {
|
||||||
|
let success
|
||||||
|
let mIn := mload(0x40)
|
||||||
|
mstore(mIn, x)
|
||||||
|
mstore(add(mIn, 32), y)
|
||||||
|
mstore(add(mIn, 64), s)
|
||||||
|
|
||||||
|
success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
|
||||||
|
|
||||||
|
if iszero(success) {
|
||||||
|
mstore(0, 0)
|
||||||
|
return (0, 0x20)
|
||||||
|
}
|
||||||
|
|
||||||
|
mstore(add(mIn, 64), mload(pR))
|
||||||
|
mstore(add(mIn, 96), mload(add(pR, 32)))
|
||||||
|
|
||||||
|
success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
|
||||||
|
|
||||||
|
if iszero(success) {
|
||||||
|
mstore(0, 0)
|
||||||
|
return (0, 0x20)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk {
|
||||||
|
let _pPairing := add(pMem, pPairing)
|
||||||
|
let _pVk := add(pMem, pVk)
|
||||||
|
|
||||||
|
mstore(_pVk, IC0x)
|
||||||
|
mstore(add(_pVk, 32), IC0y)
|
||||||
|
|
||||||
|
// Compute the linear combination vk_x
|
||||||
|
|
||||||
|
g1_mulAccC(_pVk, IC1x, IC1y, calldataload(add(pubSignals, 0)))
|
||||||
|
|
||||||
|
g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32)))
|
||||||
|
|
||||||
|
g1_mulAccC(_pVk, IC3x, IC3y, calldataload(add(pubSignals, 64)))
|
||||||
|
|
||||||
|
// -A
|
||||||
|
mstore(_pPairing, calldataload(pA))
|
||||||
|
mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q))
|
||||||
|
|
||||||
|
// B
|
||||||
|
mstore(add(_pPairing, 64), calldataload(pB))
|
||||||
|
mstore(add(_pPairing, 96), calldataload(add(pB, 32)))
|
||||||
|
mstore(add(_pPairing, 128), calldataload(add(pB, 64)))
|
||||||
|
mstore(add(_pPairing, 160), calldataload(add(pB, 96)))
|
||||||
|
|
||||||
|
// alpha1
|
||||||
|
mstore(add(_pPairing, 192), alphax)
|
||||||
|
mstore(add(_pPairing, 224), alphay)
|
||||||
|
|
||||||
|
// beta2
|
||||||
|
mstore(add(_pPairing, 256), betax1)
|
||||||
|
mstore(add(_pPairing, 288), betax2)
|
||||||
|
mstore(add(_pPairing, 320), betay1)
|
||||||
|
mstore(add(_pPairing, 352), betay2)
|
||||||
|
|
||||||
|
// vk_x
|
||||||
|
mstore(add(_pPairing, 384), mload(add(pMem, pVk)))
|
||||||
|
mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32))))
|
||||||
|
|
||||||
|
// gamma2
|
||||||
|
mstore(add(_pPairing, 448), gammax1)
|
||||||
|
mstore(add(_pPairing, 480), gammax2)
|
||||||
|
mstore(add(_pPairing, 512), gammay1)
|
||||||
|
mstore(add(_pPairing, 544), gammay2)
|
||||||
|
|
||||||
|
// C
|
||||||
|
mstore(add(_pPairing, 576), calldataload(pC))
|
||||||
|
mstore(add(_pPairing, 608), calldataload(add(pC, 32)))
|
||||||
|
|
||||||
|
// delta2
|
||||||
|
mstore(add(_pPairing, 640), deltax1)
|
||||||
|
mstore(add(_pPairing, 672), deltax2)
|
||||||
|
mstore(add(_pPairing, 704), deltay1)
|
||||||
|
mstore(add(_pPairing, 736), deltay2)
|
||||||
|
|
||||||
|
|
||||||
|
let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20)
|
||||||
|
|
||||||
|
isOk := and(success, mload(_pPairing))
|
||||||
|
}
|
||||||
|
|
||||||
|
let pMem := mload(0x40)
|
||||||
|
mstore(0x40, add(pMem, pLastMem))
|
||||||
|
|
||||||
|
// Validate that all evaluations ∈ F
|
||||||
|
|
||||||
|
checkField(calldataload(add(_pubSignals, 0)))
|
||||||
|
|
||||||
|
checkField(calldataload(add(_pubSignals, 32)))
|
||||||
|
|
||||||
|
checkField(calldataload(add(_pubSignals, 64)))
|
||||||
|
|
||||||
|
checkField(calldataload(add(_pubSignals, 96)))
|
||||||
|
|
||||||
|
// Validate all evaluations
|
||||||
|
let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem)
|
||||||
|
|
||||||
|
mstore(0, isValid)
|
||||||
|
return (0, 0x20)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ const MARKETPLACE_HARDCODED_ADDRESS = "0x59b670e9fA9D0A427751Af201D676719a970857
|
||||||
|
|
||||||
async function deployMarketplace({ deployments, getNamedAccounts }) {
|
async function deployMarketplace({ deployments, getNamedAccounts }) {
|
||||||
const token = await deployments.get("TestToken")
|
const token = await deployments.get("TestToken")
|
||||||
|
const verifier = await deployments.get("Verifier")
|
||||||
const configuration = {
|
const configuration = {
|
||||||
collateral: {
|
collateral: {
|
||||||
repairRewardPercentage: 10,
|
repairRewardPercentage: 10,
|
||||||
|
@ -15,7 +16,7 @@ async function deployMarketplace({ deployments, getNamedAccounts }) {
|
||||||
downtime: 64,
|
downtime: 64,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
const args = [token.address, configuration]
|
const args = [token.address, configuration, verifier.address]
|
||||||
const { deployer } = await getNamedAccounts()
|
const { deployer } = await getNamedAccounts()
|
||||||
await deployments.deploy("Marketplace", { args, from: deployer })
|
await deployments.deploy("Marketplace", { args, from: deployer })
|
||||||
}
|
}
|
||||||
|
@ -46,4 +47,4 @@ module.exports = async (environment) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.tags = ["Marketplace"]
|
module.exports.tags = ["Marketplace"]
|
||||||
module.exports.dependencies = ["TestToken"]
|
module.exports.dependencies = ["TestToken", "Verifier"]
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
module.exports = async ({ deployments, getNamedAccounts }) => {
|
||||||
|
const { deployer } = await getNamedAccounts()
|
||||||
|
|
||||||
|
// TODO: Add logic to deploy specific version of verifier based on the network: network.tags....
|
||||||
|
// The `contract: ...` part allows to fully specify the contract to be
|
||||||
|
// deployed even if they are with the same names.
|
||||||
|
await deployments.deploy("Verifier", { from: deployer, contract: "contracts/verifiers/testing/verifier.sol:Groth16Verifier" })
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.tags = ["Verifier"]
|
|
@ -11,6 +11,7 @@ const {
|
||||||
advanceTimeToForNextBlock,
|
advanceTimeToForNextBlock,
|
||||||
} = require("./evm")
|
} = require("./evm")
|
||||||
const { periodic } = require("./time")
|
const { periodic } = require("./time")
|
||||||
|
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")
|
||||||
|
|
||||||
|
@ -28,7 +29,9 @@ describe("Proofs", function () {
|
||||||
await snapshot()
|
await snapshot()
|
||||||
await ensureMinimumBlockHeight(256)
|
await ensureMinimumBlockHeight(256)
|
||||||
const Proofs = await ethers.getContractFactory("TestProofs")
|
const Proofs = await ethers.getContractFactory("TestProofs")
|
||||||
proofs = await Proofs.deploy({ period, timeout, downtime })
|
const Verifier = await ethers.getContractFactory("contracts/verifiers/testing/verifier.sol:Groth16Verifier")
|
||||||
|
const verifier = await Verifier.deploy()
|
||||||
|
proofs = await Proofs.deploy({ period, timeout, downtime }, verifier.address)
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(async function () {
|
afterEach(async function () {
|
||||||
|
@ -152,7 +155,7 @@ describe("Proofs", function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("when proofs are required", function () {
|
describe("when proofs are required", function () {
|
||||||
const proof = hexlify(randomBytes(42))
|
const proof = loadProof('testing')
|
||||||
|
|
||||||
beforeEach(async function () {
|
beforeEach(async function () {
|
||||||
await proofs.setSlotState(slotId, SlotState.Filled)
|
await proofs.setSlotState(slotId, SlotState.Filled)
|
||||||
|
@ -192,25 +195,26 @@ describe("Proofs", function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it("submits a correct proof", async function () {
|
it("submits a correct proof", async function () {
|
||||||
await proofs.submitProof(slotId, proof)
|
await proofs.submitProof(slotId, ...proof)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("fails proof submission when proof is incorrect", async function () {
|
it("fails proof submission when proof is incorrect", async function () {
|
||||||
await expect(proofs.submitProof(slotId, [])).to.be.revertedWith(
|
await expect(proofs.submitProof(slotId, ["0x1bcdb9a3c52070f56e8d59b29239f0528817f99745157ce4d03faefddfff6acc", "0x2496ab7dd8f0596c21653105e4af7e48eb5395ea45e0c876d7db4dd31b4df23e"],[["0x002ef03c350ccfbf234bfde498378709edea3a506383d492b58c4c35ffecc508", "0x174d475745707d35989001e9216201bdb828130b0e78dbf772c4795fa845b5eb"],["0x1f04519f202fac14311c65d827f65f787dbe01985044278292723b9ee77ce5ee", "0x1c42f4d640e94c28401392031e74426ae68145f4f520cd576ca5e5b9af97c0bb"]],["0x1db1e61b32db677f3927ec117569e068f62747986e4ac7f54db8f2acd17e4abc", "0x20a59e1daca2ab80199c5bca2c5a7d6de6348bd795a0dd999752cc462d851128"],["0x00000000000000000000000000000000000000000000000000000001b9b78422","0x2389b3770d31a09a71cda2cb2114c203172eac63b61f76cb9f81db7adbe8fc9d","0x0000000000000000000000000000000000000000000000000000000000000003"]))
|
||||||
|
.to.be.revertedWith(
|
||||||
"Invalid proof"
|
"Invalid proof"
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("emits an event when proof was submitted", async function () {
|
it("emits an event when proof was submitted", async function () {
|
||||||
await expect(proofs.submitProof(slotId, proof))
|
await expect(proofs.submitProof(slotId, ...proof))
|
||||||
.to.emit(proofs, "ProofSubmitted")
|
.to.emit(proofs, "ProofSubmitted")
|
||||||
.withArgs(slotId, proof)
|
// .withArgs(slotId, proof) // TODO: Update when ProofSubmitted updated
|
||||||
})
|
})
|
||||||
|
|
||||||
it("fails proof submission when already submitted", async function () {
|
it("fails proof submission when already submitted", async function () {
|
||||||
await advanceTimeToForNextBlock(periodEnd(periodOf(await currentTime())))
|
await advanceTimeToForNextBlock(periodEnd(periodOf(await currentTime())))
|
||||||
await proofs.submitProof(slotId, proof)
|
await proofs.submitProof(slotId, ...proof)
|
||||||
await expect(proofs.submitProof(slotId, proof)).to.be.revertedWith(
|
await expect(proofs.submitProof(slotId, ...proof)).to.be.revertedWith(
|
||||||
"Proof already submitted"
|
"Proof already submitted"
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -245,7 +249,7 @@ describe("Proofs", function () {
|
||||||
it("does not mark a submitted proof as missing", async function () {
|
it("does not mark a submitted proof as missing", async function () {
|
||||||
await waitUntilProofIsRequired(slotId)
|
await waitUntilProofIsRequired(slotId)
|
||||||
let submittedPeriod = periodOf(await currentTime())
|
let submittedPeriod = periodOf(await currentTime())
|
||||||
await proofs.submitProof(slotId, proof)
|
await proofs.submitProof(slotId, ...proof)
|
||||||
await advanceTimeToForNextBlock(periodEnd(submittedPeriod))
|
await advanceTimeToForNextBlock(periodEnd(submittedPeriod))
|
||||||
await mine()
|
await mine()
|
||||||
await expect(
|
await expect(
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
const fs = require('fs')
|
||||||
|
|
||||||
|
const BASE_PATH = __dirname + '/../contracts/verifiers'
|
||||||
|
const PROOF_FILE_NAME = 'proof.json'
|
||||||
|
const PUBLIC_FILE_NAME = 'public.json'
|
||||||
|
|
||||||
|
// TODO: Some error handling, when file don't exists or don't have expected format?
|
||||||
|
function loadProof (name) {
|
||||||
|
const proof = JSON.parse(fs.readFileSync(`${BASE_PATH}/${name}/${PROOF_FILE_NAME}`))
|
||||||
|
const publicSignals = JSON.parse(fs.readFileSync(`${BASE_PATH}/${name}/${PUBLIC_FILE_NAME}`))
|
||||||
|
|
||||||
|
// TODO: We need to do some input processing from the given files, that I did not have time to look into
|
||||||
|
// instead I hardcoded the values. Look into https://github.com/iden3/snarkjs#26-simulate-a-verification-call
|
||||||
|
// how to obtain it.
|
||||||
|
|
||||||
|
//return [proof.pi_a, proof.pi_b, proof.pi_c, public]
|
||||||
|
return [["0x1bcdb9a3c52070f56e8d49b29239f0528817f99745157ce4d03faefddfff6acc", "0x2496ab7dd8f0596c21653105e4af7e48eb5395ea45e0c876d7db4dd31b4df23e"],[["0x002ef03c350ccfbf234bfde498378709edea3a506383d492b58c4c35ffecc508", "0x174d475745707d35989001e9216201bdb828130b0e78dbf772c4795fa845b5eb"],["0x1f04519f202fac14311c65d827f65f787dbe01985044278292723b9ee77ce5ee", "0x1c42f4d640e94c28401392031e74426ae68145f4f520cd576ca5e5b9af97c0bb"]],["0x1db1e61b32db677f3927ec117569e068f62747986e4ac7f54db8f2acd17e4abc", "0x20a59e1daca2ab80199c5bca2c5a7d6de6348bd795a0dd999752cc462d851128"],["0x00000000000000000000000000000000000000000000000000000001b9b78422","0x2389b3770d31a09a71cda2cb2114c203172eac63b61f76cb9f81db7adbe8fc9d","0x0000000000000000000000000000000000000000000000000000000000000003"]]
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { loadProof }
|
Loading…
Reference in New Issue