Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -46,7 +46,7 @@ public record BlockHeaderSnapshot(
String mixHashOrPrevRandao,
long nonce,
Optional<String> baseFee,
Bytes32 parentBeaconBlockRoot) {
Optional<String> parentBeaconBlockRoot) {
public static BlockHeaderSnapshot from(BlockHeader header) {
return new BlockHeaderSnapshot(
header.getParentHash().toHexString(),
Expand All @@ -65,7 +65,7 @@ public static BlockHeaderSnapshot from(BlockHeader header) {
header.getMixHashOrPrevRandao().toHexString(),
header.getNonce(),
header.getBaseFee().map(Quantity::toHexString),
header.getParentBeaconBlockRoot().orElse(null));
header.getParentBeaconBlockRoot().map(Bytes::toHexString));
}

public BlockHeader toBlockHeader() {
Expand All @@ -87,11 +87,11 @@ public BlockHeader toBlockHeader() {
.mixHash(Hash.fromHexString(this.mixHashOrPrevRandao))
.prevRandao(Bytes32.fromHexString(this.mixHashOrPrevRandao))
.nonce(this.nonce)
.blockHeaderFunctions(new CliqueBlockHeaderFunctions())
.parentBeaconBlockRoot(parentBeaconBlockRoot);
.blockHeaderFunctions(new CliqueBlockHeaderFunctions());

this.baseFee.ifPresent(baseFee -> builder.baseFee(Wei.fromHexString(baseFee)));

this.parentBeaconBlockRoot.ifPresent(
root -> builder.parentBeaconBlockRoot(Bytes32.fromHexString(root)));
Copy link

Choose a reason for hiding this comment

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

Bug: Block Header Inconsistency Due to Null Handling

The toBlockHeader method now conditionally sets parentBeaconBlockRoot. If the root is empty, the builder method isn't called, which differs from the original code that explicitly passed null. This can cause the BlockHeaderBuilder to treat the field as "not set" instead of "set to null," leading to inconsistent header reconstruction and potentially breaking round-trip conversion.

Fix in Cursor Fix in Web

return builder.buildBlockHeader();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package net.consensys.linea.zktracer;

import static net.consensys.linea.zktracer.Fork.LONDON;
import static net.consensys.linea.zktracer.Fork.PRAGUE;
import static net.consensys.linea.zktracer.Trace.ETHEREUM_GAS_LIMIT_MAXIMUM;
import static net.consensys.linea.zktracer.Trace.ETHEREUM_GAS_LIMIT_MINIMUM;
import static net.consensys.linea.zktracer.Trace.LINEA_CHAIN_ID;
Expand All @@ -37,6 +38,8 @@ public class ChainConfig {
*/
public static final ChainConfig MAINNET_LONDON_TESTCONFIG = MAINNET_TESTCONFIG(LONDON);

public static final ChainConfig SEPOLIA_PRAGUE_TESTCONFIG = SEPOLIA_TESTCONFIG(PRAGUE);

public static final ChainConfig MAINNET_TESTCONFIG(final Fork fork) {
return new ChainConfig(
fork,
Expand All @@ -47,6 +50,16 @@ public static final ChainConfig MAINNET_TESTCONFIG(final Fork fork) {
LineaL1L2BridgeSharedConfiguration.TEST_DEFAULT);
}

public static final ChainConfig SEPOLIA_TESTCONFIG(final Fork fork) {
return new ChainConfig(
fork,
LINEA_SEPOLIA_CHAIN_ID,
true,
BigInteger.valueOf(LINEA_GAS_LIMIT_MINIMUM),
BigInteger.valueOf(LINEA_GAS_LIMIT_MAXIMUM),
LineaL1L2BridgeSharedConfiguration.TEST_DEFAULT);
}

/**
* Represents Linea mainnet prior to the block gas limit being enforced for the purposes of
* running existing replay tests. As the name suggest, this is only intended for testing purposes.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import net.consensys.linea.corset.CorsetValidator;
import net.consensys.linea.zktracer.ChainConfig;
import net.consensys.linea.zktracer.ConflationAwareOperationTracer;
import net.consensys.linea.zktracer.Fork;
import net.consensys.linea.zktracer.ZkTracer;
import net.consensys.linea.zktracer.module.hub.Hub;
import org.apache.commons.io.FileUtils;
Expand Down Expand Up @@ -288,10 +289,12 @@ private static void executeFrom(
new BlockBody(
blockSnapshot.txs().stream().map(TransactionSnapshot::toTransaction).toList(),
new ArrayList<>());
// Determine mining beneficiay
final Address miningBeneficiary =
useCoinbaseAddressFromBlockHeader
? header.getCoinbase()
: CliqueHelpers.getProposerOfBlock(header);
: determineMiningBeneficiary(header, chain.fork);

tracer.traceStartBlock(world.updater(), header, body, miningBeneficiary);
runSystemInitialTransactions(protocolSpec, chain.fork, world, header, tracer);

Expand Down Expand Up @@ -321,6 +324,15 @@ public Hub getHub() {
return zkTracer.getHub();
}

private static Address determineMiningBeneficiary(BlockHeader header, Fork fork) {
// Clique was only used on forks prior to Shanghai
if (Fork.isPostShanghai(fork)) {
return header.getCoinbase();
} else {
return CliqueHelpers.getProposerOfBlock(header);
}
}

/**
* Initialise a fresh world state from a conflation.
*
Expand Down
Loading