Skip to content
Open
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ node_modules/
# Claude Code local config
.claude/settings.local.json
.claude/plans/
zig-pkg/
10 changes: 8 additions & 2 deletions src/state_transition/epoch/process_rewards_and_penalties.zig
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,20 @@ pub fn processRewardsAndPenalties(
const balances = try state.balancesSlice(allocator);
defer allocator.free(balances);

// Use saturating arithmetic for performance. Saturating operations are branchless, which
// enables SIMD auto-vectorization of the balance update loop. This is safe because a
// balance overflow is mathematically impossible: the maximum total ETH supply (~1.2e17 Gwei)
// is more than 150x smaller than the max u64 value (~1.8e19 Gwei).
if (slashing_penalties) |slashings| {
for (rewards, penalties, balances, 0..) |reward, penalty, *balance, i| {
const slashing: u64 = if (i < slashings.len) slashings[i] else 0;
balance.* = (try std.math.add(u64, balance.*, reward)) -| penalty -| slashing;
std.debug.assert(balance.* <= std.math.maxInt(u64) - reward);
balance.* = ((balance.* +| reward) -| penalty) -| slashing;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To uphold the style guide's emphasis on safety (Safety, performance, and developer experience. In that order., line 5), it's best to add a std.debug.assert here. This will verify the no-overflow assumption during testing without impacting performance in ReleaseFast builds. This also serves as executable documentation for the invariant you've identified.

From the style guide:

Assert all function arguments and return values, pre/postconditions and invariants. (line 51)

I've also removed a redundant set of parentheses for cleaner code.

            std.debug.assert(balance.* <= std.math.maxInt(u64) - reward);
            balance.* = (balance.* +| reward) -| penalty -| slashing;
References
  1. The style guide prioritizes safety over performance and mandates asserting all pre/postconditions and invariants. Adding a debug assertion maintains safety during testing without compromising release performance. (link)

}
} else {
for (rewards, penalties, balances) |reward, penalty, *balance| {
balance.* = (try std.math.add(u64, balance.*, reward)) -| penalty;
std.debug.assert(balance.* <= std.math.maxInt(u64) - reward);
balance.* = (balance.* +| reward) -| penalty;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similarly, please add a std.debug.assert here to ensure safety during testing, in line with the style guide's emphasis on assertions.

            std.debug.assert(balance.* <= std.math.maxInt(u64) - reward);
            balance.* = (balance.* +| reward) -| penalty;
References
  1. The style guide prioritizes safety over performance and mandates asserting all pre/postconditions and invariants. Adding a debug assertion maintains safety during testing without compromising release performance. (link)

}
}

Expand Down
Loading