WIP: type conversions, start moving verifyProof

- Add type conversions from BLS12-381 to BN254
- start moving verifyProof over to BN254 in solidity
This commit is contained in:
Eric Mastro 2022-06-08 15:04:58 +10:00
parent 2bf01da728
commit c0969815a1
No known key found for this signature in database
GPG Key ID: 141E3048D95A4E63
2 changed files with 179 additions and 2 deletions

View File

@ -1,5 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma solidity >=0.6.0 <=0.8.13;
import "bls-solidity/contracts/BN256G1.sol";
import "elliptic-curve-solidity/contracts/EllipticCurve.sol";
contract Proofs {
uint256 private immutable period;
@ -10,7 +13,7 @@ contract Proofs {
uint256 __period,
uint256 __timeout,
uint8 __downtime
) {
) public {
require(block.number > 256, "Insufficient block height");
period = __period;
timeout = __timeout;
@ -129,6 +132,178 @@ contract Proofs {
return _isProofRequired(id, currentPeriod());
}
// proc verifyProof*(tau: Tau, q: openArray[QElement], mus: openArray[blst_scalar], sigma: blst_p1, spk: PublicKey): bool =
// ## Verify a BLS proof given a query
// # verify signature on Tau
// var signature: Signature
// if not signature.fromBytes(tau.signature):
// return false
// if not verify(spk.signkey, $tau.t, signature):
// return false
// var first: blst_p1
// for qelem in q :
// var prod: blst_p1
// prod.blst_p1_mult(hashNameI(tau.t.name, qelem.I), qelem.V, 255)
// first.blst_p1_add_or_double(first, prod)
// doAssert(blst_p1_on_curve(first).bool)
// let us = tau.t.u
// var second: blst_p1
// for j in 0 ..< len(us) :
// var prod: blst_p1
// prod.blst_p1_mult(us[j], mus[j], 255)
// second.blst_p1_add_or_double(second, prod)
// doAssert(blst_p1_on_curve(second).bool)
// var sum: blst_p1
// sum.blst_p1_add_or_double(first, second)
// var g{.noInit.}: blst_p2
// g.blst_p2_from_affine(BLS12_381_G2)
// return verifyPairings(sum, spk.key, sigma, g)
struct BnFr {
// in mratsim/constantine, given the following:
//
// func wordsRequired*(bits: int): int {.compileTime.} =
// ## Compute the number of limbs required
// # from the **announced** bit length
// (bits + WordBitWidth - 1) div WordBitWidth
//
// type
// SecretWord* = distinct uint64
//
// BigInt*[bits: static int] = object
// limbs*: array[bits.wordsRequired, SecretWord]
//
// Fr*[C: static Curve] = object => Fr[C: BN254_Snarks]
// mres*: matchingOrderBigInt(C) => mres*: BigInt[254]
//
// For the BN254_Snarks curve,
// orderBitwidth = 254
// wordsRequired = 4 (output of the wordsRequired func above)
//
// We can then conclude:
//
// type
// Fr*[C: BN254_Snarks] = object
// mres*: BigInt[254]
// limbs*: array[4, uint64]
//
// This matches FR = distinct BNU256 in nim-bncurve:
// type
// BNU256* = array[4, uint64]
//
// Note: for BLS curves (in nim-blscurve),
// type
// blst_fp = array[0..5, uint64]
uint64[4] ls;
}
struct BnFp {
// see notes from BnFr, the only difference is that we use the
// ordered bit width in BnFr, as opposed to the bit width for Fr.
// Both are 254 bits wide, so the data structure is identical.
uint64[4] ls;
}
struct BnFp2 {
// In mratsim/constantine, given the following:
//
// type
//
// QuadraticExt*[F] = object
// coords*: array[2, F]
//
// Fp2*[C: static Curve] =
// QuadraticExt[Fp[C]] => QuadraticExt[Fp[BN254_Snarks]]
//
// equates to
// Fp2*[C: static Curve] =
// QuadraticExt[Fp[BN254_Snarks]]
// coords: array[2, Fp[BN254_Snarks]]
BnFp[2] fp;
}
struct BnP1 {
BnFp x;
BnFp y;
BnFp z;
}
struct BnScalar {
// Taken from nim-blscurve/bls_abi, cannot find an analogue in
// mratsim/constantine nor nim-bncurve
//
// # blst_scalar
// # = typedesc[array[0..31, byte]]
// array[typeof(256)(typeof(256)(256 / typeof(256)(8))), byte]
bytes32[32] ls;
}
struct TauZero {
bytes32[512] name;
int64 n;
BnP1[] u; // seq[blst_p1]
}
struct Tau {
TauZero t;
bytes32[96] signature;
}
// x', y' affine coordinates, result of EllipticCurve.ecMul
// e.g. https://github.com/witnet/elliptic-curve-solidity/blob/master/examples/Secp256k1.sol
struct PublicKey {
uint256 x;
uint256 y;
}
struct QElement {
int64 i;
BnScalar v;
}
function isEmpty(bytes32[96] memory array) internal pure returns (bool) {
for(uint i; i< array.length; i++){
if(i > 0) {
return true;
}
}
return false;
}
function _verifyProof(
Tau memory tau,
QElement[] memory q,
BnFr[10] memory mus,
// Possibly 48 bytes long, csaba?
BnP1 memory sigma,
PublicKey memory spk) internal returns (bool) {
// is this really needed?
require(!isEmpty(tau.signature), "Signature cannot be empty");
// TODO: add verification
// if not verify(spk.signkey, $tau.t, signature):
// return false
// var first: blst_p1
// for qelem in q :
// var prod: blst_p1
// prod.blst_p1_mult(hashNameI(tau.t.name, qelem.I), qelem.V, 255)
// first.blst_p1_add_or_double(first, prod)
// doAssert(blst_p1_on_curve(first).bool)
BnP1 memory bnP1;
for (uint i = 0; i<q.length; i++) {
QElement memory qelem = q[i];
var (x, y) = EllipticCurve.hashToTryAndIncrement(bytes(string(tau.t.name)));// + string(qelem.i));
// p1Affine = toAffine(qelem.i)
// TODO: Where does 255 get used???
BnP1 memory prod = BN256G1.multiply(x, y, qelem.v);
}
}
function _willProofBeRequired(bytes32 id) internal view returns (bool) {
bool isRequired;
uint8 pointer;

View File

@ -11,6 +11,8 @@
"@nomiclabs/hardhat-ethers": "^2.0.5",
"@nomiclabs/hardhat-waffle": "^2.0.3",
"@openzeppelin/contracts": "^4.5.0",
"bls-solidity": "github:witnet/bls-solidity#5a27f14",
"elliptic-curve-solidity": "github:witnet/elliptic-curve-solidity#b6886bb",
"chai": "^4.3.6",
"ethereum-waffle": "^3.4.0",
"ethers": "^5.6.0",