Conversation
Signed-off-by: Jason Frame <jason.frame@consensys.net>
Signed-off-by: Jason Frame <jason.frame@consensys.net>
…sync Signed-off-by: Jason Frame <jason.frame@consensys.net>
Signed-off-by: Jason Frame <jason.frame@consensys.net>
Signed-off-by: Jason Frame <jason.frame@consensys.net>
Signed-off-by: Jason Frame <jason.frame@consensys.net>
Signed-off-by: Jason Frame <jason.frame@consensys.net>
Signed-off-by: Jason Frame <jason.frame@consensys.net>
Signed-off-by: Jason Frame <jason.frame@consensys.net>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jason Frame <jason.frame@consensys.net>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jason Frame <jason.frame@consensys.net>
When migration approaches the chain head (within TAIL_THRESHOLD blocks), tail mode activates: the block observer writes archive keys for new blocks directly and the target is frozen. This eliminates the race window between the last loop iteration and upgradeToFullFlatDbMode() where blocks could arrive in FULL format. The switchover ordering is also corrected to call upgradeToFullFlatDbMode() before removing the observer. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jason Frame <jason.frame@consensys.net>
Move try/catch in tail mode observer to wrap the entire branch including getTrieLogLayer(), ensuring any exception is caught and logged rather than propagating to the block import thread. Also remove duplicate removeObserver call since finally block handles it. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jason Frame <jason.frame@consensys.net>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jason Frame <jason.frame@consensys.net>
The observer fires synchronously during appendBlock, so the throwing mock must be configured before the block is appended. Pre-generate the block to get its hash, set up the mock, then append. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jason Frame <jason.frame@consensys.net>
…Block Using endBlock (chain head at migration start) caused the tail zone to grow with every block imported during the multi-hour migration. Now uses target.get() so tail mode only activates within TAIL_THRESHOLD of the current chain head. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jason Frame <jason.frame@consensys.net>
The strategy field is written on the archive-migrator thread during upgradeToFullFlatDbMode but read on the vert.x-worker thread during block processing. Without volatile, the JMM does not guarantee the vert.x thread sees the updated strategy reference promptly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jason Frame <jason.frame@consensys.net>
…d storage The migrator previously only wrote archive entries when getUpdated() was non-null, silently skipping deletions. This meant getNearestBefore would return the pre-deletion state for accounts/storage that were deleted, since no tombstone existed to indicate the removal. Now writes DELETED_ACCOUNT_VALUE and DELETED_STORAGE_VALUE markers consistent with BonsaiArchiveFlatDbStrategy.removeFlatAccount and removeFlatAccountStorageValueByStorageSlotHash. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jason Frame <jason.frame@consensys.net>
After upgradeToFullFlatDbMode() switches the flat DB strategy from PARTIAL to ARCHIVE, cached RocksDB snapshots still share the same FlatDbStrategyProvider and immediately begin using ARCHIVE read paths. These snapshots were taken before migration completed, so they lack archive-keyed entries for blocks processed after the snapshot time. The ARCHIVE getNearestBefore could then return stale historical entries instead of the correct current state from PARTIAL keys, causing invalid block validation (e.g. nonce mismatches). Notify subscribers via onClearFlatDatabaseStorage so the cached world storage manager drops stale snapshots and forces fresh reads from the live DB which has complete migration data. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jason Frame <jason.frame@consensys.net>
Signed-off-by: Jason Frame <jason.frame@consensys.net>
…once the migration is complete Signed-off-by: Jason Frame <jason.frame@consensys.net>
Signed-off-by: Jason Frame <jason.frame@consensys.net>
Add context-accepting overloads to BonsaiArchiveFlatDbStrategy (putFlatAccount, removeFlatAccount, putFlatAccountStorageValueByStorageSlotHash, removeFlatAccountStorageValueByStorageSlotHash) that take an explicit BonsaiContext. Existing storage-derived @OverRide methods now delegate to these new overloads. BonsaiFlatDbToArchiveMigrator uses the strategy methods instead of constructing archive keys directly, eliminating duplicated write logic. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Jason Frame <jason.frame@consensys.net>
Signed-off-by: Jason Frame <jason.frame@consensys.net>
Signed-off-by: Jason Frame <jason.frame@consensys.net>
Signed-off-by: Jason Frame <jason.frame@consensys.net>
Signed-off-by: Jason Frame <jason.frame@consensys.net>
Signed-off-by: Jason Frame <jason.frame@consensys.net>
There was a problem hiding this comment.
Pull request overview
Adds support for migrating an existing Bonsai node from flat DB mode to archive mode without a full resync, and wires it into controller startup so the archiver is enabled only after migration completes.
Changes:
- Introduces
BonsaiFlatDbToArchiveMigratorto backfill archive-keyed flat DB entries from trie logs and persist migration progress. - Extends
BonsaiArchiveFlatDbStrategywith overloads that accept an explicitBonsaiContextfor archive writes/removals. - Updates storage/controller flow: notify subscribers on strategy upgrade, mark strategy pointer volatile, and start migration after the node is in sync.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/pathbased/bonsaiarchive/BonsaiFlatDbToArchiveMigrator.java | New migrator that replays trie logs into archive-keyed flat DB entries and records progress. |
| ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/pathbased/bonsai/storage/flat/BonsaiArchiveFlatDbStrategy.java | Adds context-based overloads used by the migrator to write/delete archive entries at a given block context. |
| ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/pathbased/bonsai/storage/BonsaiWorldStateKeyValueStorage.java | Notifies subscribers to clear caches after switching flat DB strategy to avoid stale snapshot reads. |
| ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/pathbased/common/storage/flat/FlatDbStrategyProvider.java | Makes the strategy reference volatile for cross-thread visibility when switching strategies. |
| app/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java | Starts migration post-sync (when in FULL mode) and enables archiver only after successful migration. |
| ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/pathbased/bonsaiarchive/BonsaiFlatDbToArchiveMigratorTest.java | New unit tests covering migrator behavior (progress, concurrency, failures, block catch-up). |
| ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/pathbased/bonsai/storage/BonsaiWorldStateKeyValueStorageTest.java | Adds test ensuring subscribers are notified to clear caches on strategy upgrade. |
...rg/hyperledger/besu/ethereum/trie/pathbased/bonsaiarchive/BonsaiFlatDbToArchiveMigrator.java
Outdated
Show resolved
Hide resolved
...rg/hyperledger/besu/ethereum/trie/pathbased/bonsaiarchive/BonsaiFlatDbToArchiveMigrator.java
Outdated
Show resolved
Hide resolved
...rg/hyperledger/besu/ethereum/trie/pathbased/bonsaiarchive/BonsaiFlatDbToArchiveMigrator.java
Outdated
Show resolved
Hide resolved
app/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java
Show resolved
Hide resolved
...hyperledger/besu/ethereum/trie/pathbased/bonsai/storage/BonsaiWorldStateKeyValueStorage.java
Show resolved
Hide resolved
...hyperledger/besu/ethereum/trie/pathbased/bonsai/storage/BonsaiWorldStateKeyValueStorage.java
Outdated
Show resolved
Hide resolved
Signed-off-by: Jason Frame <jason.frame@consensys.net>
Previously showed startBlock (first block of current run) as the resumed-from value. Now passes lastProcessedBlock (-1 for a fresh start) and only shows the resumed-from message when progress actually existed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Jason Frame <jason.frame@consensys.net>
Signed-off-by: Jason Frame <jason.frame@consensys.net>
… needed when upgrading to archive mode as the flatDbStrategy is incompatible Signed-off-by: Jason Frame <jason.frame@consensys.net>
Signed-off-by: Jason Frame <jason.frame@consensys.net>
Covers commit persists, rollback discards, and post-commit put throws. Tests run for both OptimisticRocksDB and TransactionDB via the base class. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Jason Frame <jason.frame@consensys.net>
Covers commit persists, rollback discards, and post-commit put throws. Tests run for both OptimisticRocksDB and TransactionDB via the base class. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Jason Frame <jason.frame@consensys.net>
…bonsai_archive_migrate
Signed-off-by: Jason Frame <jason.frame@consensys.net>
…bonsai_archive_migrate
Signed-off-by: Jason Frame <jason.frame@consensys.net>
Signed-off-by: Jason Frame <jason.frame@consensys.net>
Signed-off-by: Jason Frame <jason.frame@consensys.net>
Signed-off-by: Jason Frame <jason.frame@consensys.net>
...rg/hyperledger/besu/ethereum/trie/pathbased/bonsaiarchive/BonsaiFlatDbToArchiveMigrator.java
Show resolved
Hide resolved
app/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java
Outdated
Show resolved
Hide resolved
…gration triggered Signed-off-by: Jason Frame <jason.frame@consensys.net>
…x a possible window where another migration could trigger another upgrade Signed-off-by: Jason Frame <jason.frame@consensys.net>
Code reviewFound 1 issue:
In 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
The general throws case is handled already by |
… a transaction and never use it due an early exit Signed-off-by: Jason Frame <jason.frame@consensys.net>
Signed-off-by: Jason Frame <jason.frame@consensys.net>
PR description
fixes #9608
This improves the sync of Bonsai archive to sync as Bonsai and then migration to Bonsai archive. This significantly improves the time taken to sync a Bonsai archive node. It does this by waiting until the node is fully in sync and then processing trie logs sequentially.
There is an impact to the engine API performance during the migration. But this is part of the syncing so some degradation is acceptable and the nodes are able to stay in sync during the migration.
Synchronizer.subscribeInSyncinstead being an additional sync step as the initial sync complete event is never fired for full sync and I want to use to the same mechanism for all networks. Placing a step in the Full sync pipeline wouldn't work for post-merge testnets that use backward syncMigration Test Results
Migration Approaches to mitigate engine API times
engine_newPayloadV4— quantiles during migration (seconds)engine_forkchoiceUpdatedV3— quantiles during migration (seconds)Fixed Issue(s)
fixes #9608
Thanks for sending a pull request! Have you done the following?
doc-change-requiredlabel to this PR if updates are required.Locally, you can run these tests to catch failures early:
./gradlew spotlessApply./gradlew build./gradlew acceptanceTest./gradlew integrationTest./gradlew ethereum:referenceTests:referenceTests