Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
workflow_dispatch:

env:
ZIG_VERSION: 0.14.1
ZIG_VERSION: 0.15.2

jobs:
build:
Expand All @@ -20,7 +20,7 @@ jobs:
- name: Set up Zig
uses: mlugg/setup-zig@v2.0.5
with:
version: 0.14.1
version: 0.15.2

- name: Formatting
run: zig fmt --check --color on .
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# enr

Ethereum Node Records (ENR) utility in Zig.

## Prerequisites

- Zig 0.14.1
- Zig 0.15.2

## Building

Expand Down
8 changes: 7 additions & 1 deletion build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ pub fn build(b: *std.Build) !void {
.optimize = optimize,
});

const peer_id_dep = multiformats_dep.builder.dependency("peer_id", .{
const multiaddr_dep = b.dependency("multiaddr", .{
.target = target,
.optimize = optimize,
});

const peer_id_dep = b.dependency("peer_id", .{
.target = target,
.optimize = optimize,
});
Expand All @@ -28,6 +33,7 @@ pub fn build(b: *std.Build) !void {
lib_mod.addImport("secp256k1", secp256k1_dep.module("secp256k1"));
lib_mod.addImport("peer-id", peer_id_dep.module("peer-id"));
lib_mod.addImport("multiformats", multiformats_dep.module("multiformats-zig"));
lib_mod.addImport("multiaddr", multiaddr_dep.module("multiaddr"));
lib_mod.linkLibrary(secp256k1_dep.artifact("libsecp"));

const lib = b.addLibrary(.{
Expand Down
18 changes: 13 additions & 5 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,24 @@

.fingerprint = 0x499ae5d2db8fed70,

.minimum_zig_version = "0.14.1",
.minimum_zig_version = "0.15.2",

.dependencies = .{
.secp256k1 = .{
.url = "git+https://github.com/zig-bitcoin/libsecp256k1-zig#b96922b375a601f3303bf43be1dceb3d101df6c6",
.hash = "secp256k1-0.0.0-AAAAAPPgAAADPOkS7brnO1B26LjbhZsxwz6Kx8a6jCwB",
.url = "git+https://github.com/blockblaz/libsecp256k1-zig#518a1370b66c6b575b4831c4a1a182f5b30b3d75",
.hash = "secp256k1-0.0.3-vtxi58DhAABoPpDgG3wagaDXiHHIDezLOPE0BI4V0bDS",
},
.zmultiformats = .{
.url = "git+https://github.com/zen-eth/multiformats-zig#92c90226ee8b14052718df724a1bc753996a6e07",
.hash = "zmultiformats-0.1.0-U2uyh94UBQCwBOXy5xZ9SZQJkQXZSiYCudWPWxNqjuE0",
.url = "git+https://github.com/zen-eth/multiformats-zig#ddf4f0af34ce8f87c2dc7df73a261738c3868093",
.hash = "zmultiformats-0.1.0-yjvchohoBADALnCylBLeQF7Vn0SKULmQ_sFOrhzgmvQO",
},
.multiaddr = .{
.url = "git+https://github.com/zen-eth/multiaddr-zig#c5e16a3a506cca8d37b732ea343818033782e874",
.hash = "multiaddr-0.1.0-Cjayds-5AAArNw0ghMgquaRygVf7-kEWQJlQGjVpZzZ0",
},
.peer_id = .{
.url = "git+https://github.com/blockblaz/peer-id#41f336b92315dcbc852345a2468487c697cfdcbe",
.hash = "peer_id-0.0.0-vHIk8ZdfAADctTzIgznksWwEzygVynEeSKDim42Pz-QL",
},
},
.paths = .{
Expand Down
47 changes: 35 additions & 12 deletions src/enr.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
const std = @import("std");

const rlp = @import("rlp.zig");
const multiaddr = @import("multiformats").multiaddr;
const Multiaddr = multiaddr.Multiaddr;
const multiaddr_mod = @import("multiaddr");
const multiaddr = multiaddr_mod.multiaddr;
const Multiaddr = multiaddr_mod.Multiaddr;
const peer_id = @import("peer-id");
const PeerId = peer_id.PeerId;

Expand All @@ -16,6 +17,8 @@ const secp256k1 = @import("secp256k1.zig");

const digest_size = secp256k1.digest_size;
pub const max_enr_size = 300;
pub const enr_txt_prefix_len = 4; // "enr:"
pub const max_enr_txt_size = enr_txt_prefix_len + std.base64.url_safe_no_pad.Encoder.calcSize(max_enr_size);
pub const signature_size = 64;
// non-kv bytes
// list_len_len, list_len, sig_len_len, sig_len, sig, seq, id_len, id_byte
Expand Down Expand Up @@ -46,9 +49,22 @@ pub const KVs = struct {
}

pub fn put(self: *KVs, key: []const u8, value: []const u8) !void {
const owned_key = try self.allocator.dupe(u8, key);
const owned_value = try self.allocator.dupe(u8, value);
try self.map.put(owned_key, owned_value);
errdefer self.allocator.free(owned_value);

const gop = try self.map.getOrPut(key);
if (gop.found_existing) {
self.allocator.free(gop.value_ptr.*);
gop.value_ptr.* = owned_value;
} else {
const owned_key = self.allocator.dupe(u8, key) catch |err| {
// Remove the uninitialized slot that getOrPut created.
self.map.removeByPtr(gop.key_ptr);
return err;
};
gop.key_ptr.* = owned_key;
gop.value_ptr.* = owned_value;
}
}

pub fn get(self: *const KVs, key: []const u8) ?[]const u8 {
Expand All @@ -61,15 +77,16 @@ pub const KVs = struct {

pub const Iterator = struct {
keys: std.ArrayList([]const u8),
allocator: std.mem.Allocator,
map: *const std.StringHashMap([]const u8),
index: usize,

pub fn init(kvs: *const KVs) Iterator {
var keys = std.ArrayList([]const u8).init(kvs.allocator);
var keys: std.ArrayList([]const u8) = .empty;

var map_it = kvs.map.iterator();
while (map_it.next()) |entry| {
keys.append(entry.key_ptr.*) catch unreachable;
keys.append(kvs.allocator, entry.key_ptr.*) catch unreachable;
}

std.sort.heap([]const u8, keys.items, {}, struct {
Expand All @@ -81,6 +98,7 @@ pub const KVs = struct {

return Iterator{
.keys = keys,
.allocator = kvs.allocator,
.map = &kvs.map,
.index = 0,
};
Expand All @@ -97,7 +115,7 @@ pub const KVs = struct {
}

pub fn deinit(self: *Iterator) void {
self.keys.deinit();
self.keys.deinit(self.allocator);
}
};

Expand Down Expand Up @@ -326,6 +344,8 @@ pub const ENR = struct {
const seq = std.mem.readVarInt(u64, seq_bytes, .big);

var kvs = KVs.init();
errdefer kvs.deinit();

while (!list_reader.finished()) {
const key = list_reader.read(.{ .short_string, .long_string }) catch unreachable;
const value = list_reader.read(.{ .single_byte, .short_string, .long_string }) catch unreachable;
Expand Down Expand Up @@ -362,13 +382,15 @@ pub const ENR = struct {
}

pub fn decodeTxtInto(enr: *ENR, source: []const u8) !void {
if (!std.mem.eql(u8, source[0..4], "enr:")) {
if (source.len < 4 or !std.mem.eql(u8, source[0..4], "enr:")) {
return Error.BadPrefix;
}

var buffer: [max_enr_size]u8 = undefined;
const decoder = std.base64.url_safe_no_pad.Decoder;
const size = try decoder.calcSizeForSlice(source[4..]);
if (size > max_enr_size) return Error.TooLong;

var buffer: [max_enr_size]u8 = undefined;
try decoder.decode(buffer[0..size], source[4..]);

try decodeInto(enr, buffer[0..size]);
Expand Down Expand Up @@ -810,12 +832,13 @@ fn kvsLen(kvs: *const KVs) usize {
}

pub fn decodeTxtIntoRlp(dest: []u8, source: []const u8) ![]u8 {
if (!std.mem.eql(u8, source[0..4], "enr:")) {
if (source.len < 4 or !std.mem.eql(u8, source[0..4], "enr:")) {
return Error.BadPrefix;
}

const decoder = std.base64.url_safe_no_pad.Decoder;
const size = try decoder.calcSizeForSlice(source[4..]);
if (size > dest.len) return Error.TooLong;
try decoder.decode(dest[0..size], source[4..]);

return dest[0..size];
Expand Down Expand Up @@ -981,7 +1004,7 @@ pub const EncodedENR = struct {
}

pub fn decodeTxtInto(source: []const u8) !Self {
if (!std.mem.eql(u8, source[0..4], "enr:")) {
if (source.len < 4 or !std.mem.eql(u8, source[0..4], "enr:")) {
return Error.BadPrefix;
}

Expand Down Expand Up @@ -1297,7 +1320,7 @@ test "ENR test vector" {
defer std.testing.allocator.free(ma);
}

var enr3_encoded_buf: [max_enr_size]u8 = undefined;
var enr3_encoded_buf: [max_enr_txt_size]u8 = undefined;
const enr3_encoded = try signable_enr3.encodeToTxt(&enr3_encoded_buf);
var enr4: ENR = undefined;
try ENR.decodeTxtInto(&enr4, enr3_encoded);
Expand Down
Loading