Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
76a73d7
feat: Support RecordBlockCreation (block reprocessing)
hudem1 Jan 12, 2026
fd84bfb
feat: Fix RecordBlockCreation with block production
hudem1 Jan 20, 2026
45df498
chore: Clean old experimental tests
hudem1 Jan 20, 2026
67e691d
Merge branch 'main' into hudem1/feat/execution-recorder-interface
hudem1 Jan 20, 2026
dc8a62d
Merge branch 'main' into hudem1/feat/execution-recorder-interface
hudem1 Jan 20, 2026
9211ade
feat: Use latest NMC master
hudem1 Jan 21, 2026
9a3950b
fix format
hudem1 Jan 21, 2026
e7c4ca5
fix: PR reviews
hudem1 Jan 21, 2026
79ed962
chore: Use header.ParentHash instead of findBlockHash
hudem1 Jan 21, 2026
646c4e1
Merge branch 'hudem1/chore/arb-tx-processor/parent-hash' into hudem1/…
hudem1 Jan 21, 2026
b25226a
fix: Sync with NMC branch to return Witness object directly
hudem1 Jan 21, 2026
764e860
fix: Improve comparison between built block hash and canonical hash
hudem1 Jan 21, 2026
2a87f19
fix format
hudem1 Jan 21, 2026
7031bef
fix: Empty calldata should still set some state even if does not impa…
hudem1 Jan 23, 2026
9eff0c4
feat: Capture user wasms
hudem1 Jan 29, 2026
d8dd366
fix: Forgotten isUserTx check
hudem1 Feb 2, 2026
6604c40
Merge branch 'main' into hudem1/feat/execution-recorder-interface
hudem1 Feb 2, 2026
effbb2f
fix: Merge conflicts
hudem1 Feb 2, 2026
6f5580d
Temporary files for docker builds
hudem1 Feb 2, 2026
40b7f1a
fix: Format check
hudem1 Feb 2, 2026
bccf26c
fix: Format check 2
hudem1 Feb 2, 2026
00f4cd3
fix: Traverse state trie for precompile account even if bytecode is e…
hudem1 Feb 3, 2026
314ebbe
tests: Record user wasms
hudem1 Feb 5, 2026
fd16814
tests: Always record bytecode for ExtCodeSize opcode
hudem1 Feb 5, 2026
c871545
tests: Record invalid bytecode for arb precompiles and nothing for et…
hudem1 Feb 5, 2026
3fc5def
fix: Format
hudem1 Feb 5, 2026
314b057
tests: User asms capture (not just stateless exec)
hudem1 Feb 6, 2026
4b5d83d
tests: BLOCKHASH opcode in witness gen mode should not benefit from g…
hudem1 Feb 6, 2026
bc394bc
tests: Querying for a block hash should record all block headers from…
hudem1 Feb 6, 2026
9e95c13
tests: ArbosStorage.Set still traverses trie even with empty bytes
hudem1 Feb 8, 2026
59c7176
tests: ArbosStorage.Set still sets state even with default value
hudem1 Feb 9, 2026
4991eba
tests: Reads and records TimeoutWindowsLeft at the right place in Try…
hudem1 Feb 9, 2026
f1a2c45
tests: Non user txs still go into gas related calculation and record …
hudem1 Feb 9, 2026
0c94213
tests: Fix existing firstUserTx related tests
hudem1 Feb 9, 2026
81834bf
Fix underflow bug
hudem1 Feb 9, 2026
3a85ae7
Merge branch 'main' into hudem1/feat/execution-recorder-interface
hudem1 Feb 10, 2026
6ceb9a2
Update to latest NMC wit gen branch
hudem1 Feb 11, 2026
2f88e33
fix: Add serializedChainConfig and initialL1BaseFee to full chain sim…
hudem1 Feb 11, 2026
91c146a
fix: Forgotten SpecHelper assignment in VM bug
hudem1 Feb 11, 2026
3269d6a
Merge branch 'main' into hudem1/feat/execution-recorder-interface
hudem1 Feb 11, 2026
443ebd4
feat: Update to latest base NMC wit gen branch (without account proof…
hudem1 Feb 11, 2026
4486385
tests: Fix AllowDebugPrecompiles to default to false
hudem1 Feb 11, 2026
b0fe887
fix: Removed stateReader parameter to wit gen worldstate constructor
hudem1 Feb 11, 2026
32f62aa
feat: Update to latest base NMC wit gen branch
hudem1 Feb 12, 2026
e044271
fix: Add stateReader parameter to wit gen worldstate constructor
hudem1 Feb 12, 2026
f7a25bf
feat: Update to latest base NMC wit gen branch
hudem1 Feb 13, 2026
952671b
tests: Reverted txs and set-then-reset storage slots still records tr…
hudem1 Feb 13, 2026
022ea9e
Merge branch 'main' into hudem1/feat/execution-recorder-interface
hudem1 Feb 14, 2026
e394cd8
feat: Update to latest base NMC wit gen branch
hudem1 Feb 17, 2026
0d11609
chore: Add explanatory comment
hudem1 Feb 17, 2026
89dbea9
Revert "Temporary files for docker builds"
hudem1 Feb 17, 2026
c394232
feat: Update to latest base wit gen branch and fix build errors
hudem1 Feb 23, 2026
3ce2628
fix: Dispose of pool array list
hudem1 Feb 23, 2026
e5eda3b
Merge branch 'main' into hudem1/feat/execution-recorder-interface
hudem1 Feb 26, 2026
e4a030e
feat: Update to latest base nmc wit gen branch
hudem1 Feb 26, 2026
720c07a
fix: merge conflicts
hudem1 Feb 26, 2026
3c2a944
Merge branch 'main' into hudem1/feat/execution-recorder-interface
hudem1 Mar 3, 2026
0abeb97
fix: Merge conflicts
hudem1 Mar 3, 2026
05d9cf6
fix: Update to latest nmc (with witness gen)
hudem1 Mar 3, 2026
50da64b
Merge branch 'main' into hudem1/feat/execution-recorder-interface
hudem1 Mar 3, 2026
0dd006f
fix: Format
hudem1 Mar 3, 2026
415ae88
feat: Use NoOp L1BlockCache instead of removing static from L1BlockCa…
hudem1 Mar 3, 2026
0bd26a0
fix build
hudem1 Mar 3, 2026
bfccaa1
Merge branch 'main' into hudem1/feat/execution-recorder-interface
hudem1 Mar 4, 2026
ec724dd
fix: Resolve IWasmStore more automatically
hudem1 Mar 6, 2026
8d63b9d
fix: Add correct licensing info
hudem1 Mar 6, 2026
5906b90
fix: Typo
hudem1 Mar 6, 2026
a425c67
fix: Use simplified DI registration syntax
hudem1 Mar 6, 2026
70d934c
feat: Subscribe to BlockAddedToMain event instead of manual active wa…
hudem1 Mar 6, 2026
459c55b
fix: Use autofac as much as possible for ArbitrumWitnessGeneratingBlo…
hudem1 Mar 9, 2026
243a2fe
fix: Use autofac as much as possible for ArbitrumStatelessBlockProces…
hudem1 Mar 9, 2026
c15a23d
Merge branch 'main' into hudem1/feat/execution-recorder-interface
hudem1 Mar 9, 2026
9b39076
fix: Remove useless declaration
hudem1 Mar 9, 2026
be46bc2
fix: Do not update branch
hudem1 Mar 9, 2026
c7c9607
fix Build
hudem1 Mar 9, 2026
35d12a8
fix tests
hudem1 Mar 10, 2026
c592197
Merge branch 'main' into hudem1/feat/execution-recorder-interface
hudem1 Mar 11, 2026
9817438
feat: Support state reconstruction
hudem1 Feb 19, 2026
3de943f
feat: Support PrepareForRecord
hudem1 Feb 19, 2026
3bacaaf
tests: RecordBlockCreation with state reconstruction and PrepareForRe…
hudem1 Feb 19, 2026
814f1cd
fix: HasRoot only check overlay memDB or database
hudem1 Feb 23, 2026
fe474b3
fix: Recover txs SenderAddress before re-executing blocks
hudem1 Feb 23, 2026
0d1b593
fix: Use lock to recreate every needed state only once
hudem1 Feb 23, 2026
6dfcc89
fix Build
hudem1 Mar 3, 2026
21857c0
feat: Make witness generation read only wrt reconstructed state trie …
hudem1 Mar 3, 2026
358cb30
feat: Prune reconstructed state that then becomes useless
hudem1 Mar 3, 2026
b717a75
feat: Flushes whole dirty cache on shutdown (commented)
hudem1 Mar 3, 2026
5173e81
feat: Add special configs for validation with memory pruning enabled
hudem1 Mar 3, 2026
21b6462
fix: Conflicts with latest master
hudem1 Mar 4, 2026
61839ce
fix existing tests
hudem1 Mar 6, 2026
b40e091
fix: Create IStateReconstructor
hudem1 Mar 6, 2026
40895ce
tests: ReconstructedState pruning and integration tests
hudem1 Mar 6, 2026
4653a70
fix: update to latest base wit gen branch
hudem1 Mar 10, 2026
8a47185
fix IStateReconstructor
hudem1 Mar 10, 2026
97c7381
fix: Update to latest wit gen v2 branch
hudem1 Mar 11, 2026
23580db
Merge branch 'main' into hudem1/feat/prepare-for-record
hudem1 Mar 13, 2026
93a45a4
fix: Use interface instead of concrete type
hudem1 Mar 13, 2026
85fc507
feat: Remove useless ReadOnlyReconstructedStateTrieStore
hudem1 Mar 13, 2026
ed35a45
fix: Remove now non-existent SpanSource
hudem1 Mar 13, 2026
10a7e08
fix: Format
hudem1 Mar 13, 2026
4a0af7f
feat: Add license info on new files
hudem1 Mar 13, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ public async Task RecordBlockCreation_WitnessWithoutUserWasms_StatelessExecution

using ArbitrumRpcTestBlockchain chain = new ArbitrumTestBlockchainBuilder()
.WithRecording(recording)
.Build();
// Flush trie nodes to underlying nodeStorage to make state roots accessible for ReconstructedStateTrieStore during witness generation
.Build(chain => chain.WorldStateManager.FlushCache(CancellationToken.None));

ResultWrapper<RecordResult> recordResultWrapper = await chain.ArbitrumRpcModule.RecordBlockCreation(new RecordBlockCreationParameters(digestMessage.Index, digestMessage.Message, WasmTargets: []));
RecordResult recordResult = ThrowOnFailure(recordResultWrapper, digestMessage.Index);
Expand Down Expand Up @@ -74,7 +75,8 @@ public async Task RecordBlockCreation_WitnessWithUserWasms_StatelessExecutionIsS

using ArbitrumRpcTestBlockchain chain = new ArbitrumTestBlockchainBuilder()
.WithRecording(recording)
.Build();
// Flush trie nodes to underlying nodeStorage to make state roots accessible for ReconstructedStateTrieStore during witness generation
.Build(chain => chain.WorldStateManager.FlushCache(CancellationToken.None));

string[] wasmTargets = chain.StylusTargetConfig.GetWasmTargets().ToArray();
ResultWrapper<RecordResult> recordResultWrapper = await chain.ArbitrumRpcModule.RecordBlockCreation(new RecordBlockCreationParameters(digestMessage.Index, digestMessage.Message, WasmTargets: wasmTargets));
Expand Down Expand Up @@ -112,7 +114,8 @@ public async Task RecordBlockCreation_WitnessWithUserWasms_CaptureAsms(ulong mes

using ArbitrumRpcTestBlockchain chain = new ArbitrumTestBlockchainBuilder()
.WithRecording(recording)
.Build();
// Flush trie nodes to underlying nodeStorage to make state roots accessible for ReconstructedStateTrieStore during witness generation
.Build(chain => chain.WorldStateManager.FlushCache(CancellationToken.None));

string[] wasmTargets = chain.StylusTargetConfig.GetWasmTargets().ToArray();
ResultWrapper<RecordResult> recordResultWrapper = await chain.ArbitrumRpcModule.RecordBlockCreation(new RecordBlockCreationParameters(digestMessage.Index, digestMessage.Message, WasmTargets: wasmTargets));
Expand Down Expand Up @@ -158,7 +161,7 @@ public async Task RecordBlockCreation_ExtCodeSizeFollowedByIsZero_StillRecordsTa

using ArbitrumRpcTestBlockchain chain = new ArbitrumTestBlockchainBuilder()
.WithGenesisBlock(initialBaseFee: (ulong)l1BaseFee)
.Build();
.Build(); // no need to flush trie here, do it before RecordBlockCreation call

Address sender = FullChainSimulationAccounts.Owner.Address;

Expand Down Expand Up @@ -272,6 +275,9 @@ public async Task RecordBlockCreation_ExtCodeSizeFollowedByIsZero_StillRecordsTa
callResult.Result.Should().Be(Result.Success);
chain.LatestReceipts()[1].StatusCode.Should().Be(StatusCode.Success);

// Flush trie nodes to underlying nodeStorage to make state roots accessible for ReconstructedStateTrieStore during witness generation
chain.WorldStateManager.FlushCache(CancellationToken.None);

// Step 5: Call RecordBlockCreation to generate the witness
ResultWrapper<RecordResult> recordResultWrapper = await chain.ArbitrumRpcModule.RecordBlockCreation(
new RecordBlockCreationParameters(callParams.Index, callParams.Message, WasmTargets: []));
Expand Down Expand Up @@ -374,6 +380,9 @@ public async Task RecordBlockCreation_PrecompileCalls_RecordsArbitrumPrecompileC
receipts[1].StatusCode.Should().Be(StatusCode.Success, "ArbSys call should succeed");
receipts[2].StatusCode.Should().Be(StatusCode.Success, "ecrecover call should succeed");

// Flush trie nodes to underlying nodeStorage to make state roots accessible for ReconstructedStateTrieStore during witness generation
chain.WorldStateManager.FlushCache(CancellationToken.None);

// Call RecordBlockCreation to generate the witness
ResultWrapper<RecordResult> recordResultWrapper = await chain.ArbitrumRpcModule.RecordBlockCreation(
new RecordBlockCreationParameters(callParams.Index, callParams.Message, WasmTargets: []));
Expand Down Expand Up @@ -493,6 +502,9 @@ public async Task RecordBlockCreation_BlockHashOpcode_RecordsStorageTrieNodeInWi
call2Result.Result.Should().Be(Result.Success);
chain.LatestReceipts()[1].StatusCode.Should().Be(StatusCode.Success);

// Flush trie nodes to underlying nodeStorage to make state roots accessible for ReconstructedStateTrieStore during witness generation
chain.WorldStateManager.FlushCache(CancellationToken.None);

// Step 2: Call the contract again (would use cached value from the block that just got built
// if cache were persisted into witness-generating env)
// Making sure witness-generating VM has its own empty cache and must access storage, recording the trie nodes.
Expand Down Expand Up @@ -552,6 +564,9 @@ public async Task RecordBlockCreation_ArbBlockHash_RecordsHeadersInWitness()
callResult.Result.Should().Be(Result.Success);
chain.LatestReceipts()[1].StatusCode.Should().Be(StatusCode.Success, "ArbBlockHash call should succeed");

// Flush trie nodes to underlying nodeStorage to make state roots accessible for ReconstructedStateTrieStore during witness generation
chain.WorldStateManager.FlushCache(CancellationToken.None);

ResultWrapper<RecordResult> recordResultWrapper = await chain.ArbitrumRpcModule.RecordBlockCreation(
new RecordBlockCreationParameters(callParams.Index, callParams.Message, WasmTargets: []));
RecordResult recordResult = ThrowOnFailure(recordResultWrapper, callParams.Index);
Expand Down Expand Up @@ -668,6 +683,9 @@ public async Task RecordBlockCreation_SubmitRetryableWithEmptyCalldata_RecordsCa
await chain.DigestAndGetParams(retryable);
result.Result.Should().Be(Result.Success);

// Flush trie nodes to underlying nodeStorage to make state roots accessible for ReconstructedStateTrieStore during witness generation
chain.WorldStateManager.FlushCache(CancellationToken.None);

ResultWrapper<RecordResult> recordResultWrapper = await chain.ArbitrumRpcModule.RecordBlockCreation(
new RecordBlockCreationParameters(digestParams.Index, digestParams.Message, WasmTargets: []));
RecordResult recordResult = ThrowOnFailure(recordResultWrapper, digestParams.Index);
Expand Down Expand Up @@ -776,6 +794,9 @@ public async Task RecordBlockCreation_TryReapRetryableNotExpired_RecordsTimeoutW
await chain.DigestAndGetParams(new TestL2Transactions(l1BaseFee, sender, transferTx));
result.Result.Should().Be(Result.Success);

// Flush trie nodes to underlying nodeStorage to make state roots accessible for ReconstructedStateTrieStore during witness generation
chain.WorldStateManager.FlushCache(CancellationToken.None);

ResultWrapper<RecordResult> recordResultWrapper = await chain.ArbitrumRpcModule.RecordBlockCreation(
new RecordBlockCreationParameters(digestParams.Index, digestParams.Message, WasmTargets: []));
RecordResult recordResult = ThrowOnFailure(recordResultWrapper, digestParams.Index);
Expand Down Expand Up @@ -812,6 +833,9 @@ public async Task RecordBlockCreation_NonUserTransaction_RecordsBrotliCompressio
await chain.DigestAndGetParams(new TestEndOfBlock(l1BaseFee));
result.Result.Should().Be(Result.Success);

// Flush trie nodes to underlying nodeStorage to make state roots accessible for ReconstructedStateTrieStore during witness generation
chain.WorldStateManager.FlushCache(CancellationToken.None);

ResultWrapper<RecordResult> recordResultWrapper = await chain.ArbitrumRpcModule.RecordBlockCreation(
new RecordBlockCreationParameters(digestParams.Index, digestParams.Message, WasmTargets: []));
RecordResult recordResult = ThrowOnFailure(recordResultWrapper, digestParams.Index);
Expand Down Expand Up @@ -931,6 +955,9 @@ public async Task RecordBlockCreation_WhenStorageSlotModifiedAndResetInSameBlock
chain.LatestReceipts()[1].StatusCode.Should().Be(StatusCode.Success, "TX1 (set to 2) should succeed");
chain.LatestReceipts()[2].StatusCode.Should().Be(StatusCode.Success, "TX2 (reset to 1) should succeed");

// Flush trie nodes to underlying nodeStorage to make state roots accessible for ReconstructedStateTrieStore during witness generation
chain.WorldStateManager.FlushCache(CancellationToken.None);

// Record block creation and generate witness
ResultWrapper<RecordResult> recordResultWrapper = await chain.ArbitrumRpcModule.RecordBlockCreation(
new RecordBlockCreationParameters(digestParams.Index, digestParams.Message, WasmTargets: []));
Expand Down Expand Up @@ -993,7 +1020,7 @@ public async Task RecordBlockCreation_WhenStateModifiedAndResetDirectlyViaWorldS
depositResult.Result.Should().Be(Result.Success);

// Pre-populate NetworkFeeAccount (ArbOS root storage, offset 3) with a known original value.
// This creates a leaf trie node at that storage path so the assertion targets something unique.
// This creates a leaf trie node at that storage path so the assertion targets a unique trie node.
Address originalFeeAccount = TestItem.AddressB;
chain.AppendBlock(chain =>
{
Expand Down Expand Up @@ -1062,6 +1089,9 @@ public async Task RecordBlockCreation_WhenStateModifiedAndResetDirectlyViaWorldS
"NetworkFeeAccount should retain its original value after modify + reset in the same block");
}

// Flush trie nodes to underlying nodeStorage to make state roots accessible for ReconstructedStateTrieStore during witness generation
chain.WorldStateManager.FlushCache(CancellationToken.None);

// Record block creation and generate witness
ResultWrapper<RecordResult> recordResultWrapper = await chain.ArbitrumRpcModule.RecordBlockCreation(
new RecordBlockCreationParameters(digestParams.Index, digestParams.Message, WasmTargets: []));
Expand Down Expand Up @@ -1191,6 +1221,9 @@ public async Task RecordBlockCreation_TransactionSetsSomeStateButReverts_StillRe
"address should not be registered since the transaction reverted");
}

// Flush trie nodes to underlying nodeStorage to make state roots accessible for ReconstructedStateTrieStore during witness generation
chain.WorldStateManager.FlushCache(CancellationToken.None);

// Record the block and generate the witness
ResultWrapper<RecordResult> recordResultWrapper = await chain.ArbitrumRpcModule.RecordBlockCreation(
new RecordBlockCreationParameters(digestParams.Index, digestParams.Message, WasmTargets: []));
Expand Down
Loading
Loading