EIP2537 part 2

This commit is contained in:
jangko 2020-11-28 23:13:10 +07:00
parent c1b7ae5b02
commit 0799b4534c
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
4 changed files with 200 additions and 37 deletions

View File

@ -11,7 +11,7 @@ PrecompileTests
+ blsG2MultiExp.json OK
- blsMapG1.json Fail
- blsMapG2.json Fail
- blsPairing.json Fail
+ blsPairing.json OK
+ bn256Add.json OK
+ bn256Add_istanbul.json OK
+ bn256mul.json OK
@ -25,7 +25,7 @@ PrecompileTests
+ ripemd160.json OK
+ sha256.json OK
```
OK: 19/22 Fail: 3/22 Skip: 0/22
OK: 20/22 Fail: 2/22 Skip: 0/22
---TOTAL---
OK: 19/22 Fail: 3/22 Skip: 0/22
OK: 20/22 Fail: 2/22 Skip: 0/22

View File

@ -1,8 +1,9 @@
import blscurve/bls_backend
when BLS_BACKEND == Miracl:
import blscurve/miracl/[common, milagro]
import blscurve/miracl/[common, milagro, hash_to_curve, bls_signature_scheme]
export common
export bls_signature_scheme.subgroupCheck
type
BLS_G1* = ECP_BLS12381
@ -12,32 +13,34 @@ when BLS_BACKEND == Miracl:
BLS_SCALAR* = BIG_384
BLS_FE* = FP_BLS12381
BLS_FE2* = FP2_BLS12381
BLS_GT* = FP12_BLS12381
proc ECP_BLS12381_map2point(P: var ECP_BLS12381, h: FP_BLS12381) {.importc, cdecl.}
proc ECP2_BLS12381_map2point(P: var ECP2_BLS12381, h: FP2_BLS12381) {.importc, cdecl.}
proc ECP_BLS12381_set(p: ptr ECP_BLS12381, x, y: BIG_384): cint {.importc, cdecl.}
proc FP_BLS12381_sqr(w: ptr FP_BLS12381, x: ptr FP_BLS12381) {.importc, cdecl.}
proc sqr*(x: FP_BLS12381): FP_BLS12381 {.inline.} =
## Retruns ``x ^ 2``.
FP_BLS12381_sqr(addr result, unsafeAddr x)
proc rhs*(x: FP_BLS12381): FP_BLS12381 {.inline.} =
## Returns ``x ^ 3 + b``.
ECP_BLS12381_rhs(addr result, unsafeAddr x)
proc isOnCurv*(x, y: FP_BLS12381 or FP2_BLS12381): bool =
## Returns ``true`` if point is on curve or points to infinite.
if x.iszilch() and y.iszilch():
result = true
else:
result = (sqr(y) == rhs(x))
proc FP12_BLS12381_mul(x: ptr FP12_BLS12381, y: ptr FP12_BLS12381) {.importc, cdecl.}
#proc ECP_BLS12381_map2point(P: var ECP_BLS12381, h: FP_BLS12381) {.importc, cdecl.}
#proc ECP2_BLS12381_map2point(P: var ECP2_BLS12381, h: FP2_BLS12381) {.importc, cdecl.}
#proc ECP_BLS12381_set(p: ptr ECP_BLS12381, x, y: BIG_384): cint {.importc, cdecl.}
#proc FP_BLS12381_sqr(w: ptr FP_BLS12381, x: ptr FP_BLS12381) {.importc, cdecl.}
#
#proc sqr*(x: FP_BLS12381): FP_BLS12381 {.inline.} =
# ## Retruns ``x ^ 2``.
# FP_BLS12381_sqr(addr result, unsafeAddr x)
#
#proc rhs*(x: FP_BLS12381): FP_BLS12381 {.inline.} =
# ## Returns ``x ^ 3 + b``.
# ECP_BLS12381_rhs(addr result, unsafeAddr x)
#
#proc isOnCurv*(x, y: FP_BLS12381 or FP2_BLS12381): bool =
# ## Returns ``true`` if point is on curve or points to infinite.
# if x.iszilch() and y.iszilch():
# result = true
# else:
# result = (sqr(y) == rhs(x))
func pack(g: var BLS_G1, x, y: BLS_FP): bool {.inline.} =
discard ECP_BLS12381_set(g.addr, x, y)
let xx = x.nres
let yy = y.nres
isOnCurv(xx, yy)
isOnCurve(xx, yy)
func unpack(g: BLS_G1, x, y: var BLS_FP): bool {.inline.} =
discard g.get(x, y)
@ -48,7 +51,7 @@ when BLS_BACKEND == Miracl:
x.fromBigs(x0, x1)
y.fromBigs(y0, y1)
discard ECP2_BLS12381_set(g.addr, x.addr, y.addr)
isOnCurv(x, y)
isOnCurve(x, y)
func unpack(g: BLS_G2, x0, x1, y0, y1: var BLS_FP): bool =
var x, y: BLS_FP2
@ -58,6 +61,24 @@ when BLS_BACKEND == Miracl:
FP_BLS12381_redc(y0, addr y.a)
FP_BLS12381_redc(y1, addr y.b)
func mapFPToG1*(fp: BLS_FE): BLS_G1 {.inline.} =
# TODO
discard
func mapFPToG2*(fp: BLS_FE2): BLS_G2 {.inline.} =
result = mapToCurveG2(fp)
result.clearCofactor()
func millerLoop*(g1: BLS_G1, g2: BLS_G2): BLS_GT =
PAIR_BLS12381_ate(result.addr, g2.unsafeAddr, g1.unsafeAddr)
proc mul*(a: var BLS_GT, b: BLS_GT) {.inline.} =
FP12_BLS12381_mul(a.addr, b.unsafeAddr)
func check*(x: BLS_GT): bool {.inline.} =
PAIR_BLS12381_fexp(x.unsafeAddr)
FP12_BLS12381_isunity(x.unsafeAddr).int == 1
else:
import blscurve/blst/[blst_lowlevel]
@ -69,6 +90,7 @@ else:
BLS_SCALAR* = blst_scalar
BLS_FE* = blst_fp
BLS_FE2* = blst_fp2
BLS_GT* = blst_fp12
func fromBytes*(ret: var BLS_SCALAR, raw: openArray[byte]): bool =
const L = 32
@ -109,7 +131,7 @@ else:
func pack(g: var BLS_G2, x0, x1, y0, y1: BLS_FP): bool =
let src = blst_p2_affine(x: blst_fp2(fp: [x0, x1]), y: blst_fp2(fp: [y0, y1]))
blst_p2_from_affine(g, src)
blst_p2_on_curve(g)
blst_p2_on_curve(g).int == 1
func unpack(g: BLS_G2, x0, x1, y0, y1: var BLS_FP): bool =
var dst: blst_p2_affine
@ -135,19 +157,48 @@ else:
result = bts.uint
func add*(a: var BLS_G1, b: BLS_G1) {.inline.} =
# ?? add_or_double ??
blst_p1_add_or_double(a, a, b)
func mul*(a: var BLS_G1, b: BLS_SCALAR) {.inline.} =
blst_p1_mult(a, a, b, b.nbits)
func add*(a: var BLS_G2, b: BLS_G2) {.inline.} =
# ?? add_or_double ??
blst_p2_add_or_double(a, a, b)
func mul*(a: var BLS_G2, b: BLS_SCALAR) {.inline.} =
blst_p2_mult(a, a, b, b.nbits)
func mapFPToG1*(fp: BLS_FE): BLS_G1 {.inline.} =
let z: ptr blst_fp = nil
blst_map_to_g1(result, fp, z[])
func mapFPToG2*(fp: BLS_FE2): BLS_G2 {.inline.} =
let z: ptr blst_fp2 = nil
blst_map_to_g2(result, fp, z[])
func subgroupCheck*(P: BLS_G1): bool {.inline.} =
blst_p1_in_g1(P).int == 1
func subgroupCheck*(P: BLS_G2): bool {.inline.} =
blst_p2_in_g2(P).int == 1
func millerLoop*(g1: BLS_G1, g2: BLS_G2): BLS_GT =
# TODO: avoid g1, g2 conversion to affine
var
P: blst_p1_affine
Q: blst_p2_affine
blst_p1_to_affine(P, g1)
blst_p2_to_affine(Q, g2)
blst_miller_loop(result, Q, P)
proc mul*(a: var BLS_GT, b: BLS_GT) {.inline.} =
blst_fp12_mul(a, a, b)
func check*(x: BLS_GT): bool {.inline.} =
var ret: BLS_GT
ret.blst_final_exp(x)
ret.blst_fp12_is_one().int == 1
# decodeFieldElement expects 64 byte input with zero top 16 bytes,
# returns lower 48 bytes.
func decodeFieldElement*(res: var BLS_FP, input: openArray[byte]): bool =
@ -175,6 +226,37 @@ when BLS_BACKEND == Miracl:
res = big.nres()
true
func decodeFieldElement*(res: var BLS_FE2, input: openArray[byte]): bool =
if input.len != 128:
debugEcho "DEF FP2 A ERR"
return false
if not res.a.decodeFieldElement input.toOpenArray(0, 63):
debugEcho "DEF FP2 B ERR"
return false
if not res.b.decodeFieldElement input.toOpenArray(64, 127):
debugEcho "DEF FP2 C ERR"
return false
true
else:
func decodeFieldElement*(res: var BLS_FE2, input: openArray[byte]): bool =
if input.len != 128:
debugEcho "DEF FP2 A ERR"
return false
if not res.fp[0].decodeFieldElement input.toOpenArray(0, 63):
debugEcho "DEF FP2 B ERR"
return false
if not res.fp[1].decodeFieldElement input.toOpenArray(64, 127):
debugEcho "DEF FP2 C ERR"
return false
true
# DecodePoint given encoded (x, y) coordinates in 128 bytes returns a valid G1 Point.
func decodePoint*(g: var BLS_G1, data: openArray[byte]): bool =
if data.len != 128:

View File

@ -572,13 +572,91 @@ proc blsG2MultiExp*(c: Computation) =
raise newException(ValidationError, "blsG2MuliExp encodePoint error")
proc blsPairing*(c: Computation) =
discard
template input: untyped =
c.msg.data
const L = 384
if (input.len == 0) or ((input.len mod L) != 0):
raise newException(ValidationError, "blsG2Pairing invalid input len")
let
K = input.len div L
gas = Bls12381PairingBaseGas + K.GasInt * Bls12381PairingPerPairGas
c.gasMeter.consumeGas(gas, reason="blsG2Pairing Precompile")
var
g1: BLS_G1
g2: BLS_G2
gt: BLS_GT
# Decode pairs
for i in 0..<K:
let off = L * i
# Decode G1 point
if not g1.decodePoint(input.toOpenArray(off, off+127)):
raise newException(ValidationError, "blsG2Pairing invalid G1")
# Decode G2 point
if not g2.decodePoint(input.toOpenArray(off+128, off+383)):
raise newException(ValidationError, "blsG2Pairing invalid G2")
# 'point is on curve' check already done,
# Here we need to apply subgroup checks.
if not g1.subgroupCheck:
raise newException(ValidationError, "blsG2Pairing invalid G1 subgroup")
if not g2.subgroupCheck:
raise newException(ValidationError, "blsG2Pairing invalid G2 subgroup")
# Update pairing engine with G1 and G2 points
if i == 0:
gt = millerLoop(g1, g2)
else:
gt.mul(millerLoop(g1, g2))
c.output = newSeq[byte](32)
if gt.check():
c.output[^1] = 1.byte
proc blsMapG1*(c: Computation) =
discard
template input: untyped =
c.msg.data
if input.len != 64:
raise newException(ValidationError, "blsMapG1 invalid input len")
c.gasMeter.consumeGas(Bls12381MapG1Gas, reason="blsMapG1 Precompile")
var fe: BLS_FE
if not fe.decodeFieldElement(input):
raise newException(ValidationError, "blsMapG1 invalid field element")
let p = fe.mapFPToG1()
c.output = newSeq[byte](128)
if not encodePoint(p, c.output):
raise newException(ValidationError, "blsMapG1 encodePoint error")
proc blsMapG2*(c: Computation) =
discard
template input: untyped =
c.msg.data
if input.len != 128:
raise newException(ValidationError, "blsMapG2 invalid input len")
c.gasMeter.consumeGas(Bls12381MapG2Gas, reason="blsMapG2 Precompile")
var fe: BLS_FE2
if not fe.decodeFieldElement(input):
raise newException(ValidationError, "blsMapG2 invalid field element")
let p = fe.mapFPToG2()
c.output = newSeq[byte](256)
if not encodePoint(p, c.output):
raise newException(ValidationError, "blsMapG2 encodePoint error")
proc getMaxPrecompileAddr(fork: Fork): PrecompileAddresses =
if fork < FkByzantium: paIdentity

View File

@ -78,12 +78,15 @@ proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
of "bn256mul" : data.doTest(fork, paEcMul)
of "ecpairing": data.doTest(fork, paPairing)
of "blake2f" : data.doTest(fork, paBlake2bf)
of "blsg1add" : data.doTest(fork, pablsG1Add)
of "blsg1mul" : data.doTest(fork, pablsG1Mul)
of "blsg1multiexp" : data.doTest(fork, pablsG1MultiExp)
of "blsg2add" : data.doTest(fork, pablsG2Add)
of "blsg2mul" : data.doTest(fork, pablsG2Mul)
of "blsg2multiexp" : data.doTest(fork, pablsG2MultiExp)
of "blsg1add" : data.doTest(fork, paBlsG1Add)
of "blsg1mul" : data.doTest(fork, paBlsG1Mul)
of "blsg1multiexp" : data.doTest(fork, paBlsG1MultiExp)
of "blsg2add" : data.doTest(fork, paBlsG2Add)
of "blsg2mul" : data.doTest(fork, paBlsG2Mul)
of "blsg2multiexp": data.doTest(fork, paBlsG2MultiExp)
of "blspairing": data.doTest(fork, paBlsPairing)
of "blsmapg1": data.doTest(fork, paBlsMapG1)
of "blsmapg2": data.doTest(fork, paBlsMapG2)
else:
echo "Unknown test vector '" & $label & "'"
testStatusIMPL = SKIPPED