From e1370f99717b29f4f5ead7d5ae6fa6e94ed3481a Mon Sep 17 00:00:00 2001 From: Koko Bhadra Date: Wed, 10 Jun 2026 14:51:55 -0400 Subject: [PATCH] Release v0.6.0: version bump and changelog consolidation Consolidate the Unreleased section into a clean 0.6.0 entry: - Added: nonce_manager (#75), mev_share (#34), eth_sendPrivateTransaction (#40), MEV-Share backrunner example (#38) - Changed: benchmark refresh vs alloy 1.6/2.0 (18/26) - Fixed: the test-harness fix (#84) plus the four issues it surfaced (#80-83) and the sse_transport feedLine break Align versions: build.zig.zon 0.5.0 -> 0.6.0, README/docs install URLs, SECURITY.md supported versions -> 0.6.x. --- CHANGELOG.md | 21 +++++++++------------ README.md | 4 ++-- SECURITY.md | 4 ++-- build.zig.zon | 2 +- docs/content/docs/installation.mdx | 4 ++-- 5 files changed, 16 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc9735b..5f2ab57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,18 +5,7 @@ All notable changes to eth.zig will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] - -### Fixed -- DEX `getAmountIn`/`getAmountOut` are correct standard Uniswap V2; the `getAmountIn inverse` round-trip test used unrealistic tiny-reserve parameters where flooring a small output legitimately breaks the within-2-units invariant. Corrected the test to balanced reserves and un-quarantined it (#83). The full unit suite now runs with zero skips. -- BIP-39 seed derivation (`mnemonic.toSeed`) was correct; its Trezor passphrase test had a wrong expected vector. Corrected the test to the canonical vector (verified against `std.crypto` PBKDF2) and un-quarantined it (#82). -- `mulDiv` now returns the correct result when the intermediate product overflows u256 with a full-width divisor, e.g. `mulDiv(MAX, MAX, MAX)` (#81). The limb-native Knuth-D divider mis-handled this boundary; the rare overflow path now computes exactly in native u512 (the benchmarked u128 fast path is unchanged). -- Pure-Zig Keccak-256 fallback (`keccak_optimized.zig`) now produces correct digests (#80): replaced the broken lane-complementing chi optimization with the standard chi step (which lowers to ANDN anyway). Verified against pinned vectors and cross-validated with stdlib across all block sizes. -- **Unit tests now actually run.** The test step aggregated module tests via `_ = eth.module` field access, which only forces semantic analysis -- it never collected the per-module `test` blocks, so assertions compiled but never executed (`zig build test` was green even with a deliberately failing test). The test artifact is now rooted at `src/root.zig`, whose test block direct-imports every module file. This surfaced real, previously-hidden defects, now fixed: `abi_json` still used the 0.15 `ArrayList` API (broken on 0.16); `rlp.bytesToUint` failed to compile for small integer types; `mnemonic.entropyToMnemonic` had a comptime-resolution bug and a u8 overflow for 24-word phrases; `parseInputs`/`parseParam` formed an inferred-error-set dependency loop; `rlp` struct reflection used the pre-0.17 `Type.Struct.fields` layout (now via `std.meta.fieldNames`, portable across 0.16 and 0.17-dev). Fixed several stale test expectations (`formatHash`/log-address length typos, a static-tuple ABI length, a fixed-size hex length error). Vendored XKCP/secp256k1 C is now built with `-fno-sanitize=undefined` so their intentional unaligned loads do not trap the Debug UBSan runtime. -- Resolved the four pre-existing issues the revived test suite exposed: two were real code bugs (broken pure-Zig Keccak fallback #80, `mulDiv` at the u256 boundary #81) and two were bad tests (a BIP-39 passphrase seed vector #82, a DEX round-trip assumption #83). All are fixed and the full unit suite now runs with zero skips (775/775). - -### Changed -- Benchmark comparison refreshed against current alloy crates (alloy-primitives 1.6.0, alloy-sol-types 1.6.0, alloy-dyn-abi 1.6.0, alloy-consensus 2.0.5, alloy-signer 2.0.5, alloy-rlp 0.3.15); bench/alloy-bench migrated from alloy-primitives 0.8 / alloy 0.6. New score: eth.zig wins 18/26 (alloy improved Keccak on larger inputs, hex encoding, RLP u256 decoding, and UniswapV4-style swap math) +## [0.6.0] - 2026-06-10 ### Added - `nonce_manager` module: atomic nonce manager for concurrent senders (#75). `NonceManager.init` seeds lazily from the `pending` transaction count (no RPC in `init`); `next()` is a lock-free atomic fetch-and-add so multiple threads never receive the same nonce; `peek()` reads the next nonce without advancing; `resync()`/`reset()` re-fetch from chain after dropped txs; and `onFailure(nonce)` returns a nonce to the pool only when it is the most recently issued one (a middle nonce cannot be safely reused once a higher one is in flight). Also adds `provider.getTransactionCountAt(address, tag)` so the nonce count can be read at any block tag (e.g. `.pending`) @@ -24,7 +13,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `mev_share` module: MEV-Share client mirroring `mev-share-client-ts` -- `sendTransaction` (eth_sendPrivateTransaction via `flashbots.Relay`), `simulateBundle` (mev_simBundle with `SimBundleOpts`/`SimBundleResult`), blocking SSE event stream subscription (`MevShareClient.on` with `PendingEvent`/`PendingTransaction`/`PendingBundle` and pure `parseEventData`), and `getEventHistory` (GET /api/v1/history) (#34) - `eth_sendPrivateTransaction` (MEV-Share private transactions) on `flashbots.Relay`: submit a single private transaction with hint preferences (calldata, contract_address, logs, function_selector), builder selection, fast mode, and max inclusion block (#40) +### Changed +- Benchmark comparison refreshed against current alloy crates (alloy-primitives 1.6.0, alloy-sol-types 1.6.0, alloy-dyn-abi 1.6.0, alloy-consensus 2.0.5, alloy-signer 2.0.5, alloy-rlp 0.3.15); bench/alloy-bench migrated from alloy-primitives 0.8 / alloy 0.6. New score: eth.zig wins 18/26 (alloy improved Keccak on larger inputs, hex encoding, RLP u256 decoding, and UniswapV4-style swap math) + ### Fixed +- **Unit tests now actually run.** The test step aggregated module tests via `_ = eth.module` field access, which only forces semantic analysis -- it never collected the per-module `test` blocks, so assertions compiled but never executed (`zig build test` was green even with a deliberately failing test). The test artifact is now rooted at `src/root.zig`, whose test block direct-imports every module file. This surfaced real, previously-hidden defects, now fixed: `abi_json` still used the 0.15 `ArrayList` API (broken on 0.16); `rlp.bytesToUint` failed to compile for small integer types; `mnemonic.entropyToMnemonic` had a comptime-resolution bug and a u8 overflow for 24-word phrases; `parseInputs`/`parseParam` formed an inferred-error-set dependency loop; `rlp` struct reflection used the pre-0.17 `Type.Struct.fields` layout (now via `std.meta.fieldNames`, portable across 0.16 and 0.17-dev). Fixed several stale test expectations (`formatHash`/log-address length typos, a static-tuple ABI length, a fixed-size hex length error). Vendored XKCP/secp256k1 C is now built with `-fno-sanitize=undefined` so their intentional unaligned loads do not trap the Debug UBSan runtime. +- Pure-Zig Keccak-256 fallback (`keccak_optimized.zig`) now produces correct digests (#80): replaced the broken lane-complementing chi optimization with the standard chi step (which lowers to ANDN anyway). Verified against pinned vectors and cross-validated with stdlib across all block sizes. +- `mulDiv` now returns the correct result when the intermediate product overflows u256 with a full-width divisor, e.g. `mulDiv(MAX, MAX, MAX)` (#81). The limb-native Knuth-D divider mis-handled this boundary; the rare overflow path now computes exactly in native u512 (the benchmarked u128 fast path is unchanged). +- BIP-39 seed derivation (`mnemonic.toSeed`) was correct; its Trezor passphrase test had a wrong expected vector. Corrected the test to the canonical vector (verified against `std.crypto` PBKDF2) and un-quarantined it (#82). +- DEX `getAmountIn`/`getAmountOut` are correct standard Uniswap V2; the `getAmountIn inverse` round-trip test used unrealistic tiny-reserve parameters where flooring a small output legitimately breaks the within-2-units invariant. Corrected the test to balanced reserves and un-quarantined it (#83). The full unit suite now runs with zero skips. - `sse_transport.SseParser.feedLine`: replaced the removed `std.mem.trimRight` with `std.mem.trimEnd` and gave the line-parse result an explicit struct type. These were latent Zig 0.16 migration misses that only surfaced when `feedLine` was semantically analyzed (it is not referenced by the unit-test root), and broke any consumer of `MevShareClient.on` -- surfaced while building the MEV-Share backrunner example (#38) ## [0.5.0] - 2026-06-10 diff --git a/README.md b/README.md index 8e459bc..06ff438 100644 --- a/README.md +++ b/README.md @@ -214,7 +214,7 @@ Built something with eth.zig? Open a PR to add it here. **One-liner:** ```bash -zig fetch --save git+https://github.com/StrobeLabs/eth.zig.git#v0.5.0 +zig fetch --save git+https://github.com/StrobeLabs/eth.zig.git#v0.6.0 ``` **Or add manually** to your `build.zig.zon`: @@ -222,7 +222,7 @@ zig fetch --save git+https://github.com/StrobeLabs/eth.zig.git#v0.5.0 ```zig .dependencies = .{ .eth = .{ - .url = "git+https://github.com/StrobeLabs/eth.zig.git#v0.5.0", + .url = "git+https://github.com/StrobeLabs/eth.zig.git#v0.6.0", .hash = "...", // run `zig build` and it will tell you the expected hash }, }, diff --git a/SECURITY.md b/SECURITY.md index edfd44d..fa4e2bb 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,8 +4,8 @@ | Version | Supported | |---------|-----------| -| 0.5.x | Yes | -| < 0.5 | No | +| 0.6.x | Yes | +| < 0.6 | No | ## Reporting a Vulnerability diff --git a/build.zig.zon b/build.zig.zon index f1c6949..f0f5f98 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,6 +1,6 @@ .{ .name = .eth_zig, - .version = "0.5.0", + .version = "0.6.0", .fingerprint = 0xd0f21900fa26f179, .minimum_zig_version = "0.16.0", .dependencies = .{}, diff --git a/docs/content/docs/installation.mdx b/docs/content/docs/installation.mdx index d6793ac..ae0827a 100644 --- a/docs/content/docs/installation.mdx +++ b/docs/content/docs/installation.mdx @@ -13,7 +13,7 @@ description: How to add eth.zig to your Zig project. **One-liner:** ```bash -zig fetch --save git+https://github.com/StrobeLabs/eth.zig.git#v0.5.0 +zig fetch --save git+https://github.com/StrobeLabs/eth.zig.git#v0.6.0 ``` **Or add manually** to your `build.zig.zon`: @@ -21,7 +21,7 @@ zig fetch --save git+https://github.com/StrobeLabs/eth.zig.git#v0.5.0 ```zig .dependencies = .{ .eth = .{ - .url = "git+https://github.com/StrobeLabs/eth.zig.git#v0.5.0", + .url = "git+https://github.com/StrobeLabs/eth.zig.git#v0.6.0", .hash = "...", // run `zig build` and it will tell you the expected hash }, },