por: separating BLST backend
WIP: func and proc names might be improved later.
This commit is contained in:
parent
bad8186939
commit
31d7e712e5
|
@ -0,0 +1,111 @@
|
|||
## Nim-POS
|
||||
## Copyright (c) 2022 Status Research & Development GmbH
|
||||
## Licensed under either of
|
||||
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
||||
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
||||
## at your option.
|
||||
## This file may not be copied, modified, or distributed except according to
|
||||
## those terms.
|
||||
|
||||
# Implementation of the BLS-based public PoS scheme from
|
||||
# Shacham H., Waters B., "Compact Proofs of Retrievability"
|
||||
# using pairing over BLS12-381 ECC
|
||||
|
||||
import blscurve
|
||||
import blscurve/blst/blst_abi
|
||||
|
||||
type
|
||||
ec_SecretKey* = blscurve.SecretKey
|
||||
ec_PublicKey* = blscurve.PublicKey
|
||||
ec_p1* = blst_p1
|
||||
ec_p2* = blst_p2
|
||||
ec_scalar* = blst_scalar
|
||||
ec_fr* = blst_fr
|
||||
ec_signature* = Signature
|
||||
|
||||
# these need to be template as a workaround for const
|
||||
template EC_G1* : blst_p1_affine = BLS12_381_G1
|
||||
template EC_G2* : blst_p2_affine = BLS12_381_G2
|
||||
|
||||
let
|
||||
ec_p1_from_affine* = blst_p1_from_affine
|
||||
ec_scalar_from_bendian* = blst_scalar_from_bendian
|
||||
ec_scalar_fr_check* = blst_scalar_fr_check
|
||||
ec_p2_from_affine* = blst_p2_from_affine
|
||||
ec_p2_mult* = blst_p2_mult
|
||||
ec_p1_mult* = blst_p1_mult
|
||||
ec_p1_add_or_double* = blst_p1_add_or_double
|
||||
ec_fr_from_scalar* = blst_fr_from_scalar
|
||||
ec_fr_mul* = blst_fr_mul
|
||||
ec_scalar_from_fr* = blst_scalar_from_fr
|
||||
ec_fr_add* = blst_fr_add
|
||||
ec_p1_on_curve* = blst_p1_on_curve
|
||||
ec_keygen* = blscurve.keyGen
|
||||
|
||||
func ec_export_raw*(signature: Signature): array[96, byte] {.inline, noinit.} =
|
||||
blscurve.exportRaw(signature)
|
||||
|
||||
proc ec_sign*[T: byte|char](secretKey: SecretKey, message: openarray[T]): Signature =
|
||||
blscurve.sign(secretKey, message)
|
||||
|
||||
proc ec_hash_to_g1*[T,U,V: byte|char](dst: var blst_p1;
|
||||
msg: openArray[T];
|
||||
domainSepTag: openArray[U];
|
||||
aug: openArray[V]) =
|
||||
blst_hash_to_g1(dst, msg, domainSepTag, aug)
|
||||
|
||||
proc pairing(a: ec_p1, b: ec_p2): blst_fp12 =
|
||||
## Calculate pairing G_1,G_2 -> G_T
|
||||
var aa: blst_p1_affine
|
||||
var bb: blst_p2_affine
|
||||
blst_p1_to_affine(aa, a)
|
||||
blst_p2_to_affine(bb, b)
|
||||
var l: blst_fp12
|
||||
blst_miller_loop(l, bb, aa)
|
||||
blst_final_exp(result, l)
|
||||
|
||||
proc verifyPairingsNaive(a1: blst_p1, a2: blst_p2, b1: blst_p1, b2: blst_p2) : bool =
|
||||
let e1 = pairing(a1, a2)
|
||||
let e2 = pairing(b1, b2)
|
||||
return e1 == e2
|
||||
|
||||
proc verifyPairingsNeg(a1: ec_p1, a2: ec_p2, b1: ec_p1, b2: ec_p2) : bool =
|
||||
## Faster pairing verification using 2 miller loops but ony one final exponentiation
|
||||
## based on https://github.com/benjaminion/c-kzg/blob/main/src/bls12_381.c
|
||||
var
|
||||
loop0, loop1, gt_point: blst_fp12
|
||||
aa1, bb1: blst_p1_affine
|
||||
aa2, bb2: blst_p2_affine
|
||||
|
||||
var a1neg = a1
|
||||
blst_p1_cneg(a1neg, 1)
|
||||
|
||||
blst_p1_to_affine(aa1, a1neg)
|
||||
blst_p1_to_affine(bb1, b1)
|
||||
blst_p2_to_affine(aa2, a2)
|
||||
blst_p2_to_affine(bb2, b2)
|
||||
|
||||
blst_miller_loop(loop0, aa2, aa1)
|
||||
blst_miller_loop(loop1, bb2, bb1)
|
||||
|
||||
blst_fp12_mul(gt_point, loop0, loop1)
|
||||
blst_final_exp(gt_point, gt_point)
|
||||
|
||||
return blst_fp12_is_one(gt_point).bool
|
||||
|
||||
proc verifyPairings*(a1: ec_p1, a2: ec_p2, b1: ec_p1, b2: ec_p2) : bool =
|
||||
## Wrapper to select verify pairings implementation
|
||||
verifyPairingsNaive(a1, a2, b1, b2)
|
||||
#verifyPairingsNeg(a1, a2, b1, b2)
|
||||
|
||||
func ec_from_bytes*(
|
||||
obj: var (Signature|ProofOfPossession),
|
||||
raw: array[96, byte] or array[192, byte]
|
||||
): bool {.inline.} =
|
||||
fromBytes(obj, raw)
|
||||
|
||||
func ec_verify*[T: byte|char](
|
||||
publicKey: PublicKey,
|
||||
message: openarray[T],
|
||||
signature: Signature) : bool =
|
||||
verify(publicKey, message, signature)
|
|
@ -78,8 +78,8 @@
|
|||
# The size of the proof is instead
|
||||
# s * 32 + 48 bytes
|
||||
|
||||
import blscurve
|
||||
import blscurve/blst/blst_abi
|
||||
import ./backends/backend_blst
|
||||
|
||||
import ../rng
|
||||
import endians
|
||||
|
||||
|
@ -90,25 +90,26 @@ const bytespersector = 31
|
|||
# length in bytes of the unique (random) name
|
||||
const namelen = 512
|
||||
|
||||
|
||||
type
|
||||
# a single sector
|
||||
ZChar = array[bytespersector, byte]
|
||||
|
||||
# secret key combining the metadata signing key and the POR generation key
|
||||
SecretKey = object
|
||||
signkey: blscurve.SecretKey
|
||||
key: blst_scalar
|
||||
signkey: ec_SecretKey
|
||||
key: ec_scalar
|
||||
|
||||
# public key combining the metadata signing key and the POR validation key
|
||||
PublicKey = object
|
||||
signkey: blscurve.PublicKey
|
||||
key: blst_p2
|
||||
signkey: ec_PublicKey
|
||||
key: ec_p2
|
||||
|
||||
# POR metadata (called "file tag t_0" in the original paper)
|
||||
TauZero = object
|
||||
name: array[namelen, byte]
|
||||
n: int64
|
||||
u: seq[blst_p1]
|
||||
u: seq[ec_p1]
|
||||
|
||||
# signed POR metadata (called "signed file tag t" in the original paper)
|
||||
Tau = object
|
||||
|
@ -118,50 +119,50 @@ type
|
|||
# PoR query element
|
||||
QElement = object
|
||||
I: int64
|
||||
V: blst_scalar
|
||||
V: ec_scalar
|
||||
|
||||
proc fromBytesBE(a: array[32, byte]): blst_scalar =
|
||||
proc fromBytesBE(a: array[32, byte]): ec_scalar =
|
||||
## Convert data to blst native form
|
||||
blst_scalar_from_bendian(result, a)
|
||||
doAssert(blst_scalar_fr_check(result).bool)
|
||||
ec_scalar_from_bendian(result, a)
|
||||
doAssert(ec_scalar_fr_check(result).bool)
|
||||
|
||||
proc fromBytesBE(a: openArray[byte]): blst_scalar =
|
||||
proc fromBytesBE(a: openArray[byte]): ec_scalar =
|
||||
## Convert data to blst native form
|
||||
var b: array[32, byte]
|
||||
doAssert(a.len <= b.len)
|
||||
let d = b.len - a.len
|
||||
for i in 0 ..< a.len:
|
||||
b[i+d] = a[i]
|
||||
blst_scalar_from_bendian(result, b)
|
||||
doAssert(blst_scalar_fr_check(result).bool)
|
||||
ec_scalar_from_bendian(result, b)
|
||||
doAssert(ec_scalar_fr_check(result).bool)
|
||||
|
||||
proc getSector(f: File, blockid: int64, sectorid: int64, spb: int64): ZChar =
|
||||
## Read file sector at given <blockid, sectorid> postion
|
||||
f.setFilePos((blockid * spb + sectorid) * sizeof(result))
|
||||
let r = f.readBytes(result, 0, sizeof(result))
|
||||
|
||||
proc rndScalar(scalar: var blst_scalar): void =
|
||||
proc rndScalar(scalar: var ec_scalar): void =
|
||||
## Generate random scalar within the subroup order r
|
||||
var scal{.noInit.}: array[32, byte]
|
||||
|
||||
while true:
|
||||
for val in scal.mitems:
|
||||
val = byte Rng.instance.rand(0xFF)
|
||||
scalar.blst_scalar_from_bendian(scal)
|
||||
if blst_scalar_fr_check(scalar).bool:
|
||||
scalar.ec_scalar_from_bendian(scal)
|
||||
if ec_scalar_fr_check(scalar).bool:
|
||||
break
|
||||
|
||||
proc rndP2(x: var blst_p2, scalar: var blst_scalar): void =
|
||||
proc rndP2(x: var ec_p2, scalar: var ec_scalar): void =
|
||||
## Generate random point on G2
|
||||
x.blst_p2_from_affine(BLS12_381_G2) # init from generator
|
||||
x.ec_p2_from_affine(EC_G2) # init from generator
|
||||
scalar.rndScalar()
|
||||
x.blst_p2_mult(x, scalar, 255)
|
||||
x.ec_p2_mult(x, scalar, 255)
|
||||
|
||||
proc rndP1(x: var blst_p1, scalar: var blst_scalar): void =
|
||||
proc rndP1(x: var ec_p1, scalar: var ec_scalar): void =
|
||||
## Generate random point on G1
|
||||
x.blst_p1_from_affine(BLS12_381_G1) # init from generator
|
||||
x.ec_p1_from_affine(EC_G1) # init from generator
|
||||
scalar.rndScalar()
|
||||
x.blst_p1_mult(x, scalar, 255)
|
||||
x.ec_p1_mult(x, scalar, 255)
|
||||
|
||||
let posKeygen = rndP2
|
||||
## Generate POS key pair
|
||||
|
@ -174,7 +175,7 @@ proc keygen*(): (PublicKey, SecretKey) =
|
|||
|
||||
for b in ikm.mitems:
|
||||
b = byte Rng.instance.rand(0xFF)
|
||||
doAssert ikm.keyGen(pk.signkey, sk.signkey)
|
||||
doAssert ikm.ec_keygen(pk.signkey, sk.signkey)
|
||||
|
||||
posKeygen(pk.key, sk.key)
|
||||
return (pk, sk)
|
||||
|
@ -190,12 +191,12 @@ proc split(f: File, s: int64): int64 =
|
|||
|
||||
return n
|
||||
|
||||
proc hashToG1[T: byte|char](msg: openArray[T]): blst_p1 =
|
||||
proc hashToG1[T: byte|char](msg: openArray[T]): ec_p1 =
|
||||
## Hash to curve with Dagger specific domain separation
|
||||
const dst = "DAGGER-PROOF-OF-CONCEPT"
|
||||
result.blst_hash_to_g1(msg, dst, aug = "")
|
||||
result.ec_hash_to_g1(msg, dst, aug = "")
|
||||
|
||||
proc hashNameI(name: array[namelen, byte], i: int64): blst_p1 =
|
||||
proc hashNameI(name: array[namelen, byte], i: int64): ec_p1 =
|
||||
## Calculate unique filname and block index based hash
|
||||
|
||||
# # naive implementation, hashing a long string representation
|
||||
|
@ -208,20 +209,20 @@ proc hashNameI(name: array[namelen, byte], i: int64): blst_p1 =
|
|||
bigEndian64(addr(namei[sizeof(name)]), unsafeAddr(i))
|
||||
return hashToG1(namei)
|
||||
|
||||
proc generateAuthenticatorNaive(i: int64, s: int64, t: TauZero, f: File, ssk: SecretKey): blst_p1 =
|
||||
proc generateAuthenticatorNaive(i: int64, s: int64, t: TauZero, f: File, ssk: SecretKey): ec_p1 =
|
||||
## Naive implementation of authenticator as in the S&W paper.
|
||||
## With the paper's multiplicative notation:
|
||||
## \sigmai=\(H(file||i)\cdot\prod{j=0}^{s-1}{uj^{m[i][j]}})^{\alpha}
|
||||
var sum: blst_p1
|
||||
var sum: ec_p1
|
||||
for j in 0 ..< s:
|
||||
var prod: blst_p1
|
||||
prod.blst_p1_mult(t.u[j], fromBytesBE(getSector(f, i, j, s)), 255)
|
||||
sum.blst_p1_add_or_double(sum, prod)
|
||||
var prod: ec_p1
|
||||
prod.ec_p1_mult(t.u[j], fromBytesBE(getSector(f, i, j, s)), 255)
|
||||
sum.ec_p1_add_or_double(sum, prod)
|
||||
|
||||
blst_p1_add_or_double(result, hashNameI(t.name, i), sum)
|
||||
result.blst_p1_mult(result, ssk.key, 255)
|
||||
ec_p1_add_or_double(result, hashNameI(t.name, i), sum)
|
||||
result.ec_p1_mult(result, ssk.key, 255)
|
||||
|
||||
proc generateAuthenticatorOpt(i: int64, s: int64, t: TauZero, ubase: openArray[blst_scalar], f: File, ssk: SecretKey): blst_p1 =
|
||||
proc generateAuthenticatorOpt(i: int64, s: int64, t: TauZero, ubase: openArray[ec_scalar], f: File, ssk: SecretKey): ec_p1 =
|
||||
## Optimized implementation of authenticator generation
|
||||
## This implementation is reduces the number of scalar multiplications
|
||||
## from s+1 to 1+1 , using knowledge about the scalars (r_j)
|
||||
|
@ -229,31 +230,31 @@ proc generateAuthenticatorOpt(i: int64, s: int64, t: TauZero, ubase: openArray[b
|
|||
##
|
||||
## With the paper's multiplicative notation, we use:
|
||||
## (H(file||i)\cdot g^{\sum{j=0}^{s-1}{r_j \cdot m[i][j]}})^{\alpha}
|
||||
var sum: blst_fr
|
||||
var sums: blst_scalar
|
||||
var sum: ec_fr
|
||||
var sums: ec_scalar
|
||||
for j in 0 ..< s:
|
||||
var a, b, x: blst_fr
|
||||
a.blst_fr_from_scalar(ubase[j])
|
||||
b.blst_fr_from_scalar(fromBytesBE(getSector(f, i, j, s)))
|
||||
x.blst_fr_mul(a, b)
|
||||
sum.blst_fr_add(sum, x)
|
||||
sums.blst_scalar_from_fr(sum)
|
||||
var a, b, x: ec_fr
|
||||
a.ec_fr_from_scalar(ubase[j])
|
||||
b.ec_fr_from_scalar(fromBytesBE(getSector(f, i, j, s)))
|
||||
x.ec_fr_mul(a, b)
|
||||
sum.ec_fr_add(sum, x)
|
||||
sums.ec_scalar_from_fr(sum)
|
||||
|
||||
result.blst_p1_from_affine(BLS12_381_G1)
|
||||
result.blst_p1_mult(result, sums, 255)
|
||||
result.ec_p1_from_affine(EC_G1)
|
||||
result.ec_p1_mult(result, sums, 255)
|
||||
|
||||
result.blst_p1_add_or_double(result, hashNameI(t.name, i))
|
||||
result.blst_p1_mult(result, ssk.key, 255)
|
||||
result.ec_p1_add_or_double(result, hashNameI(t.name, i))
|
||||
result.ec_p1_mult(result, ssk.key, 255)
|
||||
|
||||
proc generateAuthenticator(i: int64, s: int64, t: TauZero, ubase: openArray[blst_scalar], f: File, ssk: SecretKey): blst_p1 =
|
||||
proc generateAuthenticator(i: int64, s: int64, t: TauZero, ubase: openArray[ec_scalar], f: File, ssk: SecretKey): ec_p1 =
|
||||
## Wrapper to select tag generator implementation
|
||||
|
||||
# let a = generateAuthenticatorNaive(i, s, t, f, ssk)
|
||||
let b = generateAuthenticatorOpt(i, s, t, ubase, f, ssk)
|
||||
# doAssert(a.blst_p1_is_equal(b).bool)
|
||||
# doAssert(a.ec_p1_is_equal(b).bool)
|
||||
return b
|
||||
|
||||
proc setup*(ssk: SecretKey, s:int64, filename: string): (Tau, seq[blst_p1]) =
|
||||
proc setup*(ssk: SecretKey, s:int64, filename: string): (Tau, seq[ec_p1]) =
|
||||
## Set up the POR scheme by generating tags and metadata
|
||||
let file = open(filename)
|
||||
let n = split(file, s)
|
||||
|
@ -264,22 +265,22 @@ proc setup*(ssk: SecretKey, s:int64, filename: string): (Tau, seq[blst_p1]) =
|
|||
t.name[i] = byte Rng.instance.rand(0xFF)
|
||||
|
||||
# generate the coefficient vector for combining sectors of a block: U
|
||||
var ubase: seq[blst_scalar]
|
||||
var ubase: seq[ec_scalar]
|
||||
for i in 0 ..< s :
|
||||
var
|
||||
u: blst_p1
|
||||
ub: blst_scalar
|
||||
u: ec_p1
|
||||
ub: ec_scalar
|
||||
rndP1(u, ub)
|
||||
t.u.add(u)
|
||||
ubase.add(ub)
|
||||
|
||||
#TODO: a better bytearray conversion of TauZero for the signature might be needed
|
||||
# the current conversion using $t might be architecture dependent and not unique
|
||||
let signature = sign(ssk.signkey, $t)
|
||||
let tau = Tau(t: t, signature: signature.exportRaw())
|
||||
let signature = ec_sign(ssk.signkey, $t)
|
||||
let tau = Tau(t: t, signature: signature.ec_export_raw())
|
||||
|
||||
#generate sigmas
|
||||
var sigmas: seq[blst_p1]
|
||||
var sigmas: seq[ec_p1]
|
||||
for i in 0 ..< n :
|
||||
sigmas.add(generateAuthenticator(i, s, t, ubase, file, ssk))
|
||||
|
||||
|
@ -296,106 +297,62 @@ proc generateQuery*(tau: Tau, spk: PublicKey, l: int): seq[QElement] =
|
|||
q.V.rndScalar() #TODO: fix range
|
||||
result.add(q)
|
||||
|
||||
proc generateProof*(q: openArray[QElement], authenticators: openArray[blst_p1], spk: PublicKey, s: int64, filename: string): (seq[blst_scalar], blst_p1) =
|
||||
proc generateProof*(q: openArray[QElement], authenticators: openArray[ec_p1], spk: PublicKey, s: int64, filename: string): (seq[ec_scalar], ec_p1) =
|
||||
## Generata BLS proofs for a given query
|
||||
let file = open(filename)
|
||||
|
||||
var mu: seq[blst_scalar]
|
||||
var mu: seq[ec_scalar]
|
||||
for j in 0 ..< s :
|
||||
var muj: blst_fr
|
||||
var muj: ec_fr
|
||||
for qelem in q :
|
||||
var x, v, sector: blst_fr
|
||||
var x, v, sector: ec_fr
|
||||
let sect = fromBytesBE(getSector(file, qelem.I, j, s))
|
||||
sector.blst_fr_from_scalar(sect)
|
||||
v.blst_fr_from_scalar(qelem.V)
|
||||
x.blst_fr_mul(v, sector)
|
||||
muj.blst_fr_add(muj, x)
|
||||
var mujs: blst_scalar
|
||||
mujs.blst_scalar_from_fr(muj)
|
||||
sector.ec_fr_from_scalar(sect)
|
||||
v.ec_fr_from_scalar(qelem.V)
|
||||
x.ec_fr_mul(v, sector)
|
||||
muj.ec_fr_add(muj, x)
|
||||
var mujs: ec_scalar
|
||||
mujs.ec_scalar_from_fr(muj)
|
||||
mu.add(mujs)
|
||||
|
||||
var sigma: blst_p1
|
||||
var sigma: ec_p1
|
||||
for qelem in q:
|
||||
var prod: blst_p1
|
||||
prod.blst_p1_mult(authenticators[qelem.I], qelem.V, 255)
|
||||
sigma.blst_p1_add_or_double(sigma, prod)
|
||||
var prod: ec_p1
|
||||
prod.ec_p1_mult(authenticators[qelem.I], qelem.V, 255)
|
||||
sigma.ec_p1_add_or_double(sigma, prod)
|
||||
|
||||
file.close()
|
||||
return (mu, sigma)
|
||||
|
||||
proc pairing(a: blst_p1, b: blst_p2): blst_fp12 =
|
||||
## Calculate pairing G_1,G_2 -> G_T
|
||||
var aa: blst_p1_affine
|
||||
var bb: blst_p2_affine
|
||||
blst_p1_to_affine(aa, a)
|
||||
blst_p2_to_affine(bb, b)
|
||||
var l: blst_fp12
|
||||
blst_miller_loop(l, bb, aa)
|
||||
blst_final_exp(result, l)
|
||||
|
||||
proc verifyPairingsNaive(a1: blst_p1, a2: blst_p2, b1: blst_p1, b2: blst_p2) : bool =
|
||||
let e1 = pairing(a1, a2)
|
||||
let e2 = pairing(b1, b2)
|
||||
return e1 == e2
|
||||
|
||||
proc verifyPairingsNeg(a1: blst_p1, a2: blst_p2, b1: blst_p1, b2: blst_p2) : bool =
|
||||
## Faster pairing verification using 2 miller loops but ony one final exponentiation
|
||||
## based on https://github.com/benjaminion/c-kzg/blob/main/src/bls12_381.c
|
||||
var
|
||||
loop0, loop1, gt_point: blst_fp12
|
||||
aa1, bb1: blst_p1_affine
|
||||
aa2, bb2: blst_p2_affine
|
||||
|
||||
var a1neg = a1
|
||||
blst_p1_cneg(a1neg, 1)
|
||||
|
||||
blst_p1_to_affine(aa1, a1neg)
|
||||
blst_p1_to_affine(bb1, b1)
|
||||
blst_p2_to_affine(aa2, a2)
|
||||
blst_p2_to_affine(bb2, b2)
|
||||
|
||||
blst_miller_loop(loop0, aa2, aa1)
|
||||
blst_miller_loop(loop1, bb2, bb1)
|
||||
|
||||
blst_fp12_mul(gt_point, loop0, loop1)
|
||||
blst_final_exp(gt_point, gt_point)
|
||||
|
||||
return blst_fp12_is_one(gt_point).bool
|
||||
|
||||
proc verifyPairings(a1: blst_p1, a2: blst_p2, b1: blst_p1, b2: blst_p2) : bool =
|
||||
## Wrapper to select verify pairings implementation
|
||||
verifyPairingsNaive(a1, a2, b1, b2)
|
||||
#verifyPairingsNeg(a1, a2, b1, b2)
|
||||
|
||||
proc verifyProof*(tau: Tau, q: openArray[QElement], mus: openArray[blst_scalar], sigma: blst_p1, spk: PublicKey): bool =
|
||||
proc verifyProof*(tau: Tau, q: openArray[QElement], mus: openArray[ec_scalar], sigma: ec_p1, spk: PublicKey): bool =
|
||||
## Verify a BLS proof given a query
|
||||
|
||||
# verify signature on Tau
|
||||
var signature: Signature
|
||||
if not signature.fromBytes(tau.signature):
|
||||
var signature: ec_signature
|
||||
if not signature.ec_from_bytes(tau.signature):
|
||||
return false
|
||||
if not verify(spk.signkey, $tau.t, signature):
|
||||
if not ec_verify(spk.signkey, $tau.t, signature):
|
||||
return false
|
||||
|
||||
var first: blst_p1
|
||||
var first: ec_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)
|
||||
var prod: ec_p1
|
||||
prod.ec_p1_mult(hashNameI(tau.t.name, qelem.I), qelem.V, 255)
|
||||
first.ec_p1_add_or_double(first, prod)
|
||||
doAssert(ec_p1_on_curve(first).bool)
|
||||
|
||||
let us = tau.t.u
|
||||
var second: blst_p1
|
||||
var second: ec_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 prod: ec_p1
|
||||
prod.ec_p1_mult(us[j], mus[j], 255)
|
||||
second.ec_p1_add_or_double(second, prod)
|
||||
doAssert(ec_p1_on_curve(second).bool)
|
||||
|
||||
var sum: blst_p1
|
||||
sum.blst_p1_add_or_double(first, second)
|
||||
var sum: ec_p1
|
||||
sum.ec_p1_add_or_double(first, second)
|
||||
|
||||
var g{.noInit.}: blst_p2
|
||||
g.blst_p2_from_affine(BLS12_381_G2)
|
||||
var g{.noInit.}: ec_p2
|
||||
g.ec_p2_from_affine(EC_G2)
|
||||
|
||||
return verifyPairings(sum, spk.key, sigma, g)
|
||||
|
|
Loading…
Reference in New Issue