Skip to content

Commit

Permalink
added more private tracing functions
Browse files Browse the repository at this point in the history
Signed-off-by: Nischal Sharma <nischal@web3labs.com>
  • Loading branch information
NickSneo committed Jun 26, 2023
1 parent 98f5ce4 commit e38b014
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.TraceTransaction;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.PrivacyIdProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockTracer;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.privateProcessor.PrivateBlockTracer;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.api.query.PrivacyQueries;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;

Expand All @@ -23,18 +24,20 @@ public class PrivTraceTransaction extends PrivateAbstractTraceByHash implements
private static final Logger LOG = LoggerFactory.getLogger(TraceTransaction.class);

public PrivTraceTransaction(
final Supplier<BlockTracer> blockTracerSupplier,
final Supplier<PrivateBlockTracer> blockTracerSupplier,
final BlockchainQueries blockchainQueries,
final ProtocolSchedule protocolSchedule,
final PrivacyQueries privacyQueries,
final PrivacyController privacyController,
final PrivacyParameters privacyParameters,
final PrivacyIdProvider privacyIdProvider) {
super(
blockTracerSupplier,
blockchainQueries,
privacyQueries,
protocolSchedule,
privacyController,
privacyParameters,
privacyIdProvider);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.PrivacyIdProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockTrace;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockTracer;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.Tracer;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.TransactionTrace;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.privateProcessor.PrivateBlockTrace;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.privateProcessor.PrivateBlockTracer;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.privateProcessor.PrivateTracer;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.privateProcessor.PrivateTransactionTrace;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.flat.FlatTrace;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.flat.FlatTraceGenerator;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.api.query.PrivacyQueries;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.debug.TraceOptions;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.privacy.ExecutedPrivateTransaction;
Expand All @@ -33,25 +33,28 @@

public abstract class PrivateAbstractTraceByHash implements JsonRpcMethod {

protected final Supplier<BlockTracer> blockTracerSupplier;
protected final Supplier<PrivateBlockTracer> blockTracerSupplier;
protected final BlockchainQueries blockchainQueries;
protected final PrivacyQueries privacyQueries;
protected final ProtocolSchedule protocolSchedule;
protected final PrivacyController privacyController;
protected final PrivacyParameters privacyParameters;
protected final PrivacyIdProvider privacyIdProvider;

protected PrivateAbstractTraceByHash(
final Supplier<BlockTracer> blockTracerSupplier,
final Supplier<PrivateBlockTracer> blockTracerSupplier,
final BlockchainQueries blockchainQueries,
final PrivacyQueries privacyQueries,
final ProtocolSchedule protocolSchedule,
final PrivacyController privacyController,
final PrivacyParameters privacyParameters,
final PrivacyIdProvider privacyIdProvider) {
this.blockTracerSupplier = blockTracerSupplier;
this.blockchainQueries = blockchainQueries;
this.privacyQueries = privacyQueries;
this.protocolSchedule = protocolSchedule;
this.privacyController = privacyController;
this.privacyParameters = privacyParameters;
this.privacyIdProvider = privacyIdProvider;
}

Expand All @@ -69,53 +72,76 @@ public Stream<FlatTrace> resultByTransactionHash(
.findPrivateTransactionByPmtHash(transactionHash, enclaveKey)
.map(ExecutedPrivateTransaction::getBlockNumber)
.flatMap(blockNumber -> blockchainQueries.getBlockchain().getBlockHashByNumber(blockNumber))
.map(blockHash -> privacyQueries.getPrivateBlockMetaData(privacyGroupId, blockHash))
.map(
blockMetadata -> getTraceBlock(blockMetadata.orElse(null), transactionHash, enclaveKey))
.map(blockHash -> getTraceBlock(blockHash, transactionHash, enclaveKey, privacyGroupId))
.orElse(Stream.empty());
}

private Stream<FlatTrace> getTraceBlock(
final PrivateBlockMetadata blockMetadata,
final Hash blockHash,
final Hash transactionHash,
final String enclaveKey) {
if (blockMetadata == null || blockMetadata.getPrivateTransactionMetadataList().isEmpty()) {
final String enclaveKey,
final String privacyGroupId) {
Block block = blockchainQueries.getBlockchain().getBlockByHash(blockHash).orElse(null);
PrivateBlockMetadata privateBlockMetadata =
privacyQueries.getPrivateBlockMetaData(privacyGroupId, blockHash).orElse(null);

if (privateBlockMetadata == null || block == null) {
return Stream.empty();
}
return PrivateTracer.processTracing(
blockchainQueries,
blockMetadata,
Optional.of(block.getHeader()),
privacyGroupId,
enclaveKey,
privacyParameters,
privacyController,
mutableWorldState -> {
final TransactionTrace transactionTrace = getTransactionTrace(block, transactionHash);
return Optional.ofNullable(getTraceStream(transactionTrace, block));
final PrivateTransactionTrace privateTransactionTrace =
getTransactionTrace(
block, transactionHash, enclaveKey, privateBlockMetadata, privacyGroupId);
return Optional.ofNullable(getTraceStream(privateTransactionTrace, block));
})
.orElse(Stream.empty());
}

private TransactionTrace getTransactionTrace(final Block block, final Hash transactionHash) {
return Tracer.processTracing(
private PrivateTransactionTrace getTransactionTrace(
final Block block,
final Hash transactionHash,
final String enclaveKey,
final PrivateBlockMetadata privateBlockMetadata,
final String privacyGroupId) {
return PrivateTracer.processTracing(
blockchainQueries,
Optional.of(block.getHeader()),
mutableWorldState -> {
return blockTracerSupplier
.get()
.trace(
mutableWorldState,
block,
new DebugOperationTracer(new TraceOptions(false, false, true)))
.map(BlockTrace::getTransactionTraces)
.orElse(Collections.emptyList())
.stream()
.filter(trxTrace -> trxTrace.getTransaction().getHash().equals(transactionHash))
.findFirst();
})
privacyGroupId,
enclaveKey,
privacyParameters,
privacyController,
mutableWorldState ->
blockTracerSupplier
.get()
.trace(
mutableWorldState,
block,
new DebugOperationTracer(new TraceOptions(false, false, true)),
enclaveKey,
privacyGroupId,
privateBlockMetadata)
.map(PrivateBlockTrace::getTransactionTraces)
.orElse(Collections.emptyList())
.stream()
.filter(
trxTrace ->
trxTrace.getPrivateTransaction().getPmtHash().equals(transactionHash))
.findFirst())
.orElseThrow();
}

private Stream<FlatTrace> getTraceStream(
final TransactionTrace transactionTrace, final Block block) {
final PrivateTransactionTrace transactionTrace, final Block block) {
transactionTrace.getTraceFrames();
return FlatTraceGenerator.generateFromTransactionTraceAndBlock(
this.protocolSchedule, transactionTrace, block)
this.protocolSchedule, null, block)
.map(FlatTrace.class::cast);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.query.PrivacyQueries;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockBody;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.privacy.ExecutedPrivateTransaction;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.ethereum.privacy.PrivateTransactionProcessor;
import org.hyperledger.besu.ethereum.privacy.storage.PrivateBlockMetadata;

Expand All @@ -22,20 +21,14 @@ public class PrivateBlockReplay {

private final ProtocolSchedule protocolSchedule;
private final Blockchain blockchain;

private final PrivacyQueries privacyQueries;

private final PrivacyController privacyController;
;

public PrivateBlockReplay(
final ProtocolSchedule protocolSchedule,
final Blockchain blockchain,
final PrivacyQueries privacyQueries,
final PrivacyController privacyController) {
this.protocolSchedule = protocolSchedule;
this.blockchain = blockchain;
this.privacyQueries = privacyQueries;
this.privacyController = privacyController;
}

Expand Down Expand Up @@ -134,7 +127,7 @@ Optional<T> perform(
@FunctionalInterface
public interface TransactionAction<T> {
T performAction(
PrivateTransaction transaction,
ExecutedPrivateTransaction transaction,
BlockHeader blockHeader,
Blockchain blockchain,
PrivateTransactionProcessor transactionProcessor,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.privateProcessor;

import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockReplay;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockTrace;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.Tracer;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.TransactionTrace;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.debug.TraceFrame;
import org.hyperledger.besu.ethereum.privacy.storage.PrivateBlockMetadata;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
Expand All @@ -18,56 +12,64 @@
import java.util.List;
import java.util.Optional;

import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;

public class PrivateBlockTracer {
private final PrivateBlockReplay blockReplay;
// Either the initial block state or the state of the prior TX, including miner rewards.
private WorldUpdater chainedUpdater;
private WorldUpdater privateChainedUpdater;

public PrivateBlockTracer(final PrivateBlockReplay blockReplay) {
this.blockReplay = blockReplay;
}

public Optional<BlockTrace> trace(
final Tracer.TraceableState mutableWorldState,
final Hash blockHash,
final DebugOperationTracer tracer) {
return blockReplay.block(blockHash, prepareReplayAction(mutableWorldState, tracer));
}

public Optional<BlockTrace> trace(
final Tracer.TraceableState mutableWorldState,
public Optional<PrivateBlockTrace> trace(
final PrivateTracer.TraceableState mutableWorldState,
final Block block,
final DebugOperationTracer tracer,
final String enclaveKey,
final String privacyGroupId,
final PrivateBlockMetadata privateBlockMetadata) {
return blockReplay.block(block, privateBlockMetadata, enclaveKey, prepareReplayAction(mutableWorldState, tracer));
return blockReplay.block(
block,
privateBlockMetadata,
enclaveKey,
prepareReplayAction(mutableWorldState, tracer, privacyGroupId));
}

private BlockReplay.TransactionAction<TransactionTrace> prepareReplayAction(
final MutableWorldState mutableWorldState, final DebugOperationTracer tracer) {
private PrivateBlockReplay.TransactionAction<PrivateTransactionTrace> prepareReplayAction(
final PrivateTracer.TraceableState mutableWorldState,
final DebugOperationTracer tracer,
final String privacyGroupId) {
return (transaction, header, blockchain, transactionProcessor, dataGasPrice) -> {
// if we have no prior updater, it must be the first TX, so use the block's initial state
if (chainedUpdater == null) {
chainedUpdater = mutableWorldState.updater();
privateChainedUpdater = mutableWorldState.privateUpdater();

} else if (chainedUpdater instanceof StackedUpdater<?, ?> stackedUpdater) {
stackedUpdater.markTransactionBoundary();
}
// create an updater for just this tx
chainedUpdater = chainedUpdater.updater();
privateChainedUpdater = mutableWorldState.privateUpdater();
final TransactionProcessingResult result =
transactionProcessor.processTransaction(
blockchain,
chainedUpdater,
privateChainedUpdater,
header,
transaction.getPmtHash(),
transaction,
header.getCoinbase(),
tracer,
new CachingBlockHashLookup(header, blockchain),
false,
dataGasPrice);
Bytes32.wrap(Bytes.fromBase64String(privacyGroupId)));

final List<TraceFrame> traceFrames = tracer.copyTraceFrames();
tracer.reset();
return new TransactionTrace(transaction, result, traceFrames);
return new PrivateTransactionTrace(transaction, result, traceFrames);
};
}
}
Loading

0 comments on commit e38b014

Please sign in to comment.