Skip to content

Conversation

@OlivierBBB
Copy link
Collaborator

@OlivierBBB OlivierBBB commented Oct 22, 2025

Note

Adds parameterized empty-block tests and updates the Besu/MultiBlock harness to model empty blocks (null transactions) and correctly trace proof ranges; minor Osaka import tweak.

  • Tests (Empty blocks):
    • Add parameterized tests covering sequences like EENENE, NEEN, NEEE, ENNE, EEEE, EEEN, and single E in EmptyBlockTests.
    • Introduce BlockType enum and builderFromBlockTypeList helper; reuse shared accounts/txs; assert single log in mixed scenario when not using Besu.
  • Testing harness:
    • MultiBlockExecutionEnvironment: add runWithBesuNode option; when enabled, flatten blocks and represent empty blocks as null transactions; dispatch one tx per block to Besu.
    • BesuExecutionTools: accept null transactions to create empty blocks; validate inputs; avoid sending null txs; compute trace start/end when all txs are null; ensure state/receipt checks align with empty blocks; request proofs with derived block range.
  • Arithmetization:
    • Use TraceOsaka.EIP_7825_TRANSACTION_GAS_LIMIT_CAP in OsakaUserTransaction (import adjustment).

Written by Cursor Bugbot for commit c5bc7af. This will update automatically on new commits. Configure here.

@cursor
Copy link

cursor bot commented Oct 23, 2025

Bug: Null Transaction Handling Bug

When oneTxPerBlock is false, the executeTest method attempts to send all transactions without checking if they are null. This leads to a NullPointerException when calling .encoded() on a null transaction, a check that is present in the oneTxPerBlock true path.

Fix in Cursor Fix in Web

@cursor
Copy link

cursor bot commented Oct 23, 2025

Bug: Transaction List Nulls Cause Block Number Errors

The firstBlockNumber calculation is off when oneTxPerBlock is true and the transactions list includes nulls. The current logic subtracts numberOfLeadingEmptyBlocks from an already adjusted firstBlockNumber, which can lead to invalid block numbers (like zero or negative) and an incorrect tracing range.

Fix in Cursor Fix in Web

@cursor
Copy link

cursor bot commented Oct 23, 2025

Bug: Block Number Calculation Incorrect for Non-Standard Genesis Blocks

When blockNumbers.isEmpty() is true (all transactions are null), firstBlockNumber is set to 1 and finalBlockNumber is set to transactions.size(). This assumes the starting block number is 1, but blocks may start at a different number. The calculation should use the genesis block configuration or track the actual block numbers created, not hardcode 1.

Fix in Cursor Fix in Web

@cursor
Copy link

cursor bot commented Oct 23, 2025

Bug: Null Transaction Handling Mismatch

The else branch, which sends all transactions in a single block, doesn't filter out null transactions from the transactions list. This causes a NullPointerException when txs.next() returns null and encoded() is called, unlike the if branch which correctly handles these null entries.

Fix in Cursor Fix in Web

@cursor
Copy link

cursor bot commented Oct 23, 2025

Bug: Test Initialization Order Causes Null References

Instance fields (senderKeyPair, receivingAccount, storingNumber, logging, storing, reading) are initialized with references to chainConfig, but chainConfig is only initialized by the test framework after instance field initialization. This will cause these fields to use a null or uninitialized chainConfig, leading to NullPointerException or incorrect bytecode compilation. These fields should either be initialized lazily in a @beforeeach method or moved into the test methods themselves.

Fix in Cursor Fix in Web

@amkCha
Copy link
Collaborator

amkCha commented Nov 6, 2025

Thanks for fixing the daily ref tests !!

String txHash =
besuNode.execute(ethTransactions.sendRawTransaction(tx.encoded().toHexString()));
txHashes.add(txHash);
}
Copy link

Choose a reason for hiding this comment

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

Bug: NullPointer on Null Transactions in Else Branch

NullPointerException when oneTxPerBlock is false and transactions list contains null values. The else branch (lines 216-223) attempts to call .encoded() on txs.next() without checking if the transaction is null first. When a null transaction is encountered (representing an empty block), this will throw a NullPointerException. The if branch (lines 207-214) correctly handles null transactions with a null check, but the else branch is missing this protection.

Fix in Cursor Fix in Web

null);
besuExecTools.executeTest();
return;
}
Copy link

Choose a reason for hiding this comment

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

Bug: Early Exit Prevents Tracer Initialization

When runWithBesuNode is true, the run() method returns early without initializing the tracer field, leaving it null. Tests that call getHub() after running with Besu node will encounter a NullPointerException since getHub() returns tracer.getHub() and tracer is null.

Fix in Cursor Fix in Web

various configurations of empty / nonempty blocks, in particular

E
EEEE
EEEN
NEEN
NEEE
ENNE
EENENE

where E = empty block, N = nonempty block
@amkCha amkCha force-pushed the prover-tests-for-empty-blocks branch from 419045b to 7a66335 Compare November 20, 2025 11:53
@amkCha amkCha force-pushed the prover-tests-for-empty-blocks branch from 7a66335 to 5342cec Compare November 20, 2025 12:00
for (State.HubTransactionState state : hub.getState().getAll()) {
for (TraceSection section : state.traceSections().trace()) {
if (section instanceof LogSection) {
nbOfLog += 1;

Check failure

Code scanning / CodeQL

Implicit narrowing conversion in compound assignment High test

Implicit cast of source type int to narrower destination type
short
.

Copilot Autofix

AI 1 day ago

The best way to fix this problem is to widen the type of nbOfLog from short to int. This prevents any implicit narrowing conversion when performing compound assignment operations like nbOfLog += 1;. The code's logic and surrounding assumptions are not altered: the only change is the variable's type. You should update the declaration at line 180 from short to int. No additional imports or refactoring are required, and no other code changes are necessary.


Suggested changeset 1
arithmetization/src/test/java/net/consensys/linea/zktracer/EmptyBlockTests.java

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/arithmetization/src/test/java/net/consensys/linea/zktracer/EmptyBlockTests.java b/arithmetization/src/test/java/net/consensys/linea/zktracer/EmptyBlockTests.java
--- a/arithmetization/src/test/java/net/consensys/linea/zktracer/EmptyBlockTests.java
+++ b/arithmetization/src/test/java/net/consensys/linea/zktracer/EmptyBlockTests.java
@@ -177,7 +177,7 @@
 
       if (!runWithBesu) {
         final State hub = env.getHub().state();
-        short nbOfLog = 0;
+        int nbOfLog = 0;
         for (State.HubTransactionState state : hub.getState().getAll()) {
           for (TraceSection section : state.traceSections().trace()) {
             if (section instanceof LogSection) {
EOF
@@ -177,7 +177,7 @@

if (!runWithBesu) {
final State hub = env.getHub().state();
short nbOfLog = 0;
int nbOfLog = 0;
for (State.HubTransactionState state : hub.getState().getAll()) {
for (TraceSection section : state.traceSections().trace()) {
if (section instanceof LogSection) {
Copilot is powered by AI and may make mistakes. Always verify output.
@amkCha amkCha enabled auto-merge (squash) November 20, 2025 15:48
long startBlockNumber = Collections.min(blockNumbers);
long endBlockNumber = Collections.max(blockNumbers);
TraceFile traceFile = traceAndCheckTracer(startBlockNumber, endBlockNumber, currentFork);
checkState(blockNumbers.isEmpty() == allTransactionsAreNull);
Copy link

Choose a reason for hiding this comment

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

Bug: Assertion failure for mixed empty blocks

The assertion checkState(blockNumbers.isEmpty() == allTransactionsAreNull) fails when processing an empty block in a test suite containing a mix of empty and non-empty blocks. For an empty block, blockNumbers is empty (no receipts), but allTransactionsAreNull is false, causing an IllegalStateException.

Fix in Cursor Fix in Web

long firstBlockNumber = blockNumbers.isEmpty() ? 1 : Collections.min(blockNumbers);
long finalBlockNumber =
blockNumbers.isEmpty() ? transactions.size() : Collections.max(blockNumbers);
TraceFile traceFile = traceAndCheckTracer(firstBlockNumber, finalBlockNumber, currentFork);
Copy link

Choose a reason for hiding this comment

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

Bug: Tracing requests non-existent blocks for empty blocks

When processing an empty block, blockNumbers is empty, causing finalBlockNumber to default to transactions.size(). In sequential execution, this requests traces for the entire block range (up to the total count) even though future blocks have not yet been created, leading to potential RPC errors.

Fix in Cursor Fix in Web

long startBlockNumber = Collections.min(blockNumbers);
long endBlockNumber = Collections.max(blockNumbers);
TraceFile traceFile = traceAndCheckTracer(startBlockNumber, endBlockNumber, currentFork);
checkState(blockNumbers.isEmpty() == allTransactionsAreNull);
Copy link

Choose a reason for hiding this comment

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

Bug: Invalid assertion for mixed empty blocks

The checkState condition enforces that empty blocks (empty blockNumbers) can only occur if every transaction in the test is null. This causes an IllegalStateException when running tests with a mix of empty and non-empty blocks, as processing a single empty block results in blockNumbers being empty while allTransactionsAreNull is false.

Fix in Cursor Fix in Web

long firstBlockNumber = blockNumbers.isEmpty() ? 1 : Collections.min(blockNumbers);
long finalBlockNumber =
blockNumbers.isEmpty() ? transactions.size() : Collections.max(blockNumbers);
TraceFile traceFile = traceAndCheckTracer(firstBlockNumber, finalBlockNumber, currentFork);
Copy link

Choose a reason for hiding this comment

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

Bug: Trace generation requests non-existent blocks

When handling an empty block, finalBlockNumber defaults to the total number of transactions (transactions.size()). In sequential execution, this triggers a trace request for the entire planned block range before subsequent blocks have been mined, which will cause RPC errors by requesting blocks that do not yet exist.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants