From 38d98d2989c47388366ec136b34355e860503d21 Mon Sep 17 00:00:00 2001 From: rodiazet <radek.zagorowicz@gmail.com> Date: Wed, 25 Sep 2024 17:38:09 +0200 Subject: [PATCH] Use `evmone::crypto::kzg_verify_proof` instead of `silkworm::verify_kzg_proof` --- silkworm/core/crypto/kzg.cpp | 277 ------------------------- silkworm/core/crypto/kzg.hpp | 49 ----- silkworm/core/execution/precompile.cpp | 13 +- third_party/evmone/CMakeLists.txt | 3 +- 4 files changed, 9 insertions(+), 333 deletions(-) delete mode 100644 silkworm/core/crypto/kzg.cpp delete mode 100644 silkworm/core/crypto/kzg.hpp diff --git a/silkworm/core/crypto/kzg.cpp b/silkworm/core/crypto/kzg.cpp deleted file mode 100644 index f894449384..0000000000 --- a/silkworm/core/crypto/kzg.cpp +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright 2021 Benjamin Edgington - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "kzg.hpp" - -#include <blst.h> - -#include <evmone_precompiles/sha256.hpp> - -#include <silkworm/core/protocol/param.hpp> - -// Based on https://github.com/ethereum/c-kzg-4844/blob/main/src/c_kzg_4844.c -// and modified for Silkworm. - -namespace silkworm { - -/////////////////////////////////////////////////////////////////////////////// -// Types -/////////////////////////////////////////////////////////////////////////////// - -using G1 = blst_p1; -using G2 = blst_p2; -using Fr = blst_fr; - -/////////////////////////////////////////////////////////////////////////////// -// Constants -/////////////////////////////////////////////////////////////////////////////// - -// KZG_SETUP_G2[1] printed by cmd/dev/kzg_g2_uncompress -// See https://github.com/ethereum/consensus-specs/blob/dev/presets/mainnet/trusted_setups/trusted_setup_4096.json -const G2 kKzgSetupG2{ - {{{0x6120a2099b0379f9, 0xa2df815cb8210e4e, 0xcb57be5577bd3d4f, - 0x62da0ea89a0c93f8, 0x02e0ee16968e150d, 0x171f09aea833acd5}, - {0x11a3670749dfd455, 0x04991d7b3abffadc, 0x85446a8e14437f41, - 0x27174e7b4e76e3f2, 0x7bfa6dd397f60a20, 0x02fcc329ac07080f}}}, - {{{0xaa130838793b2317, 0xe236dd220f891637, 0x6502782925760980, - 0xd05c25f60557ec89, 0x6095767a44064474, 0x185693917080d405}, - {0x549f9e175b03dc0a, 0x32c0c95a77106cfe, 0x64a74eae5705d080, - 0x53deeaf56659ed9e, 0x09a1d368508afb93, 0x12cf3a4525b5e9bd}}}, - {{{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, - 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493}, - {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}}}; - -/////////////////////////////////////////////////////////////////////////////// -// Helper Functions -/////////////////////////////////////////////////////////////////////////////// - -Hash kzg_to_versioned_hash(ByteView kzg) { - Hash hash; - evmone::crypto::sha256(reinterpret_cast<std::byte*>(hash.bytes), - reinterpret_cast<const std::byte*>(kzg.data()), kzg.length()); - hash.bytes[0] = protocol::kBlobCommitmentVersionKzg; - return hash; -} - -/** - * Multiply a G1 group element by a field element. - * - * @param[out] out @p a * @p b - * @param[in] a The G1 group element - * @param[in] b The multiplier - */ -static void g1_mul(G1* out, const G1* a, const Fr* b) { - blst_scalar s; - blst_scalar_from_fr(&s, b); - /* The last argument is the number of bits in the scalar */ - blst_p1_mult(out, a, s.b, 8 * sizeof(blst_scalar)); -} - -/** - * Multiply a G2 group element by a field element. - * - * @param[out] out @p a * @p b - * @param[in] a The G2 group element - * @param[in] b The multiplier - */ -static void g2_mul(G2* out, const G2* a, const Fr* b) { - blst_scalar s; - blst_scalar_from_fr(&s, b); - /* The last argument is the number of bits in the scalar */ - blst_p2_mult(out, a, s.b, 8 * sizeof(blst_scalar)); -} - -/** - * Subtraction of G1 group elements. - * - * @param[out] out @p a - @p b - * @param[in] a A G1 group element - * @param[in] b The G1 group element to be subtracted - */ -static void g1_sub(G1* out, const G1* a, const G1* b) { - G1 bneg = *b; - blst_p1_cneg(&bneg, true); - blst_p1_add_or_double(out, a, &bneg); -} - -/** - * Subtraction of G2 group elements. - * - * @param[out] out @p a - @p b - * @param[in] a A G2 group element - * @param[in] b The G2 group element to be subtracted - */ -static void g2_sub(G2* out, const G2* a, const G2* b) { - G2 bneg = *b; - blst_p2_cneg(&bneg, true); - blst_p2_add_or_double(out, a, &bneg); -} - -/** - * Perform pairings and test whether the outcomes are equal in G_T. - * - * Tests whether `e(a1, a2) == e(b1, b2)`. - * - * @param[in] a1 A G1 group point for the first pairing - * @param[in] a2 A G2 group point for the first pairing - * @param[in] b1 A G1 group point for the second pairing - * @param[in] b2 A G2 group point for the second pairing - * - * @retval true The pairings were equal - * @retval false The pairings were not equal - */ -static bool pairings_verify( - const G1* a1, const G2* a2, const G1* b1, const G2* b2) { - blst_fp12 loop0, loop1, gt_point; - blst_p1_affine aa1, bb1; - blst_p2_affine aa2, bb2; - - /* - * As an optimisation, we want to invert one of the pairings, - * so we negate one of the points. - */ - G1 a1neg = *a1; - blst_p1_cneg(&a1neg, true); - - 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(>_point, &loop0, &loop1); - blst_final_exp(>_point, >_point); - - return blst_fp12_is_one(>_point); -} - -/////////////////////////////////////////////////////////////////////////////// -// BLS12-381 Helper Functions -/////////////////////////////////////////////////////////////////////////////// - -/** - * Convert untrusted bytes to a trusted and validated BLS scalar field - * element. - * - * @param[out] out The field element to store the deserialized data - * @param[in] b A 32-byte array containing the serialized field element - */ -static bool bytes_to_bls_field(Fr* out, std::span<const uint8_t, 32> b) { - blst_scalar tmp; - blst_scalar_from_bendian(&tmp, b.data()); - if (!blst_scalar_fr_check(&tmp)) { - return false; - } - blst_fr_from_scalar(out, &tmp); - return true; -} - -/** - * Perform BLS validation required by the types KZGProof and KZGCommitment. - * - * @remark This function deviates from the spec because it returns (via an - * output argument) the g1 point. This way is more efficient (faster) - * but the function name is a bit misleading. - * - * @param[out] out The output g1 point - * @param[in] b The proof/commitment bytes - */ -static bool validate_kzg_g1(G1* out, std::span<const uint8_t, 48> b) { - blst_p1_affine p1_affine; - - /* Convert the bytes to a p1 point */ - /* The uncompress routine checks that the point is on the curve */ - if (blst_p1_uncompress(&p1_affine, b.data()) != BLST_SUCCESS) { - return false; - } - blst_p1_from_affine(out, &p1_affine); - - /* The point at infinity is accepted! */ - if (blst_p1_is_inf(out)) { - return true; - } - - /* The point must be on the right subgroup */ - return blst_p1_in_g1(out); -} - -/////////////////////////////////////////////////////////////////////////////// -// KZG Functions -/////////////////////////////////////////////////////////////////////////////// - -/** - * Helper function: Verify KZG proof claiming that `p(z) == y`. - * - * Given a @p commitment to a polynomial, a @p proof for @p z, and the - * claimed value @p y at @p z, verify the claim. - * - * @param[in] commitment The commitment to a polynomial - * @param[in] z The point at which the proof is to be checked - * (opened) - * @param[in] y The claimed value of the polynomial at @p z - * @param[in] proof A proof of the value of the polynomial at the - * point @p z - * @return `true` if the proof is valid, `false` if not - */ -static bool verify_kzg_proof_impl( - const G1* commitment, - const Fr* z, - const Fr* y, - const G1* proof) { - G2 x_g2, X_minus_z; - G1 y_g1, P_minus_y; - - /* Calculate: X_minus_z */ - g2_mul(&x_g2, blst_p2_generator(), z); - g2_sub(&X_minus_z, &kKzgSetupG2, &x_g2); - - /* Calculate: P_minus_y */ - g1_mul(&y_g1, blst_p1_generator(), y); - g1_sub(&P_minus_y, commitment, &y_g1); - - /* Verify: P - y = Q * (X - z) */ - return pairings_verify(&P_minus_y, blst_p2_generator(), proof, &X_minus_z); -} - -bool verify_kzg_proof( - std::span<const uint8_t, 48> commitment, - std::span<const uint8_t, 32> z, - std::span<const uint8_t, 32> y, - std::span<const uint8_t, 48> proof) { - Fr z_fr, y_fr; - G1 commitment_g1, proof_g1; - - if (!validate_kzg_g1(&commitment_g1, commitment)) { - return false; - } - if (!bytes_to_bls_field(&z_fr, z)) { - return false; - } - if (!bytes_to_bls_field(&y_fr, y)) { - return false; - } - if (!validate_kzg_g1(&proof_g1, proof)) { - return false; - } - - return verify_kzg_proof_impl( - &commitment_g1, &z_fr, &y_fr, &proof_g1); -} - -} // namespace silkworm diff --git a/silkworm/core/crypto/kzg.hpp b/silkworm/core/crypto/kzg.hpp deleted file mode 100644 index e940b27350..0000000000 --- a/silkworm/core/crypto/kzg.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright 2023 The Silkworm Authors - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#pragma once - -#include <span> - -#include <silkworm/core/types/hash.hpp> - -// Cryptographic support for EIP-4844: Shard Blob Transactions. -// KZG stands for the commitment scheme introduced by Kate, Zaverucha, and Goldberg. -// See https://dankradfeist.de/ethereum/2020/06/16/kate-polynomial-commitments.html - -namespace silkworm { - -// https://eips.ethereum.org/EIPS/eip-4844#helpers -Hash kzg_to_versioned_hash(ByteView kzg); - -/** - * Verify a KZG proof claiming that `p(z) == y`. - * - * @param[in] commitment The KZG commitment corresponding to poly p(x) - * @param[in] z The evaluation point - * @param[in] y The claimed evaluation result - * @param[in] proof The KZG proof - * @return True if the proofs are valid, otherwise false - * - * @see https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/polynomial-commitments.md#verify_kzg_proof - */ -bool verify_kzg_proof( - std::span<const uint8_t, 48> commitment, - std::span<const uint8_t, 32> z, - std::span<const uint8_t, 32> y, - std::span<const uint8_t, 48> proof); - -} // namespace silkworm diff --git a/silkworm/core/execution/precompile.cpp b/silkworm/core/execution/precompile.cpp index 4a52dbabfe..1a08e441a2 100644 --- a/silkworm/core/execution/precompile.cpp +++ b/silkworm/core/execution/precompile.cpp @@ -24,6 +24,7 @@ #include <limits> #include <evmone_precompiles/blake2b.hpp> +#include <evmone_precompiles/kzg.hpp> #include <evmone_precompiles/ripemd160.hpp> #include <evmone_precompiles/sha256.hpp> @@ -39,7 +40,6 @@ #include <silkworm/core/common/endian.hpp> #include <silkworm/core/crypto/ecdsa.h> -#include <silkworm/core/crypto/kzg.hpp> #include <silkworm/core/crypto/secp256k1n.hpp> #include <silkworm/core/protocol/intrinsic_gas.hpp> #include <silkworm/core/types/hash.hpp> @@ -510,11 +510,12 @@ std::optional<Bytes> point_evaluation_run(ByteView input) noexcept { std::span<const uint8_t, 48> commitment{&input[96], 48}; std::span<const uint8_t, 48> proof{&input[144], 48}; - if (kzg_to_versioned_hash(commitment) != ByteView{versioned_hash}) { - return std::nullopt; - } - - if (!verify_kzg_proof(commitment, z, y, proof)) { + if (!evmone::crypto::kzg_verify_proof( + std::as_bytes(versioned_hash).data(), + std::as_bytes(z).data(), + std::as_bytes(y).data(), + std::as_bytes(commitment).data(), + std::as_bytes(proof).data())) { return std::nullopt; } diff --git a/third_party/evmone/CMakeLists.txt b/third_party/evmone/CMakeLists.txt index 94fc8ef58d..63e6c765b1 100644 --- a/third_party/evmone/CMakeLists.txt +++ b/third_party/evmone/CMakeLists.txt @@ -48,12 +48,13 @@ add_library( evmone/lib/evmone_precompiles/blake2b.cpp evmone/lib/evmone_precompiles/ripemd160.cpp evmone/lib/evmone_precompiles/sha256.cpp + evmone/lib/evmone_precompiles/kzg.cpp ) set_source_files_properties(evmone/lib/evmone/vm.cpp PROPERTIES COMPILE_DEFINITIONS PROJECT_VERSION="0.12.0") target_include_directories(evmone PUBLIC evmone/include evmone/lib) target_link_libraries( evmone - PUBLIC evmc intx::intx + PUBLIC evmc intx::intx blst::blst PRIVATE ethash::keccak )