Skip to content

Commit c663084

Browse files
authored
Merge pull request #37 from garyschulte/test/reproduce-hub-accumulator-diffs
bump besu version, add case to reproduce hub accumulator diffs on contract deploy revert
2 parents 6bfc24d + 78602ee commit c663084

File tree

6 files changed

+212
-9
lines changed

6 files changed

+212
-9
lines changed

build.gradle

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,13 @@ dependencies {
205205
testImplementation 'org.hyperledger.besu:evm'
206206
compileOnly 'org.hyperledger.besu.internal:core'
207207
compileOnly 'org.hyperledger.besu:evm'
208+
testImplementation "org.hyperledger.besu.internal:testutil"
209+
testImplementation "org.hyperledger.besu.internal:algorithms"
210+
211+
// pull in testSupport
212+
testImplementation "org.hyperledger.besu.internal:core:${besuVersion}:test-support@jar"
213+
214+
208215
implementation 'info.picocli:picocli'
209216
implementation 'net.consensys.linea.zktracer:arithmetization'
210217

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
releaseVersion=0.6.0-SNAPSHOT
2-
besuVersion=25.4.1-linea1
1+
releaseVersion=0.6.1-SNAPSHOT
2+
besuVersion=25.5.0-linea2
33
arithmetizationVersion=beta-v2.1-rc16

gradle/versions.gradle

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,6 @@
1515

1616
dependencyManagement {
1717
dependencies {
18-
// jackson
19-
dependencySet(group: 'com.fasterxml.jackson.core', version : '2.14.1') {
20-
entry 'jackson-annotations'
21-
entry 'jackson-core'
22-
entry 'jackson-databind'
23-
}
24-
2518
// Error prone dependencies
2619
dependencySet(group: 'com.google.errorprone', version: '2.18.0') {
2720
entry 'error_prone_annotation'
@@ -35,6 +28,9 @@ dependencyManagement {
3528
dependency "org.hyperledger.besu:plugin-api:${besuVersion}"
3629
dependency "org.hyperledger.besu:besu-datatypes:${besuVersion}"
3730
dependency "org.hyperledger.besu.internal:core:${besuVersion}"
31+
dependency "org.hyperledger.besu.internal:testutil:${besuVersion}"
32+
dependency "org.hyperledger.besu.internal:algorithms:${besuVersion}"
33+
3834

3935
// arithmetization dependencies
4036
dependency "net.consensys.linea.zktracer:arithmetization:${arithmetizationVersion}"

src/test/java/net/consensys/shomei/blocktracing/ZkBlockImportTracerProviderTest.java

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
*/
1515
package net.consensys.shomei.blocktracing;
1616

17+
import static org.junit.jupiter.api.Assertions.assertEquals;
18+
import static org.junit.jupiter.api.Assertions.assertNotNull;
19+
import static org.junit.jupiter.api.Assertions.assertTrue;
1720
import static org.mockito.ArgumentMatchers.any;
1821
import static org.mockito.Mockito.doAnswer;
1922
import static org.mockito.Mockito.mock;
@@ -22,27 +25,50 @@
2225
import static org.mockito.Mockito.times;
2326
import static org.mockito.Mockito.verify;
2427

28+
import net.consensys.linea.zktracer.ZkTracer;
2529
import net.consensys.shomei.cli.ShomeiCliOptions;
2630
import net.consensys.shomei.context.TestShomeiContext;
2731
import net.consensys.shomei.trielog.TrieLogValue;
2832
import net.consensys.shomei.trielog.ZkAccountValue;
33+
import net.consensys.shomei.trielog.ZkTrieLogFactory;
34+
import net.consensys.shomei.trielog.ZkTrieLogService;
2935

3036
import java.math.BigInteger;
3137
import java.util.Collections;
3238
import java.util.Map;
3339
import java.util.Optional;
3440
import java.util.Set;
41+
import java.util.concurrent.atomic.AtomicReference;
3542

43+
import org.apache.tuweni.bytes.Bytes;
3644
import org.apache.tuweni.bytes.Bytes32;
3745
import org.apache.tuweni.units.bigints.UInt256;
46+
import org.bouncycastle.math.ec.custom.sec.SecP256K1FieldElement;
47+
import org.hyperledger.besu.crypto.SECPSignature;
3848
import org.hyperledger.besu.datatypes.AccountValue;
3949
import org.hyperledger.besu.datatypes.Address;
4050
import org.hyperledger.besu.datatypes.Hash;
4151
import org.hyperledger.besu.datatypes.StorageSlotKey;
52+
import org.hyperledger.besu.datatypes.TransactionType;
4253
import org.hyperledger.besu.datatypes.Wei;
54+
import org.hyperledger.besu.ethereum.BlockProcessingResult;
55+
import org.hyperledger.besu.ethereum.chain.Blockchain;
56+
import org.hyperledger.besu.ethereum.core.Block;
57+
import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
58+
import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil;
59+
import org.hyperledger.besu.ethereum.core.MutableWorldState;
60+
import org.hyperledger.besu.ethereum.core.Transaction;
61+
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
62+
import org.hyperledger.besu.ethereum.mainnet.BlockProcessor;
63+
import org.hyperledger.besu.plugin.ServiceManager;
4364
import org.hyperledger.besu.plugin.data.BlockHeader;
65+
import org.hyperledger.besu.plugin.services.BlockImportTracerProvider;
66+
import org.hyperledger.besu.plugin.services.TrieLogService;
67+
import org.hyperledger.besu.plugin.services.storage.DataStorageFormat;
68+
import org.hyperledger.besu.plugin.services.tracer.BlockAwareOperationTracer;
4469
import org.hyperledger.besu.plugin.services.trielogs.TrieLog;
4570
import org.hyperledger.besu.plugin.services.trielogs.TrieLogAccumulator;
71+
import org.hyperledger.besu.testutil.BlockTestUtil;
4672
import org.junit.jupiter.api.BeforeEach;
4773
import org.junit.jupiter.api.Test;
4874
import org.junit.jupiter.api.extension.ExtendWith;
@@ -215,4 +241,132 @@ void testAccumulatorMissingSlot() {
215241
// ✅ Verify alert() was never called
216242
verify(comparator, times(1)).alert(any());
217243
}
244+
245+
@Test
246+
public void assertTrieLogContainsHubStateOnNewContractSload() {
247+
testContext.getCliOptions().zkTraceComparisonMask = 15;
248+
var mockPluginServiceManager = mock(ServiceManager.class);
249+
250+
// setup mock plugin service manager zktrielogfactory:
251+
var zkTrieLogService = mock(ZkTrieLogService.class);
252+
var zkTrieLogFactoryImpl = spy(new ZkTrieLogFactory(testContext));
253+
doAnswer(__ -> Optional.of(zkTrieLogService))
254+
.when(mockPluginServiceManager)
255+
.getService(TrieLogService.class);
256+
doAnswer(__ -> Optional.of(zkTrieLogFactoryImpl)).when(zkTrieLogService).getTrieLogFactory();
257+
AtomicReference<TrieLog> capturedTrieLog = new AtomicReference<>();
258+
doAnswer(
259+
invocation -> {
260+
var trielog = (TrieLog) invocation.callRealMethod();
261+
capturedTrieLog.set(trielog);
262+
return trielog;
263+
})
264+
.when(zkTrieLogFactoryImpl)
265+
.create(any(TrieLogAccumulator.class), any(BlockHeader.class));
266+
267+
var zkTracerProviderSpy =
268+
spy(
269+
new ZkBlockImportTracerProvider(
270+
testContext, () -> Optional.of(BigInteger.valueOf(59144L))));
271+
testContext.setBlockImportTraceProvider(zkTracerProviderSpy);
272+
273+
// Set up test world state and blockchain
274+
final BlockchainSetupUtil setupUtil =
275+
BlockchainSetupUtil.createForEthashChain(
276+
new BlockTestUtil.ChainResources(
277+
this.getClass().getClassLoader().getResource("zktestGenesis.json"),
278+
BlockTestUtil.class.getClassLoader().getResource("chain.blocks")),
279+
DataStorageFormat.BONSAI,
280+
mockPluginServiceManager);
281+
final Blockchain blockchain = setupUtil.getBlockchain();
282+
final MutableWorldState worldState = setupUtil.getWorldArchive().getWorldState();
283+
284+
var spyProtocolContext = spy(setupUtil.getProtocolContext());
285+
286+
// setup zktracerprovider plugin service
287+
AtomicReference<ZkTracer> capturedTracer = new AtomicReference<>();
288+
doAnswer(__ -> Optional.of(zkTracerProviderSpy))
289+
.when(mockPluginServiceManager)
290+
.getService(BlockImportTracerProvider.class);
291+
doAnswer(__ -> mockPluginServiceManager).when(spyProtocolContext).getPluginServiceManager();
292+
doAnswer(
293+
invocation -> {
294+
BlockAwareOperationTracer tracer =
295+
(BlockAwareOperationTracer) invocation.callRealMethod();
296+
capturedTracer.set((ZkTracer) tracer);
297+
return tracer;
298+
})
299+
.when(zkTracerProviderSpy)
300+
.getBlockImportTracer(any(BlockHeader.class));
301+
302+
var r =
303+
Bytes.fromHexString("0xde0db8ce81c8092823a2d91b3a3cc421bc6b384b562f567e67b26c5443ff28e9")
304+
.toUnsignedBigInteger();
305+
var s =
306+
Bytes.fromHexString("0x44457e69f445284d1f1ba99107b53c1d4b3d1e8c7283ff504341e5a92699c09d")
307+
.toUnsignedBigInteger();
308+
var sig = SECPSignature.create(r, s, (byte) 0, SecP256K1FieldElement.Q);
309+
310+
var tx =
311+
new Transaction.Builder()
312+
.signature(sig)
313+
.type(TransactionType.EIP1559)
314+
.sender(Address.fromHexString("0x43370108f30ee5ed54a9565f37af3be8502903f5"))
315+
.to(Address.fromHexString("0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789"))
316+
.nonce(14261)
317+
.value(Wei.ZERO)
318+
.payload(
319+
Bytes.fromHexString(
320+
"0x1fad948c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000043370108f30ee5ed54a9565f37af3be8502903f50000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000051ce6a8e868fa0c928346ac7489a74432c44bc933db076b8929744925f16e35a14de0c7e122e512efe282e76000000000000000000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000007a120000000000000000000000000000000000000000000000000000000000006b08a000000000000000000000000000000000000000000000000000000000000b1580000000000000000000000000000000000000000000000000000000065fa53ff000000000000000000000000000000000000000000000000000000005cb5068300000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000000783fbe35a874284e41c955331a363c1ea085301a8dd8fd8f440000000000000000000000001708dc05842c8fbd5e2e60a0adbd1b2efab061640000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084b61d27f60000000000000000000000000acf75e7c29bd27f1cd6ed47c8769c61bc6a68810000000000000000000000000000000000000000000000000006379da05b600000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004189f4d1fe2626f881082f93a336e51d6fad4faecfaffb843307c6c658bc4ae3ac737b6ece16b3c206b2d26efa8ca1ee6ac85e6a1e984456b7282404592e3d12e31c00000000000000000000000000000000000000000000000000000000000000"))
321+
.maxPriorityFeePerGas(Wei.wrap(Bytes.fromHexString("5cb50683")))
322+
.maxFeePerGas(Wei.wrap(Bytes.fromHexString("0x5cb5068b")))
323+
.gasLimit(1396683L)
324+
.chainId(BigInteger.valueOf(59144))
325+
.build();
326+
327+
// Process block with this tx
328+
final BlockDataGenerator gen = new BlockDataGenerator();
329+
final Block block =
330+
gen.block(
331+
BlockDataGenerator.BlockOptions.create()
332+
.addTransaction(tx)
333+
.hasOmmers(false)
334+
// .setStateRoot(Hash.fromHexString("0xc70a52d661bf92297e17d79b0cb04c508f3767acecf6145171884a82ea5e8a9d"))
335+
.setStateRoot(
336+
Hash.fromHexString(
337+
"0x543543c7c19059bbc9c384ab7344bc281fe08938732480a1bc48d01e3ba8090b")));
338+
final BlockProcessor processor =
339+
setupUtil
340+
.getProtocolSchedule()
341+
.getByBlockHeader(blockchain.getChainHeadHeader())
342+
.getBlockProcessor();
343+
344+
final BlockProcessingResult result =
345+
processor.processBlock(spyProtocolContext, blockchain, worldState, block);
346+
347+
// Assert transaction is present
348+
assertEquals(1, result.getReceipts().size());
349+
350+
// Check that status == 0 (reverted)
351+
final TransactionReceipt receipt = result.getReceipts().get(0);
352+
assertEquals(0, receipt.getStatus());
353+
354+
var create2Address = Address.fromHexString("0x51ce6a8e868fa0c928346ac7489a74432c44bc93");
355+
var create2StorageSeen =
356+
capturedTracer.get().getStoragesSeenByHubForRelativeBlock(1).get(create2Address);
357+
assertNotNull(create2StorageSeen);
358+
359+
var trieLog = capturedTrieLog.get();
360+
var create2TrielogSeen = trieLog.getStorageChanges().get(create2Address);
361+
assertNotNull(create2TrielogSeen);
362+
363+
assertEquals(create2StorageSeen.size(), create2TrielogSeen.size());
364+
// known reverted storage slot key:
365+
final Bytes32 revertedSlotKey =
366+
Bytes32.fromHexString("0x322cf19c484104d3b1a9c2982ebae869ede3fa5f6c4703ca41b9a48c76ee0300");
367+
assertTrue(create2StorageSeen.contains(revertedSlotKey));
368+
var trieLogSlotVal =
369+
create2TrielogSeen.get(new StorageSlotKey(UInt256.fromBytes(revertedSlotKey)));
370+
assertNotNull(trieLogSlotVal);
371+
}
218372
}

src/test/resources/chain.blocks

2.31 KB
Binary file not shown.

src/test/resources/zktestGenesis.json

Lines changed: 46 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)