Skip to content
Draft
47 changes: 28 additions & 19 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,53 +9,62 @@ on:
jobs:

build:
runs-on: self-hosted
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- name: Set up Zig
uses: korandoru/setup-zig@v1
uses: mlugg/setup-zig@v2
with:
zig-version: 0.13.0
version: 0.14.1

- name: Build
run: git submodule update --init --recursive && zig build

lint:
runs-on: self-hosted
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- name: Set up Zig
uses: korandoru/setup-zig@v1
uses: mlugg/setup-zig@v2
with:
zig-version: 0.13.0
version: 0.14.1

- name: Lint
run: zig fmt --check src/*.zig

test:
runs-on: self-hosted
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- name: Set up Zig
uses: korandoru/setup-zig@v1
uses: mlugg/setup-zig@v2
with:
zig-version: 0.13.0
version: 0.14.1

- name: Install cmake
run: |
sudo apt update
sudo apt install -y cmake

- name: Test
run: git submodule update --init --recursive && zig build test

build-aarch64:
runs-on: self-hosted
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- name: Set up Zig
uses: korandoru/setup-zig@v1
with:
zig-version: 0.13.0

- name: Test
run: git submodule update --init --recursive && zig build -Dtarget="aarch64-linux"
- uses: actions/checkout@v2
- name: Set up Zig
uses: mlugg/setup-zig@v2
with:
version: 0.14.1

- name: Install cmake
run: |
sudo apt update
sudo apt install -y cmake

- name: Build
run: git submodule update --init --recursive && zig build -Dtarget="aarch64-linux" -Dforce-evmone=true
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ An experimental Zig Ethereum client.

This repo is very experimental, so you have to do some things once.

We use the [Zig v0.13](https://ziglang.org/download/) compiler version.
We use the [Zig v0.14.0](https://ziglang.org/download/) compiler version.

### Initialize git submodules

Expand Down
189 changes: 99 additions & 90 deletions build.zig
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const std = @import("std");
const builtin = @import("builtin");
const LazyPath = std.Build.LazyPath;

// extract version string from build.zig.zon. The zon parser hasn't been merged
Expand Down Expand Up @@ -38,6 +39,8 @@ fn gitRevision(b: *std.Build) []const u8 {
// runner.
pub fn build(b: *std.Build) !void {
const version_file_path = "src/version.zig";
const use_zevem = b.option(bool, "use-zevem", "Use zevem instead of evmone (default=false if target = host, true otherwise)") orelse false;
const force_evmone = b.option(bool, "force-evmone", "Force evmone even when cross-compiling (uses zig cc as cmake compiler)") orelse false;

var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
Expand Down Expand Up @@ -67,74 +70,31 @@ pub fn build(b: *std.Build) !void {
// set a preferred release mode, allowing the user to decide how to optimize.
const optimize = b.standardOptimizeOption(.{});

const dep_rlp = b.dependency("zig-rlp", .{ .target = target, .optimize = optimize });
const depSecp256k1 = b.dependency("zig-eth-secp256k1", .{ .target = target, .optimize = optimize });
const dep_rlp = b.dependency("rlp", .{ .target = target, .optimize = optimize });
const zevem = b.dependency("zevem", .{ .target = target, .optimize = optimize });
const depSecp256k1 = b.dependency("zig_eth_secp256k1", .{ .target = target, .optimize = optimize });
const mod_secp256k1 = depSecp256k1.module("zig-eth-secp256k1");
const httpz = b.dependency("httpz", .{
.target = target,
.optimize = optimize,
});
const mod_httpz = httpz.module("httpz");

const ethash = b.addStaticLibrary(.{
.name = "ethash",
.optimize = optimize,
.target = target,
});
const cflags = [_][]const u8{
"-Wall", "-O3", "-fvisibility=hidden",
"-fvisibility-inlines-hidden", "-Wpedantic", "-Werror",
"-Wextra", "-Wshadow", "-Wconversion",
"-Wsign-conversion", "-Wno-unknown-pragmas", "-fno-stack-protector",
"-Wimplicit-fallthrough", "-Wmissing-declarations", "-Wno-attributes",
"-Wextra-semi", "-fno-exceptions", "-fno-rtti",
"-Wno-deprecated", // this one is used to remove a warning about char_trait deprecation
"-Wno-strict-prototypes", // this one is used by glue.c to avoid a warning that does not disappear when the prototype is added.
};
ethash.addCSourceFiles(.{ .root = b.path(""), .files = &[_][]const u8{"ethash/lib/keccak/keccak.c"}, .flags = &cflags });
ethash.addIncludePath(b.path("ethash/include"));
ethash.linkLibC();
ethash.linkLibCpp();
b.installArtifact(ethash);

const evmone = b.addStaticLibrary(.{
.name = "evmone",
const zigcli = b.dependency("zigcli", .{});

const lib_mod = b.createModule(.{
.root_source_file = b.path("src/lib.zig"),
.optimize = optimize,
.target = target,
});
const cppflags = [_][]const u8{
"-Wall", "-std=c++20", "-O3",
"-fvisibility=hidden", "-fvisibility-inlines-hidden", "-Wpedantic",
"-Werror", "-Wextra", "-Wshadow",
"-Wconversion", "-Wsign-conversion", "-Wno-unknown-pragmas",
"-fno-stack-protector", "-Wimplicit-fallthrough", "-Wmissing-declarations",
"-Wno-attributes", "-Wextra-semi", "-fno-exceptions",
"-fno-rtti",
"-Wno-deprecated", // this one is used to remove a warning about char_trait deprecation
"-DPROJECT_VERSION=\"0.14.0-dev\"",
};
evmone.addCSourceFiles(.{ .root = b.path(""), .files = &[_][]const u8{
"evmone/lib/evmone/advanced_analysis.cpp",
"evmone/lib/evmone/eof.cpp",
"evmone/lib/evmone/advanced_execution.cpp",
"evmone/lib/evmone/instructions_calls.cpp",
"evmone/lib/evmone/advanced_instructions.cpp",
"evmone/lib/evmone/instructions_storage.cpp",
"evmone/lib/evmone/baseline.cpp",
"evmone/lib/evmone/tracing.cpp",
"evmone/lib/evmone/baseline_instruction_table.cpp",
"evmone/lib/evmone/vm.cpp",
}, .flags = &cppflags });

evmone.addIncludePath(b.path("evmone/evmc/include"));
evmone.addIncludePath(b.path("evmone/include"));
evmone.addIncludePath(b.path("intx/include"));
evmone.addIncludePath(b.path("ethash/include"));
evmone.linkLibC();
evmone.linkLibCpp();
b.installArtifact(evmone);

const zigcli = b.dependency("zigcli", .{});
const lib = b.addLibrary(.{
.name = "phant",
.root_module = lib_mod,
});
// add itself as an import to solve a dependency cycle in tests
lib.root_module.addImport("lib", lib.root_module);
b.installArtifact(lib);

const exe = b.addExecutable(.{
.name = "phant",
Expand All @@ -144,25 +104,89 @@ pub fn build(b: *std.Build) !void {
.target = target,
.optimize = optimize,
});
exe.addIncludePath(b.path("evmone/include/evmone"));
exe.addIncludePath(b.path("evmone/evmc/include"));
if (target.result.cpu.arch == .x86_64) {
// On x86_64, some functions are missing from the static library,
// so we define dummy functions to make sure that it compiles.
exe.addCSourceFile(.{
.file = b.path("src/glue.c"),
.flags = &cflags,
const unit_tests = b.addTest(.{
.root_source_file = b.path("src/tests/lib_tests.zig"),
.target = target,
.optimize = optimize,
});

const is_target_host = (builtin.target.os.tag == target.result.os.tag and builtin.target.cpu.arch == target.result.cpu.arch and builtin.target.abi == target.result.abi);
const vm_mod = if (use_zevem or (!is_target_host and !force_evmone)) vm_mod: {
const vm_mod = b.createModule(.{
.root_source_file = b.path("src/blockchain/vm_zevem.zig"),
.target = target,
.optimize = optimize,
});
}
exe.linkLibrary(ethash);
exe.linkLibrary(evmone);
vm_mod.addImport("zevem", zevem.module("zevem"));
break :vm_mod vm_mod;
} else vm_mod: {
const vm_mod = b.createModule(.{
.root_source_file = b.path("src/blockchain/vm_evmc.zig"),
.target = target,
.optimize = optimize,
});
vm_mod.addIncludePath(b.path("evmone/include/evmone"));
vm_mod.addIncludePath(b.path("evmone/evmc/include"));
vm_mod.addLibraryPath(b.path("zig-out/evmone_build/lib"));
lib.linkSystemLibrary("evmone");

// use cmake to build evmone for now
const evmone_cmake_config_step = b.addSystemCommand(&.{"cmake"});
evmone_cmake_config_step.addArgs(&.{ "-S", "evmone", "-B", "zig-out/evmone_build" });

if (!is_target_host) {
// Cross-compilation: use zig cc as the C/C++ compiler
const cmake_system_name = switch (target.result.os.tag) {
.linux => "Linux",
.macos => "Darwin",
.windows => "Windows",
else => @tagName(target.result.os.tag),
};
const cmake_system_processor = switch (target.result.cpu.arch) {
.x86_64 => "x86_64",
.aarch64 => "aarch64",
.arm => "arm",
.riscv64 => "riscv64",
else => @tagName(target.result.cpu.arch),
};
const zig_target = b.fmt("{s}-{s}-{s}", .{
@tagName(target.result.cpu.arch),
@tagName(target.result.os.tag),
@tagName(target.result.abi),
});

evmone_cmake_config_step.addArgs(&.{
b.fmt("-DCMAKE_SYSTEM_NAME={s}", .{cmake_system_name}),
b.fmt("-DCMAKE_SYSTEM_PROCESSOR={s}", .{cmake_system_processor}),
b.fmt("-DCMAKE_C_COMPILER_TARGET={s}", .{zig_target}),
b.fmt("-DCMAKE_CXX_COMPILER_TARGET={s}", .{zig_target}),
"-DCMAKE_C_COMPILER=zig",
"-DCMAKE_CXX_COMPILER=zig",
"-DCMAKE_C_COMPILER_ARG1=cc",
"-DCMAKE_CXX_COMPILER_ARG1=c++",
b.fmt("-DCMAKE_C_FLAGS=-target {s}", .{zig_target}),
b.fmt("-DCMAKE_CXX_FLAGS=-target {s}", .{zig_target}),
});
}

const evmone_cmake_build_step = b.addSystemCommand(&.{ "cmake", "--build", "zig-out/evmone_build" });
evmone_cmake_build_step.step.dependOn(&evmone_cmake_config_step.step);
lib.step.dependOn(&evmone_cmake_build_step.step);
exe.step.dependOn(&evmone_cmake_build_step.step);
unit_tests.step.dependOn(&evmone_cmake_build_step.step);
break :vm_mod vm_mod;
};
vm_mod.addImport("lib", lib_mod);
lib_mod.addImport("vm", vm_mod);
exe.linkLibC();
exe.root_module.addImport("zig-rlp", dep_rlp.module("zig-rlp"));
exe.linkLibrary(lib);
lib_mod.addImport("zig-rlp", dep_rlp.module("zig-rlp"));
exe.linkLibrary(depSecp256k1.artifact("secp256k1"));
exe.root_module.addImport("zig-eth-secp256k1", mod_secp256k1);
lib_mod.addImport("zig-eth-secp256k1", mod_secp256k1);
exe.root_module.addImport("httpz", mod_httpz);
exe.root_module.addImport("simargs", zigcli.module("simargs"));
exe.root_module.addImport("pretty-table", zigcli.module("pretty-table"));
lib_mod.addImport("pretty-table", zigcli.module("pretty-table"));
exe.root_module.addImport("lib", lib_mod);

// This declares intent for the executable to be installed into the
// standard location when the user invokes the "install" step (the default
Expand Down Expand Up @@ -192,26 +216,11 @@ pub fn build(b: *std.Build) !void {
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);

// Creates a step for unit testing. This only builds the test executable
// but does not run it.
const unit_tests = b.addTest(.{
.root_source_file = b.path("src/lib.zig"),
.target = target,
.optimize = optimize,
});
unit_tests.addIncludePath(b.path("evmone/include/evmone"));
unit_tests.addIncludePath(b.path("evmone/evmc/include"));
if (target.result.cpu.arch == .x86_64) {
// On x86_64, some functions are missing from the static library,
// so we define dummy functions to make sure that it compiles.
unit_tests.addCSourceFile(.{
.file = b.path("src/glue.c"),
.flags = &cflags,
});
}
unit_tests.linkLibrary(ethash);
unit_tests.linkLibrary(evmone);
unit_tests.root_module.addImport("lib", lib_mod);
unit_tests.addLibraryPath(b.path("zig-out/evmone_build/lib"));
unit_tests.linkSystemLibrary("evmone");
unit_tests.linkLibC();
unit_tests.root_module.addImport("vm", vm_mod);
unit_tests.root_module.addImport("zig-rlp", dep_rlp.module("zig-rlp"));
unit_tests.linkLibrary(depSecp256k1.artifact("secp256k1"));
unit_tests.root_module.addImport("zig-eth-secp256k1", mod_secp256k1);
Expand Down
33 changes: 21 additions & 12 deletions build.zig.zon
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
.{
.name = "phant",
.fingerprint = 0x24619a25c388c236,
.name = .phant,
.version = "0.0.1-beta-0",
.dependencies = .{
.@"zig-rlp" = .{
.url = "https://github.com/gballet/zig-rlp/archive/refs/tags/v0.1.1-beta7.tar.gz",
.hash = "12201b3645a414dffc2bca872a1467b549d0029b9e36c80fcaeb22a06ec27fab9aee",
},
.@"zig-eth-secp256k1" = .{
.url = "https://github.com/jsign/zig-eth-secp256k1/archive/95b7f93.tar.gz",
.hash = "1220c0cf921a5311489bdd6eaf2f2b82bc9245ba39c2da346039aa311e28db633828",
.rlp = .{
.url = "https://github.com/gballet/zig-rlp/archive/v0.1.1-beta-8.tar.gz",
.hash = "rlp-0.1.0-7i0JtBGSAACU44qijBzojQzyn2kLZ-wnIn5qOJxpWnky",
},
.httpz = .{
.url = "https://github.com/karlseguin/http.zig/archive/c224ebb.tar.gz",
.hash = "12206297df84406cd4eed306acef30eb2a1a6a18b6771ebb4920391a3a7299b2e6a7",
.url = "git+https://github.com/karlseguin/http.zig?ref=master#9434eaa607f855da77b80387b0be7f7cf2aaaa63",
.hash = "httpz-0.0.0-PNVzrFy3BgC7H3cLoiB1odzkl37NJdPx-OHG6eRXeQLX",
},
.zigcli = .{
.url = "https://github.com/jiacai2050/zigcli/archive/54d095c.tar.gz",
.hash = "1220e8fb37224ab6ee9c575129594a808643b548596d63dd8b87cb42e22a7eed9f51",
.url = "https://github.com/jiacai2050/zigcli/archive/refs/tags/v0.2.0.tar.gz",
.hash = "zigcli-0.2.0-ORC7jKlzAgDYhWCmfjBE9jWPA7CqMQKlMTT3Rcadfgzv",
},
.zig_eth_secp256k1 = .{
.url = "git+https://github.com/gballet/zig-eth-secp256k1?ref=add-freestanding-support#4e7e77f50bd0e852fb6a824b9c2ac2c4f8c91bf9",
.hash = "zig_eth_secp256k1-0.1.0-_U97sBzsDACmwsVCfA9UA3UPr8pK8qaSeLHx97Q_Nnzu",
},
.zevem = .{
.url = "https://github.com/gballet/zevem/archive/73b9805.tar.gz",
.hash = "zevem-0.0.0-ur64biZ6AQCSZip8ILCEonv9qtqIHWeymNEbN6ETxfwK",
},
.curl = .{
.url = "https://github.com/jiacai2050/zig-curl/archive/refs/tags/v0.3.0.tar.gz",
.hash = "curl-0.3.0-P4tT4ZzSAADueeRzPHnzLFj9lRTJyA3rnOYycH0yu-N4",
},
},
.paths = .{""},
Expand Down
9 changes: 5 additions & 4 deletions src/blockchain/blockchain.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ const common = @import("../common/common.zig");
const blocks = @import("../types/block.zig");
const config = @import("../config/config.zig");
const transaction = @import("../types/transaction.zig");
const vm = @import("vm.zig");
const vm = @import("vm");
const rlp = @import("zig-rlp");
const signer = @import("../signer/signer.zig");
const params = @import("params.zig");
const blockchain_types = @import("types.zig");
pub const params = @import("params.zig");
const lib = @import("lib");
const blockchain_types = lib.blockchain_types;
const mpt = @import("../mpt/mpt.zig");
const Allocator = std.mem.Allocator;
const AddressSet = common.AddressSet;
Expand All @@ -20,7 +21,7 @@ const Tx = types.Tx;
pub const BlockHeader = types.BlockHeader;
const Environment = blockchain_types.Environment;
const Message = blockchain_types.Message;
const StateDB = @import("../state/state.zig").StateDB;
const StateDB = lib.state.StateDB;
const Hash32 = types.Hash32;
const Bytes32 = types.Bytes32;
const Address = types.Address;
Expand Down
Loading
Loading