Skip to content

Commit

Permalink
Use unordered_map for keep assignment tables
Browse files Browse the repository at this point in the history
  • Loading branch information
akokoshn authored and akokoshn committed Aug 16, 2024
1 parent 1506df3 commit 9d755e5
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 225 deletions.
18 changes: 14 additions & 4 deletions lib/assigner/include/assigner.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include <boost/log/expressions.hpp>
#include <boost/log/trivial.hpp>

#include <unordered_map>

#include <nil/crypto3/algebra/curves/pallas.hpp>
#include <nil/blueprint/blueprint/plonk/assignment.hpp>

Expand Down Expand Up @@ -45,21 +47,29 @@ namespace nil {
constexpr static size_t BYTECODE_TABLE_INDEX = 0;
constexpr static size_t RW_TABLE_INDEX = 1;

assigner(std::vector<nil::blueprint::assignment<ArithmetizationType>> &assignments): m_assignments(assignments) {}
assigner(std::unordered_map<uint8_t, nil::blueprint::assignment<ArithmetizationType>> &assignments): m_assignments(assignments) {}

// TODO error handling
void handle_bytecode(size_t original_code_size, const uint8_t* code) {
auto it = m_assignments.find(BYTECODE_TABLE_INDEX);
if (it == m_assignments.end()) {
return;
}
return process_bytecode_input<BlueprintFieldType>(
original_code_size, code, m_assignments[BYTECODE_TABLE_INDEX]);
original_code_size, code, it->second);
}

// TODO error handling
void handle_rw(std::vector<rw_operation<BlueprintFieldType>>& rw_trace) {
auto it = m_assignments.find(RW_TABLE_INDEX);
if (it == m_assignments.end()) {
return;
}
return process_rw_operations<BlueprintFieldType>(
rw_trace, m_assignments[RW_TABLE_INDEX]);
rw_trace, it->second);
}

std::vector<nil::blueprint::assignment<ArithmetizationType>> &m_assignments;
std::unordered_map<uint8_t, nil::blueprint::assignment<ArithmetizationType>> &m_assignments;
};

template<typename BlueprintFieldType>
Expand Down
232 changes: 11 additions & 221 deletions lib/assigner/test/assigner_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ class AssignerTest : public testing::Test
nil::crypto3::zk::snark::plonk_table_description<BlueprintFieldType> desc(
WitnessColumns, PublicInputColumns, ConstantColumns, SelectorColumns);

assignments.emplace_back(desc);
assignments.emplace_back(desc); // for check create, call op codes, where message depth = 1
assignments.insert(std::pair<uint8_t, nil::blueprint::assignment<ArithmetizationType>>(0, nil::blueprint::assignment<ArithmetizationType>(desc)));
// for check create, call op codes, where message depth = 1
assignments.insert(std::pair<uint8_t, nil::blueprint::assignment<ArithmetizationType>>(1, nil::blueprint::assignment<ArithmetizationType>(desc)));

assigner_ptr =
std::make_shared<nil::evm_assigner::assigner<BlueprintFieldType>>(assignments);
Expand Down Expand Up @@ -69,7 +70,7 @@ class AssignerTest : public testing::Test
}

static std::shared_ptr<nil::evm_assigner::assigner<BlueprintFieldType>> assigner_ptr;
static std::vector<nil::blueprint::assignment<ArithmetizationType>> assignments;
static std::unordered_map<uint8_t, nil::blueprint::assignment<ArithmetizationType>> assignments;
static const struct evmc_host_interface* host_interface;
static struct evmc_host_context* ctx;
static evmc_revision rev;
Expand All @@ -78,7 +79,7 @@ class AssignerTest : public testing::Test

std::shared_ptr<nil::evm_assigner::assigner<AssignerTest::BlueprintFieldType>>
AssignerTest::assigner_ptr;
std::vector<nil::blueprint::assignment<AssignerTest::ArithmetizationType>>
std::unordered_map<uint8_t, nil::blueprint::assignment<AssignerTest::ArithmetizationType>>
AssignerTest::assignments;
const struct evmc_host_interface* AssignerTest::host_interface;
struct evmc_host_context* AssignerTest::ctx;
Expand All @@ -91,7 +92,7 @@ inline void check_eq(const uint8_t* l, const uint8_t* r, size_t len) {
}
}

inline void rw_circuit_check(const std::vector<nil::blueprint::assignment<AssignerTest::ArithmetizationType>> assignments,
inline void rw_circuit_check(const std::unordered_map<uint8_t, nil::blueprint::assignment<AssignerTest::ArithmetizationType>> &assignments,
uint32_t start_row_index,
uint8_t operation_type,
uint32_t call_id,
Expand All @@ -102,8 +103,11 @@ inline void rw_circuit_check(const std::vector<nil::blueprint::assignment<Assign
bool is_write,
const typename AssignerTest::BlueprintFieldType::value_type& value_hi,
const typename AssignerTest::BlueprintFieldType::value_type& value_lo) {
auto& rw_table =
assignments[nil::evm_assigner::assigner<AssignerTest::BlueprintFieldType>::RW_TABLE_INDEX];
auto it = assignments.find(nil::evm_assigner::assigner<AssignerTest::BlueprintFieldType>::RW_TABLE_INDEX);
if (it == assignments.end()) {
return;
}
auto& rw_table = it->second;
// OP_TYPE
EXPECT_EQ(rw_table.witness(0, start_row_index), operation_type);
// CALL ID
Expand Down Expand Up @@ -344,217 +348,3 @@ TEST_F(AssignerTest, mul) {
rw_circuit_check(assignments, start_row_index + 4, 1/*STACK_OP*/, call_id, 1/*address in stack*/, 0/*storage key hi*/, 0/*storage key lo*/,
3/*trace size*/, false/*is_write*/, 0/*value_hi*/, 8/*value_lo*/);
}

// TODO add check assignment tables
TEST_F(AssignerTest, DISABLED_callvalue_calldataload)
{
const uint8_t index = 10;
std::vector<uint8_t> code = {
evmone::OP_CALLVALUE,
evmone::OP_PUSH1,
index,
evmone::OP_CALLDATALOAD,
};
nil::evm_assigner::evaluate<BlueprintFieldType>(host_interface, ctx, rev, &msg, code.data(), code.size(), assigner_ptr);
//EXPECT_EQ(assignments[0].witness(1, 0), nil::blueprint::to_field<BlueprintFieldType>(msg.value));
EXPECT_EQ(assignments[0].witness(1, 1), index);
}

// TODO: test dataload instruction (for now its cost is not defined)
TEST_F(AssignerTest, DISABLED_dataload) {
const uint8_t index = 10;
std::vector<uint8_t> code = {
evmone::OP_PUSH1,
index,
evmone::OP_DATALOAD,
};
nil::evm_assigner::evaluate<BlueprintFieldType>(host_interface, ctx, rev, &msg, code.data(), code.size(), assigner_ptr);
EXPECT_EQ(assignments[0].witness(1, 2), index);
}

// TODO add check assignment tables
TEST_F(AssignerTest, DISABLED_mstore_load)
{
const uint8_t value = 12;
const uint8_t index = 1;
std::vector<uint8_t> code = {
evmone::OP_PUSH1,
value,
evmone::OP_PUSH1,
index,
evmone::OP_MSTORE,
evmone::OP_PUSH1,
index,
evmone::OP_MLOAD,
};
nil::evm_assigner::evaluate<BlueprintFieldType>(host_interface, ctx, rev, &msg, code.data(), code.size(), assigner_ptr);
EXPECT_EQ(assignments[0].witness(2, 0), value);
EXPECT_EQ(assignments[0].witness(2, 1), index);
EXPECT_EQ(assignments[0].witness(2, 2), value);
}

// TODO add check assignment tables
TEST_F(AssignerTest, DISABLED_sstore_load)
{
const uint8_t value = 12;
const uint8_t key = 4;
std::vector<uint8_t> code = {
evmone::OP_PUSH1,
value,
evmone::OP_PUSH1,
key,
evmone::OP_SSTORE,
evmone::OP_PUSH1,
key,
evmone::OP_SLOAD,
};
nil::evm_assigner::evaluate<BlueprintFieldType>(host_interface, ctx, rev, &msg, code.data(), code.size(), assigner_ptr);
EXPECT_EQ(assignments[0].witness(3, 0), value);
EXPECT_EQ(assignments[0].witness(3, 1), key);
EXPECT_EQ(assignments[0].witness(3, 2), value);
}

// TODO: test transient storage opcodes (for now their costs are not defined)
TEST_F(AssignerTest, DISABLED_tstore_load) {
const uint8_t value = 12;
const uint8_t key = 4;
std::vector<uint8_t> code = {
evmone::OP_PUSH1,
value,
evmone::OP_PUSH1,
key,
evmone::OP_TSTORE,
evmone::OP_PUSH1,
key,
evmone::OP_TLOAD,
};
nil::evm_assigner::evaluate<BlueprintFieldType>(host_interface, ctx, rev, &msg, code.data(), code.size(), assigner_ptr);
EXPECT_EQ(assignments[0].witness(4, 0), value);
EXPECT_EQ(assignments[0].witness(4, 1), key);
EXPECT_EQ(assignments[0].witness(4, 2), value);
}

// TODO add check assignment tables
TEST_F(AssignerTest, DISABLED_create) {

std::vector<uint8_t> code = {
// Create an account with 0 wei and no code
evmone::OP_PUSH1,
0,
evmone::OP_PUSH1,
0,
evmone::OP_PUSH1,
0,
evmone::OP_PUSH1,
0,
evmone::OP_CREATE,

// Create an account with 9 wei and no code
evmone::OP_PUSH1,
1,
evmone::OP_PUSH1,
0,
evmone::OP_PUSH1,
0,
evmone::OP_PUSH1,
9,
evmone::OP_CREATE,

// Create an account with 0 wei and 4 FF as code
evmone::OP_PUSH13,
// code 0x63FFFFFFFF60005260046000F3 will be inserted later

evmone::OP_PUSH1,
0,
evmone::OP_MSTORE,
evmone::OP_PUSH1,
2,
evmone::OP_PUSH1,
13,
evmone::OP_PUSH1,
19,
evmone::OP_PUSH1,
0,
evmone::OP_CREATE,
};

auto push13_it = std::find(code.begin(), code.end(), evmone::OP_PUSH13);
ASSERT_NE(push13_it, code.end());
size_t push13_idx = static_cast<size_t>(push13_it - code.begin());

std::vector<uint8_t> contract_code = {0x63, 0xff, 0xff, 0xff, 0xff, 0x60, 0x00, 0x52, 0x60, 0x04, 0x60, 0x00, 0xf3};
// Code is in the last 13 bytes of the container
code.insert(code.begin() + static_cast<long int>(push13_idx) + 1, contract_code.begin(), contract_code.end());

nil::evm_assigner::evaluate<BlueprintFieldType>(host_interface, ctx, rev, &msg, code.data(), code.size(), assigner_ptr);
// Check stored witnesses of MSTORE instruction at depth 1
EXPECT_EQ(assignments[1].witness(2, 1), 0);
EXPECT_EQ(assignments[1].witness(2, 0), 0xFFFFFFFF);
}

// TODO add check assignment tables
TEST_F(AssignerTest, DISABLED_call) {

std::vector<uint8_t> code = {
// Create a contract that creates an exception if first word of calldata is 0
evmone::OP_PUSH17,
// code 0x67600035600757FE5B60005260086018F3 will be inserted later
evmone::OP_PUSH1,
0,

evmone::OP_MSTORE,
evmone::OP_PUSH1,
17,
evmone::OP_PUSH1,
15,
evmone::OP_PUSH1,
0,
evmone::OP_CREATE,

// Call with no parameters, return 0
evmone::OP_PUSH1,
0,
evmone::OP_PUSH1,
0,
evmone::OP_PUSH1,
0,
evmone::OP_PUSH1,
0,
evmone::OP_PUSH1,
0,
evmone::OP_DUP6,
evmone::OP_PUSH2,
0xFF,
0xFF,
evmone::OP_CALL,

// Call with non 0 calldata, returns success
evmone::OP_PUSH1,
0,
evmone::OP_PUSH1,
0,
evmone::OP_PUSH1,
32,
evmone::OP_PUSH1,
0,
evmone::OP_PUSH1,
0,
evmone::OP_DUP7,
evmone::OP_PUSH2,
0xFF,
0xFF,
evmone::OP_CALL,
};

auto push17_it = std::find(code.begin(), code.end(), evmone::OP_PUSH17);
ASSERT_NE(push17_it, code.end());
size_t push17_idx = static_cast<size_t>(push17_it - code.begin());

std::vector<uint8_t> contract_code = {0x67, 0x60, 0x00, 0x35, 0x60, 0x07, 0x57, 0xfe, 0x5b, 0x60, 0x00, 0x52, 0x60, 0x08, 0x60, 0x18, 0xf3};
// Code is in the last 13 bytes of the container
code.insert(code.begin() + static_cast<long int>(push17_idx) + 1, contract_code.begin(), contract_code.end());

nil::evm_assigner::evaluate<BlueprintFieldType>(host_interface, ctx, rev, &msg, code.data(), code.size(), assigner_ptr);
// Check stored witness of CALLDATALOAD instruction at depth 1
EXPECT_EQ(assignments[1].witness(1, 1), 0);
}

0 comments on commit 9d755e5

Please sign in to comment.