Skip to content

Commit

Permalink
pass all verify_blob_kzg_proof tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mratsim committed Sep 14, 2023
1 parent 8cdd4f9 commit 3d0b9ab
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 16 deletions.
12 changes: 5 additions & 7 deletions constantine/commitments/kzg_polynomial_commitments.nim
Original file line number Diff line number Diff line change
Expand Up @@ -205,11 +205,9 @@ func kzg_prove*[N: static int, C: static Curve](

# Compute 1/(ωⁱ - z) with ω a root of unity, i in [0, N).
# zIndex = i if ωⁱ - z == 0 (it is the i-th root of unity) and -1 otherwise.
var zIndex = invRootsMinusZ[].inverseRootsMinusZ_vartime(domain, challenge)

# debugEcho "\n\n roots[1]: ", domain.rootsOfUnity[1].toHex()
# debugEcho "\n\n roots[2]: ", domain.rootsOfUnity[2].toHex()

let zIndex = invRootsMinusZ[].inverseRootsMinusZ_vartime(
domain, challenge,
earlyReturnOnZero = false)

if zIndex == -1:
# p(z)
Expand Down Expand Up @@ -293,10 +291,10 @@ func kzg_verify*[F2; C: static Curve](
tauG2Jac.fromAffine(tauG2)
commitmentJac.fromAffine(commitment)

tau_minus_challenge_G2.scalarMul(challenge)
tau_minus_challenge_G2.scalarMul_vartime(challenge)
tau_minus_challenge_G2.diff(tauG2Jac, tau_minus_challenge_G2)

commitment_minus_eval_at_challenge_G1.scalarMul(eval_at_challenge)
commitment_minus_eval_at_challenge_G1.scalarMul_vartime(eval_at_challenge)
commitment_minus_eval_at_challenge_G1.diff(commitmentJac, commitment_minus_eval_at_challenge_G1)

var tmzG2 {.noInit.}: ECP_ShortW_Aff[F2, G2]
Expand Down
54 changes: 54 additions & 0 deletions constantine/ethereum_eip4844_kzg_polynomial_commitments.nim
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,60 @@ func compute_blob_kzg_proof*(
freeHeap(poly)
return cttEthKZG_Success

func verify_blob_kzg_proof*(
ctx: ptr EthereumKZGContext,
blob: ptr Blob,
commitment_bytes: array[48, byte],
proof_bytes: array[48, byte]): CttEthKzgStatus =
## Given a blob and a KZG proof, verify that the blob data corresponds to the provided commitment.

var commitment {.noInit.}: KZGCommitment
check commitment.bytes_to_kzg_commitment(commitment_bytes)

# Blob -> Polynomial
let poly = allocHeapAligned(PolynomialEval[FIELD_ELEMENTS_PER_BLOB, Fr[BLS12_381]], 64)
var status = poly.blob_to_field_polynomial(blob)
if status == cttCodecScalar_ScalarLargerThanCurveOrder:
freeHeap(poly)
return cttEthKZG_ScalarLargerThanCurveOrder
elif status != cttCodecScalar_Success:
debugEcho "Unreachable status in compute_kzg_proof: ", status
debugEcho "Panicking ..."
quit 1

var proof {.noInit.}: KZGProof
check proof.bytes_to_kzg_proof(proof_bytes)

var challengeFr {.noInit.}: Fr[BLS12_381]
challengeFr.fiatShamirChallenge(blob[], commitment_bytes)

var challenge, eval_at_challenge {.noInit.}: matchingOrderBigInt(BLS12_381)
challenge.fromField(challengeFr)

let invRootsMinusZ = allocHeapAligned(array[FIELD_ELEMENTS_PER_BLOB, Fr[BLS12_381]], alignment = 64)

# Compute 1/(ωⁱ - z) with ω a root of unity, i in [0, N).
# zIndex = i if ωⁱ - z == 0 (it is the i-th root of unity) and -1 otherwise.
let zIndex = invRootsMinusZ[].inverseRootsMinusZ_vartime(
ctx.domain, challengeFr,
earlyReturnOnZero = true)

if zIndex == -1:
var eval_at_challenge_fr{.noInit.}: Fr[BLS12_381]
eval_at_challenge_fr.evalPolyAt_vartime(
poly[], challengeFr,
invRootsMinusZ[],
ctx.domain)
eval_at_challenge.fromField(eval_at_challenge_fr)
else:
eval_at_challenge.fromField(poly.evals[zIndex])

let verif = kzg_verify(commitment.raw, challenge, eval_at_challenge, proof.raw, ctx.srs_monomial_g2.coefs[1])
if verif:
return cttEthKZG_Success
else:
return cttEthKZG_VerificationFailure

# Ethereum Trusted Setup
# ------------------------------------------------------------

Expand Down
29 changes: 20 additions & 9 deletions constantine/math/polynomials/polynomials.nim
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,19 @@ type
func inverseRootsMinusZ_vartime*[N: static int, Field](
invRootsMinusZ: var array[N, Field],
domain: PolyDomainEval[N, Field],
z: Field): int =
z: Field,
earlyReturnOnZero: static bool): int =
## Compute 1/(ωⁱ-z) for i in [0, N)
##
## Returns -1 if z ∉ {1, ω, ω², ... , ωⁿ⁻¹}
## Returns the index of ωⁱ==z otherwise
##
## If ωⁱ-z == 0, the other inverses are still computed
## and 0 is returned at that index.
## If ωⁱ-z == 0 AND earlyReturnOnZero is false
## the other inverses are still computed
## and 0 is returned at that index
## If ωⁱ-z == 0 AND earlyReturnOnZero is true
## the index of ωⁱ==z is returned
## the content of invRootsMinusZ is undefined

# Mongomery's batch inversion
# ω is a root of unity of order N,
Expand All @@ -69,13 +74,19 @@ func inverseRootsMinusZ_vartime*[N: static int, Field](
accInv.setOne()
var index0 = -1

for i in 0 ..< N:
rootsMinusZ[i].diff(domain.rootsOfUnity[i], z)
when earlyReturnOnZero: # Split computation in 2 phases
for i in 0 ..< N:
rootsMinusZ[i].diff(domain.rootsOfUnity[i], z)
if rootsMinusZ[i].isZero().bool():
return i

if rootsMinusZ[i].isZero().bool():
index0 = i
invRootsMinusZ[i].setZero()
continue
for i in 0 ..< N:
when not earlyReturnOnZero: # Fused substraction and batch inversion
rootsMinusZ[i].diff(domain.rootsOfUnity[i], z)
if rootsMinusZ[i].isZero().bool():
index0 = i
invRootsMinusZ[i].setZero()
continue

invRootsMinusZ[i] = accInv
accInv *= rootsMinusZ[i]
Expand Down
18 changes: 18 additions & 0 deletions tests/t_ethereum_eip4844_deneb_kzg.nim
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,21 @@ testGen(compute_blob_kzg_proof, testVector):
else:
doAssert testVector["output"].content == "null"

testGen(verify_blob_kzg_proof, testVector):
parseAssign(blob, 32*4096, testVector["input"]["blob"].content)
parseAssign(commitment, 48, testVector["input"]["commitment"].content)
parseAssign(proof, 48, testVector["input"]["proof"].content)

let status = verify_blob_kzg_proof(ctx, blob[].addr, commitment[], proof[])
stdout.write "[" & $status & "]\n"

if status == cttEthKZG_Success:
doAssert testVector["output"].content == "true"
elif status == cttEthKZG_VerificationFailure:
doAssert testVector["output"].content == "false"
else:
doAssert testVector["output"].content == "null"

block:
suite "Ethereum Deneb Hardfork / EIP-4844 / Proto-Danksharding / KZG Polynomial Commitments":
let ctx = load_ethereum_kzg_test_trusted_setup_mainnet()
Expand All @@ -176,4 +191,7 @@ block:
test "compute_blob_kzg_proof(proof: var array[48, byte], blob: ptr array[4096, byte], commitment: array[48, byte])":
ctx.test_compute_blob_kzg_proof()

test "verify_blob_kzg_proof(blob: ptr array[4096, byte], commitment: array[48, byte], proof: var array[48, byte])":
ctx.test_verify_blob_kzg_proof()

ctx.delete()

0 comments on commit 3d0b9ab

Please sign in to comment.