Skip to content

Commit

Permalink
keccak zkEVM bbf
Browse files Browse the repository at this point in the history
  • Loading branch information
AntoineCyr authored and ETatuzova committed Feb 27, 2025
1 parent 5e37822 commit 977dced
Show file tree
Hide file tree
Showing 11 changed files with 161 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,13 @@ namespace nil {
context_object.allocate(input.rlc_challenge, 0, 0,
column_type::public_input);
}

std::size_t max_blocks;
std::vector<keccak_map> m = std::vector<keccak_map>(max_blocks);

keccak_dynamic(context_type &context_object, input_type instance_input,
std::size_t max_blocks, bool make_links = true)
: generic_component<FieldType, stage>(context_object) {
std::size_t max_blocks_, bool make_links = true)
: max_blocks(max_blocks_), generic_component<FieldType, stage>(context_object) {
using integral_type = typename FieldType::integral_type;
using value_type = typename FieldType::value_type;

Expand All @@ -213,7 +216,6 @@ namespace nil {
TYPE RLC;
// constants

keccak_map m[max_blocks];
std::array<TYPE, 25> state;
std::vector<uint8_t> msg = std::vector<uint8_t>();
std::vector<uint8_t> padded_msg = std::vector<uint8_t>();
Expand Down
109 changes: 89 additions & 20 deletions crypto3/libs/blueprint/include/nil/blueprint/zkevm_bbf/keccak.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//---------------------------------------------------------------------------//
// Elena Tatuzova
// Copyright (c) 2024 Elena Tatuzova <[email protected]>
// Copyright (c) 2025 Antoine Cyr <[email protected]>
//
// MIT License
//
Expand All @@ -23,53 +24,121 @@
//---------------------------------------------------------------------------//
#pragma once

#include <nil/blueprint/bbf/components/hashes/keccak/keccak_dynamic.hpp>
#include <nil/blueprint/bbf/generic.hpp>
#include <nil/blueprint/zkevm_bbf/subcomponents/keccak_table.hpp>

namespace nil {
namespace blueprint {
namespace bbf {
template<typename FieldType, GenerationStage stage>
class keccak : public generic_component<FieldType, stage> {
class zkevm_keccak : public generic_component<FieldType, stage> {
using typename generic_component<FieldType, stage>::context_type;
using generic_component<FieldType, stage>::allocate;
using generic_component<FieldType, stage>::copy_constrain;
using generic_component<FieldType, stage>::constrain;
using generic_component<FieldType, stage>::lookup;
using generic_component<FieldType, stage>::lookup_table;

public:
using typename generic_component<FieldType, stage>::table_params;
using typename generic_component<FieldType,stage>::TYPE;
public:
using KeccakDynamic = typename bbf::keccak_dynamic<FieldType, stage>;
using KeccakTable = typename bbf::keccak_table<FieldType, stage>;

using private_input_type = std::conditional_t<
stage == GenerationStage::ASSIGNMENT,
std::size_t, std::monostate
>;
using typename generic_component<FieldType, stage>::table_params;
using typename generic_component<FieldType, stage>::TYPE;
using integral_type = nil::crypto3::multiprecision::big_uint<257>;
using private_input_type =
typename std::conditional<stage == GenerationStage::ASSIGNMENT,
zkevm_keccak_buffers, std::nullptr_t>::type;

struct input_type{
struct input_type {
TYPE rlc_challenge;
private_input_type private_input;
};

static table_params get_minimal_requirements() {
static table_params get_minimal_requirements(
std::size_t max_keccak_blocks) {
return {
.witnesses = 20,
.public_inputs = 1,
.constants = 3,
.rows = 300
};
.rows = KeccakDynamic::get_minimal_requirements(max_keccak_blocks)
.rows};
}

static void allocate_public_inputs(context_type &context, input_type &input) {
context.allocate(input.rlc_challenge, 0, 0, column_type::public_input);
static void allocate_public_inputs(context_type& context,
input_type& input,
std::size_t max_keccak_blocks) {
context.allocate(input.rlc_challenge, 0, 0,
column_type::public_input);
}

keccak(context_type &context_object, const input_type &input) :generic_component<FieldType,stage>(context_object) {
zkevm_keccak(context_type& context_object, const input_type& input,
std::size_t max_keccak_blocks)
: generic_component<FieldType, stage>(context_object) {
std::vector<std::size_t> keccak_lookup_area;
std::vector<std::size_t> keccak_dynamic_lookup_area;
std::size_t current_column = 0;
std::size_t dynamic_rows =
KeccakDynamic::get_minimal_requirements(max_keccak_blocks).rows;

for (std::size_t i = 0; i < KeccakTable::get_witness_amount(); i++) {
keccak_lookup_area.push_back(current_column++);
}

for (std::size_t i = 0;
i < KeccakDynamic::get_minimal_requirements(max_keccak_blocks)
.witnesses;
i++) {
keccak_dynamic_lookup_area.push_back(current_column++);
}

context_type keccak_ct = context_object.subcontext(
keccak_lookup_area, 1, dynamic_rows + 1);

context_type keccak_dynamic_ct = context_object.subcontext(
keccak_dynamic_lookup_area, 1, dynamic_rows + 1);
typename KeccakDynamic::input_type input_dynamic;
typename KeccakTable::input_type input_keccak_table;
TYPE rlc_challenge;

if constexpr (stage == GenerationStage::ASSIGNMENT) {
std::cout << "Keccak assign = " << input.private_input << std::endl;
rlc_challenge = input.rlc_challenge;
input_dynamic.rlc_challenge = input.rlc_challenge;
for (const auto& item : input.private_input.get_data()) {
const auto& buffer = item.first;
const auto& zkevm_word = item.second;

TYPE hi = w_hi<FieldType>(zkevm_word);
TYPE lo = w_lo<FieldType>(zkevm_word);
std::pair<TYPE, TYPE> pair_values = {hi, lo};

input_dynamic.input.emplace_back(buffer, pair_values);
}
input_keccak_table.rlc_challenge = input.rlc_challenge;
input_keccak_table.private_input = input.private_input;
}
KeccakTable kt =
KeccakTable(keccak_ct, input_keccak_table, max_keccak_blocks);

allocate(rlc_challenge, 0, 0);
input_dynamic.rlc_challenge = rlc_challenge;
KeccakDynamic kd = KeccakDynamic(keccak_dynamic_ct, input_dynamic,
max_keccak_blocks);

if constexpr (stage == GenerationStage::CONSTRAINTS) {
std::vector<TYPE> tmp;
for (std::size_t i = 0; i < max_keccak_blocks; i++) {
tmp = {TYPE(1), kt.RLC[i], kt.hash_hi[i], kt.hash_lo[i],
kt.is_last[i]};
lookup(tmp, "keccak_dynamic");
tmp = {kd.m[i].h.is_last, kd.m[i].h.RLC, kd.m[i].h.hash_hi,
kd.m[i].h.hash_lo};
lookup(tmp, "keccak_table");
}
}
}
};
}
}
}
} // namespace bbf
} // namespace blueprint
} // namespace nil
Original file line number Diff line number Diff line change
Expand Up @@ -80,17 +80,11 @@ namespace nil {
carry1 = (A_128.first + B_128.first + carry0 >= two_128);
}
for( std::size_t i = 0; i < 16; i++){
std::cout<<"i: "<<i<<std::endl;
std::cout<<"A[i]: "<<A[i]<<std::endl;
allocate(A[i], i, 0);
std::cout<<"B[i]: "<<B[i]<<std::endl;
allocate(B[i], i + 16, 0);
std::cout<<"A[i]: "<<A[i]<<std::endl;
allocate(S[i], i, 1);
}
std::cout<<"allocate carry0"<<std::endl;
allocate(carry0, 32, 0);
std::cout<<"allocate carry1"<<std::endl;
allocate(carry1, 33, 0);
auto A_128 = chunks16_to_chunks128<TYPE>(A);
auto B_128 = chunks16_to_chunks128<TYPE>(B);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ namespace nil {
) :
max_blocks(max_blocks_),
generic_component<FieldType,stage>(context_object) {
std::cout << "a";
if constexpr (stage == GenerationStage::ASSIGNMENT) {
TYPE theta = input.rlc_challenge;

Expand Down
87 changes: 49 additions & 38 deletions crypto3/libs/blueprint/test/zkevm_bbf/hardhat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,9 @@ class zkEVMHardhatTestFixture: public CircuitTestFixture {

auto rw_assignment_input = circuit_inputs.rw_operations();

typename keccak<field_type, GenerationStage::ASSIGNMENT>::input_type keccak_assignment_input;
keccak_assignment_input.private_input = 12345;
typename zkevm_keccak<field_type,GenerationStage::ASSIGNMENT>::input_type keccak_assignment_input;
keccak_assignment_input.rlc_challenge = 7;
keccak_assignment_input.private_input = circuit_inputs.keccaks();

typename bytecode<field_type, GenerationStage::ASSIGNMENT>::input_type bytecode_assignment_input;
bytecode_assignment_input.rlc_challenge = 7;
Expand All @@ -121,6 +122,18 @@ class zkEVMHardhatTestFixture: public CircuitTestFixture {
auto exp_assignment_input = circuit_inputs.exponentiations();

bool result{false};
// Max_rows, max_bytecode, max_rw
result = test_bbf_component<field_type, zkevm>(
"zkevm",
{}, zkevm_assignment_input,
max_zkevm_rows,
max_copy,
max_rw,
max_exponentiations,
max_bytecode
);
BOOST_ASSERT(result);
std::cout << std::endl;

const std::string zkevm_circuit = "zkevm";
if (should_run_circuit(zkevm_circuit)) {
Expand All @@ -141,8 +154,6 @@ class zkEVMHardhatTestFixture: public CircuitTestFixture {

const std::string exp_circuit = "exp";
if (should_run_circuit(exp_circuit)) {
std::cout << "circuit '" << exp_circuit << "'" << std::endl;

// Max_copy, Max_rw, Max_keccak, Max_bytecode
result =test_bbf_component<field_type, nil::blueprint::bbf::exponentiation>(
exp_circuit,
Expand Down Expand Up @@ -173,9 +184,9 @@ class zkEVMHardhatTestFixture: public CircuitTestFixture {
std::cout << "circuit '" << keccak_circuit << "'" << std::endl;

// Max_keccak
result = test_bbf_component<field_type, nil::blueprint::bbf::keccak>(
result = test_bbf_component<field_type, nil::blueprint::bbf::zkevm_keccak>(
keccak_circuit,
{}, keccak_assignment_input
{}, keccak_assignment_input,max_keccak_blocks
);
BOOST_ASSERT(result);
std::cout << std::endl;
Expand Down Expand Up @@ -218,14 +229,14 @@ BOOST_AUTO_TEST_CASE(minimal_math) {
auto [bytecodes, pts] = load_hardhat_input("minimal_math/");
l1_size_restrictions max_sizes;

max_sizes.max_keccak_blocks = 10;
max_sizes.max_bytecode = 3000;
max_sizes.max_keccak_blocks = 3;
max_sizes.max_bytecode = 300;
max_sizes.max_mpt = 0;
max_sizes.max_rw = 500;
max_sizes.max_copy = 500;
max_sizes.max_copy = 70;
max_sizes.max_zkevm_rows = 500;
max_sizes.max_exponentiations = 50;
max_sizes.max_exp_rows = 500;
max_sizes.max_exponentiations = 10;
max_sizes.max_exp_rows = 100;

complex_test<field_type>(bytecodes, pts, max_sizes);
}
Expand All @@ -235,14 +246,14 @@ BOOST_AUTO_TEST_CASE(modular_operations) {
auto [bytecodes, pts] = load_hardhat_input("modular_operations/");
l1_size_restrictions max_sizes;

max_sizes.max_keccak_blocks = 10;
max_sizes.max_bytecode = 3000;
max_sizes.max_keccak_blocks = 4;
max_sizes.max_bytecode = 300;
max_sizes.max_mpt = 0;
max_sizes.max_rw = 500;
max_sizes.max_copy = 500;
max_sizes.max_copy = 70;
max_sizes.max_zkevm_rows = 500;
max_sizes.max_exponentiations = 50;
max_sizes.max_exp_rows = 500;
max_sizes.max_exponentiations = 10;
max_sizes.max_exp_rows = 100;

complex_test<field_type>(bytecodes, pts, max_sizes);
}
Expand All @@ -252,14 +263,14 @@ BOOST_AUTO_TEST_CASE(exp) {
auto [bytecodes, pts] = load_hardhat_input("exp/");
l1_size_restrictions max_sizes;

max_sizes.max_keccak_blocks = 10;
max_sizes.max_bytecode = 3000;
max_sizes.max_keccak_blocks = 4;
max_sizes.max_bytecode = 400;
max_sizes.max_mpt = 0;
max_sizes.max_rw = 1000;
max_sizes.max_copy = 500;
max_sizes.max_zkevm_rows = 2000;
max_sizes.max_exp_rows = 500;
max_sizes.max_exponentiations = 50;
max_sizes.max_rw = 950;
max_sizes.max_copy = 80;
max_sizes.max_zkevm_rows = 1250;
max_sizes.max_exponentiations = 10;
max_sizes.max_exp_rows = 100;

complex_test<field_type>(bytecodes, pts, max_sizes);
}
Expand All @@ -269,14 +280,14 @@ BOOST_AUTO_TEST_CASE(keccak) {
auto [bytecodes, pts] = load_hardhat_input("keccak/");
l1_size_restrictions max_sizes;

max_sizes.max_keccak_blocks = 10;
max_sizes.max_bytecode = 3000;
max_sizes.max_keccak_blocks = 5;
max_sizes.max_bytecode = 400;
max_sizes.max_mpt = 0;
max_sizes.max_rw = 1000;
max_sizes.max_copy = 500;
max_sizes.max_rw = 900;
max_sizes.max_copy = 200;
max_sizes.max_zkevm_rows = 500;
max_sizes.max_exponentiations = 50;
max_sizes.max_exp_rows = 500;
max_sizes.max_exponentiations = 10;
max_sizes.max_exp_rows = 100;

complex_test<field_type>(bytecodes, pts, max_sizes);
}
Expand All @@ -286,7 +297,7 @@ BOOST_AUTO_TEST_CASE(mstore8) {
auto [bytecodes, pts] = load_hardhat_input("mstore8/");
l1_size_restrictions max_sizes;

max_sizes.max_keccak_blocks = 50;
max_sizes.max_keccak_blocks = 25;
max_sizes.max_bytecode = 3000;
max_sizes.max_mpt = 0;
max_sizes.max_rw = 5000;
Expand All @@ -303,7 +314,7 @@ BOOST_AUTO_TEST_CASE(meminit) {
auto [bytecodes, pts] = load_hardhat_input("mem_init/");
l1_size_restrictions max_sizes;

max_sizes.max_keccak_blocks = 50;
max_sizes.max_keccak_blocks = 10;
max_sizes.max_bytecode = 3000;
max_sizes.max_mpt = 0;
max_sizes.max_rw = 10000;
Expand All @@ -320,14 +331,14 @@ BOOST_AUTO_TEST_CASE(calldatacopy) {
auto [bytecodes, pts] = load_hardhat_input("calldatacopy/");
l1_size_restrictions max_sizes;

max_sizes.max_keccak_blocks = 50;
max_sizes.max_bytecode = 3000;
max_sizes.max_keccak_blocks = 4;
max_sizes.max_bytecode = 300;
max_sizes.max_mpt = 0;
max_sizes.max_rw = 5000;
max_sizes.max_copy = 3000;
max_sizes.max_zkevm_rows = 4500;
max_sizes.max_exponentiations = 50;
max_sizes.max_exp_rows = 500;
max_sizes.max_rw = 500;
max_sizes.max_copy = 90;
max_sizes.max_zkevm_rows = 500;
max_sizes.max_exponentiations = 10;
max_sizes.max_exp_rows = 100;

complex_test<field_type>(bytecodes, pts, max_sizes);
}
Expand Down
2 changes: 1 addition & 1 deletion crypto3/libs/blueprint/test/zkevm_bbf/opcodes/byte_ops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ BOOST_AUTO_TEST_CASE(byte_ops) {
opcode_tester.push_opcode(zkevm_opcode::SHL);
opcode_tester.push_opcode(zkevm_opcode::STOP);

max_sizes.max_keccak_blocks = 400;
max_sizes.max_keccak_blocks = 30;
max_sizes.max_bytecode = 5000;
max_sizes.max_mpt = 0;
max_sizes.max_rw = 3000;
Expand Down
Loading

0 comments on commit 977dced

Please sign in to comment.