-
Notifications
You must be signed in to change notification settings - Fork 862
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
TraceService: return results for transactions in block #6087
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,13 +26,16 @@ | |
import org.hyperledger.besu.ethereum.chain.Blockchain; | ||
import org.hyperledger.besu.ethereum.core.Block; | ||
import org.hyperledger.besu.ethereum.core.BlockHeader; | ||
import org.hyperledger.besu.ethereum.core.Transaction; | ||
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor; | ||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; | ||
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.WorldUpdater; | ||
import org.hyperledger.besu.plugin.Unstable; | ||
import org.hyperledger.besu.plugin.data.BlockTraceResult; | ||
import org.hyperledger.besu.plugin.data.TransactionTraceResult; | ||
import org.hyperledger.besu.plugin.services.TraceService; | ||
import org.hyperledger.besu.plugin.services.tracer.BlockAwareOperationTracer; | ||
|
||
|
@@ -72,10 +75,9 @@ public TraceServiceImpl( | |
* @param tracer an instance of OperationTracer | ||
*/ | ||
@Override | ||
public void traceBlock(final long blockNumber, final BlockAwareOperationTracer tracer) { | ||
checkArgument(tracer != null); | ||
final Optional<Block> block = blockchainQueries.getBlockchain().getBlockByNumber(blockNumber); | ||
block.ifPresent(value -> trace(value, tracer)); | ||
public BlockTraceResult traceBlock( | ||
final long blockNumber, final BlockAwareOperationTracer tracer) { | ||
return traceBlock(blockchainQueries.getBlockchain().getBlockByNumber(blockNumber), tracer); | ||
} | ||
|
||
/** | ||
|
@@ -85,10 +87,41 @@ public void traceBlock(final long blockNumber, final BlockAwareOperationTracer t | |
* @param tracer an instance of OperationTracer | ||
*/ | ||
@Override | ||
public void traceBlock(final Hash hash, final BlockAwareOperationTracer tracer) { | ||
public BlockTraceResult traceBlock(final Hash hash, final BlockAwareOperationTracer tracer) { | ||
return traceBlock(blockchainQueries.getBlockchain().getBlockByHash(hash), tracer); | ||
} | ||
|
||
private BlockTraceResult traceBlock( | ||
final Optional<Block> maybeBlock, final BlockAwareOperationTracer tracer) { | ||
checkArgument(tracer != null); | ||
final Optional<Block> block = blockchainQueries.getBlockchain().getBlockByHash(hash); | ||
block.ifPresent(value -> trace(value, tracer)); | ||
if (maybeBlock.isEmpty()) { | ||
return BlockTraceResult.empty(); | ||
} | ||
|
||
final Optional<List<TransactionProcessingResult>> results = trace(maybeBlock.get(), tracer); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is it more efficient to assign a variable to maybeBlock.get() - it's used below as well |
||
|
||
if (results.isEmpty()) { | ||
return BlockTraceResult.empty(); | ||
} | ||
|
||
final BlockTraceResult.Builder builder = BlockTraceResult.builder(); | ||
|
||
final List<TransactionProcessingResult> transactionProcessingResults = results.get(); | ||
final List<Transaction> transactions = maybeBlock.get().getBody().getTransactions(); | ||
for (int i = 0; i < transactionProcessingResults.size(); i++) { | ||
final TransactionProcessingResult transactionProcessingResult = | ||
transactionProcessingResults.get(i); | ||
final TransactionTraceResult transactionTraceResult = | ||
transactionProcessingResult.isInvalid() | ||
? TransactionTraceResult.error( | ||
transactions.get(i).getHash(), | ||
transactionProcessingResult.getValidationResult().getErrorMessage()) | ||
: TransactionTraceResult.success(transactions.get(i).getHash()); | ||
|
||
builder.addTransactionTraceResult(transactionTraceResult); | ||
} | ||
|
||
return builder.build(); | ||
} | ||
|
||
/** | ||
|
@@ -136,15 +169,20 @@ public void trace( | |
}); | ||
} | ||
|
||
private void trace(final Block block, final BlockAwareOperationTracer tracer) { | ||
private Optional<List<TransactionProcessingResult>> trace( | ||
final Block block, final BlockAwareOperationTracer tracer) { | ||
LOG.debug("Tracing block {}", block.toLogString()); | ||
final Blockchain blockchain = blockchainQueries.getBlockchain(); | ||
Tracer.processTracing( | ||
blockchainQueries, | ||
block.getHash(), | ||
traceableState -> | ||
Optional.of(trace(blockchain, block, new ChainUpdater(traceableState), tracer))); | ||
|
||
final Optional<List<TransactionProcessingResult>> results = | ||
Tracer.processTracing( | ||
blockchainQueries, | ||
block.getHash(), | ||
traceableState -> | ||
Optional.of(trace(blockchain, block, new ChainUpdater(traceableState), tracer))); | ||
tracer.traceEndBlock(block.getHeader(), block.getBody()); | ||
|
||
return results; | ||
} | ||
|
||
private List<TransactionProcessingResult> trace( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -500,7 +500,8 @@ public TransactionProcessingResult processTransaction( | |
LOG.error("Critical Exception Processing Transaction", re); | ||
return TransactionProcessingResult.invalid( | ||
ValidationResult.invalid( | ||
TransactionInvalidReason.INTERNAL_ERROR, "Internal Error in Besu - " + re)); | ||
TransactionInvalidReason.INTERNAL_ERROR, | ||
"Internal Error in Besu - " + re + "\n" + printableStackTraceFromThrowable(re))); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what does this look like in reality? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an example: Internal Error in Besu - java.lang.IllegalStateException |
||
} | ||
} | ||
|
||
|
@@ -525,4 +526,14 @@ protected long refunded( | |
final long refundAllowance = Math.min(maxRefundAllowance, gasRefund); | ||
return gasRemaining + refundAllowance; | ||
} | ||
|
||
private String printableStackTraceFromThrowable(final RuntimeException re) { | ||
final StringBuilder builder = new StringBuilder(); | ||
|
||
for (final StackTraceElement stackTraceElement : re.getStackTrace()) { | ||
builder.append("\tat ").append(stackTraceElement.toString()).append("\n"); | ||
} | ||
|
||
return builder.toString(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
/* | ||
* 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.plugin.data; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Iterator; | ||
import java.util.List; | ||
import java.util.Objects; | ||
|
||
/** | ||
* Represents the result of tracing a block, containing information about the transaction traces. | ||
*/ | ||
public class BlockTraceResult { | ||
final List<TransactionTraceResult> transactionTraceResults; | ||
|
||
/** | ||
* Constructs a BlockTraceResult with the given list of transaction trace results. | ||
* | ||
* @param transactionTraceResults The list of transaction trace results to be associated with this | ||
* block. | ||
*/ | ||
public BlockTraceResult(final List<TransactionTraceResult> transactionTraceResults) { | ||
this.transactionTraceResults = transactionTraceResults; | ||
} | ||
|
||
/** | ||
* Creates an empty BlockTraceResult with no transaction trace results. | ||
* | ||
* @return An empty BlockTraceResult. | ||
*/ | ||
public static BlockTraceResult empty() { | ||
return new BlockTraceResult(new ArrayList<>()); | ||
} | ||
|
||
/** | ||
* Get the list of transaction trace results for this block. | ||
* | ||
* @return The list of transaction trace results. | ||
*/ | ||
public List<TransactionTraceResult> transactionTraceResults() { | ||
return transactionTraceResults; | ||
} | ||
|
||
@Override | ||
public boolean equals(final Object o) { | ||
if (this == o) { | ||
return true; | ||
} | ||
if (o == null || getClass() != o.getClass()) { | ||
return false; | ||
} | ||
final BlockTraceResult that = (BlockTraceResult) o; | ||
return transactionTraceResults.equals(that.transactionTraceResults()); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(transactionTraceResults); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
final StringBuilder builder = new StringBuilder(); | ||
builder.append("BlockTraceResult{transactionTraceResults=["); | ||
|
||
final Iterator<TransactionTraceResult> iterator = transactionTraceResults.iterator(); | ||
while (iterator.hasNext()) { | ||
builder.append(iterator.next().toString()); | ||
|
||
if (iterator.hasNext()) { | ||
builder.append(","); | ||
} | ||
} | ||
builder.append("]}"); | ||
return builder.toString(); | ||
} | ||
|
||
/** | ||
* Creates a new builder to construct a BlockTraceResult. | ||
* | ||
* @return A new BlockTraceResult.Builder instance. | ||
*/ | ||
public static Builder builder() { | ||
return new Builder(); | ||
} | ||
|
||
/** A builder class for constructing a BlockTraceResult. */ | ||
public static class Builder { | ||
List<TransactionTraceResult> transactionTraceResults = new ArrayList<>(); | ||
|
||
/** | ||
* Adds a transaction trace result to the builder. | ||
* | ||
* @param transactionTraceResult The transaction trace result to add to the builder. | ||
* @return This builder instance, for method chaining. | ||
*/ | ||
public Builder addTransactionTraceResult(final TransactionTraceResult transactionTraceResult) { | ||
transactionTraceResults.add(transactionTraceResult); | ||
|
||
return this; | ||
} | ||
|
||
/** | ||
* Constructs a BlockTraceResult using the transaction trace results added to the builder. | ||
* | ||
* @return A BlockTraceResult containing the added transaction trace results. | ||
*/ | ||
public BlockTraceResult build() { | ||
return new BlockTraceResult(transactionTraceResults); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#6086 is closed? this one is #6087