txpool: add txpool_contentFrom, fix txpool_status hex format, fix txpool_content#11305
Conversation
|
Claude finished @svlachakis's task in 5m 17s —— View job PR Review:
|
| # | File | Issue |
|---|---|---|
| 1 | TxPoolContentFrom.cs |
File naming inconsistency — All sibling files use TransactionPool*.cs: TransactionPoolContent.cs, TransactionPoolStatus.cs, TransactionPoolInspection.cs. The new file should be TransactionPoolContentFrom.cs. (Inline comment posted) |
Low
| # | File | Issue |
|---|---|---|
| 2 | TransactionPoolStatus.cs:11-12 |
Sum() returns int before widening — Enumerable.Sum(Func<T, int>) accumulates in int and overflows at ~2.1B entries before the implicit widening to long. Won't happen in practice, but cast inside the lambda: Sum(static t => (long)t.Value.Count). (Inline comment posted) |
| 3 | TransactionPoolStatus.cs |
long vs ulong — Pool counts are semantically non-negative; ulong would be more precise. Both serialize identically as hex via their converters, so this is cosmetic. |
| 4 | TxPoolContentFrom.cs |
Missing XML doc comments — Coding rules require XML docs for all public APIs. The class and its Pending/Queued properties have none. |
What's correct
IntConverter.Write→WriteNumberValue(decimal) was the actual bug;LongConverter.Write→NumericConverterHelper.Write(hex) is the correct fix. ✓ulongdictionary keys fall back to STJ's built-in decimal property-name behavior (noWriteAsPropertyNameonULongConverter), producing"806"not"0x326". ✓TxPoolContentFrom.MapTransactionsuses manual iteration — correct per the no-LINQ-on-simple-loops rule. ✓- Empty address returns
new Dictionary<ulong, TransactionForRpc>(0)→ serializes as{}. ✓ - File-scoped namespaces on new/modified files. ✓
- Test coverage validates wire format, empty cases, and filtering. ✓
| @@ -0,0 +1,38 @@ | |||
| // SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited | |||
There was a problem hiding this comment.
Medium — File naming inconsistency
The sibling files in this directory follow a TransactionPool*.cs naming convention:
TransactionPoolContent.cs→ classTxPoolContentTransactionPoolStatus.cs→ classTxPoolStatusTransactionPoolInspection.cs→ classTxPoolInspection
This new file breaks that pattern. It should be renamed to TransactionPoolContentFrom.cs for consistency.
txpool_contentFrom, fix txpool_status hex formattxpool_contentFrom, fix txpool_status hex format, fix txpool_content
|
@claude review again please |
|
Claude finished @svlachakis's task in 4m 7s —— View job PR Review:
|
| # | Severity | Finding | Status |
|---|---|---|---|
| 1 | Medium | File naming: TxPoolContentFrom.cs should be TransactionPoolContentFrom.cs |
✅ Resolved — file is TransactionPoolContentFrom.cs |
| 2 | Low | Sum() accumulates in int, overflows before widening to long |
✅ Resolved — (ulong)info.Pending.Sum(static t => (long)t.Value.Count) |
| 3 | Low | long vs ulong for pool counts |
✅ Resolved — now ulong |
| 4 | Low | Missing XML doc comments on TxPoolContentFrom |
✅ Resolved — class summary and property <summary> docs added |
New findings
Low
| # | File | Issue |
|---|---|---|
| 1 | ITxPoolRpcModule.cs:22 |
ExampleResponse is missing blockTimestamp — TransactionForRpc.BlockTimestamp is declared [JsonIgnore(Condition = JsonIgnoreCondition.Never)], so it serializes as "blockTimestamp":null for mempool transactions. The example string omits this field. Not runtime-impacting, but the doc example is inaccurate. |
What's correct
ulong Pending/Queued→ULongConverter→NumericConverterHelper.Write→ hex string in JSON-RPC Hex mode. Bothulongandlongroute through the same helper; the fix is correct. ✓(ulong)Sum(static t => (long)t.Value.Count)— accumulates in 64-bit (longoverload ofSum), then safely widened toulongsince counts are non-negative. ✓Dictionary<string, ...>keyed byaddress.ToString(withZeroX: true, withEip55Checksum: true)— the oldDictionary<AddressAsKey, ...>routed throughAddressConverter.WriteAsPropertyNamewhich outputs lowercase hex; the new approach pre-computes the EIP-55 key. ✓Dictionary<ulong, TransactionForRpc>keys — STJ uses the built-in decimal integer property-name serialization (noWriteAsPropertyNameoverride onULongConverter), so nonce 806 →"806"not"0x326". ✓MapTransactionsreturnsnew Dictionary<ulong, TransactionForRpc>(0)when address is missing → serializes as{}. ✓- No LINQ in the new mapping helpers — manual
foreach. ✓ - File-scoped namespaces on all new/converted files. ✓
TransactionPoolContent.csretains brace-style namespace — correct per the rule ("for existing files, follow their style"). ✓- Test coverage: wire-format serialization tests for
txpool_statushex counts, decimal nonce keys, null block fields,txpool_contentFromfiltering, and empty-address cases. ✓
|
@claude review again |
|
Claude finished @svlachakis's task in 2m 38s —— View job PR Review:
|
| # | Severity | Finding | Status |
|---|---|---|---|
| 1 | Medium | File naming: TxPoolContentFrom.cs → TransactionPoolContentFrom.cs |
✅ Resolved |
| 2 | Low | Sum() accumulates in int, overflows before widening |
✅ Resolved — (ulong)Sum(static t => (long)t.Value.Count) |
| 3 | Low | long vs ulong for pool counts |
✅ Resolved — now ulong |
| 4 | Low | Missing XML doc comments on TxPoolContentFrom |
✅ Resolved |
| 5 | Low | txpool_contentFrom ExampleResponse omitting blockTimestamp |
✅ Resolved |
New findings
Low
| # | File | Issue |
|---|---|---|
| 1 | ITxPoolRpcModule.cs:16 |
txpool_content ExampleResponse omits blockTimestamp — The txpool_contentFrom example was fixed in this PR; the txpool_content example still has "blockNumber":null,"transactionIndex":null with blockTimestamp absent. The new test explicitly asserts blockTimestamp:null is always emitted. (Inline comment posted) |
| 2 | TxPoolRpcModule.cs:28 |
Missing null guard on address — address is untrusted RPC caller input; the robustness rules require ArgumentNullException.ThrowIfNull(address) before dereferencing it. A null address passes silently into AddressAsKey key = address and throws NullReferenceException. (Inline comment posted) |
What's correct
ulong Pending/Queued+ULongConverter→ hex wire format. ✓(ulong)Sum(static t => (long)t.Value.Count)— 64-bit accumulation, safe widening. ✓Dictionary<string, ...>keyed byaddress.ToString(withZeroX: true, withEip55Checksum: true)— correct EIP-55 keys. ✓Dictionary<ulong, TransactionForRpc>nonce keys — STJ decimal property-name serialization ("806"not"0x326"). ✓MapTransactionsreturnsnew Dictionary<ulong, TransactionForRpc>(0)on missing address → serializes as{}. ✓- No LINQ in the new mapping helpers — manual
foreachthroughout. ✓ - File-scoped namespaces on all new/converted files. ✓
TransactionPoolContent.csretains brace-style namespace (existing file convention). ✓- Test coverage: hex counts, decimal nonce keys, null block fields, filtering, empty-address cases. ✓
|
@claude review again |
|
Claude finished @svlachakis's task in 2m 33s —— View job PR Review:
|
| # | Severity | Finding | Status |
|---|---|---|---|
| 1 | Medium | File naming: TxPoolContentFrom.cs → TransactionPoolContentFrom.cs |
✅ Resolved |
| 2 | Low | Sum() accumulates in int, overflows before widening to long |
✅ Resolved — (ulong)Sum(static t => (long)t.Value.Count) |
| 3 | Low | long vs ulong for pool counts |
✅ Resolved — now ulong |
| 4 | Low | Missing XML doc comments on new class | ✅ Resolved — class summary and property <summary> docs added |
| 5 | Low | txpool_contentFrom ExampleResponse omitting blockTimestamp |
✅ Resolved |
| 6 | Low | txpool_content ExampleResponse omitting blockTimestamp |
✅ Resolved — "blockTimestamp":null is present in the example string |
| 7 | Low | Missing ArgumentNullException.ThrowIfNull(address) before dereferencing RPC input |
✅ Resolved — TxPoolRpcModule.cs:31 |
New findings
None.
What's correct
ulong Pending/Queued+ULongConverter→NumericConverterHelper.Write→ hex wire format. ✓(ulong)Sum(static t => (long)t.Value.Count)— 64-bit accumulation, safe widening toulong. ✓Dictionary<string, ...>keyed byaddress.ToString(withZeroX: true, withEip55Checksum: true)— correct EIP-55 keys on outer dict. ✓Dictionary<ulong, TransactionForRpc>nonce keys — STJ decimal property-name serialization ("806"not"0x326"). ✓MapTransactionsreturnsnew Dictionary<ulong, TransactionForRpc>(0)on missing address → serializes as{}. ✓ArgumentNullException.ThrowIfNull(address)guards the RPC input before any dereference. ✓- No LINQ in new mapping helpers — manual
foreachthroughout. ✓ - File-scoped namespaces on all new/modified files (existing
TransactionPoolContent.csretains brace-style — correct). ✓ - Test coverage: hex counts, decimal nonce keys, null block fields, EIP-55 address keys, filtering, empty-address wire format. ✓
The PR is clean. All previously raised findings are resolved and no new issues were found.
|
Claude finished @svlachakis's task in 2m 21s —— View job PR Review:
|
| # | Severity | Finding | Status |
|---|---|---|---|
| 1 | Medium | File naming: TxPoolContentFrom.cs → TransactionPoolContentFrom.cs |
✅ Resolved |
| 2 | Low | Sum() accumulates in int, overflows before widening to long |
✅ Resolved — (ulong)Sum(static t => (long)t.Value.Count) |
| 3 | Low | long vs ulong for pool counts |
✅ Resolved — now ulong |
| 4 | Low | Missing XML doc comments on new class | ✅ Resolved — class summary and property <summary> docs added |
| 5 | Low | txpool_contentFrom ExampleResponse omitting blockTimestamp |
✅ Resolved |
| 6 | Low | txpool_content ExampleResponse omitting blockTimestamp |
✅ Resolved |
| 7 | Low | Missing ArgumentNullException.ThrowIfNull(address) before dereferencing RPC input |
✅ Resolved — TxPoolRpcModule.cs:31 |
New findings
None.
What's correct
ulong Pending/Queued+ULongConverter→NumericConverterHelper.Write→ hex wire format. ✓(ulong)Sum(static t => (long)t.Value.Count)— 64-bit accumulation, safe widening toulong. ✓Dictionary<string, ...>keyed byaddress.ToString(withZeroX: true, withEip55Checksum: true)— correct EIP-55 keys on outer dict. ✓Dictionary<ulong, TransactionForRpc>nonce keys — STJ decimal property-name serialization ("806"not"0x326"). ✓MapTransactionsreturnsnew Dictionary<ulong, TransactionForRpc>(0)on missing address → serializes as{}. ✓ArgumentNullException.ThrowIfNull(address)guards the RPC input before any dereference. ✓- No LINQ in new mapping helpers — manual
foreachthroughout. ✓ - File-scoped namespaces on all new/modified files (existing
TransactionPoolContent.csretains brace-style — correct per rule). ✓ - Test coverage: hex counts, decimal nonce keys, null block fields, EIP-55 address keys, filtering, empty-address wire format. ✓
The PR is clean. All previously raised findings are resolved and no new issues were found.
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Implements missing txpool_contentFrom and aligns txpool RPC JSON serialization with the spec (hex-quantity counts and checksummed address keys), with added serialization-level tests.
Changes:
- Added
txpool_contentFrom(Address address)RPC method +TxPoolContentFromresponse model. - Updated
txpool_statusresponse to serializepending/queuedas hex-encoded quantities. - Updated
txpool_contentto emit EIP-55 checksummed address keys and refactored mapping logic.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Nethermind/Nethermind.JsonRpc/Modules/TxPool/TxPoolRpcModule.cs | Adds txpool_contentFrom endpoint and modernizes module declaration. |
| src/Nethermind/Nethermind.JsonRpc/Modules/TxPool/TransactionPoolStatus.cs | Changes status counts to unsigned type for hex-quantity serialization. |
| src/Nethermind/Nethermind.JsonRpc/Modules/TxPool/TransactionPoolContentFrom.cs | Introduces response model that filters txpool content to a single sender. |
| src/Nethermind/Nethermind.JsonRpc/Modules/TxPool/TransactionPoolContent.cs | Emits checksummed address keys and refactors mapping to explicit loops. |
| src/Nethermind/Nethermind.JsonRpc/Modules/TxPool/ITxPoolRpcModule.cs | Adds new RPC method and updates txpool_status example response. |
| src/Nethermind/Nethermind.JsonRpc.Test/Modules/TxPoolRpcModuleTests.cs | Adds wire-format serialization tests covering status/content/contentFrom behaviors. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@batrr it becomes very messy because we would need two GetInfo() & GetInfo(Address)..that's why I didn't.
There's no way to collapse them without regressing the other three methods. The only way to eliminate |
… `txpool_content` (#11305) * txpool fixes & tests * fix hive get_content * claude review * checksummed address only in get-content * build fix * claude review * claude review * format
Fixes Closes Resolves #11308
Changes
txpool_content — requires checksumed addresses
txpool_status —
pendingandqueuedwere serialized as raw integers (e.g.1010). The spec defines them asuint(hex-encoded quantity). Updated the property type frominttolongsoLongConverterproduces the correct wire format (e.g."0x3f2").txpool_contentFrom — method was missing entirely. Added:
ITxPoolRpcModule.txpool_contentFrom(Address address)TxPoolContentFromresponse model — filters pool content to a single sender, returning:{ "pending": { "nonce → tx" }, "queued": { "nonce → tx" } }TxPoolRpcModuletxpool_content — no changes needed; nonce keys already serialize as decimal strings (spec requirement) via STJ’s default
ulongdictionary key behavior, andblockHash/blockNumber/blockTimestamp/transactionIndexare alreadynullwithfrompresent.Tests
Added serialization-level tests via
RpcTest.TestSerializedRequestto validate the actual JSON wire format:txpool_statusemits"0xa"instead of10"806") instead of hex ("0x326")nullblock fields andfromtxpool_contentFromfilters correctly and serializes empty maps as{}Types of changes
What types of changes does your code introduce?
Testing
Hive tests: https://github.com/NethermindEth/nethermind/actions/runs/24787512946
Requires testing
If yes, did you write tests?