Skip to content

Commit

Permalink
Add assigner executable
Browse files Browse the repository at this point in the history
  • Loading branch information
akokoshn committed Apr 10, 2024
1 parent 5b2814d commit f31604d
Show file tree
Hide file tree
Showing 22 changed files with 814 additions and 53 deletions.
18 changes: 18 additions & 0 deletions .github/workflows/run-tests-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,24 @@ jobs:
uses: actions/checkout@v3
with:
fetch-depth: 0
submodules: false

- name: Checkout submodules
run: |
git submodule update --init --recursive --depth=1
- name: Configure CMake
#env:
# BOOST_ROOT: "${{ steps.install-boost.outputs.BOOST_ROOT }}"
run: |
cmake . \
-G "Ninja" \
-B build \
-DCMAKE_BUILD_TYPE=Release
- name: Build assigner
run: |
cmake --build build
- name: Run checks
run: nix flake -L check
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "assigner"]
path = libs/assigner
url = ../../NilFoundation/evm-assigner
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
cmake_minimum_required(VERSION 3.27)

project(zkEVM-framework)

set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})

option(BUILD_DOCS "Build documentation" FALSE)
option(ENABLE_TESTS "Enable tests" FALSE)
option(ENABLE_ASSIGNER "Enable assigner executable" TRUE)

add_subdirectory(libs)
add_subdirectory(bin)

if(BUILD_DOCS)
find_package(Doxygen REQUIRED)
Expand Down
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ Framework for test verification of state of claster based on EVM
* intx: GMP (intx dependency) [Homepage](https://gmplib.org/), intx [Repository](https://github.com/chfast/intx)
* SSZ++ [Repository](https://github.com/OffchainLabs/sszpp)

### EVM based assigner

* assigner [EVM based assigner](https://github.com/NilFoundation/evm-assigner)

## Nix environment

Instead of installing all dependencies manually,
Expand All @@ -28,6 +32,11 @@ you can activate [Nix](https://nixos.org/download#download-nix) environment with
```plain
nix develop
```
## Clone

```plain
git clone --recurse-submodules https://github.com/NilFoundation/zkEVM-framework.git
```

## Build

Expand All @@ -41,6 +50,24 @@ Or with Nix:
```bash
nix build
```
## Assigner executable

### Build dependency

```bash
cd libs/assigner
cmake -G "Ninja" -B build .
cmake --build build
cmake --install build
cd ../..
```

### Build executable

```bash
cmake -G "Ninja" -B build -DENABLE_ASSIGNER=TRUE .
cmake --build build
```

## Test

Expand Down
6 changes: 6 additions & 0 deletions bin/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
if(NOT Boost_FOUND)
find_package(Boost COMPONENTS REQUIRED filesystem log log_setup program_options thread system)
endif()
if (ENABLE_ASSIGNER)
add_subdirectory(assigner)
endif()
19 changes: 19 additions & 0 deletions bin/assigner/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
set(TARGET_NAME assigner)
set(SOURCES
src/main.cpp)

add_executable(${TARGET_NAME} ${SOURCES})

target_compile_options(${TARGET_NAME} PRIVATE -std=c++23)

set(ASSIGNER_INCLUDES ${CMAKE_INSTALL_PREFIX}/include ${CMAKE_CURRENT_SOURCE_DIR}/include)
set(ASSIGNER_LIBS ${CMAKE_INSTALL_PREFIX}/lib)

target_include_directories(${TARGET_NAME}
PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../libs/data_types/include>
$<$<BOOL:${Boost_FOUND}>:${Boost_INCLUDE_DIRS}>
${ASSIGNER_INCLUDES})

target_link_directories(${TARGET_NAME} PRIVATE ${ASSIGNER_LIBS})
target_link_libraries(${TARGET_NAME} PRIVATE evmone zkEVMDataTypes ${Boost_LIBRARIES})
212 changes: 212 additions & 0 deletions bin/assigner/include/utils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
#ifndef ZKEMV_FRAMEWORK_BIN_ASSIGNER_INCLUDE_UTILS_HPP_
#define ZKEMV_FRAMEWORK_BIN_ASSIGNER_INCLUDE_UTILS_HPP_

#include <execution_state.hpp>
#include <vm.hpp>

#include "zkevm_framework/data_types/base.hpp"
#include "zkevm_framework/data_types/block.hpp"

struct vm_account {
virtual ~vm_account() = default;

// evmc::uint256be = evmc::bytes32 = uint8_t[32]

evmc::uint256be balance = {};
// TODO check what code
std::vector<uint8_t> code;

// sload/sstore op codes
std::map<evmc::bytes32, evmc::bytes32> storage;
// tload/tstore op codes
std::map<evmc::bytes32, evmc::bytes32> transient_storage;

virtual evmc::bytes32 code_hash() const {
// Extremely dumb "hash" function.
evmc::bytes32 ret{};
for (const auto v : code) ret.bytes[v % sizeof(ret.bytes)] ^= v;
return ret;
}
};

using vm_accounts = std::map<evmc::address, vm_account>;

class VmHost : public evmc::Host {
vm_accounts accounts;
evmc_tx_context tx_context{};

public:
VmHost() = default;
explicit VmHost(evmc_tx_context& _tx_context) noexcept : tx_context{_tx_context} {}
VmHost(evmc_tx_context& _tx_context, vm_accounts& _accounts) noexcept
: accounts{_accounts}, tx_context{_tx_context} {}

bool account_exists(const evmc::address& addr) const noexcept final {
return accounts.find(addr) != accounts.end();
}

evmc::bytes32 get_storage(const evmc::address& addr,
const evmc::bytes32& key) const noexcept final {
const auto account_iter = accounts.find(addr);
if (account_iter == accounts.end()) {
return {};
}

const auto storage_iter = account_iter->second.storage.find(key);
if (storage_iter != account_iter->second.storage.end()) {
return storage_iter->second;
}
return {};
}

evmc_storage_status set_storage(const evmc::address& addr, const evmc::bytes32& key,
const evmc::bytes32& value) noexcept final {
if (accounts.find(addr) == accounts.end()) {
return EVMC_STORAGE_DELETED;
}
auto& account = accounts[addr];
auto prev_value = account.storage[key];
account.storage[key] = value;

return (prev_value == value) ? EVMC_STORAGE_ASSIGNED : EVMC_STORAGE_MODIFIED;
}

evmc::uint256be get_balance(const evmc::address& addr) const noexcept final {
auto it = accounts.find(addr);
if (it != accounts.end()) {
return it->second.balance;
}
return {};
}

size_t get_code_size(const evmc::address& addr) const noexcept final {
auto it = accounts.find(addr);
if (it != accounts.end()) {
return it->second.code.size();
}
return 0;
}

evmc::bytes32 get_code_hash(const evmc::address& addr) const noexcept final {
auto it = accounts.find(addr);
if (it != accounts.end()) {
return it->second.code_hash();
}
return {};
}

size_t copy_code(const evmc::address& addr, size_t code_offset, uint8_t* buffer_data,
size_t buffer_size) const noexcept final {
const auto it = accounts.find(addr);
if (it == accounts.end()) {
return 0;
}

const auto& code = it->second.code;

if (code_offset >= code.size()) {
return 0;
}

const auto n = std::min(buffer_size, code.size() - code_offset);

if (n > 0) {
std::copy_n(&code[code_offset], n, buffer_data);
}
return n;
}

bool selfdestruct(const evmc::address& addr, const evmc::address& beneficiary) noexcept final {
(void)addr;
(void)beneficiary;
return false;
}

evmc::Result call(const evmc_message& msg) noexcept final {
return evmc::Result{EVMC_REVERT, msg.gas, 0, msg.input_data, msg.input_size};
}

evmc_tx_context get_tx_context() const noexcept final { return tx_context; }

evmc::bytes32 get_block_hash(int64_t number) const noexcept final {
evmc::bytes32 ret{};
return ret;
}

void emit_log(const evmc::address& addr, const uint8_t* data, size_t data_size,
const evmc::bytes32 topics[], size_t topics_count) noexcept final {
(void)addr;
(void)data;
(void)data_size;
(void)topics;
(void)topics_count;
}

evmc_access_status access_account(const evmc::address& addr) noexcept final {
(void)addr;
return EVMC_ACCESS_COLD;
}

evmc_access_status access_storage(const evmc::address& addr,
const evmc::bytes32& key) noexcept final {
(void)addr;
(void)key;
return EVMC_ACCESS_COLD;
}

evmc::bytes32 get_transient_storage(const evmc::address& addr,
const evmc::bytes32& key) const noexcept override {
const auto account_iter = accounts.find(addr);
if (account_iter == accounts.end()) {
return {};
}

const auto transient_storage_iter = account_iter->second.transient_storage.find(key);
if (transient_storage_iter != account_iter->second.transient_storage.end()) {
return transient_storage_iter->second;
}
return {};
}

void set_transient_storage(const evmc::address& addr, const evmc::bytes32& key,
const evmc::bytes32& value) noexcept override {
accounts[addr].transient_storage[key] = value;
}
};

std::optional<data_types::Block> read_input_block(const std::string& file_name) {
std::ifstream input_block_file(file_name.c_str(), std::ios_base::binary | std::ios_base::out);
if (!input_block_file.is_open()) {
std::cerr << "Could not open the file - '" << file_name << "'" << std::endl;
return std::nullopt;
}
data_types::bytes serialized_block(input_block_file.tellg());
input_block_file.read(reinterpret_cast<char*>(serialized_block.data()),
serialized_block.size());
if (input_block_file.fail()) {
std::cerr << "Error occurred during reading file " << file_name << std::endl;
return std::nullopt;
}
input_block_file.close();
return data_types::Block::deserialize(serialized_block);
}

template<typename T>
evmc::uint256be to_uint256be(T v) {
evmc::uint256be res;
uint8_t mask = (1 << 8) - 1;
for (uint8_t i = 0; i <= 31; i++) {
res.bytes[i] = (v >> (i - 31) * 8);
}
return res;
}

evmc_address to_evmc_address(const data_types::Address& v) {
evmc_address res = {
v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9],
v[10], v[11], v[12], v[13], v[14], v[15], v[16], v[17], v[18], v[19],
};
return res;
}

#endif // ZKEMV_FRAMEWORK_BIN_ASSIGNER_INCLUDE_UTILS_HPP_
Loading

0 comments on commit f31604d

Please sign in to comment.