Skip to content

eth/71 - #10844

Merged
flcl42 merged 39 commits into
masterfrom
eth-71
May 7, 2026
Merged

eth/71#10844
flcl42 merged 39 commits into
masterfrom
eth-71

Conversation

@flcl42

@flcl42 flcl42 commented Mar 16, 2026

Copy link
Copy Markdown
Contributor

Changes

  • Add eth/71 support(historical BALs sync)
  • BAL sync happens after we got headers and state, in parallel to bodies/receipts
  • Rewire inheritance for messages of new protocols like eth/70 eth/71 (containing of message replaced with inheritance)

Types of changes

What types of changes does your code introduce?

  • Bugfix (a non-breaking change that fixes an issue)
  • New feature (a non-breaking change that adds functionality)
  • Breaking change (a change that causes existing functionality not to work as expected)
  • Optimization
  • Refactoring
  • Documentation update
  • Build-related changes
  • Other: Description

Testing

Requires testing

  • Yes
  • No

If yes, did you write tests?

  • Yes
  • No

@LukaszRozmej

Copy link
Copy Markdown
Member

merge back master please

flcl42 added 2 commits March 16, 2026 17:05
# Conflicts:
#	src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncPeer.cs
#	src/Nethermind/Nethermind.Init/Modules/NetworkModule.cs
#	src/Nethermind/Nethermind.Network/ProtocolsManager.cs
#	src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs
#	src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncProgressResolver.cs
@github-actions github-actions Bot removed rocksdb evm taiko related to the taiko alethia rollup state+storage labels Mar 16, 2026
flcl42 added 3 commits April 23, 2026 12:34
# Conflicts:
#	src/Nethermind/Nethermind.Network.Test/Builders/SerializationBuilder.cs
#	src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V70/Eth70ProtocolHandlerTests.cs
#	src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V70/Eth70ProtocolHandler.cs
#	src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V70/Messages/GetReceiptsMessage70.cs
#	src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V70/Messages/ReceiptsMessage70.cs
#	src/Nethermind/Nethermind.Synchronization.Test/E2ESyncTests.cs
#	src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorBeaconTests.cs
#	src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorFastSyncTests.cs
#	src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs
#	src/Nethermind/Nethermind.Synchronization.Test/SyncPointersTests.cs
#	src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloadRequest.cs
#	src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloader.cs
#	src/Nethermind/Nethermind.Synchronization/ParallelSync/MultiSyncModeSelector.cs
#	src/Nethermind/Nethermind.Synchronization/SyncServer.cs
# Conflicts:
#	src/Nethermind/Nethermind.History.Test/HistoryPrunerTests.cs
@LukaszRozmej

Copy link
Copy Markdown
Member

IMO fix: Low/Nit — BlocksRequest default field initializers - rest is good, will do manual review later

@LukaszRozmej LukaszRozmej left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Close, few things to polish

Comment thread src/Nethermind/Ethereum.Test.Base/ChainUtils.cs Outdated
Comment thread src/Nethermind/Nethermind.Blockchain/BlockAccessLists/IBlockAccessListStore.cs Outdated
Comment thread src/Nethermind/Nethermind.Db/MetadataDbKeys.cs
Comment thread src/Nethermind/Nethermind.Merge.Plugin/Handlers/ForkchoiceUpdatedHandler.cs Outdated
Comment thread src/Nethermind/Nethermind.Synchronization/Reporting/SyncReport.cs Outdated
Comment thread src/Nethermind/Nethermind.Synchronization/Reporting/SyncReport.cs Outdated
Comment thread src/Nethermind/Nethermind.Synchronization/FastBlocks/BlockAccessListsSyncFeed.cs Outdated
Comment thread src/Nethermind/Nethermind.Synchronization/FastBlocks/BlockAccessListsSyncFeed.cs Outdated
@flcl42
flcl42 requested a review from smartprogrammer93 as a code owner May 4, 2026 09:40
flcl42 added 2 commits May 5, 2026 14:41
# Conflicts:
#	src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs
#	src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTestsBase.Scenario.cs
#	src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs
#	src/Nethermind/Nethermind.Synchronization.Test/SynchronizerModuleTests.cs
#	src/Nethermind/Nethermind.Synchronization/ParallelSync/MultiSyncModeSelector.cs
#	src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncMode.cs
#	src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncProgressResolver.cs
@LukaszRozmej

Copy link
Copy Markdown
Member

@claude review

@claude

claude Bot commented May 5, 2026

Copy link
Copy Markdown
Contributor

Claude finished @LukaszRozmej's task in 4m 18s —— View job


PR Re-review: eth/71 (Re-review #6)

Tasks

  • Load repo rules
  • Check commits since last review (b7571a3, 03dd76a, 1aa43b1, 911b5d9)
  • Verify LukaszRozmej's May 1 inline comments were addressed
  • Deep-check key changed files
  • Post findings

Resolved since LukaszRozmej's May 1 deep review ✅

All 21 inline comments from LukaszRozmej's May 1 review have been addressed across commits 1aa43b1, b7571a3, 03dd76a, and 911b5d9:

Finding Status
ChainUtils.csAmsterdam => AmsterdamGnosis.Instance FixedAmsterdamGnosis.cs added (NamedGnosisReleaseSpec<AmsterdamGnosis>(Amsterdam.Instance, ...)) and mapping updated.
IBlockAccessListStore.csThrowXXX helper FixedThrowMissingBlockHash([DoesNotReturn, StackTraceHidden]) added.
MetadataDbKeys.cs:21WhenStarted suffix Acknowledged — consistent with existing ReceiptsBarrierWhenStarted / BodiesBarrierWhenStarted.
ForkchoiceUpdatedHandler.cs — unrelated change Removed.
GetReceiptsMessageSerializerTests.csTestCaseSource Fixed[TestCaseSource(nameof(InvalidPayloads))] pattern now used.
Eth70ProtocolHandlerTests.cs:120 — test dedup Done — tests refactored (769 lines, down from 884).
Eth71ProtocolHandlerTests.cs:52 — test dedup Done — tests refactored (269 lines, down from ~380).
Eth66MessageSerializer.csThrowXXX helper FixedThrowUnexpectedTrailingData([DoesNotReturn, StackTraceHidden]).
GetReceiptsMessage70.cs:11 — inheritance justification Acknowledged — fewer allocations + clarity; approved in prior review.
SyncServerTests.cs — dedup Done (commit 03dd76a).
BlockDownloader.cs — name the nulls Fixed — named arguments: Block: null, Receipts: null, PeerInfo: null, EncodedAccessList: null.
BlockDownloader.cs:528 — long block, helper method FixedTryHandleBlockAccessListResponse extracted as a private helper.
BlocksSyncPeerAllocationStrategyFactory.cs:11 — make base extensible Fixed — private BlockAccessListsPeerAllocationStrategy inner class extends FilterPeerAllocationStrategy via abstract Filter(PeerInfo).
BlocksRequest.csrequest.AllCounts FixedAllCounts => BodiesRequests.Count + BlockAccessListsRequests.Count + ReceiptsRequests.Count.
SyncServer.cs — single return FixedGetBlockAccessListRlp is now an expression-bodied member.
Synchronizer.csWasAnyModeFinished(params ReadOnlySpan) Fixedprivate static bool WasAnyModeFinished(SyncModeChangedEventArgs e, params ReadOnlySpan<SyncMode> modes) added.
SyncReport.cs — helper method per if FixedLogProgressIfActive(SyncMode, SyncMode, ProgressLogger) helper.
SyncReport.csHasAllEnded(params ReadOnlySpan) Fixedprivate static bool HasAllEnded(params ReadOnlySpan<ProgressLogger> progressLoggers).
FastBlocksPeerAllocationStrategyFactory.cs — switch expression FixedTransferSpeedType speedType = request switch { ... }.
BlockAccessListsSyncFeed.cs — single return FixedIsValidAccessList uses single-return via bool isValid.
BlockAccessListsSyncFeed.cs — base Exception? Addressedcatch (Exception ex) when (ex is not OperationCanceledException) retained; broad catch is correct here to guarantee MarkPending before re-throw.

Additional change verified ✅

IOwnedReadOnlyList<T>.Empty (1aa43b1): BlocksRequest fields now default to IOwnedReadOnlyList<T>.Empty instead of new ArrayPoolList<T>(0). The EmptyOwnedReadOnlyList singleton has a no-op Dispose(), so the existing BlocksRequest.Dispose() path is safe.


Verdict: mergeable. All Critical/High/Medium findings from all prior reviews are resolved, and all inline feedback from LukaszRozmej's May 1 deep review has been addressed. No new issues found in this pass.

Comment thread src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloader.cs
Comment thread src/Nethermind/Nethermind.Synchronization/SyncPointers.cs Outdated
Comment thread src/Nethermind/Nethermind.Synchronization/SyncPointers.cs Outdated
Comment thread src/Nethermind/Nethermind.Blockchain/BlockAccessLists/IBlockAccessListStore.cs Outdated
@flcl42
flcl42 requested a review from dipkakwani as a code owner May 6, 2026 11:15
@github-actions github-actions Bot added the taiko related to the taiko alethia rollup label May 6, 2026
@flcl42

flcl42 commented May 6, 2026

Copy link
Copy Markdown
Contributor Author

@claude check it again

@claude

claude Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

Claude finished @flcl42's task in 8m 29s —— View job


PR Re-review: eth/71 (Re-review #7)

Tasks

  • Gather context and load repo rules
  • Check recent commits since last review (a58dc4eb Review, 4f5e94c1 Migration, ab77c21c Fix build)
  • Verify asdacap's review comments were addressed
  • Deep review of BlockAccessListsMessageSerializer, SyncPointers, BlockDownloader
  • Verify memory ownership and dispose correctness
  • Post findings

Resolved since review #6

All three comments from asdacap's 2026-05-06 review have been addressed:

asdacap's Finding Status
BlockDownloader.cs:328 — need bodiesOnly-style flag for BAL-only requests Fixedbool? bodiesOnly replaced with BlocksRequestContentType? enum (Bodies, BlockAccessLists, Receipts). Each type now gates the others via requestContentType is null or BlocksRequestContentType.X, correctly enforcing one-type-per-request.
BlockAccessListsMessage.cs — use RlpByteArrayList / DeferredRlpItemList.Builder Fixed — message type changed from IOwnedReadOnlyList<byte[]?> to IByteArrayList. Deserializer uses NettyBufferMemoryOwner + RlpByteArrayList.DecodeList for zero-copy read. Server-side Handle(GetBlockAccessListsMessage) uses DeferredRlpItemList.Builder + Writer for zero-copy construction. SerializeInternal goes through IRlpWrapper.Write path (direct buffer write, no item-by-item re-encoding).
SyncPointers.cs — use metadata DB instead of raw BAL/blocks DB key Fixed — both LowestInsertedBodyNumber and LowestInsertedBlockAccessListBlockNumber now stored under MetadataDbKeys.LowestInsertedBodyNumber (15) and MetadataDbKeys.LowestInsertedBlockAccessListBlockNumber (16). Migration for legacy LowestInsertedBodyNumber (stored as IDb[0] in blocks DB) is included and tested (MigrateLegacyLowestInsertedBodyNumber).

Memory ownership trace (verified correct)

Deserialization path (client):
NettyBufferMemoryOwnerRlpItemList (via DecodeList) → RlpByteArrayListBlockAccessListsMessage.BlockAccessLists. After GetBlockAccessLists returns, caller owns the IByteArrayList. BlocksRequest.Dispose() / BlockAccessListsSyncBatch.Dispose() both call BlockAccessLists?.Dispose() / Response?.Dispose(), which chains through RlpByteArrayList.Dispose()RlpItemList.Dispose() (idempotent via Interlocked.CompareExchange) → releases the Netty buffer. Spans passed to _blockAccessListStore.Insert(hash, span) and encodedAccessList.ToArray() are all consumed before the owning list is disposed. ✅

Serialization path (server):
DeferredRlpItemList.Builder.ToRlpItemList() transfers ownership (sets _entries = null; subsequent builder.Dispose() is a no-op). RlpByteArrayList backed by DeferredRlpItemList (owned ArrayPoolList<Entry> + ArrayPoolList<byte>). Written directly via IRlpWrapper.Write path → no extra copies. Disposed when BlockAccessListsMessage.Dispose() is called after the Netty frame is sent. ✅

Error paths in BlockAccessListsMessageSerializer.Deserialize:
If Rlp.GuardLimit / ctx.Check throw before memoryOwner = null (ownership transfer), catch block disposes both blockAccessLists and memoryOwner. NettyBufferMemoryOwner.Dispose() is idempotent (_disposed flag), so the double-dispose is safe. ✅


No new issues found

  • BlocksRequestContentType enum covers all three types cleanly; the break conditions (Count >= requestSize) remain correct for each type.
  • InsertBlockAccessLists hasBreachedProtocol flag (fixed in review Hive #4) remains correct.
  • HasPivot pre-fork guard (fixed in review Patricia alt 2 #5) remains correct.
  • All resource leaks from reviews Feature/networking #2Hive #4 remain fixed.
  • BlockAccessListsMessageSerializer.DeserializeInternal throwing NotSupportedException is an intentional guard (correct design — the base class's Deserialize(IByteBuffer) is overridden and the DeserializeInternal path is unreachable in normal operation).
  • RLP security audit: count limits, position checks, and null-span handling all intact. ✅

Low / Nit (non-blocking)

  • IByteArrayList.cs and RlpByteArrayList.cs carry // SPDX-FileCopyrightText: 2025 while the rest of the PR is 2026. Trivial inconsistency.
  • No migration for LowestInsertedBlockAccessListBlockNumber from the old BAL DB key (_blockAccessListsDb.Set(Keccak.Zero, ...)) used in prior revisions of this branch. Since eth/71 was never on master, this only affects intermediate-build testers; production nodes are unaffected.

Verdict: mergeable. All Critical/High/Medium findings from all prior reviews are resolved. asdacap's three comments are all addressed. No new issues found in this pass.

@flcl42
flcl42 merged commit ac4fc15 into master May 7, 2026
896 of 901 checks passed
@flcl42
flcl42 deleted the eth-71 branch May 7, 2026 06:32
stdevMac pushed a commit that referenced this pull request May 26, 2026
stdevMac added a commit that referenced this pull request Jun 1, 2026
* RLP tx decoding fixes (#11496)

* Handle null txs

* PR feedback

* Revert `BlobTxStorage.TryDecodeFullTx` changes

Silent `false` may be worse that NRE on DB corruption

---------

Co-authored-by: Alexey Osipov <me@flcl.me>

* eth/71 (#10844)

* Improve eth/70 checks (#11456)

* Improve eth/70 verification

* Comments

* Gas remake

* Fix full sync

* fix: prevent negative RequestSize crash when beacon pivot destination advances mid-sync (#11478)

* fix: prevent negative RequestSize crash when beacon pivot destination advances mid-sync

`HeadersSyncFeed.ShouldBuildANewBatch` checked
`_lowestRequestedHeaderNumber == HeadersDestinationNumber`. For beacon
headers, `HeadersDestinationNumber` is `BeaconPivot.PivotDestinationNumber`,
which tracks `Head.Number - Reorganization.MaxDepth + 1` and so advances
upward as the chain head progresses. When it stepped above
`_lowestRequestedHeaderNumber` mid-sync, the `==` check missed it,
`BuildNewBatch` produced a negative `RequestSize`, and
`HeaderStore.FindReversedHeaders` crashed with
`ArgumentOutOfRangeException` on `new Dictionary<>(negativeCount)`.

Widen the guard to `<=` and add a regression test that reproduces the
scenario via mocked `IBeaconPivot`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore: shorten inline comments per review

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Add new default for gnosis and gnosis archive config (#11269)

feat: add Db.SkipCheckingSstFileSizesOnDbOpen=true default for gnosis and gnosis archive

* Alchemy - Code Fix (#11714)

* feat: add SkipMetricsTracking property to DbSettings (#11515)

* feat: add SkipMetricsTracking property to DbSettings

- Introduced SkipMetricsTracking property in DbSettings to control metrics tracking for specific databases.
- Updated FullPruningInnerDbFactory to set SkipMetricsTracking to true for inner databases to prevent stale references after pruning.
- Added unit tests to verify the behavior of metrics tracking based on the new property.
- Enhanced DbMonitoringModule to respect the SkipMetricsTracking setting when adding databases to the tracker.

* fix: address PR feedback for db metrics tracking

- Add XML doc to DbSettings.SkipMetricsTracking property
- Clarify WorldStateModule comment for both FullPruningInnerDbFactory
  and MemDbFactory branches
- DbMonitoringModule: clear stale dictionary entries on GatherMetric
  failure and log only once per failure streak (with recovery info log)
- DbTrackerTests: add [TearDown] to reset shared static metrics keys,
  collapse double enumeration in TestSkipMetricsTracking, and add
  FullPruningDbTrackedWrapper_SurvivesPruningCycle integration test

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor: dedupe DbTrackerTests container setup and metric-map iteration

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: Initialize _failingDbs with an empty HashSet

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: lukasz.rozmej <lukasz.rozmej@gmail.com>

* Fix DbTracker repeatedly logging ObjectDisposedException after disposal (#11720)

* Fix DbTracker repeatedly logging ObjectDisposedException after disposal

When the Autofac LifetimeScope (or the shared cache SafeHandle) is disposed
while MonitoringService's timer is still scheduled, `_sharedBlockCache.Value`
in `UpdateDbMetrics` throws `ObjectDisposedException` via Autofac's
LazyRegistrationSource. The generic catch logs it at Error and the callback
stays registered, so the same exception re-fires on every metric interval —
producing dozens of identical errors per minute on affected nodes.

Catch `ObjectDisposedException` explicitly and short-circuit subsequent ticks
via a `_stopped` flag. Adds a regression test that disposes the container
and asserts the callback neither throws nor logs on repeated invocations.

Fixes #11719

* Address review: debug-log first stop, drop redundant CreateDb in test

- Log at Debug level in the new `ObjectDisposedException` branch so there is
  a (no-cost on production) signal that DbTracker has stopped updating
  metrics, rather than only inferring it from the absence of further Error
  logs.
- Remove the duplicate `CreateDb` call in the regression test — the helper
  `ConfigureMetricUpdater` already registers the test DB.
- Disable `TestLogger.IsDebug` in the regression test so the new Debug
  message does not trip the `LogList.Should().BeEmpty()` assertion; the
  test still asserts no Error-level spam, which was the bug.

* Address review: make DbTracker IDisposable, drop redundant comment

- Implement IDisposable on DbTracker so Autofac proactively sets _stopped
  during scope teardown, short-circuiting subsequent monitoring ticks
  before they touch disposed resources. The catch (ObjectDisposedException)
  remains as a backstop for the race where a tick is already executing
  when Dispose runs.
- Mark _stopped as volatile since it is now written from the disposing
  thread and read from the monitoring timer thread.
- Drop the inline comment in the catch block; the Debug log message
  already conveys the same information.

* Fix Eth69/Eth70 receipt tests for null-means-unknown contract

After dropping the FindHeader pre-check, the response loop relies solely
on GetReceipts returning null to detect an unknown block. The two
"unknown block hash" tests still mocked the old contract (FindHeader
returns null + GetReceipts returns []), so the loop saw [] as a
legitimate zero-tx block and kept going instead of breaking.

Update the mocks to return null for unknown hashes, matching the
ISyncServer.GetReceipts contract (null = unknown, [] = exists w/ 0 txs).

* Make EraE tests visible and green (#11727)

* fix(eth/70): reject null receipt payloads (#11615)

* fix(eth/70): reject null receipt payloads

* fix(eth/70): validate receipt payloads while decoding

* refactor(eth): move null receipt validation into base serializer

Apply the validation in V63 ReceiptsMessageSerializer so eth/63, eth/66,
eth/69 and eth/70 all reject null receipt payloads at decode time.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: lukasz.rozmej <lukasz.rozmej@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
(cherry picked from commit fd2fd25)

* fix(eth/70): stop response early when block has txs but no receipts

FulfillReceiptsRequest used to emit `txReceipts.Add([])` for any block where
SyncServer.GetReceipts(hash) returned empty, regardless of whether the block
actually had zero transactions. The eth/70 receiver validates segment-complete
responses against its own transaction count and throws SubprotocolException
("Receipt count mismatch with block transactions count") + disconnects the
peer when an [] arrives for a block that locally has transactions.

That made a node that is briefly without receipts (e.g. still syncing
receipts, or its receipt store is pruned for the requested block) appear
malicious to the requester. We observed this disconnect-storm pattern
materially starving receipt-sync on small networks.

Distinguish the two cases at the sender by looking up the block:
- block is null or body is missing  → we can't safely claim anything; break
  the response and let the requester ask another peer
- block.Transactions.Length > 0     → same: we don't actually have the
  receipts even though we have the body; break
- block.Transactions.Length == 0    → block is legitimately empty; emit []
  as before

Update Should_return_empty_receipts_block_when_local_block_has_no_receipts
→ ..._has_no_transactions to reflect the new precondition, and stub
SyncServer.Find on two pre-existing empty-receipts-in-the-middle tests so
they still represent the legitimate empty case. Add new regression test
Should_stop_response_when_local_block_has_transactions_but_no_receipts
covering the bug.

Closes #11752.

(cherry picked from commit f0f6ea2)

* refactor(eth/70): disambiguate "unknown" vs "legit empty" in ISyncServer.GetReceipts

Following @LukaszRozmej's review suggestion on #11752: rather than have the
protocol handler do a second SyncServer.Find lookup to figure out whether an
empty receipts array means "block has zero transactions" or "I don't have the
receipts yet", push the disambiguation down to where the data lives.

ISyncServer.GetReceipts now returns TxReceipt[]?:
  null      → receipts are not known locally (block missing, body missing, or
              receipts not stored). Callers MUST NOT emit [] on the wire.
  empty []  → block is known and legitimately has zero transactions.
  non-empty → receipts for an executed block.

SyncServer.GetReceipts implements the three cases directly:
  - blockHash is null OR block not found OR block body missing → null
  - block.Transactions.Length == 0                              → []
  - block has txs, receipts not stored                          → null
  - block has txs and receipts                                  → receipts

Eth70ProtocolHandler.FulfillReceiptsRequest is now a single null-check instead
of the previous Find-then-classify dance. SyncPeerProtocolHandlerBase.Fulfill
(eth/63-69 path) gets the same fix for free — same bug, same one-line guard.

Tests: replace the Find-based stubs with GetReceipts-returning-null stubs and
update OldStyleFullSynchronizerTests.Can_retrieve_empty_receipts to assert the
new contract (genesis → BeEmpty; unknown blocks → BeNull).

Closes #11752.

(cherry picked from commit 1d880be)

* Apply suggestions from code review

Co-authored-by: Lukasz Rozmej <lukasz.rozmej@gmail.com>
(cherry picked from commit c01295b)

* Apply suggestion from @LukaszRozmej

(cherry picked from commit 27258b9)

* Drop redundant FindHeader pre-check in receipt response loop

GetReceipts now returns null for unknown blocks (block missing, body
missing, or receipts not stored), so the up-front FindHeader call before
GetReceipts is redundant — the `if (receipts is null) break;` below it
already handles the unknown case.

Per @flcl42 review on #11754.

(cherry picked from commit 742cb1a)

* Fix shutdown race in SnapProvider PLINQ (closes #11806) (#11807)

* Unwrap AggregateException(ObjectDisposedException) from snap PLINQ on shutdown

When the node is stopped during snap sync, SnapProvider.AddAccountRange's
parallel code-existence check (codeHashes.AsParallel().Where(_codeDb.KeyExists))
races RocksDB disposal in the DI container teardown. The resulting
ObjectDisposedException is wrapped by PLINQ in an AggregateException, which
falls past the snap dispatcher's existing `catch (ObjectDisposedException) →
Info("Ignoring sync response as the DB has already closed.")` guard and lands
on `catch (Exception) → Error("Error when handling response", e)`.

The node recovers correctly on restart — this is purely a noisy shutdown log
line — but the post-merge fuzz tests' StabilityVerification watchdog scans
for non-allowlisted exception lines and fails the test on it, blocking the
1.38 release smoke run.

Unwrap the AggregateException at the point of throw so the dispatcher's
existing benign guard handles it uniformly. No new log path; reuses the
already-tested "Ignoring sync response..." Info message.

Race introduced 2024-03-28 by PR #6873 "Perf/dont redownload downloaded code"
(commit 7059b45), latent until the fuzz watchdog started catching it.

* Tidy unwrap: single Flatten, preserve stack via ExceptionDispatchInfo

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Guard against empty InnerExceptions in unwrap filter

Enumerable.All() returns true vacuously on an empty sequence, which
would let the filter pass and then InnerExceptions[0] throw
ArgumentOutOfRangeException instead of re-throwing the original.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: lukasz.rozmej <lukasz.rozmej@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Default Discovery to V4 (#11614)

* Default Discovery to V4

* Update tests

* Activate BAL only when needed (#11795)

* Activate BAL only when needed

* Guard ChangeState against same-state transitions

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Align IsFinished with ShouldFinish; short-circuit cheap checks first

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: lukasz.rozmej <lukasz.rozmej@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore: update Directory.Build.props for 1.38.0

---------

Co-authored-by: Alex <alexb5dh@gmail.com>
Co-authored-by: Alexey Osipov <me@flcl.me>
Co-authored-by: Amirul Ashraf <asdacap@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Stavros Vlachakis <89769224+svlachakis@users.noreply.github.com>
Co-authored-by: Carlos Bermudez Porto <43155355+cbermudez97@users.noreply.github.com>
Co-authored-by: lukasz.rozmej <lukasz.rozmej@gmail.com>
Co-authored-by: DeFi Junkie <deffie.jnkiee@gmail.com>
Co-authored-by: Ben {chmark} Adams <thundercat@illyriad.co.uk>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants