From b33479d0112a8f9481b07b136a1c71d3073b25fb Mon Sep 17 00:00:00 2001 From: Mamy Ratsimbazafy Date: Thu, 13 Jun 2024 11:13:52 +0200 Subject: [PATCH] API: argument order of functions (breaking external Nim/C/Go/Rust API of Ethereum KZG EIP-4844) (#394) --- ARCHITECTURE.md | 35 +++++ benchmarks/bench_eth_eip4844_kzg.nim | 12 +- constantine-go/constantine.go | 43 ++++-- constantine-go/constantine_test.go | 145 +++++++++--------- .../constantine-ethereum-kzg/src/lib.rs | 60 ++++++-- .../tests/t_ethereum_kzg_vectors.rs | 54 ++++--- .../constantine-sys/src/bindings32.rs | 10 +- .../constantine-sys/src/bindings64.rs | 10 +- .../kzg_polynomial_commitments.nim | 22 +-- .../kzg_polynomial_commitments_parallel.nim | 17 +- .../commitments_setups/ethereum_kzg_srs.nim | 1 + constantine/eth_verkle_ipa/ipa_prover.nim | 2 +- constantine/eth_verkle_ipa/ipa_verifier.nim | 2 +- constantine/eth_verkle_ipa/multiproof.nim | 2 +- constantine/ethereum_eip4844_kzg.nim | 28 ++-- constantine/ethereum_eip4844_kzg_parallel.nim | 34 ++-- constantine/math/polynomials/polynomials.nim | 28 ++-- .../math/polynomials/polynomials_parallel.nim | 13 +- .../protocols/ethereum_eip4844_kzg_parallel.h | 10 +- .../t_ethereum_eip4844_deneb_kzg_parallel.nim | 12 +- tests/t_ethereum_verkle_ipa_primitives.nim | 10 +- 21 files changed, 323 insertions(+), 227 deletions(-) create mode 100644 ARCHITECTURE.md diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 00000000..3243383c --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,35 @@ +# Architecture + +## APIs + +### Argument orders + +Function calls have arguments ordered the following way: + +1. Context arguments +2. Threadpool context +3. OUT arguments (only written to) +4. INOUT arguments +5. IN arguments + +The first context argument should allow method call syntax + +In C, length of arrays immediately follow the array, unless there are multiple array arguments with same length. +If an argument is associated with a label, for domain separation for example, +that label precedes the argument. + +### Return values + +Constantine avoids returning values bigger than the word size +and prefer mutable out parameters. + +1. In some cases they introduce extra copies. +2. There is less guarantees over stack space usage. +3. Nim will zero the values without {.noInit.} + and that zeroing might not be optimized away by the compiler + on large inputs like `Fp12[BLS12_381]` 48\*12 bytes = 576 bytes. +4. As we sometimes return SecretBool or status code, this keeps the API consistent. + +## Code organization + +TBD diff --git a/benchmarks/bench_eth_eip4844_kzg.nim b/benchmarks/bench_eth_eip4844_kzg.nim index b105e1ed..fb8f416c 100644 --- a/benchmarks/bench_eth_eip4844_kzg.nim +++ b/benchmarks/bench_eth_eip4844_kzg.nim @@ -79,7 +79,7 @@ proc benchBlobToKzgCommitment(b: BenchSet, ctx: ptr EthereumKZGContext, iters: i block: bench("blob_to_kzg_commitment", $tp.numThreads & " threads", iters): var commitment {.noInit.}: array[48, byte] - doAssert cttEthKzg_Success == ctx.blob_to_kzg_commitment_parallel(tp, commitment, b.blobs[0].addr) + doAssert cttEthKzg_Success == tp.blob_to_kzg_commitment_parallel(ctx, commitment, b.blobs[0].addr) let stopParallel = getMonotime() tp.shutdown() @@ -108,7 +108,7 @@ proc benchComputeKzgProof(b: BenchSet, ctx: ptr EthereumKZGContext, iters: int) bench("compute_kzg_proof", $tp.numThreads & " threads", iters): var proof {.noInit.}: array[48, byte] var eval_at_challenge {.noInit.}: array[32, byte] - doAssert cttEthKzg_Success == ctx.compute_kzg_proof_parallel(tp, proof, eval_at_challenge, b.blobs[0].addr, b.challenge) + doAssert cttEthKzg_Success == tp.compute_kzg_proof_parallel(ctx, proof, eval_at_challenge, b.blobs[0].addr, b.challenge) let stopParallel = getMonotime() tp.shutdown() @@ -135,7 +135,7 @@ proc benchComputeBlobKzgProof(b: BenchSet, ctx: ptr EthereumKZGContext, iters: i block: bench("compute_blob_kzg_proof", $tp.numThreads & " threads", iters): var proof {.noInit.}: array[48, byte] - doAssert cttEthKzg_Success == ctx.compute_blob_kzg_proof_parallel(tp, proof, b.blobs[0].addr, b.commitments[0]) + doAssert cttEthKzg_Success == tp.compute_blob_kzg_proof_parallel(ctx, proof, b.blobs[0].addr, b.commitments[0]) let stopParallel = getMonotime() tp.shutdown() @@ -167,7 +167,7 @@ proc benchVerifyBlobKzgProof(b: BenchSet, ctx: ptr EthereumKZGContext, iters: in let startParallel = getMonotime() block: bench("verify_blob_kzg_proof", $tp.numThreads & " threads", iters): - discard ctx.verify_blob_kzg_proof_parallel(tp, b.blobs[0].addr, b.commitments[0], b.proofs[0]) + discard tp.verify_blob_kzg_proof_parallel(ctx, b.blobs[0].addr, b.commitments[0], b.proofs[0]) let stopParallel = getMonotime() tp.shutdown() @@ -205,8 +205,8 @@ proc benchVerifyBlobKzgProofBatch(b: BenchSet, ctx: ptr EthereumKZGContext, iter let startParallel = getMonotime() block: bench("verify_blob_kzg_proof (batch " & $i & ')', $tp.numThreads & " threads", iters): - discard ctx.verify_blob_kzg_proof_batch_parallel( - tp, + discard tp.verify_blob_kzg_proof_batch_parallel( + ctx, b.blobs.asUnchecked(), b.commitments.asUnchecked(), b.proofs.asUnchecked(), diff --git a/constantine-go/constantine.go b/constantine-go/constantine.go index 418a95a2..fddfef72 100644 --- a/constantine-go/constantine.go +++ b/constantine-go/constantine.go @@ -57,6 +57,7 @@ type ( type EthKzgContext struct { cCtx *C.ctt_eth_kzg_context + threadpool Threadpool } func EthKzgContextNew(trustedSetupFile string) (ctx EthKzgContext, err error) { @@ -72,9 +73,14 @@ func EthKzgContextNew(trustedSetupFile string) (ctx EthKzgContext, err error) { C.GoString(C.ctt_eth_trusted_setup_status_to_string(status)), ) } + ctx.threadpool.ctx = nil return ctx, err } +func (ctx *EthKzgContext) SetThreadpool(tp Threadpool) { + ctx.threadpool = tp +} + func (ctx EthKzgContext) Delete() { C.ctt_eth_trusted_setup_delete(ctx.cCtx) } @@ -183,9 +189,12 @@ func (ctx EthKzgContext) VerifyBlobKzgProofBatch(blobs []EthBlob, commitments [] // Ethereum EIP-4844 KZG API - Parallel // ----------------------------------------------------- -func (ctx EthKzgContext) BlobToKZGCommitmentParallel(tp Threadpool, blob EthBlob) (commitment EthKzgCommitment, err error) { +func (ctx EthKzgContext) BlobToKZGCommitmentParallel(blob EthBlob) (commitment EthKzgCommitment, err error) { + if ctx.threadpool.ctx == nil { + return commitment, errors.New("BlobToKZGCommitmentParallel: The threadpool is not configured.") + } status := C.ctt_eth_kzg_blob_to_kzg_commitment_parallel( - ctx.cCtx, tp.ctx, + ctx.threadpool.ctx, ctx.cCtx, (*C.ctt_eth_kzg_commitment)(unsafe.Pointer(&commitment)), (*C.ctt_eth_kzg_blob)(unsafe.Pointer(&blob)), ) @@ -197,9 +206,12 @@ func (ctx EthKzgContext) BlobToKZGCommitmentParallel(tp Threadpool, blob EthBlob return commitment, err } -func (ctx EthKzgContext) ComputeKzgProofParallel(tp Threadpool, blob EthBlob, z EthKzgChallenge) (proof EthKzgProof, y EthKzgEvalAtChallenge, err error) { +func (ctx EthKzgContext) ComputeKzgProofParallel(blob EthBlob, z EthKzgChallenge) (proof EthKzgProof, y EthKzgEvalAtChallenge, err error) { + if ctx.threadpool.ctx == nil { + return proof, y, errors.New("ComputeKzgProofParallel: The Constantine's threadpool is not configured.") + } status := C.ctt_eth_kzg_compute_kzg_proof_parallel( - ctx.cCtx, tp.ctx, + ctx.threadpool.ctx, ctx.cCtx, (*C.ctt_eth_kzg_proof)(unsafe.Pointer(&proof)), (*C.ctt_eth_kzg_eval_at_challenge)(unsafe.Pointer(&y)), (*C.ctt_eth_kzg_blob)(unsafe.Pointer(&blob)), @@ -213,9 +225,12 @@ func (ctx EthKzgContext) ComputeKzgProofParallel(tp Threadpool, blob EthBlob, z return proof, y, err } -func (ctx EthKzgContext) ComputeBlobKzgProofParallel(tp Threadpool, blob EthBlob, commitment EthKzgCommitment) (proof EthKzgProof, err error) { +func (ctx EthKzgContext) ComputeBlobKzgProofParallel(blob EthBlob, commitment EthKzgCommitment) (proof EthKzgProof, err error) { + if ctx.threadpool.ctx == nil { + return proof, errors.New("ComputeBlobKzgProofParallel: The threadpool is not configured.") + } status := C.ctt_eth_kzg_compute_blob_kzg_proof_parallel( - ctx.cCtx, tp.ctx, + ctx.threadpool.ctx, ctx.cCtx, (*C.ctt_eth_kzg_proof)(unsafe.Pointer(&proof)), (*C.ctt_eth_kzg_blob)(unsafe.Pointer(&blob)), (*C.ctt_eth_kzg_commitment)(unsafe.Pointer(&commitment)), @@ -228,9 +243,12 @@ func (ctx EthKzgContext) ComputeBlobKzgProofParallel(tp Threadpool, blob EthBlob return proof, err } -func (ctx EthKzgContext) VerifyBlobKzgProofParallel(tp Threadpool, blob EthBlob, commitment EthKzgCommitment, proof EthKzgProof) (bool, error) { +func (ctx EthKzgContext) VerifyBlobKzgProofParallel(blob EthBlob, commitment EthKzgCommitment, proof EthKzgProof) (bool, error) { + if ctx.threadpool.ctx == nil { + return false, errors.New("VerifyBlobKzgProofParallel: The threadpool is not configured.") + } status := C.ctt_eth_kzg_verify_blob_kzg_proof_parallel( - ctx.cCtx, tp.ctx, + ctx.threadpool.ctx, ctx.cCtx, (*C.ctt_eth_kzg_blob)(unsafe.Pointer(&blob)), (*C.ctt_eth_kzg_commitment)(unsafe.Pointer(&commitment)), (*C.ctt_eth_kzg_proof)(unsafe.Pointer(&proof)), @@ -244,14 +262,15 @@ func (ctx EthKzgContext) VerifyBlobKzgProofParallel(tp Threadpool, blob EthBlob, return true, nil } -func (ctx EthKzgContext) VerifyBlobKzgProofBatchParallel(tp Threadpool, blobs []EthBlob, commitments []EthKzgCommitment, proofs []EthKzgProof, secureRandomBytes [32]byte) (bool, error) { - +func (ctx EthKzgContext) VerifyBlobKzgProofBatchParallel(blobs []EthBlob, commitments []EthKzgCommitment, proofs []EthKzgProof, secureRandomBytes [32]byte) (bool, error) { if len(blobs) != len(commitments) || len(blobs) != len(proofs) { return false, errors.New("VerifyBlobKzgProofBatch: Lengths of inputs do not match.") } - + if ctx.threadpool.ctx == nil { + return false, errors.New("VerifyBlobKzgProofBatch: The threadpool is not configured.") + } status := C.ctt_eth_kzg_verify_blob_kzg_proof_batch_parallel( - ctx.cCtx, tp.ctx, + ctx.threadpool.ctx, ctx.cCtx, *(**C.ctt_eth_kzg_blob)(unsafe.Pointer(&blobs)), *(**C.ctt_eth_kzg_commitment)(unsafe.Pointer(&commitments)), *(**C.ctt_eth_kzg_proof)(unsafe.Pointer(&proofs)), diff --git a/constantine-go/constantine_test.go b/constantine-go/constantine_test.go index 7df64015..8fb4578a 100644 --- a/constantine-go/constantine_test.go +++ b/constantine-go/constantine_test.go @@ -13,21 +13,20 @@ import ( "crypto/rand" "encoding/hex" "errors" + "fmt" "os" "path/filepath" "runtime" "strings" "testing" - "fmt" + "encoding/json" "github.com/stretchr/testify/require" "gopkg.in/yaml.v3" - "encoding/json" "github.com/mratsim/constantine/constantine-go/sha256" ) - // Threadpool smoke test // ---------------------------------------------------------- @@ -456,9 +455,9 @@ func createTestThreadpool(t *testing.T) Threadpool { // Register a cleanup function t.Cleanup(func() { - tp.Shutdown() + tp.Shutdown() runtime.UnlockOSThread() - }) + }) return tp } @@ -476,6 +475,7 @@ func TestBlobToKZGCommitmentParallel(t *testing.T) { defer ctx.Delete() tp := createTestThreadpool(t) + ctx.SetThreadpool(tp) tests, err := filepath.Glob(blobToKZGCommitmentTests) require.NoError(t, err) @@ -497,7 +497,7 @@ func TestBlobToKZGCommitmentParallel(t *testing.T) { continue } - commitment, err := ctx.BlobToKZGCommitmentParallel(tp, blob) + commitment, err := ctx.BlobToKZGCommitmentParallel(blob) if err == nil { require.NotNil(t, test.Output) require.Equal(t, test.Output[:], commitment[:]) @@ -521,6 +521,7 @@ func TestComputeKzgProofParallel(t *testing.T) { defer ctx.Delete() tp := createTestThreadpool(t) + ctx.SetThreadpool(tp) tests, err := filepath.Glob(computeKZGProofTests) require.NoError(t, err) @@ -549,7 +550,7 @@ func TestComputeKzgProofParallel(t *testing.T) { continue } - proof, y, err := ctx.ComputeKzgProofParallel(tp, blob, z) + proof, y, err := ctx.ComputeKzgProofParallel(blob, z) if err == nil { require.NotNil(t, test.Output) var expectedProof EthKzgProof @@ -580,6 +581,7 @@ func TestComputeBlobKzgProofParallel(t *testing.T) { defer ctx.Delete() tp := createTestThreadpool(t) + ctx.SetThreadpool(tp) tests, err := filepath.Glob(computeBlobKZGProofTests) require.NoError(t, err) @@ -608,7 +610,7 @@ func TestComputeBlobKzgProofParallel(t *testing.T) { continue } - proof, err := ctx.ComputeBlobKzgProofParallel(tp, blob, commitment) + proof, err := ctx.ComputeBlobKzgProofParallel(blob, commitment) if err == nil { require.NotNil(t, test.Output) require.Equal(t, test.Output[:], proof[:]) @@ -633,6 +635,7 @@ func TestVerifyBlobKzgProofParallel(t *testing.T) { defer ctx.Delete() tp := createTestThreadpool(t) + ctx.SetThreadpool(tp) tests, err := filepath.Glob(verifyBlobKZGProofTests) require.NoError(t, err) @@ -668,7 +671,7 @@ func TestVerifyBlobKzgProofParallel(t *testing.T) { continue } - valid, err := ctx.VerifyBlobKzgProofParallel(tp, blob, commitment, proof) + valid, err := ctx.VerifyBlobKzgProofParallel(blob, commitment, proof) if err == nil { require.NotNil(t, test.Output) require.Equal(t, *test.Output, valid) @@ -695,6 +698,7 @@ func TestVerifyBlobKzgProofBatchParallel(t *testing.T) { defer ctx.Delete() tp := createTestThreadpool(t) + ctx.SetThreadpool(tp) var secureRandomBytes [32]byte _, _ = rand.Read(secureRandomBytes[:]) @@ -745,7 +749,7 @@ func TestVerifyBlobKzgProofBatchParallel(t *testing.T) { proofs = append(proofs, proof) } - valid, err := ctx.VerifyBlobKzgProofBatchParallel(tp, blobs, commitments, proofs, secureRandomBytes) + valid, err := ctx.VerifyBlobKzgProofBatchParallel(blobs, commitments, proofs, secureRandomBytes) if err == nil { require.NotNil(t, test.Output) require.Equal(t, *test.Output, valid) @@ -793,16 +797,16 @@ func TestExampleCBlsSig(t *testing.T) { } var ( - testDirBls = "../tests/protocol_blssig_pop_on_bls12381_g2_test_vectors_v0.1.1" - aggregate_verifyTests = filepath.Join(testDirBls, "aggregate_verify/*") - aggregateTests = filepath.Join(testDirBls, "aggregate/*") - deserialization_G1Tests = filepath.Join(testDirBls, "deserialization_G1/*") - batch_verifyTests = filepath.Join(testDirBls, "batch_verify/*") - fast_aggregate_verifyTests = filepath.Join(testDirBls, "fast_aggregate_verify/*") - hash_to_G2Tests = filepath.Join(testDirBls, "hash_to_G2/*") - deserialization_G2Tests = filepath.Join(testDirBls, "deserialization_G2/*") - verifyTests = filepath.Join(testDirBls, "verify/*") - signTests = filepath.Join(testDirBls, "sign/*") + testDirBls = "../tests/protocol_blssig_pop_on_bls12381_g2_test_vectors_v0.1.1" + aggregate_verifyTests = filepath.Join(testDirBls, "aggregate_verify/*") + aggregateTests = filepath.Join(testDirBls, "aggregate/*") + deserialization_G1Tests = filepath.Join(testDirBls, "deserialization_G1/*") + batch_verifyTests = filepath.Join(testDirBls, "batch_verify/*") + fast_aggregate_verifyTests = filepath.Join(testDirBls, "fast_aggregate_verify/*") + hash_to_G2Tests = filepath.Join(testDirBls, "hash_to_G2/*") + deserialization_G2Tests = filepath.Join(testDirBls, "deserialization_G2/*") + verifyTests = filepath.Join(testDirBls, "verify/*") + signTests = filepath.Join(testDirBls, "sign/*") ) // These types correspond to the serialized pub/sec keys / signatures @@ -836,12 +840,10 @@ func (dst *EthBlsTestOutput) UnmarshalText(input []byte) error { return fromHexImpl(dst[:], input) } - func TestDeserializeG1(t *testing.T) { type Test struct { Input struct { PubKey string `json:"pubkey"` - } `json:"input"` Output bool `json:"output"` } @@ -889,7 +891,6 @@ func TestDeserializeG2(t *testing.T) { type Test struct { Input struct { Signature string `json:"signature"` - } `json:"input"` Output bool `json:"output"` } @@ -938,7 +939,6 @@ func TestSign(t *testing.T) { Input struct { PrivKey string `json:"privkey"` Message string `json:"message"` - } `json:"input"` Output string `json:"output"` } @@ -993,7 +993,7 @@ func TestSign(t *testing.T) { } status = sig.AreEqual(output) if !status { // signatures mismatch - var sigBytes [96]byte + var sigBytes [96]byte var roundTrip [96]byte sb_status, _ := sig.SerializeCompressed(&sigBytes) rt_status, _ := output.SerializeCompressed(&roundTrip) @@ -1030,10 +1030,9 @@ func TestSign(t *testing.T) { func TestVerify(t *testing.T) { type Test struct { Input struct { - PubKey string `json:"pubkey"` - Message string `json:"message"` + PubKey string `json:"pubkey"` + Message string `json:"message"` Signature string `json:"signature"` - } `json:"input"` Output bool `json:"output"` } @@ -1045,7 +1044,6 @@ func TestVerify(t *testing.T) { test := Test{} err = json.NewDecoder(testFile).Decode(&test) - var rawPk EthBlsPubKeyRaw err = rawPk.UnmarshalText([]byte(test.Input.PubKey)) if err != nil { @@ -1088,8 +1086,8 @@ func TestVerify(t *testing.T) { } if status != test.Output { fmt.Println("Verification differs from expected \n", - " valid sig? ", status, "\n", - " expected: ", test.Output, + " valid sig? ", status, "\n", + " expected: ", test.Output, ) require.True(t, false) return @@ -1122,10 +1120,9 @@ func TestVerify(t *testing.T) { func TestFastAggregateVerify(t *testing.T) { type Test struct { Input struct { - PubKeys []string `json:"pubkeys"` - Message string `json:"message"` - Signature string `json:"signature"` - + PubKeys []string `json:"pubkeys"` + Message string `json:"message"` + Signature string `json:"signature"` } `json:"input"` Output bool `json:"output"` } @@ -1183,8 +1180,8 @@ func TestFastAggregateVerify(t *testing.T) { require.Equal(t, status, test.Output) if status != test.Output { fmt.Println("Verification differs from expected \n", - " valid sig? ", status, "\n", - " expected: ", test.Output, + " valid sig? ", status, "\n", + " expected: ", test.Output, ) return } @@ -1280,10 +1277,9 @@ func TestFastAggregateVerify(t *testing.T) { func TestBatchVerify(t *testing.T) { type Test struct { Input struct { - PubKeys []string `json:"pubkeys"` - Messages []string `json:"messages"` + PubKeys []string `json:"pubkeys"` + Messages []string `json:"messages"` Signatures []string `json:"signatures"` - } `json:"input"` Output bool `json:"output"` } @@ -1380,8 +1376,6 @@ func TestBatchVerify(t *testing.T) { } } - - // -------------------------------- // ------- EVM precompiles -------- // -------------------------------- @@ -1392,9 +1386,9 @@ func TestSha256(t *testing.T) { fmt.Println("Running SHA256 tests") var inputBytes []byte - inputBytes = make([]byte, len(input) / 2, len(input) / 2) + inputBytes = make([]byte, len(input)/2, len(input)/2) var expectedBytes []byte - expectedBytes = make([]byte, len(expected) / 2, len(expected) / 2) + expectedBytes = make([]byte, len(expected)/2, len(expected)/2) err := fromHexImpl(inputBytes[:], []byte(input)) if err != nil { @@ -1417,45 +1411,45 @@ func TestSha256(t *testing.T) { } var ( - testDirEvm = "../tests/protocol_ethereum_evm_precompiles/" + testDirEvm = "../tests/protocol_ethereum_evm_precompiles/" - modexp_tests = filepath.Join(testDirEvm, "modexp.json") - modexp_eip2565_tests = filepath.Join(testDirEvm, "modexp_eip2565.json") + modexp_tests = filepath.Join(testDirEvm, "modexp.json") + modexp_eip2565_tests = filepath.Join(testDirEvm, "modexp_eip2565.json") - bn256Add_tests = filepath.Join(testDirEvm, "bn256Add.json") - bn256ScalarMul_tests = filepath.Join(testDirEvm, "bn256ScalarMul.json") - bn256Pairing_tests = filepath.Join(testDirEvm, "bn256Pairing.json") + bn256Add_tests = filepath.Join(testDirEvm, "bn256Add.json") + bn256ScalarMul_tests = filepath.Join(testDirEvm, "bn256ScalarMul.json") + bn256Pairing_tests = filepath.Join(testDirEvm, "bn256Pairing.json") - add_G1_bls_tests = filepath.Join(testDirEvm, "eip-2537/add_G1_bls.json") - fail_add_G1_bls_tests = filepath.Join(testDirEvm, "eip-2537/fail-add_G1_bls.json") - add_G2_bls_tests = filepath.Join(testDirEvm, "eip-2537/add_G2_bls.json") - fail_add_G2_bls_tests = filepath.Join(testDirEvm, "eip-2537/fail-add_G2_bls.json") + add_G1_bls_tests = filepath.Join(testDirEvm, "eip-2537/add_G1_bls.json") + fail_add_G1_bls_tests = filepath.Join(testDirEvm, "eip-2537/fail-add_G1_bls.json") + add_G2_bls_tests = filepath.Join(testDirEvm, "eip-2537/add_G2_bls.json") + fail_add_G2_bls_tests = filepath.Join(testDirEvm, "eip-2537/fail-add_G2_bls.json") - mul_G1_bls_tests = filepath.Join(testDirEvm, "eip-2537/mul_G1_bls.json") - fail_mul_G1_bls_tests = filepath.Join(testDirEvm, "eip-2537/fail-mul_G1_bls.json") - mul_G2_bls_tests = filepath.Join(testDirEvm, "eip-2537/mul_G2_bls.json") - fail_mul_G2_bls_tests = filepath.Join(testDirEvm, "eip-2537/fail-mul_G2_bls.json") + mul_G1_bls_tests = filepath.Join(testDirEvm, "eip-2537/mul_G1_bls.json") + fail_mul_G1_bls_tests = filepath.Join(testDirEvm, "eip-2537/fail-mul_G1_bls.json") + mul_G2_bls_tests = filepath.Join(testDirEvm, "eip-2537/mul_G2_bls.json") + fail_mul_G2_bls_tests = filepath.Join(testDirEvm, "eip-2537/fail-mul_G2_bls.json") - multiexp_G1_bls_tests = filepath.Join(testDirEvm, "eip-2537/multiexp_G1_bls.json") - fail_multiexp_G1_bls_tests = filepath.Join(testDirEvm, "eip-2537/fail-multiexp_G1_bls.json") - multiexp_G2_bls_tests = filepath.Join(testDirEvm, "eip-2537/multiexp_G2_bls.json") - fail_multiexp_G2_bls_tests = filepath.Join(testDirEvm, "eip-2537/fail-multiexp_G2_bls.json") + multiexp_G1_bls_tests = filepath.Join(testDirEvm, "eip-2537/multiexp_G1_bls.json") + fail_multiexp_G1_bls_tests = filepath.Join(testDirEvm, "eip-2537/fail-multiexp_G1_bls.json") + multiexp_G2_bls_tests = filepath.Join(testDirEvm, "eip-2537/multiexp_G2_bls.json") + fail_multiexp_G2_bls_tests = filepath.Join(testDirEvm, "eip-2537/fail-multiexp_G2_bls.json") - pairing_check_bls_tests = filepath.Join(testDirEvm, "eip-2537/pairing_check_bls.json") - fail_pairing_check_bls_tests = filepath.Join(testDirEvm, "eip-2537/fail-pairing_check_bls.json") + pairing_check_bls_tests = filepath.Join(testDirEvm, "eip-2537/pairing_check_bls.json") + fail_pairing_check_bls_tests = filepath.Join(testDirEvm, "eip-2537/fail-pairing_check_bls.json") - map_fp_to_G1_bls_tests = filepath.Join(testDirEvm, "eip-2537/map_fp_to_G1_bls.json") - fail_map_fp_to_G1_bls_tests = filepath.Join(testDirEvm, "eip-2537/fail-map_fp_to_G1_bls.json") - map_fp2_to_G2_bls_tests = filepath.Join(testDirEvm, "eip-2537/map_fp2_to_G2_bls.json") - fail_map_fp2_to_G2_bls_tests = filepath.Join(testDirEvm, "eip-2537/fail-map_fp2_to_G2_bls.json") + map_fp_to_G1_bls_tests = filepath.Join(testDirEvm, "eip-2537/map_fp_to_G1_bls.json") + fail_map_fp_to_G1_bls_tests = filepath.Join(testDirEvm, "eip-2537/fail-map_fp_to_G1_bls.json") + map_fp2_to_G2_bls_tests = filepath.Join(testDirEvm, "eip-2537/map_fp2_to_G2_bls.json") + fail_map_fp2_to_G2_bls_tests = filepath.Join(testDirEvm, "eip-2537/fail-map_fp2_to_G2_bls.json") ) type HexString string type PrecompileTest struct { - Input HexString - Expected HexString - Name string - Gas int + Input HexString + Expected HexString + Name string + Gas int NoBenchmark bool } @@ -1473,7 +1467,6 @@ func loadVectors(fname string) (result []PrecompileTest) { type TestFunction func([]byte, []byte) (bool, error) - // Helper function to simplify the test generation. No need to duplicate test logic, all the same func runTest(t *testing.T, testPath string, fn TestFunction) { fmt.Println("Running test for path: ", testPath) @@ -1489,9 +1482,9 @@ func runTest(t *testing.T, testPath string, fn TestFunction) { expected := vec.Expected var inputBytes []byte - inputBytes = make([]byte, len(input) / 2, len(input) / 2) + inputBytes = make([]byte, len(input)/2, len(input)/2) var expectedBytes []byte - expectedBytes = make([]byte, len(expected) / 2, len(expected) / 2) + expectedBytes = make([]byte, len(expected)/2, len(expected)/2) err := fromHexImpl(inputBytes[:], []byte(input)) if err != nil { @@ -1502,7 +1495,7 @@ func runTest(t *testing.T, testPath string, fn TestFunction) { require.True(t, false) } - r := make([]byte, len(expected) / 2, len(expected) / 2) + r := make([]byte, len(expected)/2, len(expected)/2) // Call the test function status, err := fn(r, inputBytes) diff --git a/constantine-rust/constantine-ethereum-kzg/src/lib.rs b/constantine-rust/constantine-ethereum-kzg/src/lib.rs index bf6ca3bf..2cf7075d 100644 --- a/constantine-rust/constantine-ethereum-kzg/src/lib.rs +++ b/constantine-rust/constantine-ethereum-kzg/src/lib.rs @@ -16,19 +16,25 @@ use std::{ffi::CString, path::Path}; // ------------------------------------------------------------ #[derive(Debug)] -pub struct EthKzgContext { +pub struct EthKzgContext<'tp> { ctx: *const ctt_eth_kzg_context, + threadpool: Option<&'tp Threadpool>, } -impl Drop for EthKzgContext { +pub struct EthKzgContextBuilder<'tp> { + ctx: Option<*const ctt_eth_kzg_context>, + threadpool: Option<&'tp Threadpool>, +} + +impl<'tp> Drop for EthKzgContext<'tp> { #[inline(always)] fn drop(&mut self) { unsafe { ctt_eth_trusted_setup_delete(self.ctx as *mut ctt_eth_kzg_context) } } } -impl EthKzgContext { - pub fn load_trusted_setup(file_path: &Path) -> Result { +impl<'tp> EthKzgContextBuilder<'tp> { + pub fn load_trusted_setup(self, file_path: &Path) -> Result { // The joy of OS Paths / C Paths: // https://users.rust-lang.org/t/easy-way-to-pass-a-path-to-c/51829 // https://doc.rust-lang.org/std/ffi/index.html#conversions @@ -64,11 +70,40 @@ impl EthKzgContext { ) }; match status { - ctt_eth_trusted_setup_status::cttEthTS_Success => Ok(Self { ctx }), + ctt_eth_trusted_setup_status::cttEthTS_Success => Ok(Self { ctx: Some(ctx), threadpool: self.threadpool }), _ => Err(status), } } + pub fn set_threadpool(self, tp: &'tp Threadpool) -> Self { + // Copy all other parameters + let Self { ctx, .. } = self; + // Return with threadpool + Self { ctx, threadpool: Some(tp)} + } + + pub fn build(self) -> Result, ctt_eth_trusted_setup_status> { + let ctx = self.ctx.ok_or(ctt_eth_trusted_setup_status::cttEthTS_MissingOrInaccessibleFile)?; + Ok(EthKzgContext{ + ctx, + threadpool: self.threadpool, + }) + } + +} + +impl<'tp> EthKzgContext<'tp> { + pub fn builder() -> EthKzgContextBuilder<'tp> { + EthKzgContextBuilder{ctx: None, threadpool: None} + } + + pub fn load_trusted_setup(file_path: &Path) -> Result { + Ok(Self::builder() + .load_trusted_setup(file_path)? + .build() + .expect("Trusted setup should be loaded properly")) + } + #[inline] pub fn blob_to_kzg_commitment( &self, @@ -215,14 +250,13 @@ impl EthKzgContext { #[inline] pub fn blob_to_kzg_commitment_parallel( &self, - tp: &Threadpool, blob: &[u8; 4096 * 32], ) -> Result<[u8; 48], ctt_eth_kzg_status> { let mut result: MaybeUninit<[u8; 48]> = MaybeUninit::uninit(); unsafe { let status = ctt_eth_kzg_blob_to_kzg_commitment_parallel( + self.threadpool.expect("Threadpool has been set").get_private_context(), self.ctx, - tp.get_private_context(), result.as_mut_ptr() as *mut ctt_eth_kzg_commitment, blob.as_ptr() as *const ctt_eth_kzg_blob, ); @@ -236,7 +270,6 @@ impl EthKzgContext { #[inline] pub fn compute_kzg_proof_parallel( &self, - tp: &Threadpool, blob: &[u8; 4096 * 32], z_challenge: &[u8; 32], ) -> Result<([u8; 48], [u8; 32]), ctt_eth_kzg_status> { @@ -244,8 +277,8 @@ impl EthKzgContext { let mut y_eval = MaybeUninit::<[u8; 32]>::uninit(); unsafe { let status = ctt_eth_kzg_compute_kzg_proof_parallel( + self.threadpool.expect("Threadpool has been set").get_private_context(), self.ctx, - tp.get_private_context(), proof.as_mut_ptr() as *mut ctt_eth_kzg_proof, y_eval.as_mut_ptr() as *mut ctt_eth_kzg_eval_at_challenge, blob.as_ptr() as *const ctt_eth_kzg_blob, @@ -263,15 +296,14 @@ impl EthKzgContext { #[inline] pub fn compute_blob_kzg_proof_parallel( &self, - tp: &Threadpool, blob: &[u8; 4096 * 32], commitment: &[u8; 48], ) -> Result<[u8; 48], ctt_eth_kzg_status> { let mut proof = MaybeUninit::<[u8; 48]>::uninit(); unsafe { let status = ctt_eth_kzg_compute_blob_kzg_proof_parallel( + self.threadpool.expect("Threadpool has been set").get_private_context(), self.ctx, - tp.get_private_context(), proof.as_mut_ptr() as *mut ctt_eth_kzg_proof, blob.as_ptr() as *const ctt_eth_kzg_blob, commitment.as_ptr() as *const ctt_eth_kzg_commitment, @@ -286,15 +318,14 @@ impl EthKzgContext { #[inline] pub fn verify_blob_kzg_proof_parallel( &self, - tp: &Threadpool, blob: &[u8; 4096 * 32], commitment: &[u8; 48], proof: &[u8; 48], ) -> Result { let status = unsafe { ctt_eth_kzg_verify_blob_kzg_proof_parallel( + self.threadpool.expect("Threadpool has been set").get_private_context(), self.ctx, - tp.get_private_context(), blob.as_ptr() as *const ctt_eth_kzg_blob, commitment.as_ptr() as *const ctt_eth_kzg_commitment, proof.as_ptr() as *const ctt_eth_kzg_proof, @@ -310,7 +341,6 @@ impl EthKzgContext { #[inline] pub fn verify_blob_kzg_proof_batch_parallel( &self, - tp: &Threadpool, blobs: &[[u8; 4096 * 32]], commitments: &[[u8; 48]], proofs: &[[u8; 48]], @@ -322,8 +352,8 @@ impl EthKzgContext { let status = unsafe { ctt_eth_kzg_verify_blob_kzg_proof_batch_parallel( + self.threadpool.expect("Threadpool has been set").get_private_context(), self.ctx, - tp.get_private_context(), blobs.as_ptr() as *const ctt_eth_kzg_blob, commitments.as_ptr() as *const ctt_eth_kzg_commitment, proofs.as_ptr() as *const ctt_eth_kzg_proof, diff --git a/constantine-rust/constantine-ethereum-kzg/tests/t_ethereum_kzg_vectors.rs b/constantine-rust/constantine-ethereum-kzg/tests/t_ethereum_kzg_vectors.rs index c0f8fc86..0839c697 100644 --- a/constantine-rust/constantine-ethereum-kzg/tests/t_ethereum_kzg_vectors.rs +++ b/constantine-rust/constantine-ethereum-kzg/tests/t_ethereum_kzg_vectors.rs @@ -480,10 +480,13 @@ fn t_blob_to_kzg_commitment_parallel() { output: OptBytes<48>, } - let ctx = EthKzgContext::load_trusted_setup(Path::new(SRS_PATH)) - .expect("Trusted setup should be loaded without error."); - let tp = Threadpool::new(hardware::get_num_threads_os()); + let ctx = EthKzgContext::builder() + .load_trusted_setup(Path::new(SRS_PATH)) + .expect("Trusted setup loaded successfully") + .set_threadpool(&tp) + .build() + .expect("EthKzgContext initialized successfully"); let test_files: Vec = glob(BLOB_TO_KZG_COMMITMENT_TESTS) .unwrap() @@ -512,7 +515,7 @@ fn t_blob_to_kzg_commitment_parallel() { continue; }; - match ctx.blob_to_kzg_commitment_parallel(&tp, &*blob) { + match ctx.blob_to_kzg_commitment_parallel(&*blob) { Ok(commitment) => { assert_eq!(commitment, *test.output.opt_bytes.0.unwrap()); println!("{}=> SUCCESS", tv); @@ -540,10 +543,13 @@ fn t_compute_kzg_proof_parallel() { output: Option<(OptBytes<48>, OptBytes<32>)>, } - let ctx = EthKzgContext::load_trusted_setup(Path::new(SRS_PATH)) - .expect("Trusted setup should be loaded without error."); - let tp = Threadpool::new(hardware::get_num_threads_os()); + let ctx = EthKzgContext::builder() + .load_trusted_setup(Path::new(SRS_PATH)) + .expect("Trusted setup loaded successfully") + .set_threadpool(&tp) + .build() + .expect("EthKzgContext initialized successfully"); let test_files: Vec = glob(COMPUTE_KZG_PROOF_TESTS) .unwrap() @@ -573,7 +579,7 @@ fn t_compute_kzg_proof_parallel() { continue; }; - match ctx.compute_kzg_proof_parallel(&tp, &*blob, &*challenge) { + match ctx.compute_kzg_proof_parallel(&*blob, &*challenge) { Ok((proof, eval)) => { let (true_proof, true_eval) = test.output.unwrap(); assert_eq!(proof, *true_proof.opt_bytes.0.unwrap()); @@ -602,10 +608,13 @@ fn t_compute_blob_kzg_proof_parallel() { output: OptBytes<48>, } - let ctx = EthKzgContext::load_trusted_setup(Path::new(SRS_PATH)) - .expect("Trusted setup should be loaded without error."); - let tp = Threadpool::new(hardware::get_num_threads_os()); + let ctx = EthKzgContext::builder() + .load_trusted_setup(Path::new(SRS_PATH)) + .expect("Trusted setup loaded successfully") + .set_threadpool(&tp) + .build() + .expect("EthKzgContext initialized successfully"); let test_files: Vec = glob(COMPUTE_BLOB_KZG_PROOF_TESTS) .unwrap() @@ -637,7 +646,7 @@ fn t_compute_blob_kzg_proof_parallel() { continue; }; - match ctx.compute_blob_kzg_proof_parallel(&tp, &*blob, &*commitment) { + match ctx.compute_blob_kzg_proof_parallel(&*blob, &*commitment) { Ok(proof) => { assert_eq!(proof, *test.output.opt_bytes.0.unwrap()); println!("{}=> SUCCESS", tv); @@ -666,10 +675,13 @@ fn t_verify_blob_kzg_proof_parallel() { output: Option, } - let ctx = EthKzgContext::load_trusted_setup(Path::new(SRS_PATH)) - .expect("Trusted setup should be loaded without error."); - let tp = Threadpool::new(hardware::get_num_threads_os()); + let ctx = EthKzgContext::builder() + .load_trusted_setup(Path::new(SRS_PATH)) + .expect("Trusted setup loaded successfully") + .set_threadpool(&tp) + .build() + .expect("EthKzgContext initialized successfully"); let test_files: Vec = glob(VERIFY_BLOB_KZG_PROOF_TESTS) .unwrap() @@ -702,7 +714,7 @@ fn t_verify_blob_kzg_proof_parallel() { continue; }; - match ctx.verify_blob_kzg_proof_parallel(&tp, &*blob, &*commitment, &*proof) { + match ctx.verify_blob_kzg_proof_parallel(&*blob, &*commitment, &*proof) { Ok(valid) => { assert_eq!(valid, test.output.unwrap()); if valid { @@ -735,10 +747,13 @@ fn t_verify_blob_kzg_proof_batch_parallel() { output: Option, } - let ctx = EthKzgContext::load_trusted_setup(Path::new(SRS_PATH)) - .expect("Trusted setup should be loaded without error."); - let tp = Threadpool::new(hardware::get_num_threads_os()); + let ctx = EthKzgContext::builder() + .load_trusted_setup(Path::new(SRS_PATH)) + .expect("Trusted setup loaded successfully") + .set_threadpool(&tp) + .build() + .expect("EthKzgContext initialized successfully"); let mut secure_random_bytes = [0u8; 32]; csprngs::sysrand(secure_random_bytes.as_mut_slice()); @@ -788,7 +803,6 @@ fn t_verify_blob_kzg_proof_batch_parallel() { .collect(); match ctx.verify_blob_kzg_proof_batch_parallel( - &tp, &blobs, &commitments, &proofs, diff --git a/constantine-rust/constantine-sys/src/bindings32.rs b/constantine-rust/constantine-sys/src/bindings32.rs index a72aa2fc..8bc98fe5 100644 --- a/constantine-rust/constantine-sys/src/bindings32.rs +++ b/constantine-rust/constantine-sys/src/bindings32.rs @@ -5010,8 +5010,8 @@ extern "C" { #[must_use] #[doc = " Compute a commitment to the `blob`.\n The commitment can be verified without needing the full `blob`\n\n Mathematical description\n commitment = [p(τ)]₁\n\n The blob data is used as a polynomial,\n the polynomial is evaluated at powers of tau τ, a trusted setup.\n\n Verification can be done by verifying the relation:\n proof.(τ - z) = p(τ)-p(z)\n which doesn't require the full blob but only evaluations of it\n - at τ, p(τ) is the commitment\n - and at the verification challenge z.\n\n with proof = [(p(τ) - p(z)) / (τ-z)]₁"] pub fn ctt_eth_kzg_blob_to_kzg_commitment_parallel( - ctx: *const ctt_eth_kzg_context, tp: *const ctt_threadpool, + ctx: *const ctt_eth_kzg_context, dst: *mut ctt_eth_kzg_commitment, blob: *const ctt_eth_kzg_blob, ) -> ctt_eth_kzg_status; @@ -5020,8 +5020,8 @@ extern "C" { #[must_use] #[doc = " Generate:\n - A proof of correct evaluation.\n - y = p(z), the evaluation of p at the challenge z, with p being the Blob interpreted as a polynomial.\n\n Mathematical description\n [proof]₁ = [(p(τ) - p(z)) / (τ-z)]₁, with p(τ) being the commitment, i.e. the evaluation of p at the powers of τ\n The notation [a]₁ corresponds to the scalar multiplication of a by the generator of 𝔾1\n\n Verification can be done by verifying the relation:\n proof.(τ - z) = p(τ)-p(z)\n which doesn't require the full blob but only evaluations of it\n - at τ, p(τ) is the commitment\n - and at the verification challenge z."] pub fn ctt_eth_kzg_compute_kzg_proof_parallel( - ctx: *const ctt_eth_kzg_context, tp: *const ctt_threadpool, + ctx: *const ctt_eth_kzg_context, proof: *mut ctt_eth_kzg_proof, y: *mut ctt_eth_kzg_eval_at_challenge, blob: *const ctt_eth_kzg_blob, @@ -5032,8 +5032,8 @@ extern "C" { #[must_use] #[doc = " Given a blob, return the KZG proof that is used to verify it against the commitment.\n This method does not verify that the commitment is correct with respect to `blob`."] pub fn ctt_eth_kzg_compute_blob_kzg_proof_parallel( - ctx: *const ctt_eth_kzg_context, tp: *const ctt_threadpool, + ctx: *const ctt_eth_kzg_context, proof: *mut ctt_eth_kzg_proof, blob: *const ctt_eth_kzg_blob, commitment: *const ctt_eth_kzg_commitment, @@ -5043,8 +5043,8 @@ extern "C" { #[must_use] #[doc = " Given a blob and a KZG proof, verify that the blob data corresponds to the provided commitment."] pub fn ctt_eth_kzg_verify_blob_kzg_proof_parallel( - ctx: *const ctt_eth_kzg_context, tp: *const ctt_threadpool, + ctx: *const ctt_eth_kzg_context, blob: *const ctt_eth_kzg_blob, commitment: *const ctt_eth_kzg_commitment, proof: *const ctt_eth_kzg_proof, @@ -5054,8 +5054,8 @@ extern "C" { #[must_use] #[doc = " Verify `n` (blob, commitment, proof) sets efficiently\n\n `n` is the number of verifications set\n - if n is negative, this procedure returns verification failure\n - if n is zero, this procedure returns verification success\n\n `secure_random_bytes` random bytes must come from a cryptographically secure RNG\n or computed through the Fiat-Shamir heuristic.\n It serves as a random number\n that is not in the control of a potential attacker to prevent potential\n rogue commitments attacks due to homomorphic properties of pairings,\n i.e. commitments that are linear combination of others and sum would be zero."] pub fn ctt_eth_kzg_verify_blob_kzg_proof_batch_parallel( - ctx: *const ctt_eth_kzg_context, tp: *const ctt_threadpool, + ctx: *const ctt_eth_kzg_context, blobs: *const ctt_eth_kzg_blob, commitments: *const ctt_eth_kzg_commitment, proofs: *const ctt_eth_kzg_proof, diff --git a/constantine-rust/constantine-sys/src/bindings64.rs b/constantine-rust/constantine-sys/src/bindings64.rs index 13e960d8..aac925e7 100644 --- a/constantine-rust/constantine-sys/src/bindings64.rs +++ b/constantine-rust/constantine-sys/src/bindings64.rs @@ -5010,8 +5010,8 @@ extern "C" { #[must_use] #[doc = " Compute a commitment to the `blob`.\n The commitment can be verified without needing the full `blob`\n\n Mathematical description\n commitment = [p(τ)]₁\n\n The blob data is used as a polynomial,\n the polynomial is evaluated at powers of tau τ, a trusted setup.\n\n Verification can be done by verifying the relation:\n proof.(τ - z) = p(τ)-p(z)\n which doesn't require the full blob but only evaluations of it\n - at τ, p(τ) is the commitment\n - and at the verification challenge z.\n\n with proof = [(p(τ) - p(z)) / (τ-z)]₁"] pub fn ctt_eth_kzg_blob_to_kzg_commitment_parallel( - ctx: *const ctt_eth_kzg_context, tp: *const ctt_threadpool, + ctx: *const ctt_eth_kzg_context, dst: *mut ctt_eth_kzg_commitment, blob: *const ctt_eth_kzg_blob, ) -> ctt_eth_kzg_status; @@ -5020,8 +5020,8 @@ extern "C" { #[must_use] #[doc = " Generate:\n - A proof of correct evaluation.\n - y = p(z), the evaluation of p at the challenge z, with p being the Blob interpreted as a polynomial.\n\n Mathematical description\n [proof]₁ = [(p(τ) - p(z)) / (τ-z)]₁, with p(τ) being the commitment, i.e. the evaluation of p at the powers of τ\n The notation [a]₁ corresponds to the scalar multiplication of a by the generator of 𝔾1\n\n Verification can be done by verifying the relation:\n proof.(τ - z) = p(τ)-p(z)\n which doesn't require the full blob but only evaluations of it\n - at τ, p(τ) is the commitment\n - and at the verification challenge z."] pub fn ctt_eth_kzg_compute_kzg_proof_parallel( - ctx: *const ctt_eth_kzg_context, tp: *const ctt_threadpool, + ctx: *const ctt_eth_kzg_context, proof: *mut ctt_eth_kzg_proof, y: *mut ctt_eth_kzg_eval_at_challenge, blob: *const ctt_eth_kzg_blob, @@ -5032,8 +5032,8 @@ extern "C" { #[must_use] #[doc = " Given a blob, return the KZG proof that is used to verify it against the commitment.\n This method does not verify that the commitment is correct with respect to `blob`."] pub fn ctt_eth_kzg_compute_blob_kzg_proof_parallel( - ctx: *const ctt_eth_kzg_context, tp: *const ctt_threadpool, + ctx: *const ctt_eth_kzg_context, proof: *mut ctt_eth_kzg_proof, blob: *const ctt_eth_kzg_blob, commitment: *const ctt_eth_kzg_commitment, @@ -5043,8 +5043,8 @@ extern "C" { #[must_use] #[doc = " Given a blob and a KZG proof, verify that the blob data corresponds to the provided commitment."] pub fn ctt_eth_kzg_verify_blob_kzg_proof_parallel( - ctx: *const ctt_eth_kzg_context, tp: *const ctt_threadpool, + ctx: *const ctt_eth_kzg_context, blob: *const ctt_eth_kzg_blob, commitment: *const ctt_eth_kzg_commitment, proof: *const ctt_eth_kzg_proof, @@ -5054,8 +5054,8 @@ extern "C" { #[must_use] #[doc = " Verify `n` (blob, commitment, proof) sets efficiently\n\n `n` is the number of verifications set\n - if n is negative, this procedure returns verification failure\n - if n is zero, this procedure returns verification success\n\n `secure_random_bytes` random bytes must come from a cryptographically secure RNG\n or computed through the Fiat-Shamir heuristic.\n It serves as a random number\n that is not in the control of a potential attacker to prevent potential\n rogue commitments attacks due to homomorphic properties of pairings,\n i.e. commitments that are linear combination of others and sum would be zero."] pub fn ctt_eth_kzg_verify_blob_kzg_proof_batch_parallel( - ctx: *const ctt_eth_kzg_context, tp: *const ctt_threadpool, + ctx: *const ctt_eth_kzg_context, blobs: *const ctt_eth_kzg_blob, commitments: *const ctt_eth_kzg_commitment, proofs: *const ctt_eth_kzg_proof, diff --git a/constantine/commitments/kzg_polynomial_commitments.nim b/constantine/commitments/kzg_polynomial_commitments.nim index 6df180c7..4642fb8e 100644 --- a/constantine/commitments/kzg_polynomial_commitments.nim +++ b/constantine/commitments/kzg_polynomial_commitments.nim @@ -174,22 +174,21 @@ import # as the powers of τ func kzg_commit*[N: static int, C: static Curve]( + powers_of_tau: PolynomialEval[N, ECP_ShortW_Aff[Fp[C], G1]], commitment: var ECP_ShortW_Aff[Fp[C], G1], - poly_evals: array[N, BigInt], - powers_of_tau: PolynomialEval[N, ECP_ShortW_Aff[Fp[C], G1]]) {.tags:[Alloca, HeapAlloc, Vartime].} = + poly_evals: array[N, BigInt]) {.tags:[Alloca, HeapAlloc, Vartime].} = var commitmentJac {.noInit.}: ECP_ShortW_Jac[Fp[C], G1] commitmentJac.multiScalarMul_vartime(poly_evals, powers_of_tau.evals) commitment.affine(commitmentJac) func kzg_prove*[N: static int, C: static Curve]( + powers_of_tau: PolynomialEval[N, ECP_ShortW_Aff[Fp[C], G1]], + domain: PolyEvalRootsDomain[N, Fr[C]], proof: var ECP_ShortW_Aff[Fp[C], G1], eval_at_challenge: var Fr[C], poly: PolynomialEval[N, Fr[C]], - domain: PolyEvalRootsDomain[N, Fr[C]], - challenge: Fr[C], - powers_of_tau: PolynomialEval[N, ECP_ShortW_Aff[Fp[C], G1]], - isBitReversedDomain: static bool) {.tags:[Alloca, HeapAlloc, Vartime].} = + challenge: Fr[C]) {.tags:[Alloca, HeapAlloc, Vartime].} = # Note: # The order of inputs in @@ -210,10 +209,10 @@ func kzg_prove*[N: static int, C: static Curve]( if zIndex == -1: # p(z) - eval_at_challenge.evalPolyOffDomainAt( + domain.evalPolyOffDomainAt( + eval_at_challenge, poly, challenge, - invRootsMinusZ[], - domain) + invRootsMinusZ[]) # q(x) = (p(x) - p(z)) / (x - z) diffQuotientPolyFr[].differenceQuotientEvalOffDomain( @@ -224,8 +223,9 @@ func kzg_prove*[N: static int, C: static Curve]( eval_at_challenge = poly.evals[zIndex] # q(x) = (p(x) - p(z)) / (x - z) - diffQuotientPolyFr[].differenceQuotientEvalInDomain( - poly, uint32 zIndex, invRootsMinusZ[], domain, isBitReversedDomain) + domain.differenceQuotientEvalInDomain( + diffQuotientPolyFr[], + poly, uint32 zIndex, invRootsMinusZ[]) freeHeapAligned(invRootsMinusZ) diff --git a/constantine/commitments/kzg_polynomial_commitments_parallel.nim b/constantine/commitments/kzg_polynomial_commitments_parallel.nim index 5b1f2768..fe6bf69b 100644 --- a/constantine/commitments/kzg_polynomial_commitments_parallel.nim +++ b/constantine/commitments/kzg_polynomial_commitments_parallel.nim @@ -31,9 +31,10 @@ export kzg_polynomial_commitments proc kzg_commit_parallel*[N: static int, C: static Curve]( tp: Threadpool, + powers_of_tau: PolynomialEval[N, ECP_ShortW_Aff[Fp[C], G1]], commitment: var ECP_ShortW_Aff[Fp[C], G1], poly_evals: array[N, BigInt], - powers_of_tau: PolynomialEval[N, ECP_ShortW_Aff[Fp[C], G1]]) = +) = ## KZG Commit to a polynomial in Lagrange / Evaluation form ## Parallelism: This only returns when computation is fully done var commitmentJac {.noInit.}: ECP_ShortW_Jac[Fp[C], G1] @@ -42,13 +43,12 @@ proc kzg_commit_parallel*[N: static int, C: static Curve]( proc kzg_prove_parallel*[N: static int, C: static Curve]( tp: Threadpool, + powers_of_tau: PolynomialEval[N, ECP_ShortW_Aff[Fp[C], G1]], + domain: ptr PolyEvalRootsDomain[N, Fr[C]], proof: var ECP_ShortW_Aff[Fp[C], G1], eval_at_challenge: var Fr[C], poly: ptr PolynomialEval[N, Fr[C]], - domain: ptr PolyEvalRootsDomain[N, Fr[C]], - challenge: ptr Fr[C], - powers_of_tau: PolynomialEval[N, ECP_ShortW_Aff[Fp[C], G1]], - isBitReversedDomain: static bool) = + challenge: ptr Fr[C]) = ## KZG prove commitment to a polynomial in Lagrange / Evaluation form ## ## Outputs: @@ -76,10 +76,10 @@ proc kzg_prove_parallel*[N: static int, C: static Curve]( if zIndex == -1: # p(z) tp.evalPolyOffDomainAt_parallel( + domain, eval_at_challenge, poly, challenge, - invRootsMinusZ, - domain) + invRootsMinusZ) # q(x) = (p(x) - p(z)) / (x - z) tp.differenceQuotientEvalOffDomain_parallel( @@ -92,8 +92,9 @@ proc kzg_prove_parallel*[N: static int, C: static Curve]( # q(x) = (p(x) - p(z)) / (x - z) tp.differenceQuotientEvalInDomain_parallel( + domain, diffQuotientPolyFr, - poly, uint32 zIndex, invRootsMinusZ, domain, isBitReversedDomain) + poly, uint32 zIndex, invRootsMinusZ) freeHeapAligned(invRootsMinusZ) diff --git a/constantine/commitments_setups/ethereum_kzg_srs.nim b/constantine/commitments_setups/ethereum_kzg_srs.nim index 7f1b25f6..2c9cbe6f 100644 --- a/constantine/commitments_setups/ethereum_kzg_srs.nim +++ b/constantine/commitments_setups/ethereum_kzg_srs.nim @@ -268,6 +268,7 @@ proc load_ckzg4844(ctx: ptr EthereumKZGContext, f: File): TrustedSetupStatus = # Bit-reversal permutations ctx.srs_lagrange_g1.evals.bit_reversal_permutation() ctx.domain.rootsOfUnity.bit_reversal_permutation() + ctx.domain.isBitReversed = true return tsSuccess diff --git a/constantine/eth_verkle_ipa/ipa_prover.nim b/constantine/eth_verkle_ipa/ipa_prover.nim index e89242ec..38895584 100644 --- a/constantine/eth_verkle_ipa/ipa_prover.nim +++ b/constantine/eth_verkle_ipa/ipa_prover.nim @@ -145,7 +145,7 @@ func createIPAProof*[IPAProof]( transcript.domain_separator(asBytes"ipa") var b: array[EthVerkleDomain, Fr[Banderwagon]] - b.getLagrangeBasisPolysAt(ic.domain, evalPoint) + ic.domain.getLagrangeBasisPolysAt(b, evalPoint) var innerProd {.noInit.}: Fr[Banderwagon] innerProd.computeInnerProducts(a, b) diff --git a/constantine/eth_verkle_ipa/ipa_verifier.nim b/constantine/eth_verkle_ipa/ipa_verifier.nim index 73501d5c..506c6fd8 100644 --- a/constantine/eth_verkle_ipa/ipa_verifier.nim +++ b/constantine/eth_verkle_ipa/ipa_verifier.nim @@ -45,7 +45,7 @@ func checkIPAProof* (ic: IPASettings, transcript: var CryptoHash, got: var EC_P, var b {.noInit.}: array[EthVerkleDomain, Fr[Banderwagon]] # b.computeBarycentricCoefficients(ic.precompWeights,evalPoint) - b.getLagrangeBasisPolysAt(ic.domain, evalPoint) + ic.domain.getLagrangeBasisPolysAt(b, evalPoint) transcript.pointAppend(asBytes"C", commitment) transcript.scalarAppend(asBytes"input point", evalPoint.toBig()) diff --git a/constantine/eth_verkle_ipa/multiproof.nim b/constantine/eth_verkle_ipa/multiproof.nim index c5f841ee..6e878bd6 100644 --- a/constantine/eth_verkle_ipa/multiproof.nim +++ b/constantine/eth_verkle_ipa/multiproof.nim @@ -115,7 +115,7 @@ func createMultiProof* [MultiProof] (res: var MultiProof, transcript: var Crypto continue var quotient {.noInit.}: PolynomialEval[EthVerkleDomain, Fr[Banderwagon]] - quotient.differenceQuotientEvalInDomain(groupedFs[i], i, ipaSetting.domain) + ipaSetting.domain.differenceQuotientEvalInDomain(quotient, groupedFs[i], i) for j in 0 ..< EthVerkleDomain: gx[j] += quotient.evals[j] diff --git a/constantine/ethereum_eip4844_kzg.nim b/constantine/ethereum_eip4844_kzg.nim index 53964ba0..83342f95 100644 --- a/constantine/ethereum_eip4844_kzg.nim +++ b/constantine/ethereum_eip4844_kzg.nim @@ -294,7 +294,7 @@ func blob_to_kzg_commitment*( check HappyPath, poly.blob_to_bigint_polynomial(blob) var r {.noinit.}: ECP_ShortW_Aff[Fp[BLS12_381], G1] - kzg_commit(r, poly.evals, ctx.srs_lagrange_g1) + kzg_commit(ctx.srs_lagrange_g1, r, poly.evals) discard dst.serialize_g1_compressed(r) result = cttEthKzg_Success @@ -337,10 +337,11 @@ func compute_kzg_proof*( var proof {.noInit.}: ECP_ShortW_Aff[Fp[BLS12_381], G1] # [proof]₁ = [(p(τ) - p(z)) / (τ-z)]₁ kzg_prove( + ctx.srs_lagrange_g1, + ctx.domain, proof, y, - poly[], ctx.domain, - z, ctx.srs_lagrange_g1, - isBitReversedDomain = true) + poly[], + z) discard proof_bytes.serialize_g1_compressed(proof) # cannot fail y_bytes.marshal(y, bigEndian) # cannot fail @@ -405,10 +406,11 @@ func compute_blob_kzg_proof*( var proof {.noInit.}: ECP_ShortW_Aff[Fp[BLS12_381], G1] # [proof]₁ = [(p(τ) - p(z)) / (τ-z)]₁ kzg_prove( + ctx.srs_lagrange_g1, + ctx.domain, proof, y, - poly[], ctx.domain, - challenge, ctx.srs_lagrange_g1, - isBitReversedDomain = true) + poly[], + challenge) discard proof_bytes.serialize_g1_compressed(proof) # cannot fail @@ -456,10 +458,10 @@ func verify_blob_kzg_proof*( # 2. Actual evaluation if zIndex == -1: var eval_at_challenge_fr{.noInit.}: Fr[BLS12_381] - eval_at_challenge_fr.evalPolyOffDomainAt( + ctx.domain.evalPolyOffDomainAt( + eval_at_challenge_fr, poly[], challengeFr, - invRootsMinusZ[], - ctx.domain) + invRootsMinusZ[]) eval_at_challenge.fromField(eval_at_challenge_fr) else: eval_at_challenge.fromField(poly.evals[zIndex]) @@ -528,10 +530,10 @@ func verify_blob_kzg_proof_batch*( # 2. Actual evaluation if zIndex == -1: var eval_at_challenge_fr{.noInit.}: Fr[BLS12_381] - eval_at_challenge_fr.evalPolyOffDomainAt( + ctx.domain.evalPolyOffDomainAt( + eval_at_challenge_fr, poly[], challenges[i], - invRootsMinusZ[], - ctx.domain) + invRootsMinusZ[]) evals_at_challenges[i].fromField(eval_at_challenge_fr) else: evals_at_challenges[i].fromField(poly.evals[zIndex]) diff --git a/constantine/ethereum_eip4844_kzg_parallel.nim b/constantine/ethereum_eip4844_kzg_parallel.nim index e3aad857..c1dec0df 100644 --- a/constantine/ethereum_eip4844_kzg_parallel.nim +++ b/constantine/ethereum_eip4844_kzg_parallel.nim @@ -123,8 +123,8 @@ func kzgifyStatus(status: CttCodecScalarStatus or CttCodecEccStatus): cttEthKzgS checkReturn status proc blob_to_kzg_commitment_parallel*( - ctx: ptr EthereumKZGContext, tp: Threadpool, + ctx: ptr EthereumKZGContext, dst: var array[48, byte], blob: ptr Blob): cttEthKzgStatus {.libPrefix: prefix_eth_kzg4844.} = ## Compute a commitment to the `blob`. @@ -150,7 +150,7 @@ proc blob_to_kzg_commitment_parallel*( check HappyPath, tp.blob_to_bigint_polynomial_parallel(poly, blob) var r {.noinit.}: ECP_ShortW_Aff[Fp[BLS12_381], G1] - tp.kzg_commit_parallel(r, poly.evals, ctx.srs_lagrange_g1) + tp.kzg_commit_parallel(ctx.srs_lagrange_g1, r, poly.evals) discard dst.serialize_g1_compressed(r) result = cttEthKzg_Success @@ -159,8 +159,8 @@ proc blob_to_kzg_commitment_parallel*( return result proc compute_kzg_proof_parallel*( - ctx: ptr EthereumKZGContext, tp: Threadpool, + ctx: ptr EthereumKZGContext, proof_bytes: var array[48, byte], y_bytes: var array[32, byte], blob: ptr Blob, @@ -194,10 +194,11 @@ proc compute_kzg_proof_parallel*( var proof {.noInit.}: ECP_ShortW_Aff[Fp[BLS12_381], G1] # [proof]₁ = [(p(τ) - p(z)) / (τ-z)]₁ tp.kzg_prove_parallel( + ctx.srs_lagrange_g1, + ctx.domain.addr, proof, y, - poly, ctx.domain.addr, - z.addr, ctx.srs_lagrange_g1, - isBitReversedDomain = true) + poly, + z.addr) discard proof_bytes.serialize_g1_compressed(proof) # cannot fail y_bytes.marshal(y, bigEndian) # cannot fail @@ -207,8 +208,8 @@ proc compute_kzg_proof_parallel*( return result proc compute_blob_kzg_proof_parallel*( - ctx: ptr EthereumKZGContext, tp: Threadpool, + ctx: ptr EthereumKZGContext, proof_bytes: var array[48, byte], blob: ptr Blob, commitment_bytes: array[48, byte]): cttEthKzgStatus {.libPrefix: prefix_eth_kzg4844.} = @@ -237,10 +238,11 @@ proc compute_blob_kzg_proof_parallel*( var proof {.noInit.}: ECP_ShortW_Aff[Fp[BLS12_381], G1] # [proof]₁ = [(p(τ) - p(z)) / (τ-z)]₁ tp.kzg_prove_parallel( + ctx.srs_lagrange_g1, + ctx.domain.addr, proof, y, - poly, ctx.domain.addr, - challenge.addr, ctx.srs_lagrange_g1, - isBitReversedDomain = true) + poly, + challenge.addr) discard proof_bytes.serialize_g1_compressed(proof) # cannot fail @@ -250,8 +252,8 @@ proc compute_blob_kzg_proof_parallel*( return result proc verify_blob_kzg_proof_parallel*( - ctx: ptr EthereumKZGContext, tp: Threadpool, + ctx: ptr EthereumKZGContext, blob: ptr Blob, commitment_bytes: array[48, byte], proof_bytes: array[48, byte]): cttEthKzgStatus {.libPrefix: prefix_eth_kzg4844.} = @@ -293,10 +295,10 @@ proc verify_blob_kzg_proof_parallel*( if zIndex == -1: var eval_at_challenge_fr{.noInit.}: Fr[BLS12_381] tp.evalPolyOffDomainAt_parallel( + ctx.domain.addr, eval_at_challenge_fr, poly, challengeFr.addr, - invRootsMinusZ, - ctx.domain.addr) + invRootsMinusZ) eval_at_challenge.fromField(eval_at_challenge_fr) else: eval_at_challenge.fromField(poly.evals[zIndex]) @@ -316,8 +318,8 @@ proc verify_blob_kzg_proof_parallel*( return result proc verify_blob_kzg_proof_batch_parallel*( - ctx: ptr EthereumKZGContext, tp: Threadpool, + ctx: ptr EthereumKZGContext, blobs: ptr UncheckedArray[Blob], commitments_bytes: ptr UncheckedArray[array[48, byte]], proof_bytes: ptr UncheckedArray[array[48, byte]], @@ -386,10 +388,10 @@ proc verify_blob_kzg_proof_batch_parallel*( if zIndex == -1: var eval_at_challenge_fr{.noInit.}: Fr[BLS12_381] tp.evalPolyOffDomainAt_parallel( + ctx.domain.addr, eval_at_challenge_fr, polys[i].addr, challenges[i].addr, - invRootsMinusZs[i].addr, - ctx.domain.addr) + invRootsMinusZs[i].addr) evals_at_challenges[i].fromField(eval_at_challenge_fr) else: evals_at_challenges[i].fromField(polys[i].evals[zIndex]) diff --git a/constantine/math/polynomials/polynomials.nim b/constantine/math/polynomials/polynomials.nim index 219e648a..22586e72 100644 --- a/constantine/math/polynomials/polynomials.nim +++ b/constantine/math/polynomials/polynomials.nim @@ -56,6 +56,7 @@ type ## This translates into rootsOfUnity[brp((N-brp(i)) and (N-1))] when bit-reversal permuted rootsOfUnity*{.align: 64.}: array[N, Field] invMaxDegree*: Field + isBitReversed*: bool PolyEvalDomain*[N: static int, Field] = object ## Metadata for polynomial in Lagrange basis (evaluation form) @@ -238,11 +239,11 @@ func differenceQuotientEvalOffDomain*[N: static int, Field]( # ------------------------------------------------------ func evalPolyOffDomainAt*[N: static int, Field]( + domain: PolyEvalRootsDomain[N, Field], r: var Field, poly: PolynomialEval[N, Field], z: Field, - invRootsMinusZ: array[N, Field], - domain: PolyEvalRootsDomain[N, Field]) = + invRootsMinusZ: array[N, Field]) = ## Evaluate a polynomial in evaluation form ## at the point z ## z MUST NOT be one of the roots of unity @@ -266,12 +267,11 @@ func evalPolyOffDomainAt*[N: static int, Field]( r *= domain.invMaxDegree func differenceQuotientEvalInDomain*[N: static int, Field]( + domain: PolyEvalRootsDomain[N, Field], r: var PolynomialEval[N, Field], poly: PolynomialEval[N, Field], zIndex: uint32, - invRootsMinusZ: array[N, Field], - domain: PolyEvalRootsDomain[N, Field], - isBitReversedDomain: static bool) = + invRootsMinusZ: array[N, Field]) = ## Compute r(x) = (p(x) - p(z)) / (x - z) ## ## for z = ωⁱ a power of a root of unity @@ -307,7 +307,7 @@ func differenceQuotientEvalInDomain*[N: static int, Field]( # Compute contribution of qᵢ to qz which can't be computed directly # qz = - ∑ q'ᵢ * ωⁱ/z var ri {.noinit.}: Field - when isBitReversedDomain: + if domain.isBitReversed: const logN = log2_vartime(uint32 N) let invZidx = N - reverseBits(uint32 zIndex, logN) let canonI = reverseBits(i, logN) @@ -397,9 +397,9 @@ func evalVanishingPolyDerivativeAtRoot*[N: static int, Field]( r *= t func evalPolyAt*[N: static int, Field]( + domain: PolyEvalDomain[N, Field], r: var Field, poly: PolynomialEval[N, Field], - domain: PolyEvalDomain[N, Field], z: Field) = ## Evaluate a polynomial p at z: r <- p(z) ## @@ -446,8 +446,8 @@ func evalPolyAt*[N: static int, Field]( freeHeapAligned(invZminusDomain) func getLagrangeBasisPolysAt*[N: static int, Field]( - lagrangePolys: var array[N, Field], domain: PolyEvalDomain[N, Field], + lagrangePolys: var array[N, Field], z: Field) = ## A polynomial p(X) in evaluation form ## is represented by its evaluations @@ -512,23 +512,23 @@ func getLagrangeBasisPolysAt*[N: static int, Field]( # ------------------------------------------------------ func evalPolyAt*[N: static int, Field]( + lindom: PolyEvalLinearDomain[N, Field], r: var Field, poly: PolynomialEval[N, Field], - lindom: PolyEvalLinearDomain[N, Field], z: Field) = - r.evalPolyAt(poly, lindom.dom, z) + lindom.dom.evalPolyAt(r, poly, z) func getLagrangeBasisPolysAt*[N: static int, Field]( - lagrangePolys: var array[N, Field], lindom: PolyEvalLinearDomain[N, Field], + lagrangePolys: var array[N, Field], z: Field) = - lagrangePolys.getLagrangeBasisPolysAt(lindom.dom, z) + lindom.dom.getLagrangeBasisPolysAt(lagrangePolys, z) func differenceQuotientEvalInDomain*[N: static int, Field]( + lindom: PolyEvalLinearDomain[N, Field], r: var PolynomialEval[N, Field], poly: PolynomialEval[N, Field], - zIndex: uint32, - lindom: PolyEvalLinearDomain[N, Field]) = + zIndex: uint32) = ## Compute r(x) = (p(x) - p(z)) / (x - z) ## ## for z = xᵢ, one of the element in the domain. diff --git a/constantine/math/polynomials/polynomials_parallel.nim b/constantine/math/polynomials/polynomials_parallel.nim index ebbaf3fd..a3cdc6d7 100644 --- a/constantine/math/polynomials/polynomials_parallel.nim +++ b/constantine/math/polynomials/polynomials_parallel.nim @@ -24,11 +24,11 @@ import proc evalPolyOffDomainAt_parallel*[N: static int, Field]( tp: Threadpool, + domain: ptr PolyEvalRootsDomain[N, Field], r: var Field, poly: ptr PolynomialEval[N, Field], z: ptr Field, - invRootsMinusZ: ptr array[N, Field], - domain: ptr PolyEvalRootsDomain[N, Field]) = + invRootsMinusZ: ptr array[N, Field]) = ## Evaluate a polynomial in evaluation form ## at the point z ## z MUST NOT be one of the roots of unity @@ -96,12 +96,11 @@ proc differenceQuotientEvalOffDomain_parallel*[N: static int, Field]( proc differenceQuotientEvalInDomain_parallel*[N: static int, Field]( tp: Threadpool, + domain: ptr PolyEvalRootsDomain[N, Field], r: ptr PolynomialEval[N, Field], poly: ptr PolynomialEval[N, Field], zIndex: uint32, - invRootsMinusZ: ptr array[N, Field], - domain: ptr PolyEvalRootsDomain[N, Field], - isBitReversedDomain: static bool) = + invRootsMinusZ: ptr array[N, Field]) = ## Compute r(x) = (p(x) - p(z)) / (x - z) ## ## for z = ωⁱ a power of a root of unity @@ -139,14 +138,14 @@ proc differenceQuotientEvalInDomain_parallel*[N: static int, Field]( # q'ᵢ = -qᵢ * ωⁱ/z # q'idx = ∑ q'ᵢ iter_ri.neg(r.evals[i]) # -qᵢ - when isBitReversedDomain: + if domain.isBitReversed: const logN = log2_vartime(uint32 N) let invZidx = N - reverseBits(uint32 zIndex, logN) let canonI = reverseBits(uint32 i, logN) let idx = reverseBits((canonI + invZidx) and (N-1), logN) iter_ri *= domain.rootsOfUnity[idx] # -qᵢ * ωⁱ/z (explanation at the bottom of serial impl) else: - iter_ri *= domain.rootsOfUnity[(i+N-zIndex) and (N-1)] # -qᵢ * ωⁱ/z (explanation at the bottom of serial impl) + iter_ri *= domain.rootsOfUnity[(i+N-int(zIndex)) and (N-1)] # -qᵢ * ωⁱ/z (explanation at the bottom of serial impl) worker_ri += iter_ri merge(remote_ri: Flowvar[Field]): worker_ri += sync(remote_ri) diff --git a/include/constantine/protocols/ethereum_eip4844_kzg_parallel.h b/include/constantine/protocols/ethereum_eip4844_kzg_parallel.h index 57585142..347ecb94 100644 --- a/include/constantine/protocols/ethereum_eip4844_kzg_parallel.h +++ b/include/constantine/protocols/ethereum_eip4844_kzg_parallel.h @@ -38,8 +38,8 @@ extern "C" { * with proof = [(p(τ) - p(z)) / (τ-z)]₁ */ ctt_eth_kzg_status ctt_eth_kzg_blob_to_kzg_commitment_parallel( - const ctt_eth_kzg_context* ctx, const ctt_threadpool* tp, + const ctt_eth_kzg_context* ctx, ctt_eth_kzg_commitment* dst, const ctt_eth_kzg_blob* blob ) __attribute__((warn_unused_result)); @@ -59,8 +59,8 @@ ctt_eth_kzg_status ctt_eth_kzg_blob_to_kzg_commitment_parallel( * - and at the verification challenge z. */ ctt_eth_kzg_status ctt_eth_kzg_compute_kzg_proof_parallel( - const ctt_eth_kzg_context* ctx, const ctt_threadpool* tp, + const ctt_eth_kzg_context* ctx, ctt_eth_kzg_proof* proof, ctt_eth_kzg_eval_at_challenge* y, const ctt_eth_kzg_blob* blob, @@ -71,8 +71,8 @@ ctt_eth_kzg_status ctt_eth_kzg_compute_kzg_proof_parallel( * This method does not verify that the commitment is correct with respect to `blob`. */ ctt_eth_kzg_status ctt_eth_kzg_compute_blob_kzg_proof_parallel( - const ctt_eth_kzg_context* ctx, const ctt_threadpool* tp, + const ctt_eth_kzg_context* ctx, ctt_eth_kzg_proof* proof, const ctt_eth_kzg_blob* blob, const ctt_eth_kzg_commitment* commitment @@ -81,8 +81,8 @@ ctt_eth_kzg_status ctt_eth_kzg_compute_blob_kzg_proof_parallel( /** Given a blob and a KZG proof, verify that the blob data corresponds to the provided commitment. */ ctt_eth_kzg_status ctt_eth_kzg_verify_blob_kzg_proof_parallel( - const ctt_eth_kzg_context* ctx, const ctt_threadpool* tp, + const ctt_eth_kzg_context* ctx, const ctt_eth_kzg_blob* blob, const ctt_eth_kzg_commitment* commitment, const ctt_eth_kzg_proof* proof @@ -102,8 +102,8 @@ ctt_eth_kzg_status ctt_eth_kzg_verify_blob_kzg_proof_parallel( * i.e. commitments that are linear combination of others and sum would be zero. */ ctt_eth_kzg_status ctt_eth_kzg_verify_blob_kzg_proof_batch_parallel( - const ctt_eth_kzg_context* ctx, const ctt_threadpool* tp, + const ctt_eth_kzg_context* ctx, const ctt_eth_kzg_blob blobs[], const ctt_eth_kzg_commitment commitments[], const ctt_eth_kzg_proof proofs[], diff --git a/tests/t_ethereum_eip4844_deneb_kzg_parallel.nim b/tests/t_ethereum_eip4844_deneb_kzg_parallel.nim index 258c9cdf..2c3541e2 100644 --- a/tests/t_ethereum_eip4844_deneb_kzg_parallel.nim +++ b/tests/t_ethereum_eip4844_deneb_kzg_parallel.nim @@ -139,7 +139,7 @@ testGen(blob_to_kzg_commitment, testVector): var commitment: array[48, byte] - let status = ctx.blob_to_kzg_commitment_parallel(tp, commitment, blob[].addr) + let status = tp.blob_to_kzg_commitment_parallel(ctx, commitment, blob[].addr) stdout.write "[" & $status & "]\n" if status == cttEthKzg_Success: @@ -157,7 +157,7 @@ testGen(compute_kzg_proof, testVector): var proof: array[48, byte] var y: array[32, byte] - let status = ctx.compute_kzg_proof_parallel(tp, proof, y, blob[].addr, z[]) + let status = tp.compute_kzg_proof_parallel(ctx, proof, y, blob[].addr, z[]) stdout.write "[" & $status & "]\n" if status == cttEthKzg_Success: @@ -195,7 +195,7 @@ testGen(compute_blob_kzg_proof, testVector): var proof: array[48, byte] - let status = ctx.compute_blob_kzg_proof_parallel(tp, proof, blob[].addr, commitment[]) + let status = tp.compute_blob_kzg_proof_parallel(ctx, proof, blob[].addr, commitment[]) stdout.write "[" & $status & "]\n" if status == cttEthKzg_Success: @@ -212,7 +212,7 @@ testGen(verify_blob_kzg_proof, testVector): parseAssign(commitment, 48, testVector["input"]["commitment"].content) parseAssign(proof, 48, testVector["input"]["proof"].content) - let status = ctx.verify_blob_kzg_proof_parallel(tp, blob[].addr, commitment[], proof[]) + let status = tp.verify_blob_kzg_proof_parallel(ctx, blob[].addr, commitment[], proof[]) stdout.write "[" & $status & "]\n" if status == cttEthKzg_Success: @@ -246,8 +246,8 @@ testGen(verify_blob_kzg_proof_batch, testVector): else: nil - let status = ctx.verify_blob_kzg_proof_batch_parallel( - tp, + let status = tp.verify_blob_kzg_proof_batch_parallel( + ctx, blobs.asUnchecked(), commitments.asUnchecked(), proofs.asUnchecked(), diff --git a/tests/t_ethereum_verkle_ipa_primitives.nim b/tests/t_ethereum_verkle_ipa_primitives.nim index 1b03c70f..56ec2291 100644 --- a/tests/t_ethereum_verkle_ipa_primitives.nim +++ b/tests/t_ethereum_verkle_ipa_primitives.nim @@ -100,13 +100,13 @@ suite "Barycentric Form Tests": lindom.setupLinearEvaluationDomain() var bar_coeffs {.noInit.}: array[256, Fr[Banderwagon]] - bar_coeffs.getLagrangeBasisPolysAt(lindom, p_outside_dom) + lindom.getLagrangeBasisPolysAt(bar_coeffs, p_outside_dom) var expected0: Fr[Banderwagon] expected0.computeInnerProducts(lagrange_values.evals, bar_coeffs) var expected1: Fr[Banderwagon] - expected1.evalPolyAt(lagrange_values, lindom, p_outside_dom) + lindom.evalPolyAt(expected1, lagrange_values, p_outside_dom) # testing with a no-precompute optimized Lagrange Interpolation value from Go-IPA doAssert expected0.toHex(littleEndian) == "0x50b9c3b3c42a06347e58d8d33047a7f8868965703567100657aceaf429562d04", "Barycentric Precompute and Lagrange should NOT give different values" @@ -151,7 +151,7 @@ suite "Barycentric Form Tests": evaluations.evals[i] = points[i].y var quotient: PolynomialEval[EthVerkleDomain, Fr[Banderwagon]] - quotient.differenceQuotientEvalInDomain(evaluations, zIndex = 1, lindom) + lindom.differenceQuotientEvalInDomain(quotient, evaluations, zIndex = 1) doAssert quotient.evals[255].toHex(littleEndian) == "0x616b0e203a877177e2090013a77ce4ea8726941aac613b532002f3653d54250b", "Issue with Divide on Domain using Barycentric Precomputes!" @@ -499,7 +499,7 @@ suite "IPA proof tests": doAssert stat11 == true, "Problem creating IPA proof 1" var lagrange_coeffs: array[256, Fr[Banderwagon]] - lagrange_coeffs.getLagrangeBasisPolysAt(ipaConfig.domain, point) + ipaConfig.domain.getLagrangeBasisPolysAt(lagrange_coeffs, point) var op_point: Fr[Banderwagon] op_point.computeInnerProducts(lagrange_coeffs, poly) @@ -585,7 +585,7 @@ suite "IPA proof tests": doAssert stat == true, "Problem creating IPA proof" var lagrange_coeffs : array[EthVerkleDomain, Fr[Banderwagon]] - lagrange_coeffs.getLagrangeBasisPolysAt(ipaConfig.domain, point) + ipaConfig.domain.getLagrangeBasisPolysAt(lagrange_coeffs, point) var innerProd : Fr[Banderwagon] innerProd.computeInnerProducts(poly, lagrange_coeffs)