Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Range tracing with worldstate #5844

Merged
merged 9 commits into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
add tests
Signed-off-by: Karim TAAM <karim.t2am@gmail.com>
  • Loading branch information
matkt committed Sep 8, 2023
commit 128b19d0ae2ab132dae1fa68f1d1b6516af8931a
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.evm.worldstate.WorldState;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.plugin.Unstable;
import org.hyperledger.besu.plugin.services.TraceService;
import org.hyperledger.besu.plugin.services.tracer.BlockAwareOperationTracer;
Expand Down Expand Up @@ -104,8 +104,8 @@ public void traceBlock(final Hash hash, final BlockAwareOperationTracer tracer)
public void trace(
final long fromBlockNumber,
final long toBlockNumber,
final Consumer<WorldState> beforeTracing,
final Consumer<WorldState> afterTracing,
final Consumer<WorldUpdater> beforeTracing,
final Consumer<WorldUpdater> afterTracing,
final BlockAwareOperationTracer tracer) {
checkArgument(tracer != null);
garyschulte marked this conversation as resolved.
Show resolved Hide resolved
LOG.debug("Tracing from block {} to block {}", fromBlockNumber, toBlockNumber);
Expand All @@ -122,14 +122,16 @@ public void trace(
blockchainQueries,
blocks.get(0).getHash(),
garyschulte marked this conversation as resolved.
Show resolved Hide resolved
traceableState -> {
beforeTracing.accept(traceableState);
final WorldUpdater worldStateUpdater = traceableState.updater();
final ChainUpdater chainUpdater = new ChainUpdater(traceableState, worldStateUpdater);
beforeTracing.accept(worldStateUpdater);
final List<TransactionProcessingResult> results = new ArrayList<>();
blocks.forEach(
block -> {
results.addAll(trace(blockchain, block, traceableState, tracer));
results.addAll(trace(blockchain, block, chainUpdater, tracer));
tracer.traceEndBlock(block.getHeader(), block.getBody());
});
afterTracing.accept(traceableState);
afterTracing.accept(chainUpdater.getNextUpdater());
return Optional.of(results);
});
}
Expand All @@ -140,17 +142,17 @@ private void trace(final Block block, final BlockAwareOperationTracer tracer) {
Tracer.processTracing(
blockchainQueries,
block.getHash(),
traceableState -> Optional.of(trace(blockchain, block, traceableState, tracer)));
traceableState ->
Optional.of(trace(blockchain, block, new ChainUpdater(traceableState), tracer)));
tracer.traceEndBlock(block.getHeader(), block.getBody());
}

private List<TransactionProcessingResult> trace(
final Blockchain blockchain,
final Block block,
final Tracer.TraceableState traceableState,
final ChainUpdater chainUpdater,
final BlockAwareOperationTracer tracer) {
final List<TransactionProcessingResult> results = new ArrayList<>();
final ChainUpdater chainUpdater = new ChainUpdater(traceableState);
final ProtocolSpec protocolSpec = protocolSchedule.getByBlockHeader(block.getHeader());
final MainnetTransactionProcessor transactionProcessor = protocolSpec.getTransactionProcessor();
final BlockHeader header = block.getHeader();
Expand Down
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.services;

import static org.assertj.core.api.Assertions.assertThat;

import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil;
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.plugin.services.TraceService;
import org.hyperledger.besu.plugin.services.tracer.BlockAwareOperationTracer;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
class TraceServiceImplTest {

TraceService traceService;
private MutableBlockchain blockchain;
private WorldStateArchive worldStateArchive;
private BlockchainQueries blockchainQueries;

/**
* The blockchain for testing has a height of 32 and the account
* 0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b makes a transaction per block. So, in the head, the
* nonce of this account should be 32.
*/
@BeforeEach
public void setup() {
final BlockchainSetupUtil blockchainSetupUtil =
BlockchainSetupUtil.forTesting(DataStorageFormat.BONSAI);
blockchainSetupUtil.importAllBlocks();
blockchain = blockchainSetupUtil.getBlockchain();
worldStateArchive = blockchainSetupUtil.getWorldArchive();
blockchainQueries = new BlockchainQueries(blockchain, worldStateArchive);
traceService =
new TraceServiceImpl(blockchainQueries, blockchainSetupUtil.getProtocolSchedule());
}

@Test
void shouldRetrieveStateUpdatePostTracingForOneBlock() {

final Address addressToVerify =
Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b");

final long persistedNonceForAccount =
worldStateArchive.getMutable().get(addressToVerify).getNonce();

traceService.trace(
2,
2,
worldState -> {
assertThat(worldState.get(addressToVerify).getNonce()).isEqualTo(1);
},
worldState -> {
assertThat(worldState.get(addressToVerify).getNonce()).isEqualTo(2);
},
BlockAwareOperationTracer.NO_TRACING);

assertThat(worldStateArchive.getMutable().get(addressToVerify).getNonce())
.isEqualTo(persistedNonceForAccount);
}

@Test
void shouldRetrieveStateUpdatePostTracingForAllBlocks() {
final Address addressToVerify =
Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b");

final long persistedNonceForAccount =
worldStateArchive.getMutable().get(addressToVerify).getNonce();

traceService.trace(
0,
32,
worldState -> {
assertThat(worldState.get(addressToVerify).getNonce()).isEqualTo(0);
},
worldState -> {
assertThat(worldState.get(addressToVerify).getNonce())
.isEqualTo(persistedNonceForAccount);
},
BlockAwareOperationTracer.NO_TRACING);

assertThat(worldStateArchive.getMutable().get(addressToVerify).getNonce())
.isEqualTo(persistedNonceForAccount);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,11 @@ public ChainUpdater(final MutableWorldState worldState) {
this.worldState = worldState;
}

public ChainUpdater(final MutableWorldState worldState, final WorldUpdater updater) {
this.worldState = worldState;
this.updater = updater;
}

public WorldUpdater getNextUpdater() {
// if we have no prior updater, it must be the first TX, so use the block's initial state
if (updater == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
package org.hyperledger.besu.plugin.services;

import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.evm.worldstate.WorldState;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.plugin.Unstable;
import org.hyperledger.besu.plugin.services.tracer.BlockAwareOperationTracer;

Expand Down Expand Up @@ -52,7 +52,7 @@ public interface TraceService extends BesuService {
void trace(
final long fromBlockNumber,
final long toBlockNumber,
final Consumer<WorldState> beforeTracing,
final Consumer<WorldState> afterTracing,
final Consumer<WorldUpdater> beforeTracing,
final Consumer<WorldUpdater> afterTracing,
final BlockAwareOperationTracer tracer);
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
* <p>In both methods, the block header and body are provided.
*/
public interface BlockAwareOperationTracer extends OperationTracer {

BlockAwareOperationTracer NO_TRACING = new BlockAwareOperationTracer() {};

/**
* Trace the start of a block.
*
Expand Down