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
22 changes: 11 additions & 11 deletions src/ssz/tree_view/array_basic.zig
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@ pub fn ArrayBasicTreeView(comptime ST: type) type {

pub fn hashTreeRootInto(self: *Self, out: *[32]u8) !void {
try self.commit();
out.* = self.chunks.root.getRoot(self.chunks.pool).*;
out.* = self.chunks.state.root.getRoot(self.chunks.state.pool).*;
}

pub fn hashTreeRoot(self: *Self) !*const [32]u8 {
try self.commit();
return self.chunks.root.getRoot(self.chunks.pool);
return self.chunks.state.root.getRoot(self.chunks.state.pool);
}

pub fn fromValue(allocator: Allocator, pool: *Node.Pool, value: *const ST.Type) !*Self {
Expand All @@ -89,11 +89,11 @@ pub fn ArrayBasicTreeView(comptime ST: type) type {

pub fn toValue(self: *Self, _: Allocator, out: *ST.Type) !void {
try self.commit();
try ST.tree.toValue(self.chunks.root, self.chunks.pool, out);
try ST.tree.toValue(self.chunks.state.root, self.chunks.state.pool, out);
}

pub fn getRoot(self: *const Self) Node.Id {
return self.chunks.root;
return self.chunks.state.root;
}

pub fn get(self: *Self, index: usize) !Element {
Expand All @@ -119,7 +119,7 @@ pub fn ArrayBasicTreeView(comptime ST: type) type {
/// Returns the number of bytes written.
pub fn serializeIntoBytes(self: *Self, out: []u8) !usize {
try self.commit();
return try ST.tree.serializeIntoBytes(self.chunks.root, self.chunks.pool, out);
return try ST.tree.serializeIntoBytes(self.chunks.state.root, self.chunks.state.pool, out);
}

/// Get the serialized size of this tree view.
Expand Down Expand Up @@ -330,13 +330,13 @@ test "TreeView vector clone(true) does not transfer cache" {
defer v.deinit();

_ = try v.get(0);
try std.testing.expect(v.chunks.children_nodes.count() > 0);
try std.testing.expect(v.chunks.state.children_nodes.count() > 0);

var cloned_no_cache = try v.clone(.{ .transfer_cache = false });
defer cloned_no_cache.deinit();

try std.testing.expect(v.chunks.children_nodes.count() > 0);
try std.testing.expectEqual(@as(usize, 0), cloned_no_cache.chunks.children_nodes.count());
try std.testing.expect(v.chunks.state.children_nodes.count() > 0);
try std.testing.expectEqual(@as(usize, 0), cloned_no_cache.chunks.state.children_nodes.count());
}

test "TreeView vector clone(false) transfers cache and clears source" {
Expand All @@ -354,13 +354,13 @@ test "TreeView vector clone(false) transfers cache and clears source" {
defer v.deinit();

_ = try v.get(0);
try std.testing.expect(v.chunks.children_nodes.count() > 0);
try std.testing.expect(v.chunks.state.children_nodes.count() > 0);

var cloned = try v.clone(.{});
defer cloned.deinit();

try std.testing.expectEqual(@as(usize, 0), v.chunks.children_nodes.count());
try std.testing.expect(cloned.chunks.children_nodes.count() > 0);
try std.testing.expectEqual(@as(usize, 0), v.chunks.state.children_nodes.count());
try std.testing.expect(cloned.chunks.state.children_nodes.count() > 0);
}

// Tests ported from TypeScript ssz packages/ssz/test/unit/byType/vector/tree.test.ts
Expand Down
16 changes: 8 additions & 8 deletions src/ssz/tree_view/array_composite.zig
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ pub fn ArrayCompositeTreeView(comptime ST: type) type {

pub fn hashTreeRootInto(self: *Self, out: *[32]u8) !void {
try self.commit();
out.* = self.chunks.root.getRoot(self.chunks.pool).*;
out.* = self.chunks.state.root.getRoot(self.chunks.state.pool).*;
}

pub fn hashTreeRoot(self: *Self) !*const [32]u8 {
try self.commit();
return self.chunks.root.getRoot(self.chunks.pool);
return self.chunks.state.root.getRoot(self.chunks.state.pool);
}

pub fn fromValue(allocator: Allocator, pool: *Node.Pool, value: *const ST.Type) !*Self {
Expand All @@ -96,14 +96,14 @@ pub fn ArrayCompositeTreeView(comptime ST: type) type {
pub fn toValue(self: *Self, allocator: Allocator, out: *ST.Type) !void {
try self.commit();
if (comptime isFixedType(ST)) {
try ST.tree.toValue(self.chunks.root, self.chunks.pool, out);
try ST.tree.toValue(self.chunks.state.root, self.chunks.state.pool, out);
} else {
try ST.tree.toValue(allocator, self.chunks.root, self.chunks.pool, out);
try ST.tree.toValue(allocator, self.chunks.state.root, self.chunks.state.pool, out);
}
}

pub fn getRoot(self: *const Self) Node.Id {
return self.chunks.root;
return self.chunks.state.root;
}

pub fn get(self: *Self, index: usize) !Element {
Expand All @@ -130,7 +130,7 @@ pub fn ArrayCompositeTreeView(comptime ST: type) type {
if (index >= length) return error.IndexOutOfBounds;
const elem = try self.chunks.get(index);
try elem.commit();
return elem.getRoot().getRoot(self.chunks.pool);
return elem.getRoot().getRoot(self.chunks.state.pool);
}

pub fn set(self: *Self, index: usize, value: Element) !void {
Expand All @@ -150,7 +150,7 @@ pub fn ArrayCompositeTreeView(comptime ST: type) type {
/// Returns the number of bytes written.
pub fn serializeIntoBytes(self: *Self, out: []u8) !usize {
try self.commit();
return try ST.tree.serializeIntoBytes(self.chunks.root, self.chunks.pool, out);
return try ST.tree.serializeIntoBytes(self.chunks.state.root, self.chunks.state.pool, out);
}

/// Get the serialized size of this tree view.
Expand All @@ -159,7 +159,7 @@ pub fn ArrayCompositeTreeView(comptime ST: type) type {
if (comptime isFixedType(ST)) {
return ST.fixed_size;
} else {
return ST.tree.serializedSize(self.chunks.root, self.chunks.pool);
return ST.tree.serializedSize(self.chunks.state.root, self.chunks.state.pool);
}
}
};
Expand Down
60 changes: 20 additions & 40 deletions src/ssz/tree_view/bit_array.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6,55 +6,35 @@ const Depth = hashing.Depth;

const Node = @import("persistent_merkle_tree").Node;
const Gindex = @import("persistent_merkle_tree").Gindex;
const ChildNodes = @import("utils/child_nodes.zig").ChildNodes;
const TreeViewState = @import("utils/tree_view_state.zig").TreeViewState;
const CloneOpts = @import("utils/clone_opts.zig").CloneOpts;

/// Provides common bit array operations for both BitVectorTreeView and BitListTreeView.
pub fn BitArray(comptime chunk_depth: Depth) type {
return struct {
const bits_per_chunk: usize = 256;
allocator: Allocator,
pool: *Node.Pool,
root: Node.Id,

/// cached nodes for faster access of already-visited children
children_nodes: std.AutoHashMapUnmanaged(Gindex, Node.Id),

/// whether the corresponding child node/data has changed since the last update of the root
changed: std.AutoArrayHashMapUnmanaged(Gindex, void),
state: TreeViewState,

const Self = @This();

pub fn init(self: *Self, allocator: Allocator, pool: *Node.Pool, root: Node.Id) !void {
try pool.ref(root);
errdefer pool.unref(root);
self.* = .{
.allocator = allocator,
.pool = pool,
.root = root,
.children_nodes = .empty,
.changed = .empty,
};
try self.state.init(allocator, pool, root);
}

pub fn clone(self: *Self, opts: CloneOpts, out: *Self) !void {
try ChildNodes.Change.cloneAndTransferCache(Self, self, opts, out);
try self.state.clone(opts, &out.state);
}

pub fn deinit(self: *Self) void {
self.pool.unref(self.root);
self.clearChildrenNodesCache();
self.children_nodes.deinit(self.allocator);
self.changed.deinit(self.allocator);
self.state.deinit();
}

pub fn commit(self: *Self) !void {
try ChildNodes.Change.commit(self);
try self.state.commitNodes();
}

pub fn clearCache(self: *Self) void {
self.clearChildrenNodesCache();
self.changed.clearRetainingCapacity();
self.state.clearCache();
}

pub fn get(self: *Self, index: usize, len: usize) !bool {
Expand All @@ -65,8 +45,8 @@ pub fn BitArray(comptime chunk_depth: Depth) type {
const byte_in_chunk = bit_in_chunk / 8;
const bit_in_byte: u3 = @intCast(bit_in_chunk % 8);

const leaf_node = try self.getChildNode(Gindex.fromDepth(chunk_depth, chunk_index));
const leaf = leaf_node.getRoot(self.pool);
const leaf_node = try self.state.getChildNode(Gindex.fromDepth(chunk_depth, chunk_index));
const leaf = leaf_node.getRoot(self.state.pool);
const mask = @as(u8, 1) << bit_in_byte;
return (leaf[byte_in_chunk] & mask) != 0;
}
Expand All @@ -80,8 +60,8 @@ pub fn BitArray(comptime chunk_depth: Depth) type {
const bit_in_byte: u3 = @intCast(bit_in_chunk % 8);

const gindex = Gindex.fromDepth(chunk_depth, chunk_index);
const leaf_node = try self.getChildNode(gindex);
var leaf_bytes = leaf_node.getRoot(self.pool).*;
const leaf_node = try self.state.getChildNode(gindex);
var leaf_bytes = leaf_node.getRoot(self.state.pool).*;

const mask = @as(u8, 1) << bit_in_byte;
if (value) {
Expand All @@ -90,8 +70,8 @@ pub fn BitArray(comptime chunk_depth: Depth) type {
leaf_bytes[byte_in_chunk] &= ~mask;
}

const new_leaf = try self.pool.createLeaf(&leaf_bytes);
try self.setChildNode(gindex, new_leaf);
const new_leaf = try self.state.pool.createLeaf(&leaf_bytes);
try self.state.setChildNode(gindex, new_leaf);
}

pub fn fillBools(self: *Self, values: []bool, len: usize) !void {
Expand All @@ -103,8 +83,8 @@ pub fn BitArray(comptime chunk_depth: Depth) type {
var dest = values;

for (0..full_chunks) |chunk_idx| {
const leaf_node = try self.getChildNode(Gindex.fromDepth(chunk_depth, chunk_idx));
const leaf = leaf_node.getRoot(self.pool);
const leaf_node = try self.state.getChildNode(Gindex.fromDepth(chunk_depth, chunk_idx));
const leaf = leaf_node.getRoot(self.state.pool);

for (leaf) |b| {
inline for (0..8) |j| {
Expand All @@ -115,8 +95,8 @@ pub fn BitArray(comptime chunk_depth: Depth) type {
}

if (remainder_bits != 0) {
const leaf_node = try self.getChildNode(Gindex.fromDepth(chunk_depth, full_chunks));
const leaf = leaf_node.getRoot(self.pool);
const leaf_node = try self.state.getChildNode(Gindex.fromDepth(chunk_depth, full_chunks));
const leaf = leaf_node.getRoot(self.state.pool);

const full_bytes = remainder_bits / 8;
const tail_bits = remainder_bits % 8;
Expand All @@ -138,15 +118,15 @@ pub fn BitArray(comptime chunk_depth: Depth) type {
}

pub fn getChildNode(self: *Self, gindex: Gindex) !Node.Id {
return ChildNodes.getChildNode(self, gindex);
return self.state.getChildNode(gindex);
}

pub fn setChildNode(self: *Self, gindex: Gindex, node: Node.Id) !void {
try ChildNodes.setChildNode(self, gindex, node);
try self.state.setChildNode(gindex, node);
}

pub fn clearChildrenNodesCache(self: *Self) void {
ChildNodes.clearChildrenNodesCache(self, self.pool);
self.state.clearChildrenNodesCache();
}
};
}
18 changes: 9 additions & 9 deletions src/ssz/tree_view/bit_list.zig
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,16 @@ pub fn BitListTreeView(comptime ST: type) type {

pub fn hashTreeRoot(self: *Self, out: *[32]u8) !void {
try self.commit();
out.* = self.data.root.getRoot(self.data.pool).*;
out.* = self.data.state.root.getRoot(self.data.state.pool).*;
}

pub fn getRoot(self: *const Self) Node.Id {
return self.data.root;
return self.data.state.root;
}

fn readLength(self: *Self) !usize {
const length_node = try self.data.getChildNode(@enumFromInt(3));
const length_chunk = length_node.getRoot(self.data.pool);
const length_chunk = length_node.getRoot(self.data.state.pool);
return std.mem.readInt(usize, length_chunk[0..@sizeOf(usize)], .little);
}

Expand Down Expand Up @@ -167,13 +167,13 @@ test "BitListTreeView clone(true) does not transfer cache" {
defer view.deinit();

_ = try view.get(0);
try std.testing.expect(view.data.children_nodes.count() > 0);
try std.testing.expect(view.data.state.children_nodes.count() > 0);

var cloned_no_cache = try view.clone(.{ .transfer_cache = false });
defer cloned_no_cache.deinit();

try std.testing.expect(view.data.children_nodes.count() > 0);
try std.testing.expectEqual(@as(usize, 0), cloned_no_cache.data.children_nodes.count());
try std.testing.expect(view.data.state.children_nodes.count() > 0);
try std.testing.expectEqual(@as(usize, 0), cloned_no_cache.data.state.children_nodes.count());
}

test "BitListTreeView clone(false) transfers cache and clears source" {
Expand All @@ -193,13 +193,13 @@ test "BitListTreeView clone(false) transfers cache and clears source" {
defer view.deinit();

_ = try view.get(0);
try std.testing.expect(view.data.children_nodes.count() > 0);
try std.testing.expect(view.data.state.children_nodes.count() > 0);

var cloned = try view.clone(.{});
defer cloned.deinit();

try std.testing.expectEqual(@as(usize, 0), view.data.children_nodes.count());
try std.testing.expect(cloned.data.children_nodes.count() > 0);
try std.testing.expectEqual(@as(usize, 0), view.data.state.children_nodes.count());
try std.testing.expect(cloned.data.state.children_nodes.count() > 0);
}

test "BitListTreeView clone isolates updates" {
Expand Down
18 changes: 9 additions & 9 deletions src/ssz/tree_view/bit_vector.zig
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ pub fn BitVectorTreeView(comptime ST: type) type {

pub fn hashTreeRoot(self: *Self, out: *[32]u8) !void {
try self.commit();
out.* = self.data.root.getRoot(self.data.pool).*;
out.* = self.data.state.root.getRoot(self.data.state.pool).*;
}

pub fn getRoot(self: *const Self) Node.Id {
return self.data.root;
return self.data.state.root;
}

pub fn get(self: *Self, index: usize) !Element {
Expand All @@ -89,7 +89,7 @@ pub fn BitVectorTreeView(comptime ST: type) type {

pub fn toValue(self: *Self, _: Allocator, out: *ST.Type) !void {
try self.commit();
try ST.tree.toValue(self.data.root, self.data.pool, out);
try ST.tree.toValue(self.data.state.root, self.data.state.pool, out);
}

/// Caller must free the returned slice.
Expand Down Expand Up @@ -164,13 +164,13 @@ test "BitVectorTreeView clone(true) does not transfer cache" {
defer view.deinit();

_ = try view.get(0);
try std.testing.expect(view.data.children_nodes.count() > 0);
try std.testing.expect(view.data.state.children_nodes.count() > 0);

var cloned_no_cache = try view.clone(.{ .transfer_cache = false });
defer cloned_no_cache.deinit();

try std.testing.expect(view.data.children_nodes.count() > 0);
try std.testing.expectEqual(@as(usize, 0), cloned_no_cache.data.children_nodes.count());
try std.testing.expect(view.data.state.children_nodes.count() > 0);
try std.testing.expectEqual(@as(usize, 0), cloned_no_cache.data.state.children_nodes.count());
}

test "BitVectorTreeView clone(false) transfers cache and clears source" {
Expand All @@ -190,13 +190,13 @@ test "BitVectorTreeView clone(false) transfers cache and clears source" {
defer view.deinit();

_ = try view.get(0);
try std.testing.expect(view.data.children_nodes.count() > 0);
try std.testing.expect(view.data.state.children_nodes.count() > 0);

var cloned = try view.clone(.{});
defer cloned.deinit();

try std.testing.expectEqual(@as(usize, 0), view.data.children_nodes.count());
try std.testing.expect(cloned.data.children_nodes.count() > 0);
try std.testing.expectEqual(@as(usize, 0), view.data.state.children_nodes.count());
try std.testing.expect(cloned.data.state.children_nodes.count() > 0);
}

test "BitVectorTreeView clone isolates updates" {
Expand Down
Loading
Loading