Merge branch 'main' into zkbesu

# Conflicts:
#	.github/workflows/draft-release.yml
This commit is contained in:
Fabio Di Fabio
2025-01-15 11:24:31 +01:00
103 changed files with 5402 additions and 7581 deletions

View File

@@ -5,6 +5,8 @@
### Breaking Changes
- `--host-whitelist` has been deprecated since 2020 and this option is removed. Use the equivalent `--host-allowlist` instead.
- Changed tracer API to include the mining beneficiary in BlockAwareOperationTracer::traceStartBlock [#8096](https://github.com/hyperledger/besu/pull/8096)
- Change the input defaults on debug_trace* calls to not trace memory by default ("disableMemory": true, "disableStack": false, "disableStorage": false)
- Change the output format of debug_trace* and trace_* calls to match Geth behaviour
### Upcoming Breaking Changes
- `MetricSystem::createLabelledGauge` is deprecated and will be removed in a future release, replace it with `MetricSystem::createLabelledSuppliedGauge`
@@ -20,7 +22,9 @@
- Retrieve all transaction receipts for a block in one request [#6646](https://github.com/hyperledger/besu/pull/6646)
- Implement EIP-7840: Add blob schedule to config files [#8042](https://github.com/hyperledger/besu/pull/8042)
- Allow gasPrice (legacy) and 1559 gasPrice params to be specified simultaneously for `eth_call`, `eth_createAccessList`, and `eth_estimateGas` [#8059](https://github.com/hyperledger/besu/pull/8059)
- Improve debug_traceBlock calls performance and reduce output size [#8076](https://github.com/hyperledger/besu/pull/8076)
- Add support for EIP-7702 transaction in the txpool [#8018](https://github.com/hyperledger/besu/pull/8018) [#7984](https://github.com/hyperledger/besu/pull/7984)
- Add support for `movePrecompileToAddress` in `StateOverrides` (`eth_call`)[8115](https://github.com/hyperledger/besu/pull/8115)
### Bug fixes
- Fix serialization of state overrides when `movePrecompileToAddress` is present [#8204](https://github.com/hyperledger/besu/pull/8024)

View File

@@ -140,8 +140,8 @@ public class CodeDelegationTransactionAcceptanceTest extends AcceptanceTestBase
*/
@Test
public void shouldCheckNonceAfterNonceIncreaseOfSender() throws IOException {
final long GAS_LIMIT = 1000000L;
cluster.verify(authorizer.balanceEquals(Amount.ether(90000)));
final long GAS_LIMIT = 1_000_000L;
cluster.verify(authorizer.balanceEquals(Amount.ether(90_000)));
final CodeDelegation authorization =
org.hyperledger.besu.ethereum.core.CodeDelegation.builder()
@@ -159,7 +159,7 @@ public class CodeDelegationTransactionAcceptanceTest extends AcceptanceTestBase
.type(TransactionType.DELEGATE_CODE)
.chainId(BigInteger.valueOf(20211))
.nonce(0)
.maxPriorityFeePerGas(Wei.of(1000000000))
.maxPriorityFeePerGas(Wei.of(1_000_000_000))
.maxFeePerGas(Wei.fromHexString("0x02540BE400"))
.gasLimit(GAS_LIMIT)
.to(Address.fromHexStringStrict(authorizer.getAddress()))
@@ -209,7 +209,7 @@ public class CodeDelegationTransactionAcceptanceTest extends AcceptanceTestBase
.nonce(2)
.maxPriorityFeePerGas(Wei.of(10))
.maxFeePerGas(Wei.of(100))
.gasLimit(21000)
.gasLimit(21_000)
.to(Address.fromHexStringStrict(otherAccount.getAddress()))
.value(Wei.ONE)
.payload(Bytes.EMPTY)

View File

@@ -98,6 +98,10 @@ public class PragueAcceptanceTestHelper {
executionPayload.toString(), parentBeaconBlockRoot, executionRequests.toString()));
try (final Response newPayloadResponse = newPayloadRequest.execute()) {
assertThat(newPayloadResponse.code()).isEqualTo(200);
final String responseStatus =
mapper.readTree(newPayloadResponse.body().string()).get("result").get("status").asText();
assertThat(responseStatus).isEqualTo("VALID");
}
final Call moveChainAheadRequest = createEngineCall(createForkChoiceRequest(newBlockHash));

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorInterval="30">
<Configuration level="WARN" monitorInterval="30">
<Properties>
<Property name="root.log.level">INFO</Property>
</Properties>

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -74,6 +74,7 @@ import org.hyperledger.besu.ethereum.core.MiningConfiguration;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.precompiles.privacy.FlexiblePrivacyPrecompiledContract;
@@ -836,7 +837,8 @@ public class RunnerBuilder {
besuPluginContext.getNamedPlugins(),
dataDir,
rpcEndpointServiceImpl,
transactionSimulator);
transactionSimulator,
besuController.getProtocolManager().ethContext().getScheduler());
jsonRpcHttpService =
Optional.of(
@@ -882,7 +884,8 @@ public class RunnerBuilder {
besuPluginContext.getNamedPlugins(),
dataDir,
rpcEndpointServiceImpl,
transactionSimulator);
transactionSimulator,
besuController.getProtocolManager().ethContext().getScheduler());
final Optional<AuthenticationService> authToUse =
engineJsonRpcConfiguration.get().isAuthenticationEnabled()
@@ -978,7 +981,8 @@ public class RunnerBuilder {
besuPluginContext.getNamedPlugins(),
dataDir,
rpcEndpointServiceImpl,
transactionSimulator);
transactionSimulator,
besuController.getProtocolManager().ethContext().getScheduler());
createLogsSubscriptionService(
context.getBlockchain(), subscriptionManager, privacyParameters, blockchainQueries);
@@ -1059,7 +1063,8 @@ public class RunnerBuilder {
besuPluginContext.getNamedPlugins(),
dataDir,
rpcEndpointServiceImpl,
transactionSimulator);
transactionSimulator,
besuController.getProtocolManager().ethContext().getScheduler());
jsonRpcIpcService =
Optional.of(
@@ -1099,7 +1104,8 @@ public class RunnerBuilder {
besuPluginContext.getNamedPlugins(),
dataDir,
rpcEndpointServiceImpl,
transactionSimulator);
transactionSimulator,
besuController.getProtocolManager().ethContext().getScheduler());
} else {
inProcessRpcMethods = Map.of();
}
@@ -1262,7 +1268,8 @@ public class RunnerBuilder {
final Map<String, BesuPlugin> namedPlugins,
final Path dataDir,
final RpcEndpointServiceImpl rpcEndpointServiceImpl,
final TransactionSimulator transactionSimulator) {
final TransactionSimulator transactionSimulator,
final EthScheduler ethScheduler) {
// sync vertx for engine consensus API, to process requests in FIFO order;
final Vertx consensusEngineServer = Vertx.vertx(new VertxOptions().setWorkerPoolSize(1));
@@ -1300,7 +1307,8 @@ public class RunnerBuilder {
consensusEngineServer,
apiConfiguration,
enodeDnsConfiguration,
transactionSimulator);
transactionSimulator,
ethScheduler);
methods.putAll(besuController.getAdditionalJsonRpcMethods(jsonRpcApis));
final var pluginMethods =

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Configuration level="WARN">
<Properties>
<Property name="root.log.level">${env:LOG_LEVEL:-INFO}</Property>
<Property name="root.log.logger">${env:LOGGER:-Console}</Property>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Configuration level="WARN">
<Properties>
<Property name="root.log.level">DEBUG</Property>
</Properties>

View File

@@ -52,15 +52,9 @@ public class Hash extends DelegatingBytes32 {
public static final Hash EMPTY = hash(Bytes.EMPTY);
/**
* Hash of empty requests or "0x6036c41849da9c076ed79654d434017387a88fb833c2856b32e18218b3341c5f"
* Hash of empty requests or "0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
*/
public static final Hash EMPTY_REQUESTS_HASH =
Hash.wrap(
sha256(
Bytes.concatenate(
sha256(Bytes.of(RequestType.DEPOSIT.getSerializedType())),
sha256(Bytes.of(RequestType.WITHDRAWAL.getSerializedType())),
sha256(Bytes.of(RequestType.CONSOLIDATION.getSerializedType())))));
public static final Hash EMPTY_REQUESTS_HASH = Hash.wrap(sha256(Bytes.EMPTY));
/**
* Instantiates a new Hash.

View File

@@ -36,16 +36,19 @@ public class StateOverride {
private final Optional<Long> nonce;
private final Optional<String> code;
private final Optional<Map<String, String>> stateDiff;
private final Optional<Address> movePrecompileToAddress;
private StateOverride(
final Optional<Wei> balance,
final Optional<Long> nonce,
final Optional<String> code,
final Optional<Map<String, String>> stateDiff) {
final Optional<Map<String, String>> stateDiff,
final Optional<Address> movePrecompileToAddress) {
this.balance = balance;
this.nonce = nonce;
this.code = code;
this.stateDiff = stateDiff;
this.movePrecompileToAddress = movePrecompileToAddress;
}
/**
@@ -84,6 +87,15 @@ public class StateOverride {
return stateDiff;
}
/**
* Gets the new address for the pre-compiled contract
*
* @return the new address for the pre-compiled contract if present
*/
public Optional<Address> getMovePrecompileToAddress() {
return movePrecompileToAddress;
}
/** Builder class for Account overrides */
@JsonIgnoreProperties(ignoreUnknown = true)
public static class Builder {
@@ -91,6 +103,7 @@ public class StateOverride {
private Optional<Long> nonce = Optional.empty();
private Optional<String> code = Optional.empty();
private Optional<Map<String, String>> stateDiff = Optional.empty();
private Optional<Address> movePrecompileToAddress = Optional.empty();
/** Default constructor. */
public Builder() {}
@@ -139,13 +152,24 @@ public class StateOverride {
return this;
}
/**
* Sets the new address for the pre-compiled contract
*
* @param newPrecompileAddress the new address for the pre-compile contract
* @return the builder
*/
public Builder withMovePrecompileToAddress(final Address newPrecompileAddress) {
this.movePrecompileToAddress = Optional.ofNullable(newPrecompileAddress);
return this;
}
/**
* build the account override from the builder
*
* @return account override
*/
public StateOverride build() {
return new StateOverride(balance, nonce, code, stateDiff);
return new StateOverride(balance, nonce, code, stateDiff, movePrecompileToAddress);
}
}
@@ -195,6 +219,8 @@ public class StateOverride {
+ code
+ ", stateDiff="
+ stateDiff
+ ", movePrecompileToAddress="
+ movePrecompileToAddress
+ '}';
}
}

View File

@@ -31,7 +31,6 @@ public class HashTest {
public void shouldGetExpectedValueForEmptyRequestsHash() {
assertThat(Hash.EMPTY_REQUESTS_HASH)
.isEqualTo(
Hash.fromHexString(
"0x6036c41849da9c076ed79654d434017387a88fb833c2856b32e18218b3341c5f"));
Hash.fromHexString("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -51,6 +51,7 @@ import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.nat.NatService;
import org.hyperledger.besu.testutil.DeterministicEthScheduler;
import java.math.BigInteger;
import java.nio.file.Path;
@@ -228,6 +229,7 @@ public class JsonRpcTestMethodsFactory {
Vertx.vertx(new VertxOptions().setWorkerPoolSize(1)),
ImmutableApiConfiguration.builder().build(),
Optional.empty(),
transactionSimulator);
transactionSimulator,
new DeterministicEthScheduler());
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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

View File

@@ -0,0 +1,151 @@
/*
* Copyright contributors to Besu.
*
* 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.ethereum.api.jsonrpc.internal.methods;
import static org.hyperledger.besu.services.pipeline.PipelineBuilder.createPipelineFrom;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.TransactionTraceParams;
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.response.RpcErrorType;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.DebugTraceTransactionResult;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.debug.TraceOptions;
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
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.vm.DebugOperationTracer;
import org.hyperledger.besu.metrics.BesuMetricCategory;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.plugin.services.metrics.Counter;
import org.hyperledger.besu.plugin.services.metrics.LabelledMetric;
import org.hyperledger.besu.services.pipeline.Pipeline;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.function.Supplier;
import com.google.common.base.Suppliers;
public abstract class AbstractDebugTraceBlock implements JsonRpcMethod {
private final ProtocolSchedule protocolSchedule;
private final LabelledMetric<Counter> outputCounter;
private final Supplier<BlockchainQueries> blockchainQueriesSupplier;
private final EthScheduler ethScheduler;
public AbstractDebugTraceBlock(
final ProtocolSchedule protocolSchedule,
final BlockchainQueries blockchainQueries,
final ObservableMetricsSystem metricsSystem,
final EthScheduler ethScheduler) {
this.blockchainQueriesSupplier = Suppliers.ofInstance(blockchainQueries);
this.protocolSchedule = protocolSchedule;
this.outputCounter =
metricsSystem.createLabelledCounter(
BesuMetricCategory.BLOCKCHAIN,
"transactions_debugTraceblock_pipeline_processed_total",
"Number of transactions processed for each block",
"step",
"action");
this.ethScheduler = ethScheduler;
}
protected BlockchainQueries getBlockchainQueries() {
return blockchainQueriesSupplier.get();
}
protected TraceOptions getTraceOptions(final JsonRpcRequestContext requestContext) {
final TraceOptions traceOptions;
try {
traceOptions =
requestContext
.getOptionalParameter(1, TransactionTraceParams.class)
.map(TransactionTraceParams::traceOptions)
.orElse(TraceOptions.DEFAULT);
} catch (JsonRpcParameter.JsonRpcParameterException e) {
throw new InvalidJsonRpcParameters(
"Invalid transaction trace parameter (index 1)",
RpcErrorType.INVALID_TRANSACTION_TRACE_PARAMS,
e);
}
return traceOptions;
}
protected Collection<DebugTraceTransactionResult> getTraces(
final JsonRpcRequestContext requestContext,
final TraceOptions traceOptions,
final Optional<Block> maybeBlock) {
return maybeBlock
.flatMap(
block ->
Tracer.processTracing(
getBlockchainQueries(),
block.getHash(),
traceableState -> {
List<DebugTraceTransactionResult> tracesList =
Collections.synchronizedList(new ArrayList<>());
final ProtocolSpec protocolSpec =
protocolSchedule.getByBlockHeader(block.getHeader());
final MainnetTransactionProcessor transactionProcessor =
protocolSpec.getTransactionProcessor();
final TraceBlock.ChainUpdater chainUpdater =
new TraceBlock.ChainUpdater(traceableState);
TransactionSource transactionSource = new TransactionSource(block);
DebugOperationTracer debugOperationTracer =
new DebugOperationTracer(traceOptions, true);
ExecuteTransactionStep executeTransactionStep =
new ExecuteTransactionStep(
chainUpdater,
transactionProcessor,
getBlockchainQueries().getBlockchain(),
debugOperationTracer,
protocolSpec,
block);
DebugTraceTransactionStep debugTraceTransactionStep =
new DebugTraceTransactionStep();
Pipeline<TransactionTrace> traceBlockPipeline =
createPipelineFrom(
"getTransactions",
transactionSource,
4,
outputCounter,
false,
"debug_trace_block")
.thenProcess("executeTransaction", executeTransactionStep)
.thenProcessAsyncOrdered(
"debugTraceTransactionStep", debugTraceTransactionStep, 4)
.andFinishWith("collect_results", tracesList::add);
try {
ethScheduler.startPipeline(traceBlockPipeline).get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
return Optional.of(tracesList);
}))
.orElse(null);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -18,10 +18,6 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.TransactionTraceParams;
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.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
@@ -31,32 +27,32 @@ import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions;
import org.hyperledger.besu.ethereum.debug.TraceOptions;
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.rlp.RLPException;
import org.hyperledger.besu.ethereum.vm.DebugOperationTracer;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import java.util.Collection;
import java.util.Optional;
import java.util.function.Supplier;
import org.apache.tuweni.bytes.Bytes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DebugTraceBlock implements JsonRpcMethod {
public class DebugTraceBlock extends AbstractDebugTraceBlock {
private static final Logger LOG = LoggerFactory.getLogger(DebugTraceBlock.class);
private final Supplier<BlockTracer> blockTracerSupplier;
private final BlockHeaderFunctions blockHeaderFunctions;
private final BlockchainQueries blockchainQueries;
public DebugTraceBlock(
final Supplier<BlockTracer> blockTracerSupplier,
final BlockHeaderFunctions blockHeaderFunctions,
final BlockchainQueries blockchainQueries) {
this.blockTracerSupplier = blockTracerSupplier;
this.blockHeaderFunctions = blockHeaderFunctions;
this.blockchainQueries = blockchainQueries;
final ProtocolSchedule protocolSchedule,
final BlockchainQueries blockchainQueries,
final ObservableMetricsSystem metricsSystem,
final EthScheduler ethScheduler) {
super(protocolSchedule, blockchainQueries, metricsSystem, ethScheduler);
this.blockHeaderFunctions = ScheduleBasedBlockHeaderFunctions.create(protocolSchedule);
}
@Override
@@ -70,7 +66,7 @@ public class DebugTraceBlock implements JsonRpcMethod {
try {
final String input = requestContext.getRequiredParameter(0, String.class);
block = Block.readFrom(RLP.input(Bytes.fromHexString(input)), this.blockHeaderFunctions);
} catch (final RLPException e) {
} catch (final RLPException | IllegalArgumentException e) {
LOG.debug("Failed to parse block RLP (index 0)", e);
return new JsonRpcErrorResponse(
requestContext.getRequest().getId(), RpcErrorType.INVALID_BLOCK_PARAMS);
@@ -78,35 +74,14 @@ public class DebugTraceBlock implements JsonRpcMethod {
throw new InvalidJsonRpcParameters(
"Invalid block params (index 0)", RpcErrorType.INVALID_BLOCK_PARAMS, e);
}
final TraceOptions traceOptions;
try {
traceOptions =
requestContext
.getOptionalParameter(1, TransactionTraceParams.class)
.map(TransactionTraceParams::traceOptions)
.orElse(TraceOptions.DEFAULT);
} catch (JsonRpcParameterException e) {
throw new InvalidJsonRpcParameters(
"Invalid transaction trace parameter (index 1)",
RpcErrorType.INVALID_TRANSACTION_TRACE_PARAMS,
e);
}
final TraceOptions traceOptions = getTraceOptions(requestContext);
if (this.blockchainQueries.blockByHash(block.getHeader().getParentHash()).isPresent()) {
if (getBlockchainQueries()
.getBlockchain()
.getBlockByHash(block.getHeader().getParentHash())
.isPresent()) {
final Collection<DebugTraceTransactionResult> results =
Tracer.processTracing(
blockchainQueries,
Optional.of(block.getHeader()),
mutableWorldState ->
blockTracerSupplier
.get()
.trace(
mutableWorldState,
block,
new DebugOperationTracer(traceOptions, true))
.map(BlockTrace::getTransactionTraces)
.map(DebugTraceTransactionResult::of))
.orElse(null);
getTraces(requestContext, traceOptions, Optional.ofNullable(block));
return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), results);
} else {
return new JsonRpcErrorResponse(

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -19,31 +19,28 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.TransactionTraceParams;
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.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.DebugTraceTransactionResult;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.debug.TraceOptions;
import org.hyperledger.besu.ethereum.vm.DebugOperationTracer;
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import java.util.Collection;
import java.util.function.Supplier;
import java.util.Optional;
public class DebugTraceBlockByHash implements JsonRpcMethod {
private final Supplier<BlockTracer> blockTracerSupplier;
private final Supplier<BlockchainQueries> blockchainQueries;
public class DebugTraceBlockByHash extends AbstractDebugTraceBlock {
public DebugTraceBlockByHash(
final Supplier<BlockTracer> blockTracerSupplier,
final Supplier<BlockchainQueries> blockchainQueriesSupplier) {
this.blockTracerSupplier = blockTracerSupplier;
this.blockchainQueries = blockchainQueriesSupplier;
final ProtocolSchedule protocolSchedule,
final BlockchainQueries blockchainQueries,
final ObservableMetricsSystem metricsSystem,
final EthScheduler ethScheduler) {
super(protocolSchedule, blockchainQueries, metricsSystem, ethScheduler);
}
@Override
@@ -60,34 +57,12 @@ public class DebugTraceBlockByHash implements JsonRpcMethod {
throw new InvalidJsonRpcParameters(
"Invalid block hash parameter (index 0)", RpcErrorType.INVALID_BLOCK_HASH_PARAMS, e);
}
final TraceOptions traceOptions;
try {
traceOptions =
requestContext
.getOptionalParameter(1, TransactionTraceParams.class)
.map(TransactionTraceParams::traceOptions)
.orElse(TraceOptions.DEFAULT);
} catch (JsonRpcParameterException e) {
throw new InvalidJsonRpcParameters(
"Invalid transaction trace parameter (index 1)",
RpcErrorType.INVALID_TRANSACTION_TRACE_PARAMS,
e);
}
TraceOptions traceOptions = getTraceOptions(requestContext);
Optional<Block> maybeBlock = getBlockchainQueries().getBlockchain().getBlockByHash(blockHash);
final Collection<DebugTraceTransactionResult> results =
Tracer.processTracing(
blockchainQueries.get(),
blockHash,
mutableWorldState ->
blockTracerSupplier
.get()
.trace(
mutableWorldState,
blockHash,
new DebugOperationTracer(traceOptions, true))
.map(BlockTrace::getTransactionTraces)
.map(DebugTraceTransactionResult::of))
.orElse(null);
getTraces(requestContext, traceOptions, maybeBlock);
return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), results);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -14,33 +14,59 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;
import org.hyperledger.besu.datatypes.Hash;
import static org.hyperledger.besu.services.pipeline.PipelineBuilder.createPipelineFrom;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.BlockParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.TransactionTraceParams;
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.response.RpcErrorType;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.DebugTraceTransactionResult;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.debug.TraceOptions;
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
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.vm.DebugOperationTracer;
import org.hyperledger.besu.metrics.BesuMetricCategory;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.plugin.services.metrics.Counter;
import org.hyperledger.besu.plugin.services.metrics.LabelledMetric;
import org.hyperledger.besu.services.pipeline.Pipeline;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.concurrent.ExecutionException;
public class DebugTraceBlockByNumber extends AbstractBlockParameterMethod {
private final Supplier<BlockTracer> blockTracerSupplier;
protected final ProtocolSchedule protocolSchedule;
private final LabelledMetric<Counter> outputCounter;
private final EthScheduler ethScheduler;
public DebugTraceBlockByNumber(
final Supplier<BlockTracer> blockTracerSupplier, final BlockchainQueries blockchain) {
super(blockchain);
this.blockTracerSupplier = blockTracerSupplier;
final ProtocolSchedule protocolSchedule,
final BlockchainQueries blockchainQueries,
final ObservableMetricsSystem metricsSystem,
final EthScheduler ethScheduler) {
super(blockchainQueries);
this.protocolSchedule = protocolSchedule;
this.outputCounter =
metricsSystem.createLabelledCounter(
BesuMetricCategory.BLOCKCHAIN,
"transactions_debugtraceblock_pipeline_processed_total",
"Number of transactions processed for each block",
"step",
"action");
this.ethScheduler = ethScheduler;
}
@Override
@@ -61,7 +87,7 @@ public class DebugTraceBlockByNumber extends AbstractBlockParameterMethod {
@Override
protected Object resultByBlockNumber(
final JsonRpcRequestContext request, final long blockNumber) {
final Optional<Hash> blockHash = getBlockchainQueries().getBlockHashByNumber(blockNumber);
final TraceOptions traceOptions;
try {
traceOptions =
@@ -75,22 +101,58 @@ public class DebugTraceBlockByNumber extends AbstractBlockParameterMethod {
RpcErrorType.INVALID_TRANSACTION_TRACE_PARAMS,
e);
}
Optional<Block> maybeBlock =
getBlockchainQueries().getBlockchain().getBlockByNumber(blockNumber);
return blockHash
return maybeBlock
.flatMap(
hash ->
block ->
Tracer.processTracing(
blockchainQueriesSupplier.get(),
hash,
mutableWorldState ->
blockTracerSupplier
.get()
.trace(
mutableWorldState,
hash,
new DebugOperationTracer(traceOptions, true))
.map(BlockTrace::getTransactionTraces)
.map(DebugTraceTransactionResult::of)))
getBlockchainQueries(),
Optional.of(block.getHeader()),
traceableState -> {
List<DebugTraceTransactionResult> tracesList =
Collections.synchronizedList(new ArrayList<>());
final ProtocolSpec protocolSpec =
protocolSchedule.getByBlockHeader(block.getHeader());
final MainnetTransactionProcessor transactionProcessor =
protocolSpec.getTransactionProcessor();
final TraceBlock.ChainUpdater chainUpdater =
new TraceBlock.ChainUpdater(traceableState);
TransactionSource transactionSource = new TransactionSource(block);
DebugOperationTracer debugOperationTracer =
new DebugOperationTracer(traceOptions, true);
ExecuteTransactionStep executeTransactionStep =
new ExecuteTransactionStep(
chainUpdater,
transactionProcessor,
getBlockchainQueries().getBlockchain(),
debugOperationTracer,
protocolSpec,
block);
DebugTraceTransactionStep debugTraceTransactionStep =
new DebugTraceTransactionStep();
Pipeline<TransactionTrace> traceBlockPipeline =
createPipelineFrom(
"getTransactions",
transactionSource,
4,
outputCounter,
false,
"debug_trace_block_by_number")
.thenProcess("executeTransaction", executeTransactionStep)
.thenProcessAsyncOrdered(
"debugTraceTransactionStep", debugTraceTransactionStep, 4)
.andFinishWith("collect_results", tracesList::add);
try {
ethScheduler.startPipeline(traceBlockPipeline).get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
return Optional.of(tracesList);
}))
.orElse(null);
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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.ethereum.api.jsonrpc.internal.methods;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.TransactionTrace;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.DebugTraceTransactionResult;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
public class DebugTraceTransactionStep
implements Function<TransactionTrace, CompletableFuture<DebugTraceTransactionResult>> {
@Override
public CompletableFuture<DebugTraceTransactionResult> apply(
final TransactionTrace transactionTrace) {
return CompletableFuture.completedFuture(new DebugTraceTransactionResult(transactionTrace));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -39,7 +39,6 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.vm.DebugOperationTracer;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.metrics.BesuMetricCategory;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.plugin.services.metrics.Counter;
import org.hyperledger.besu.plugin.services.metrics.LabelledMetric;
@@ -57,11 +56,13 @@ public class TraceBlock extends AbstractBlockParameterMethod {
private static final ObjectMapper MAPPER = new ObjectMapper();
protected final ProtocolSchedule protocolSchedule;
private final LabelledMetric<Counter> outputCounter;
protected final EthScheduler ethScheduler;
public TraceBlock(
final ProtocolSchedule protocolSchedule,
final BlockchainQueries queries,
final MetricsSystem metricsSystem) {
final MetricsSystem metricsSystem,
final EthScheduler ethScheduler) {
super(queries);
this.protocolSchedule = protocolSchedule;
this.outputCounter =
@@ -71,6 +72,7 @@ public class TraceBlock extends AbstractBlockParameterMethod {
"Number of transactions processed for each block",
"step",
"action");
this.ethScheduler = ethScheduler;
}
@Override
@@ -153,16 +155,7 @@ public class TraceBlock extends AbstractBlockParameterMethod {
traceStream -> traceStream.forEachOrdered(buildArrayNodeStep));
try {
if (getBlockchainQueries().getEthScheduler().isPresent()) {
getBlockchainQueries()
.getEthScheduler()
.get()
.startPipeline(traceBlockPipeline)
.get();
} else {
EthScheduler ethScheduler = new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem());
ethScheduler.startPipeline(traceBlockPipeline).get();
}
ethScheduler.startPipeline(traceBlockPipeline).get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright contributors to Hyperledger Besu.
* Copyright contributors to Besu.
*
* 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

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -43,7 +43,6 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.vm.DebugOperationTracer;
import org.hyperledger.besu.metrics.BesuMetricCategory;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.plugin.services.metrics.Counter;
import org.hyperledger.besu.plugin.services.metrics.LabelledMetric;
@@ -74,8 +73,9 @@ public class TraceFilter extends TraceBlock {
final ProtocolSchedule protocolSchedule,
final BlockchainQueries blockchainQueries,
final Long maxRange,
final MetricsSystem metricsSystem) {
super(protocolSchedule, blockchainQueries, metricsSystem);
final MetricsSystem metricsSystem,
final EthScheduler ethScheduler) {
super(protocolSchedule, blockchainQueries, metricsSystem, ethScheduler);
this.maxRange = maxRange;
this.outputCounter =
metricsSystem.createLabelledCounter(
@@ -196,14 +196,7 @@ public class TraceFilter extends TraceBlock {
traceStream -> traceStream.forEachOrdered(buildArrayNodeStep));
try {
Optional<EthScheduler> ethSchedulerOpt =
getBlockchainQueries().getEthScheduler();
ethSchedulerOpt
.orElse(new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem()))
.startPipeline(traceBlockPipeline)
.get();
ethScheduler.startPipeline(traceBlockPipeline).get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -38,7 +38,6 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.vm.DebugOperationTracer;
import org.hyperledger.besu.metrics.BesuMetricCategory;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.plugin.services.metrics.Counter;
import org.hyperledger.besu.plugin.services.metrics.LabelledMetric;
@@ -60,11 +59,13 @@ public class TraceReplayBlockTransactions extends AbstractBlockParameterMethod {
private static final ObjectMapper MAPPER = new ObjectMapper();
private final ProtocolSchedule protocolSchedule;
private final LabelledMetric<Counter> outputCounter;
private final EthScheduler ethScheduler;
public TraceReplayBlockTransactions(
final ProtocolSchedule protocolSchedule,
final BlockchainQueries queries,
final MetricsSystem metricsSystem) {
final MetricsSystem metricsSystem,
final EthScheduler ethScheduler) {
super(queries);
this.protocolSchedule = protocolSchedule;
this.outputCounter =
@@ -74,6 +75,7 @@ public class TraceReplayBlockTransactions extends AbstractBlockParameterMethod {
"Number of transactions processed for each block",
"step",
"action");
this.ethScheduler = ethScheduler;
}
@Override
@@ -173,16 +175,7 @@ public class TraceReplayBlockTransactions extends AbstractBlockParameterMethod {
"traceReplayTransaction", traceReplayTransactionStep, 4)
.andFinishWith("buildArrayNode", buildArrayNodeStep::accept);
try {
if (getBlockchainQueries().getEthScheduler().isPresent()) {
getBlockchainQueries()
.getEthScheduler()
.get()
.startPipeline(traceBlockPipeline)
.get();
} else {
EthScheduler ethScheduler = new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem());
ethScheduler.startPipeline(traceBlockPipeline).get();
}
ethScheduler.startPipeline(traceBlockPipeline).get();
} catch (final InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright contributors to Hyperledger Besu.
* Copyright contributors to Besu.
*
* 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
@@ -22,6 +22,7 @@ import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.Executi
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.VALID;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.RequestValidatorProvider.getRequestsValidator;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.WithdrawalsValidatorProvider.getWithdrawalsValidator;
import static org.hyperledger.besu.metrics.BesuMetricCategory.BLOCK_PROCESSING;
import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator;
import org.hyperledger.besu.datatypes.BlobGas;
@@ -61,6 +62,7 @@ import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator;
import org.hyperledger.besu.ethereum.rlp.RLPException;
import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.plugin.services.exception.StorageException;
import java.security.InvalidParameterException;
@@ -69,7 +71,6 @@ import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import io.vertx.core.Vertx;
import io.vertx.core.json.Json;
@@ -85,6 +86,7 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
private static final BlockHeaderFunctions headerFunctions = new MainnetBlockHeaderFunctions();
private final MergeMiningCoordinator mergeCoordinator;
private final EthPeers ethPeers;
private long lastExecutionTime = 0L;
public AbstractEngineNewPayload(
final Vertx vertx,
@@ -92,10 +94,16 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
final ProtocolContext protocolContext,
final MergeMiningCoordinator mergeCoordinator,
final EthPeers ethPeers,
final EngineCallListener engineCallListener) {
final EngineCallListener engineCallListener,
final MetricsSystem metricsSystem) {
super(vertx, protocolSchedule, protocolContext, engineCallListener);
this.mergeCoordinator = mergeCoordinator;
this.ethPeers = ethPeers;
metricsSystem.createLongGauge(
BLOCK_PROCESSING,
"execution_time_head",
"The execution time of the last block (head)",
this::getLastExecutionTime);
}
@Override
@@ -347,8 +355,8 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
// execute block and return result response
final long startTimeMs = System.currentTimeMillis();
final BlockProcessingResult executionResult = mergeCoordinator.rememberBlock(block);
if (executionResult.isSuccessful()) {
lastExecutionTime = System.currentTimeMillis() - startTimeMs;
logImportedBlockInfo(
block,
blobTransactions.stream()
@@ -356,7 +364,7 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
.flatMap(Optional::stream)
.mapToInt(List::size)
.sum(),
(System.currentTimeMillis() - startTimeMs) / 1000.0,
lastExecutionTime / 1000.0,
executionResult.getNbParallelizedTransations());
return respondWith(reqId, blockParam, newBlockHeader.getHash(), VALID);
} else {
@@ -587,8 +595,12 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
return maybeRequestsParam.map(
requests ->
IntStream.range(0, requests.size())
.mapToObj(i -> new Request(RequestType.of(i), Bytes.fromHexString(requests.get(i))))
requests.stream()
.map(
s -> {
final Bytes request = Bytes.fromHexString(s);
return new Request(RequestType.of(request.get(0)), request.slice(1));
})
.collect(Collectors.toList()));
}
@@ -629,4 +641,8 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
messageArgs.add(ethPeers.peerCount());
LOG.info(String.format(message.toString(), messageArgs.toArray()));
}
private long getLastExecutionTime() {
return this.lastExecutionTime;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright contributors to Hyperledger Besu.
* Copyright contributors to Besu.
*
* 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
@@ -27,6 +27,7 @@ import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import java.util.List;
import java.util.Optional;
@@ -41,8 +42,16 @@ public class EngineNewPayloadV1 extends AbstractEngineNewPayload {
final ProtocolContext protocolContext,
final MergeMiningCoordinator mergeCoordinator,
final EthPeers ethPeers,
final EngineCallListener engineCallListener) {
super(vertx, protocolSchedule, protocolContext, mergeCoordinator, ethPeers, engineCallListener);
final EngineCallListener engineCallListener,
final MetricsSystem metricsSystem) {
super(
vertx,
protocolSchedule,
protocolContext,
mergeCoordinator,
ethPeers,
engineCallListener,
metricsSystem);
}
@Override

View File

@@ -1,5 +1,5 @@
/*
* Copyright contributors to Hyperledger Besu.
* Copyright contributors to Besu.
*
* 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
@@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import java.util.List;
import java.util.Optional;
@@ -43,8 +44,16 @@ public class EngineNewPayloadV2 extends AbstractEngineNewPayload {
final ProtocolContext protocolContext,
final MergeMiningCoordinator mergeCoordinator,
final EthPeers ethPeers,
final EngineCallListener engineCallListener) {
super(vertx, protocolSchedule, protocolContext, mergeCoordinator, ethPeers, engineCallListener);
final EngineCallListener engineCallListener,
final MetricsSystem metricsSystem) {
super(
vertx,
protocolSchedule,
protocolContext,
mergeCoordinator,
ethPeers,
engineCallListener,
metricsSystem);
cancunMilestone = protocolSchedule.milestoneFor(CANCUN);
}

View File

@@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import java.util.List;
import java.util.Optional;
@@ -40,9 +41,16 @@ public class EngineNewPayloadV3 extends AbstractEngineNewPayload {
final ProtocolContext protocolContext,
final MergeMiningCoordinator mergeCoordinator,
final EthPeers ethPeers,
final EngineCallListener engineCallListener) {
final EngineCallListener engineCallListener,
final MetricsSystem metricsSystem) {
super(
vertx, timestampSchedule, protocolContext, mergeCoordinator, ethPeers, engineCallListener);
vertx,
timestampSchedule,
protocolContext,
mergeCoordinator,
ethPeers,
engineCallListener,
metricsSystem);
this.cancunMilestone = timestampSchedule.milestoneFor(CANCUN);
}

View File

@@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import java.util.List;
import java.util.Optional;
@@ -40,9 +41,16 @@ public class EngineNewPayloadV4 extends AbstractEngineNewPayload {
final ProtocolContext protocolContext,
final MergeMiningCoordinator mergeCoordinator,
final EthPeers ethPeers,
final EngineCallListener engineCallListener) {
final EngineCallListener engineCallListener,
final MetricsSystem metricsSystem) {
super(
vertx, timestampSchedule, protocolContext, mergeCoordinator, ethPeers, engineCallListener);
vertx,
timestampSchedule,
protocolContext,
mergeCoordinator,
ethPeers,
engineCallListener,
metricsSystem);
pragueMilestone = timestampSchedule.milestoneFor(PRAGUE);
}

View File

@@ -167,7 +167,9 @@ public class BlockResultFactory {
rqs ->
rqs.stream()
.sorted(Comparator.comparing(Request::getType))
.map(r -> r.getData().toHexString())
.filter(r -> !r.getData().isEmpty())
.map(Request::getEncodedRequest)
.map(Bytes::toHexString)
.toList());
final BlobsBundleV1 blobsBundleV1 =

View File

@@ -17,6 +17,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.TransactionTrace;
import org.hyperledger.besu.ethereum.debug.TraceFrame;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
@@ -35,10 +36,10 @@ public class DebugTraceTransactionResult {
public DebugTraceTransactionResult(final TransactionTrace transactionTrace) {
gas = transactionTrace.getGas();
returnValue = transactionTrace.getResult().getOutput().toString().substring(2);
structLogs =
transactionTrace.getTraceFrames().stream()
.map(DebugTraceTransactionResult::createStructLog)
.collect(Collectors.toList());
structLogs = new ArrayList<>(transactionTrace.getTraceFrames().size());
transactionTrace.getTraceFrames().parallelStream()
.map(DebugTraceTransactionResult::createStructLog)
.forEachOrdered(structLogs::add);
failed = !transactionTrace.getResult().isSuccessful();
}

View File

@@ -22,14 +22,15 @@ import java.util.Objects;
import java.util.TreeMap;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
@JsonPropertyOrder({"pc", "op", "gas", "gasCost", "depth", "stack", "memory", "storage"})
public class StructLog {
private static final char[] hexChars = "0123456789abcdef".toCharArray();
private final int depth;
private final long gas;
private final long gasCost;
@@ -39,7 +40,6 @@ public class StructLog {
private final String[] stack;
private final Object storage;
private final String reason;
static final String bytes32ZeroString = Bytes32.ZERO.toUnprefixedHexString();
public StructLog(final TraceFrame traceFrame) {
depth = traceFrame.getDepth() + 1;
@@ -48,7 +48,9 @@ public class StructLog {
memory =
traceFrame
.getMemory()
.map(a -> Arrays.stream(a).map(Bytes::toUnprefixedHexString).toArray(String[]::new))
.map(
a ->
Arrays.stream(a).map(bytes -> toCompactHex(bytes, true)).toArray(String[]::new))
.orElse(null);
op = traceFrame.getOpcode();
pc = traceFrame.getPc();
@@ -57,28 +59,17 @@ public class StructLog {
.getStack()
.map(
a ->
Arrays.stream(a)
.map(Bytes::toUnprefixedHexString)
.map(this::stringLeftPadTo64)
.toArray(String[]::new))
Arrays.stream(a).map(bytes -> toCompactHex(bytes, true)).toArray(String[]::new))
.orElse(null);
storage = traceFrame.getStorage().map(StructLog::formatStorage).orElse(null);
reason = traceFrame.getRevertReason().map(Bytes::toShortHexString).orElse(null);
}
private String stringLeftPadTo64(final String unPaddedHexString) {
StringBuilder sb = new StringBuilder(64);
sb.append(bytes32ZeroString, 0, 64 - unPaddedHexString.length());
sb.append(unPaddedHexString);
return sb.toString();
reason = traceFrame.getRevertReason().map(bytes -> toCompactHex(bytes, true)).orElse(null);
}
private static Map<String, String> formatStorage(final Map<UInt256, UInt256> storage) {
final Map<String, String> formattedStorage = new TreeMap<>();
storage.forEach(
(key, value) ->
formattedStorage.put(key.toUnprefixedHexString(), value.toUnprefixedHexString()));
(key, value) -> formattedStorage.put(toCompactHex(key, false), toCompactHex(value, false)));
return formattedStorage;
}
@@ -98,6 +89,7 @@ public class StructLog {
}
@JsonGetter("memory")
@JsonInclude(JsonInclude.Include.NON_NULL)
public String[] memory() {
return memory;
}
@@ -113,16 +105,19 @@ public class StructLog {
}
@JsonGetter("stack")
@JsonInclude(JsonInclude.Include.NON_NULL)
public String[] stack() {
return stack;
}
@JsonGetter("storage")
@JsonInclude(JsonInclude.Include.NON_NULL)
public Object storage() {
return storage;
}
@JsonGetter("reason")
@JsonInclude(JsonInclude.Include.NON_NULL)
public String reason() {
return reason;
}
@@ -153,4 +148,39 @@ public class StructLog {
result = 31 * result + Arrays.hashCode(stack);
return result;
}
public static String toCompactHex(final Bytes abytes, final boolean prefix) {
if (abytes.isEmpty()) {
if (prefix) return "0x0";
else return "0";
}
byte[] bytes = abytes.toArrayUnsafe();
final int size = bytes.length;
final StringBuilder result = new StringBuilder(prefix ? (size * 2) + 2 : size * 2);
if (prefix) {
result.append("0x");
}
boolean leadingZero = true;
for (int i = 0; i < size; i++) {
byte b = bytes[i];
int highNibble = (b >> 4) & 0xF;
if (!leadingZero || highNibble != 0) {
result.append(hexChars[highNibble]);
leadingZero = false;
}
int lowNibble = b & 0xF;
if (!leadingZero || lowNibble != 0 || i == size - 1) {
result.append(hexChars[lowNibble]);
leadingZero = false;
}
}
return result.toString();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -43,9 +43,9 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.TransactionT
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.BlockResultFactory;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
@@ -64,6 +64,7 @@ public class DebugJsonRpcMethods extends ApiGroupJsonRpcMethods {
private final Synchronizer synchronizer;
private final Path dataDir;
private final TransactionSimulator transactionSimulator;
private final EthScheduler ethScheduler;
DebugJsonRpcMethods(
final BlockchainQueries blockchainQueries,
@@ -73,7 +74,8 @@ public class DebugJsonRpcMethods extends ApiGroupJsonRpcMethods {
final TransactionPool transactionPool,
final Synchronizer synchronizer,
final Path dataDir,
final TransactionSimulator transactionSimulator) {
final TransactionSimulator transactionSimulator,
final EthScheduler ethScheduler) {
this.blockchainQueries = blockchainQueries;
this.protocolContext = protocolContext;
this.protocolSchedule = protocolSchedule;
@@ -82,6 +84,7 @@ public class DebugJsonRpcMethods extends ApiGroupJsonRpcMethods {
this.synchronizer = synchronizer;
this.dataDir = dataDir;
this.transactionSimulator = transactionSimulator;
this.ethScheduler = ethScheduler;
}
@Override
@@ -100,14 +103,12 @@ public class DebugJsonRpcMethods extends ApiGroupJsonRpcMethods {
new DebugStorageRangeAt(blockchainQueries, blockReplay),
new DebugMetrics(metricsSystem),
new DebugResyncWorldstate(protocolContext, synchronizer),
new DebugTraceBlock(
() -> new BlockTracer(blockReplay),
ScheduleBasedBlockHeaderFunctions.create(protocolSchedule),
blockchainQueries),
new DebugTraceBlock(protocolSchedule, blockchainQueries, metricsSystem, ethScheduler),
new DebugSetHead(blockchainQueries, protocolContext),
new DebugReplayBlock(blockchainQueries, protocolContext, protocolSchedule),
new DebugTraceBlockByNumber(() -> new BlockTracer(blockReplay), blockchainQueries),
new DebugTraceBlockByHash(() -> new BlockTracer(blockReplay), () -> blockchainQueries),
new DebugTraceBlockByNumber(
protocolSchedule, blockchainQueries, metricsSystem, ethScheduler),
new DebugTraceBlockByHash(protocolSchedule, blockchainQueries, metricsSystem, ethScheduler),
new DebugBatchSendRawTransaction(transactionPool),
new DebugGetBadBlocks(protocolContext, blockResult),
new DebugStandardTraceBlockToFile(

View File

@@ -42,6 +42,7 @@ import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import java.util.ArrayList;
import java.util.Arrays;
@@ -63,6 +64,7 @@ public class ExecutionEngineJsonRpcMethods extends ApiGroupJsonRpcMethods {
private final String clientVersion;
private final String commit;
private final TransactionPool transactionPool;
private final MetricsSystem metricsSystem;
ExecutionEngineJsonRpcMethods(
final MiningCoordinator miningCoordinator,
@@ -72,7 +74,8 @@ public class ExecutionEngineJsonRpcMethods extends ApiGroupJsonRpcMethods {
final Vertx consensusEngineServer,
final String clientVersion,
final String commit,
final TransactionPool transactionPool) {
final TransactionPool transactionPool,
final MetricsSystem metricsSystem) {
this.mergeCoordinator =
Optional.ofNullable(miningCoordinator)
.filter(mc -> mc.isCompatibleWithEngineApi())
@@ -84,6 +87,7 @@ public class ExecutionEngineJsonRpcMethods extends ApiGroupJsonRpcMethods {
this.clientVersion = clientVersion;
this.commit = commit;
this.transactionPool = transactionPool;
this.metricsSystem = metricsSystem;
}
@Override
@@ -117,21 +121,24 @@ public class ExecutionEngineJsonRpcMethods extends ApiGroupJsonRpcMethods {
protocolContext,
mergeCoordinator.get(),
ethPeers,
engineQosTimer),
engineQosTimer,
metricsSystem),
new EngineNewPayloadV2(
consensusEngineServer,
protocolSchedule,
protocolContext,
mergeCoordinator.get(),
ethPeers,
engineQosTimer),
engineQosTimer,
metricsSystem),
new EngineNewPayloadV3(
consensusEngineServer,
protocolSchedule,
protocolContext,
mergeCoordinator.get(),
ethPeers,
engineQosTimer),
engineQosTimer,
metricsSystem),
new EngineForkchoiceUpdatedV1(
consensusEngineServer,
protocolSchedule,
@@ -193,7 +200,8 @@ public class ExecutionEngineJsonRpcMethods extends ApiGroupJsonRpcMethods {
protocolContext,
mergeCoordinator.get(),
ethPeers,
engineQosTimer));
engineQosTimer,
metricsSystem));
}
return mapOf(executionEngineApisSupported);

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -29,6 +29,7 @@ import org.hyperledger.besu.ethereum.core.MiningConfiguration;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
@@ -87,7 +88,8 @@ public class JsonRpcMethodsFactory {
final Vertx consensusEngineServer,
final ApiConfiguration apiConfiguration,
final Optional<EnodeDnsConfiguration> enodeDnsConfiguration,
final TransactionSimulator transactionSimulator) {
final TransactionSimulator transactionSimulator,
final EthScheduler ethScheduler) {
final Map<String, JsonRpcMethod> enabled = new HashMap<>();
if (!rpcApis.isEmpty()) {
final JsonRpcMethod modules = new RpcModules(rpcApis);
@@ -113,7 +115,8 @@ public class JsonRpcMethodsFactory {
transactionPool,
synchronizer,
dataDir,
transactionSimulator),
transactionSimulator,
ethScheduler),
new EeaJsonRpcMethods(
blockchainQueries, protocolSchedule, transactionPool, privacyParameters),
new ExecutionEngineJsonRpcMethods(
@@ -124,7 +127,8 @@ public class JsonRpcMethodsFactory {
consensusEngineServer,
clientVersion,
commit,
transactionPool),
transactionPool,
metricsSystem),
new EthJsonRpcMethods(
blockchainQueries,
synchronizer,
@@ -159,7 +163,8 @@ public class JsonRpcMethodsFactory {
protocolContext,
apiConfiguration,
transactionSimulator,
metricsSystem),
metricsSystem,
ethScheduler),
new TxPoolJsonRpcMethods(transactionPool),
new PluginsJsonRpcMethods(namedPlugins));

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -29,6 +29,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.TraceTransacti
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockReplay;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockTracer;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.plugin.services.MetricsSystem;
@@ -43,6 +44,7 @@ public class TraceJsonRpcMethods extends ApiGroupJsonRpcMethods {
private final ProtocolContext protocolContext;
private final TransactionSimulator transactionSimulator;
private final MetricsSystem metricsSystem;
private final EthScheduler ethScheduler;
TraceJsonRpcMethods(
final BlockchainQueries blockchainQueries,
@@ -50,13 +52,15 @@ public class TraceJsonRpcMethods extends ApiGroupJsonRpcMethods {
final ProtocolContext protocolContext,
final ApiConfiguration apiConfiguration,
final TransactionSimulator transactionSimulator,
final MetricsSystem metricsSystem) {
final MetricsSystem metricsSystem,
final EthScheduler ethScheduler) {
this.blockchainQueries = blockchainQueries;
this.protocolSchedule = protocolSchedule;
this.protocolContext = protocolContext;
this.apiConfiguration = apiConfiguration;
this.transactionSimulator = transactionSimulator;
this.metricsSystem = metricsSystem;
this.ethScheduler = ethScheduler;
}
@Override
@@ -69,16 +73,18 @@ public class TraceJsonRpcMethods extends ApiGroupJsonRpcMethods {
final BlockReplay blockReplay =
new BlockReplay(protocolSchedule, protocolContext, blockchainQueries.getBlockchain());
return mapOf(
new TraceReplayBlockTransactions(protocolSchedule, blockchainQueries, metricsSystem),
new TraceReplayBlockTransactions(
protocolSchedule, blockchainQueries, metricsSystem, ethScheduler),
new TraceFilter(
protocolSchedule,
blockchainQueries,
apiConfiguration.getMaxTraceFilterRange(),
metricsSystem),
metricsSystem,
ethScheduler),
new TraceGet(() -> new BlockTracer(blockReplay), blockchainQueries, protocolSchedule),
new TraceTransaction(
() -> new BlockTracer(blockReplay), protocolSchedule, blockchainQueries),
new TraceBlock(protocolSchedule, blockchainQueries, metricsSystem),
new TraceBlock(protocolSchedule, blockchainQueries, metricsSystem, ethScheduler),
new TraceCall(blockchainQueries, protocolSchedule, transactionSimulator),
new TraceCallMany(blockchainQueries, protocolSchedule, transactionSimulator),
new TraceRawTransaction(protocolSchedule, blockchainQueries, transactionSimulator));

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -42,6 +42,7 @@ import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.eth.EthProtocol;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
@@ -214,7 +215,8 @@ public abstract class AbstractJsonRpcHttpServiceTest {
syncVertx,
mock(ApiConfiguration.class),
Optional.empty(),
transactionSimulator);
transactionSimulator,
new EthScheduler(1, 1, 1, new NoOpMetricsSystem()));
}
protected void startService() throws Exception {

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -45,6 +45,7 @@ import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.nat.NatService;
import org.hyperledger.besu.testutil.DeterministicEthScheduler;
import java.io.IOException;
import java.math.BigInteger;
@@ -140,7 +141,8 @@ public class JsonRpcHttpServiceHostAllowlistTest {
vertx,
mock(ApiConfiguration.class),
Optional.empty(),
mock(TransactionSimulator.class));
mock(TransactionSimulator.class),
new DeterministicEthScheduler());
service = createJsonRpcHttpService();
service.start().join();

View File

@@ -1,5 +1,5 @@
/*
* Copyright contributors to Hyperledger Besu.
* Copyright contributors to Besu.
*
* 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
@@ -50,6 +50,7 @@ import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.nat.NatService;
import org.hyperledger.besu.testutil.DeterministicEthScheduler;
import java.io.IOException;
import java.math.BigInteger;
@@ -171,7 +172,8 @@ public class JsonRpcHttpServiceLoginTest {
vertx,
mock(ApiConfiguration.class),
Optional.empty(),
mock(TransactionSimulator.class));
mock(TransactionSimulator.class),
new DeterministicEthScheduler());
service = createJsonRpcHttpService();
jwtAuth = service.authenticationService.get().getJwtAuthProvider();
service.start().join();

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -55,6 +55,7 @@ import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.nat.NatService;
import org.hyperledger.besu.testutil.DeterministicEthScheduler;
import java.math.BigInteger;
import java.nio.file.Path;
@@ -237,7 +238,8 @@ public class JsonRpcHttpServiceRpcApisTest {
vertx,
mock(ApiConfiguration.class),
Optional.empty(),
mock(TransactionSimulator.class));
mock(TransactionSimulator.class),
new DeterministicEthScheduler());
final JsonRpcHttpService jsonRpcHttpService =
new JsonRpcHttpService(
vertx,
@@ -349,7 +351,8 @@ public class JsonRpcHttpServiceRpcApisTest {
vertx,
mock(ApiConfiguration.class),
Optional.empty(),
mock(TransactionSimulator.class));
mock(TransactionSimulator.class),
new DeterministicEthScheduler());
final JsonRpcHttpService jsonRpcHttpService =
new JsonRpcHttpService(
vertx,

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -46,6 +46,7 @@ import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.nat.NatService;
import org.hyperledger.besu.testutil.DeterministicEthScheduler;
import java.math.BigInteger;
import java.nio.file.Path;
@@ -149,7 +150,8 @@ public class JsonRpcHttpServiceTestBase {
vertx,
mock(ApiConfiguration.class),
Optional.empty(),
mock(TransactionSimulator.class));
mock(TransactionSimulator.class),
new DeterministicEthScheduler());
disabledRpcMethods = new HashMap<>();
addedRpcMethods = new HashSet<>();

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -52,6 +52,7 @@ import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.nat.NatService;
import org.hyperledger.besu.testutil.DeterministicEthScheduler;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -156,7 +157,8 @@ public class JsonRpcHttpServiceTlsClientAuthTest {
vertx,
mock(ApiConfiguration.class),
Optional.empty(),
mock(TransactionSimulator.class));
mock(TransactionSimulator.class),
new DeterministicEthScheduler());
System.setProperty("javax.net.ssl.trustStore", CLIENT_AS_CA_CERT.getKeyStoreFile().toString());
System.setProperty(

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -51,6 +51,7 @@ import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.nat.NatService;
import org.hyperledger.besu.testutil.DeterministicEthScheduler;
import java.io.IOException;
import java.math.BigInteger;
@@ -142,7 +143,8 @@ class JsonRpcHttpServiceTlsMisconfigurationTest {
vertx,
mock(ApiConfiguration.class),
Optional.empty(),
mock(TransactionSimulator.class));
mock(TransactionSimulator.class),
new DeterministicEthScheduler());
}
@AfterEach

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -51,6 +51,7 @@ import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.nat.NatService;
import org.hyperledger.besu.testutil.DeterministicEthScheduler;
import java.io.IOException;
import java.io.UncheckedIOException;
@@ -143,7 +144,8 @@ public class JsonRpcHttpServiceTlsTest {
vertx,
mock(ApiConfiguration.class),
Optional.empty(),
mock(TransactionSimulator.class));
mock(TransactionSimulator.class),
new DeterministicEthScheduler());
service = createJsonRpcHttpService(createJsonRpcConfig());
service.start().join();
baseUrl = service.url();

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -15,65 +15,60 @@
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
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.exception.InvalidJsonRpcParameters;
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.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.DebugTraceTransactionResult;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.debug.TraceFrame;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.testutil.DeterministicEthScheduler;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.OptionalLong;
import java.util.function.Function;
import org.apache.tuweni.bytes.Bytes;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Answers;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class DebugTraceBlockByHashTest {
private final BlockTracer blockTracer = mock(BlockTracer.class);
private final BlockchainQueries blockchainQueries =
mock(BlockchainQueries.class, Answers.RETURNS_DEEP_STUBS);
private final MutableWorldState mutableWorldState = mock(MutableWorldState.class);
private final BlockHeader blockHeader = mock(BlockHeader.class, Answers.RETURNS_DEEP_STUBS);
private final DebugTraceBlockByHash debugTraceBlockByHash =
new DebugTraceBlockByHash(() -> blockTracer, () -> blockchainQueries);
@Mock private ProtocolSchedule protocolSchedule;
@Mock private BlockchainQueries blockchainQueries;
@Mock private ObservableMetricsSystem metricsSystem;
@Mock private Blockchain blockchain;
@Mock private Block block;
private DebugTraceBlockByHash debugTraceBlockByHash;
private final Hash blockHash =
Hash.fromHexString("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
@BeforeEach
public void setUp() {
doAnswer(
invocation ->
invocation
.<Function<MutableWorldState, Optional<? extends JsonRpcResponse>>>getArgument(
1)
.apply(mutableWorldState))
.when(blockchainQueries)
.getAndMapWorldState(any(), any());
when(blockchainQueries.getBlockHeaderByHash(any(Hash.class)))
.thenReturn(Optional.of(blockHeader));
debugTraceBlockByHash =
new DebugTraceBlockByHash(
protocolSchedule, blockchainQueries, metricsSystem, new DeterministicEthScheduler());
}
@Test
@@ -81,59 +76,54 @@ public class DebugTraceBlockByHashTest {
assertThat(debugTraceBlockByHash.getName()).isEqualTo("debug_traceBlockByHash");
}
@SuppressWarnings("unchecked")
@Test
public void shouldReturnCorrectResponse() {
final Object[] params = new Object[] {blockHash};
final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("2.0", "debug_traceBlockByHash", params));
final TraceFrame traceFrame =
new TraceFrame(
12,
Optional.of("NONE"),
Integer.MAX_VALUE,
45L,
OptionalLong.of(56L),
0L,
2,
Optional.empty(),
null,
Wei.ZERO,
Bytes.EMPTY,
Bytes.EMPTY,
Optional.empty(),
Optional.empty(),
Optional.empty(),
null,
Optional.empty(),
Optional.empty(),
Optional.empty(),
0,
Optional.empty(),
false,
Optional.empty(),
Optional.empty());
when(blockchainQueries.getBlockchain()).thenReturn(blockchain);
when(blockchain.getBlockByHash(blockHash)).thenReturn(Optional.of(block));
when(block.getHash()).thenReturn(blockHash);
final TransactionProcessingResult transaction1Result = mock(TransactionProcessingResult.class);
final TransactionProcessingResult transaction2Result = mock(TransactionProcessingResult.class);
DebugTraceTransactionResult result1 = mock(DebugTraceTransactionResult.class);
DebugTraceTransactionResult result2 = mock(DebugTraceTransactionResult.class);
final TransactionTrace transaction1Trace = mock(TransactionTrace.class);
final TransactionTrace transaction2Trace = mock(TransactionTrace.class);
List<DebugTraceTransactionResult> resultList = Arrays.asList(result1, result2);
BlockTrace blockTrace = new BlockTrace(Arrays.asList(transaction1Trace, transaction2Trace));
try (MockedStatic<Tracer> mockedTracer = mockStatic(Tracer.class)) {
mockedTracer
.when(
() ->
Tracer.processTracing(eq(blockchainQueries), eq(blockHash), any(Function.class)))
.thenReturn(Optional.of(resultList));
when(transaction1Trace.getTraceFrames()).thenReturn(Arrays.asList(traceFrame));
when(transaction2Trace.getTraceFrames()).thenReturn(Arrays.asList(traceFrame));
when(transaction1Trace.getResult()).thenReturn(transaction1Result);
when(transaction2Trace.getResult()).thenReturn(transaction2Result);
when(transaction1Result.getOutput()).thenReturn(Bytes.fromHexString("1234"));
when(transaction2Result.getOutput()).thenReturn(Bytes.fromHexString("1234"));
when(blockTracer.trace(any(Tracer.TraceableState.class), eq(blockHash), any()))
.thenReturn(Optional.of(blockTrace));
final JsonRpcResponse jsonRpcResponse = debugTraceBlockByHash.response(request);
assertThat(jsonRpcResponse).isInstanceOf(JsonRpcSuccessResponse.class);
JsonRpcSuccessResponse response = (JsonRpcSuccessResponse) jsonRpcResponse;
final JsonRpcSuccessResponse response =
(JsonRpcSuccessResponse) debugTraceBlockByHash.response(request);
final Collection<?> result = (Collection<?>) response.getResult();
assertThat(result).hasSize(2);
final Collection<DebugTraceTransactionResult> traceResult = getResult(response);
assertThat(traceResult).isNotEmpty();
assertThat(traceResult).isInstanceOf(Collection.class).hasSize(2);
assertThat(traceResult).containsExactly(result1, result2);
}
}
@SuppressWarnings("unchecked")
private Collection<DebugTraceTransactionResult> getResult(final JsonRpcSuccessResponse response) {
return (Collection<DebugTraceTransactionResult>) response.getResult();
}
@Test
public void shouldHandleInvalidParametersGracefully() {
final Object[] invalidParams = new Object[] {"aaaa"};
final JsonRpcRequestContext request =
new JsonRpcRequestContext(
new JsonRpcRequest("2.0", "debug_traceBlockByHash", invalidParams));
assertThatThrownBy(() -> debugTraceBlockByHash.response(request))
.isInstanceOf(InvalidJsonRpcParameters.class)
.hasMessageContaining("Invalid block hash parameter");
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -14,131 +14,118 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
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.exception.InvalidJsonRpcParameters;
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.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.DebugTraceTransactionResult;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
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.MutableWorldState;
import org.hyperledger.besu.ethereum.debug.TraceFrame;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.testutil.DeterministicEthScheduler;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.OptionalLong;
import java.util.function.Function;
import org.apache.tuweni.bytes.Bytes;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Answers;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class DebugTraceBlockByNumberTest {
private final BlockchainQueries blockchainQueries =
mock(BlockchainQueries.class, Answers.RETURNS_DEEP_STUBS);
@Mock private BlockchainQueries blockchainQueries;
@Mock private Blockchain blockchain;
@Mock private Block block;
@Mock private BlockHeader blockHeader;
@Mock private ProtocolSchedule protocolSchedule;
@Mock private ObservableMetricsSystem metricsSystem;
private DebugTraceBlockByNumber debugTraceBlockByNumber;
private final Tracer.TraceableState worldState = mock(Tracer.TraceableState.class);
private final BlockTracer blockTracer = mock(BlockTracer.class, Answers.RETURNS_DEEP_STUBS);
private final DebugTraceBlockByNumber debugTraceBlockByNumber =
new DebugTraceBlockByNumber(() -> blockTracer, blockchainQueries);
private final Hash blockHash =
Hash.fromHexString("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
@BeforeEach
public void setUp() {
debugTraceBlockByNumber =
new DebugTraceBlockByNumber(
protocolSchedule, blockchainQueries, metricsSystem, new DeterministicEthScheduler());
}
@Test
public void nameShouldBeDebugTraceBlockByNumber() {
assertThat(debugTraceBlockByNumber.getName()).isEqualTo("debug_traceBlockByNumber");
}
@SuppressWarnings("unchecked")
@Test
public void shouldReturnCorrectResponse() {
final long blockNumber = 1L;
final Object[] params = new Object[] {Long.toHexString(blockNumber)};
final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("2.0", "debug_traceBlockByNumber", params));
when(blockchainQueries.getBlockchain()).thenReturn(blockchain);
when(blockchain.getBlockByNumber(blockNumber)).thenReturn(Optional.of(block));
when(block.getHeader()).thenReturn(blockHeader);
final TraceFrame traceFrame =
new TraceFrame(
12,
Optional.of("NONE"),
Integer.MAX_VALUE,
45L,
OptionalLong.of(56L),
0L,
2,
Optional.empty(),
null,
Wei.ZERO,
Bytes.EMPTY,
Bytes.EMPTY,
Optional.empty(),
Optional.empty(),
Optional.empty(),
null,
Optional.empty(),
Optional.empty(),
Optional.empty(),
0,
Optional.empty(),
false,
Optional.empty(),
Optional.empty());
DebugTraceTransactionResult result1 = mock(DebugTraceTransactionResult.class);
DebugTraceTransactionResult result2 = mock(DebugTraceTransactionResult.class);
final TransactionProcessingResult transaction1Result = mock(TransactionProcessingResult.class);
final TransactionProcessingResult transaction2Result = mock(TransactionProcessingResult.class);
List<DebugTraceTransactionResult> resultList = Arrays.asList(result1, result2);
final TransactionTrace transaction1Trace = mock(TransactionTrace.class);
final TransactionTrace transaction2Trace = mock(TransactionTrace.class);
try (MockedStatic<Tracer> mockedTracer = mockStatic(Tracer.class)) {
mockedTracer
.when(
() ->
Tracer.processTracing(
eq(blockchainQueries), eq(Optional.of(blockHeader)), any(Function.class)))
.thenReturn(Optional.of(resultList));
final BlockTrace blockTrace = new BlockTrace(asList(transaction1Trace, transaction2Trace));
final JsonRpcResponse jsonRpcResponse = debugTraceBlockByNumber.response(request);
assertThat(jsonRpcResponse).isInstanceOf(JsonRpcSuccessResponse.class);
JsonRpcSuccessResponse response = (JsonRpcSuccessResponse) jsonRpcResponse;
when(transaction1Trace.getTraceFrames()).thenReturn(singletonList(traceFrame));
when(transaction2Trace.getTraceFrames()).thenReturn(singletonList(traceFrame));
when(transaction1Trace.getResult()).thenReturn(transaction1Result);
when(transaction2Trace.getResult()).thenReturn(transaction2Result);
when(transaction1Result.getOutput()).thenReturn(Bytes.fromHexString("1234"));
when(transaction2Result.getOutput()).thenReturn(Bytes.fromHexString("1234"));
when(blockchainQueries.getBlockHashByNumber(blockNumber)).thenReturn(Optional.of(blockHash));
when(blockchainQueries.getBlockHeaderByHash(any(Hash.class)))
.thenReturn(Optional.of(mock(BlockHeader.class, Answers.RETURNS_DEEP_STUBS)));
doAnswer(
invocation ->
invocation
.<Function<MutableWorldState, ? extends Optional<? extends JsonRpcResponse>>>
getArgument(1)
.apply(worldState))
.when(blockchainQueries)
.getAndMapWorldState(any(), any());
when(blockTracer.trace(any(Tracer.TraceableState.class), any(Hash.class), any()))
.thenReturn(Optional.of(blockTrace));
final JsonRpcSuccessResponse response =
(JsonRpcSuccessResponse) debugTraceBlockByNumber.response(request);
final Collection<DebugTraceTransactionResult> result = getResult(response);
assertThat(result)
.usingFieldByFieldElementComparator()
.isEqualTo(DebugTraceTransactionResult.of(blockTrace.getTransactionTraces()));
final Collection<DebugTraceTransactionResult> traceResult = getResult(response);
assertThat(traceResult).isNotEmpty();
assertThat(traceResult).isInstanceOf(Collection.class).hasSize(2);
assertThat(traceResult).containsExactly(result1, result2);
}
}
@SuppressWarnings("unchecked")
private Collection<DebugTraceTransactionResult> getResult(final JsonRpcSuccessResponse response) {
return (Collection<DebugTraceTransactionResult>) response.getResult();
}
@Test
public void shouldHandleInvalidParametersGracefully() {
final Object[] invalidParams = new Object[] {"invalid-block-number"};
final JsonRpcRequestContext request =
new JsonRpcRequestContext(
new JsonRpcRequest("2.0", "debug_traceBlockByNumber", invalidParams));
assertThatThrownBy(() -> debugTraceBlockByNumber.response(request))
.isInstanceOf(InvalidJsonRpcParameters.class)
.hasMessageContaining("Invalid block parameter");
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright contributors to Besu.
*
* 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
@@ -14,53 +14,114 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.config.GenesisConfig;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
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.response.JsonRpcErrorResponse;
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.jsonrpc.internal.response.RpcErrorType;
import org.hyperledger.besu.ethereum.api.query.BlockWithMetadata;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.DebugTraceTransactionResult;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.chain.BadBlockManager;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
import org.hyperledger.besu.ethereum.debug.TraceFrame;
import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture;
import org.hyperledger.besu.ethereum.core.MiningConfiguration;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters;
import org.hyperledger.besu.ethereum.mainnet.TransactionValidatorFactory;
import org.hyperledger.besu.ethereum.mainnet.WithdrawalsProcessor;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.testutil.DeterministicEthScheduler;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.OptionalLong;
import java.util.function.Function;
import org.apache.tuweni.bytes.Bytes;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class DebugTraceBlockTest {
@Mock private BlockchainQueries blockchainQueries;
@Mock private Blockchain blockchain;
@Mock private ObservableMetricsSystem metricsSystem;
@Mock private WithdrawalsProcessor withdrawalsProcessor;
@Mock private TransactionValidatorFactory alwaysValidTransactionValidatorFactory;
private DebugTraceBlock debugTraceBlock;
private final BlockTracer blockTracer = mock(BlockTracer.class);
private final BlockchainQueries blockchainQueries = mock(BlockchainQueries.class);
private final DebugTraceBlock debugTraceBlock =
new DebugTraceBlock(() -> blockTracer, new MainnetBlockHeaderFunctions(), blockchainQueries);
@BeforeEach
public void setUp() {
// As we build the block from RLP in DebugTraceBlock, we need to have non mocked
// protocolSchedule (and ProtocolSpec)
// to be able to get the hash of the block
final var genesisConfig =
GenesisConfig.fromResource(
"/org/hyperledger/besu/ethereum/api/jsonrpc/trace/chain-data/genesis.json");
final ProtocolSpecAdapters protocolSpecAdapters =
ProtocolSpecAdapters.create(
0,
specBuilder -> {
specBuilder.isReplayProtectionSupported(true);
specBuilder.withdrawalsProcessor(withdrawalsProcessor);
specBuilder.transactionValidatorFactoryBuilder(
(evm, gasLimitCalculator, feeMarket) -> alwaysValidTransactionValidatorFactory);
return specBuilder;
});
final ExecutionContextTestFixture executionContextTestFixture =
ExecutionContextTestFixture.builder(genesisConfig)
.protocolSchedule(
new ProtocolScheduleBuilder(
genesisConfig.getConfigOptions(),
Optional.of(BigInteger.valueOf(42)),
protocolSpecAdapters,
PrivacyParameters.DEFAULT,
false,
EvmConfiguration.DEFAULT,
MiningConfiguration.MINING_DISABLED,
new BadBlockManager(),
false,
new NoOpMetricsSystem())
.createProtocolSchedule())
.build();
debugTraceBlock =
new DebugTraceBlock(
executionContextTestFixture.getProtocolSchedule(),
blockchainQueries,
metricsSystem,
new DeterministicEthScheduler());
}
@Test
public void nameShouldBeDebugTraceBlock() {
assertThat(debugTraceBlock.getName()).isEqualTo("debug_traceBlock");
}
@SuppressWarnings("unchecked")
@Test
public void shouldReturnCorrectResponse() {
final Block parentBlock =
@@ -79,71 +140,37 @@ public class DebugTraceBlockTest {
final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("2.0", "debug_traceBlock", params));
final TraceFrame traceFrame =
new TraceFrame(
12,
Optional.of("NONE"),
Integer.MAX_VALUE,
45L,
OptionalLong.of(56L),
0L,
2,
Optional.empty(),
null,
Wei.ZERO,
Bytes.EMPTY,
Bytes.EMPTY,
Optional.empty(),
Optional.empty(),
Optional.empty(),
null,
Optional.empty(),
Optional.empty(),
Optional.empty(),
0,
Optional.empty(),
false,
Optional.empty(),
Optional.empty());
when(blockchainQueries.getBlockchain()).thenReturn(blockchain);
when(blockchain.getBlockByHash(block.getHeader().getParentHash()))
.thenReturn(Optional.of(parentBlock));
final TransactionProcessingResult transaction1Result = mock(TransactionProcessingResult.class);
final TransactionProcessingResult transaction2Result = mock(TransactionProcessingResult.class);
DebugTraceTransactionResult result1 = mock(DebugTraceTransactionResult.class);
DebugTraceTransactionResult result2 = mock(DebugTraceTransactionResult.class);
final TransactionTrace transaction1Trace = mock(TransactionTrace.class);
final TransactionTrace transaction2Trace = mock(TransactionTrace.class);
List<DebugTraceTransactionResult> resultList = Arrays.asList(result1, result2);
final BlockTrace blockTrace = new BlockTrace(asList(transaction1Trace, transaction2Trace));
try (MockedStatic<Tracer> mockedTracer = mockStatic(Tracer.class)) {
mockedTracer
.when(
() ->
Tracer.processTracing(
eq(blockchainQueries), eq(block.getHash()), any(Function.class)))
.thenReturn(Optional.of(resultList));
when(transaction1Trace.getTraceFrames()).thenReturn(singletonList(traceFrame));
when(transaction2Trace.getTraceFrames()).thenReturn(singletonList(traceFrame));
when(transaction1Trace.getResult()).thenReturn(transaction1Result);
when(transaction2Trace.getResult()).thenReturn(transaction2Result);
when(transaction1Result.getOutput()).thenReturn(Bytes.fromHexString("1234"));
when(transaction2Result.getOutput()).thenReturn(Bytes.fromHexString("1234"));
when(blockTracer.trace(any(Tracer.TraceableState.class), eq(block), any()))
.thenReturn(Optional.of(blockTrace));
final JsonRpcResponse jsonRpcResponse = debugTraceBlock.response(request);
assertThat(jsonRpcResponse).isInstanceOf(JsonRpcSuccessResponse.class);
JsonRpcSuccessResponse response = (JsonRpcSuccessResponse) jsonRpcResponse;
when(blockchainQueries.blockByHash(parentBlock.getHash()))
.thenReturn(
Optional.of(
new BlockWithMetadata<>(
parentBlock.getHeader(),
Collections.emptyList(),
Collections.emptyList(),
parentBlock.getHeader().getDifficulty(),
parentBlock.calculateSize())));
when(blockchainQueries.getAndMapWorldState(eq(parentBlock.getHash()), any()))
.thenAnswer(
invocationOnMock -> {
Function<Tracer.TraceableState, ? extends Optional<BlockTracer>> mapper =
invocationOnMock.getArgument(1);
return mapper.apply(mock(Tracer.TraceableState.class));
});
final Collection<DebugTraceTransactionResult> traceResult = getResult(response);
assertThat(traceResult).isNotEmpty();
assertThat(traceResult).isInstanceOf(Collection.class).hasSize(2);
assertThat(traceResult).containsExactly(result1, result2);
}
}
final JsonRpcSuccessResponse response =
(JsonRpcSuccessResponse) debugTraceBlock.response(request);
final Collection<?> result = (Collection<?>) response.getResult();
assertThat(result).hasSize(2);
@SuppressWarnings("unchecked")
private Collection<DebugTraceTransactionResult> getResult(final JsonRpcSuccessResponse response) {
return (Collection<DebugTraceTransactionResult>) response.getResult();
}
@Test
@@ -158,9 +185,26 @@ public class DebugTraceBlockTest {
final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("2.0", "debug_traceBlock", params));
when(blockchainQueries.blockByHash(any())).thenReturn(Optional.empty());
when(blockchainQueries.getBlockchain()).thenReturn(blockchain);
when(blockchain.getBlockByHash(block.getHeader().getParentHash())).thenReturn(Optional.empty());
final JsonRpcResponse jsonRpcResponse = debugTraceBlock.response(request);
assertThat(jsonRpcResponse).isInstanceOf(JsonRpcErrorResponse.class);
final JsonRpcErrorResponse response = (JsonRpcErrorResponse) debugTraceBlock.response(request);
assertThat(response.getErrorType()).isEqualByComparingTo(RpcErrorType.PARENT_BLOCK_NOT_FOUND);
}
@Test
public void shouldHandleInvalidParametersGracefully() {
final Object[] invalidParams = new Object[] {"invalid RLP"};
final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("2.0", "debug_traceBlock", invalidParams));
final JsonRpcResponse jsonRpcResponse = debugTraceBlock.response(request);
assertThat(jsonRpcResponse).isInstanceOf(JsonRpcErrorResponse.class);
final JsonRpcErrorResponse response = (JsonRpcErrorResponse) debugTraceBlock.response(request);
assertThat(response.getError().getMessage()).contains("Invalid block, unable to parse RLP");
}
}

View File

@@ -165,10 +165,10 @@ public class DebugTraceTransactionTest {
assertThat(transactionResult.getStructLogs().size()).isEqualTo(1);
assertThat(transactionResult.getStructLogs().get(0).stack().length).isEqualTo(1);
assertThat(transactionResult.getStructLogs().get(0).stack()[0])
.isEqualTo(stackBytes[0].toUnprefixedHexString());
.isEqualTo(StructLog.toCompactHex(stackBytes[0], true));
assertThat(transactionResult.getStructLogs().get(0).memory().length).isEqualTo(1);
assertThat(transactionResult.getStructLogs().get(0).memory()[0])
.isEqualTo(memoryBytes[0].toUnprefixedHexString());
.isEqualTo(StructLog.toCompactHex(memoryBytes[0], true));
}
@Test

View File

@@ -55,6 +55,7 @@ import org.hyperledger.besu.ethereum.transaction.PreCloseStateHandler;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult;
import java.util.Map;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
@@ -123,6 +124,33 @@ public class EthCallTest {
assertThat(overrideMap).containsValue(override);
}
@Test
public void fullStateOverrides() {
StateOverrideMap suppliedOverrides = new StateOverrideMap();
StateOverride override =
new StateOverride.Builder()
.withNonce(new UnsignedLongParameter("0x9e"))
.withBalance(Wei.of(100))
.withCode("0x1234")
.withStateDiff(Map.of("0x1234", "0x5678"))
.withMovePrecompileToAddress(Address.fromHexString("0x1234"))
.build();
final Address address = Address.fromHexString("0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3");
suppliedOverrides.put(address, override);
final JsonRpcRequestContext request =
ethCallRequestWithStateOverrides(callParameter(), "latest", suppliedOverrides);
Optional<StateOverrideMap> maybeOverrideMap = method.getAddressStateOverrideMap(request);
assertThat(maybeOverrideMap.isPresent()).isTrue();
StateOverrideMap actualOverrideMap = maybeOverrideMap.get();
assertThat(actualOverrideMap.keySet()).hasSize(1);
assertThat(actualOverrideMap.values()).hasSize(1);
assertThat(actualOverrideMap).containsKey(address);
assertThat(actualOverrideMap).containsValue(override);
}
@Test
public void shouldReturnInternalErrorWhenProcessorReturnsEmpty() {
final JsonRpcRequestContext request = ethCallRequest(callParameter(), "latest");

View File

@@ -27,6 +27,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.testutil.DeterministicEthScheduler;
import java.util.function.Supplier;
@@ -71,7 +72,11 @@ public class TraceFilterTest {
method =
new TraceFilter(
protocolSchedule, blockchainQueries, maxFilterRange, new NoOpMetricsSystem());
protocolSchedule,
blockchainQueries,
maxFilterRange,
new NoOpMetricsSystem(),
new DeterministicEthScheduler());
final JsonRpcResponse response = method.response(request);
assertThat(response).isInstanceOf(JsonRpcErrorResponse.class);

View File

@@ -147,7 +147,8 @@ public class EngineGetPayloadV4Test extends AbstractEngineGetPayloadTest {
final List<String> requestsWithoutRequestId =
requests.stream()
.sorted(Comparator.comparing(Request::getType))
.map(r -> r.getData().toHexString())
.map(Request::getEncodedRequest)
.map(Bytes::toHexString)
.toList();
Optional.of(resp)
.map(JsonRpcSuccessResponse.class::cast)
@@ -172,6 +173,53 @@ public class EngineGetPayloadV4Test extends AbstractEngineGetPayloadTest {
verify(engineCallListener, times(1)).executionEngineCalled();
}
@Test
public void shouldExcludeEmptyRequestsInRequestsList() {
BlockHeader header =
new BlockHeaderTestFixture().timestamp(pragueHardfork.milestone() + 1).buildHeader();
PayloadIdentifier payloadIdentifier =
PayloadIdentifier.forPayloadParams(
Hash.ZERO,
pragueHardfork.milestone(),
Bytes32.random(),
Address.fromHexString("0x42"),
Optional.empty(),
Optional.empty());
BlockWithReceipts block =
new BlockWithReceipts(
new Block(header, new BlockBody(emptyList(), emptyList(), Optional.of(emptyList()))),
emptyList());
final List<Request> unorderedRequests =
List.of(
new Request(RequestType.CONSOLIDATION, Bytes.of(1)),
new Request(RequestType.DEPOSIT, Bytes.of(1)),
new Request(RequestType.WITHDRAWAL, Bytes.EMPTY));
PayloadWrapper payload =
new PayloadWrapper(payloadIdentifier, block, Optional.of(unorderedRequests));
when(mergeContext.retrievePayloadById(payloadIdentifier)).thenReturn(Optional.of(payload));
final var resp = resp(RpcMethod.ENGINE_GET_PAYLOAD_V4.getMethodName(), payloadIdentifier);
assertThat(resp).isInstanceOf(JsonRpcSuccessResponse.class);
final List<String> expectedRequests =
List.of(
Bytes.concatenate(Bytes.of(RequestType.DEPOSIT.getSerializedType()), Bytes.of(1))
.toHexString(),
Bytes.concatenate(Bytes.of(RequestType.CONSOLIDATION.getSerializedType()), Bytes.of(1))
.toHexString());
Optional.of(resp)
.map(JsonRpcSuccessResponse.class::cast)
.ifPresent(
r -> {
assertThat(r.getResult()).isInstanceOf(EngineGetPayloadResultV4.class);
final EngineGetPayloadResultV4 res = (EngineGetPayloadResultV4) r.getResult();
assertThat(res.getExecutionRequests()).isEqualTo(expectedRequests);
});
}
@Test
public void shouldReturnUnsupportedFork() {
final var resp = resp(RpcMethod.ENGINE_GET_PAYLOAD_V4.getMethodName(), mockPid);

View File

@@ -18,6 +18,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.INVALID_BLOCK_HASH;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -43,7 +44,8 @@ public class EngineNewPayloadV1Test extends AbstractEngineNewPayloadTest {
protocolContext,
mergeCoordinator,
ethPeers,
engineCallListener);
engineCallListener,
new NoOpMetricsSystem());
}
@Override

View File

@@ -35,6 +35,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Withdrawal;
import org.hyperledger.besu.ethereum.mainnet.WithdrawalsValidator;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import java.util.Collections;
import java.util.List;
@@ -64,7 +65,8 @@ public class EngineNewPayloadV2Test extends AbstractEngineNewPayloadTest {
protocolContext,
mergeCoordinator,
ethPeers,
engineCallListener);
engineCallListener,
new NoOpMetricsSystem());
}
@Override

View File

@@ -54,6 +54,7 @@ import org.hyperledger.besu.ethereum.mainnet.BodyValidation;
import org.hyperledger.besu.ethereum.mainnet.CancunTargetingGasLimitCalculator;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import java.math.BigInteger;
import java.util.List;
@@ -95,7 +96,8 @@ public class EngineNewPayloadV3Test extends EngineNewPayloadV2Test {
protocolContext,
mergeCoordinator,
ethPeers,
engineCallListener);
engineCallListener,
new NoOpMetricsSystem());
lenient().when(protocolSpec.getGasCalculator()).thenReturn(new CancunGasCalculator());
lenient()
.when(protocolSpec.getGasLimitCalculator())
@@ -120,7 +122,8 @@ public class EngineNewPayloadV3Test extends EngineNewPayloadV2Test {
protocolContext,
mergeCoordinator,
ethPeers,
engineCallListener);
engineCallListener,
new NoOpMetricsSystem());
final JsonRpcResponse badParam =
methodV3.response(
new JsonRpcRequestContext(

View File

@@ -43,6 +43,7 @@ import org.hyperledger.besu.ethereum.mainnet.BodyValidation;
import org.hyperledger.besu.ethereum.mainnet.requests.MainnetRequestsValidator;
import org.hyperledger.besu.ethereum.mainnet.requests.ProhibitedRequestValidator;
import org.hyperledger.besu.evm.gascalculator.PragueGasCalculator;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import java.util.Comparator;
import java.util.List;
@@ -78,7 +79,8 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test {
protocolContext,
mergeCoordinator,
ethPeers,
engineCallListener);
engineCallListener,
new NoOpMetricsSystem());
lenient().when(protocolSchedule.hardforkFor(any())).thenReturn(Optional.of(pragueHardfork));
lenient().when(protocolSpec.getGasCalculator()).thenReturn(new PragueGasCalculator());
mockAllowedRequestsValidator();
@@ -168,7 +170,10 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test {
final List<String> requestsWithoutRequestId =
VALID_REQUESTS.stream()
.sorted(Comparator.comparing(Request::getType))
.map(r -> r.getData().toHexString())
.map(
r ->
Bytes.concatenate(Bytes.of(r.getType().getSerializedType()), r.getData())
.toHexString())
.toList();
Object[] params =
maybeParentBeaconBlockRoot

View File

@@ -0,0 +1,239 @@
/*
* Copyright contributors to Besu.
*
* 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.ethereum.api.jsonrpc.internal.results;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.ethereum.debug.TraceFrame;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalLong;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.UInt256;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class StructLogTest {
@Mock private TraceFrame traceFrame;
private StructLog structLog;
private ObjectMapper objectMapper;
@BeforeEach
public void setUp() {
objectMapper = new ObjectMapper();
}
@Test
public void constructorShouldInitializeFields() throws Exception {
// Given
final String op = "PUSH1";
final int depth = 0;
final long gas = 100L;
final OptionalLong gasCost = OptionalLong.of(10L);
final String[] memory =
new String[] {"0x01", "0x02", "0x0003", "0x04", "0x00000005", "0x000000"};
final String[] stack = new String[] {"0x00000000000000", "0x01", "0x000002", "0x03"};
final Map<String, String> storage =
Map.of(
"0x01", "0x2233333",
"0x02", "0x4455667");
final String reason = "0x0001";
// Mock TraceFrame behaviors
when(traceFrame.getDepth()).thenReturn(depth);
when(traceFrame.getGasRemaining()).thenReturn(gas);
when(traceFrame.getGasCost()).thenReturn(gasCost);
when(traceFrame.getMemory())
.thenReturn(
Optional.of(
Arrays.stream(memory)
.map(Bytes::fromHexString) // Convert each string to Bytes
.toArray(Bytes[]::new)));
when(traceFrame.getOpcode()).thenReturn(op);
when(traceFrame.getPc()).thenReturn(1);
when(traceFrame.getStack())
.thenReturn(
Optional.of(
Arrays.stream(stack)
.map(Bytes::fromHexString) // Convert each string to Bytes
.toArray(Bytes[]::new)));
Map<UInt256, UInt256> storageMap = new HashMap<>();
for (Map.Entry<String, String> entry : storage.entrySet()) {
storageMap.put(
UInt256.fromHexString(entry.getKey()), UInt256.fromHexString(entry.getValue()));
}
when(traceFrame.getStorage()).thenReturn(Optional.of(storageMap));
when(traceFrame.getRevertReason()).thenReturn(Optional.of(Bytes.fromHexString(reason)));
// When
structLog = new StructLog(traceFrame);
// Then
assertThat(structLog.depth()).isEqualTo(depth + 1);
assertThat(structLog.gas()).isEqualTo(gas);
assertThat(structLog.gasCost()).isEqualTo(gasCost.getAsLong());
assertThat(structLog.memory())
.isEqualTo(new String[] {"0x1", "0x2", "0x3", "0x4", "0x5", "0x0"});
assertThat(structLog.op()).isEqualTo(op);
assertThat(structLog.pc()).isEqualTo(1);
assertThat(structLog.stack()).isEqualTo(new String[] {"0x0", "0x1", "0x2", "0x3"});
assertThat(structLog.storage())
.isEqualTo(
Map.of(
"1", "2233333",
"2", "4455667"));
assertThat(structLog.reason()).isEqualTo("0x1");
}
@Test
public void shouldGenerateJsonCorrectly() throws Exception {
final String op = "PUSH1";
final int depth = 0;
final long gas = 100L;
final OptionalLong gasCost = OptionalLong.of(10L);
final String[] memory =
new String[] {"0x01", "0x02", "0x0023", "0x04", "0x000000e5", "0x000000"};
final String[] stack = new String[] {"0x00000000000000", "0x01", "0x000002", "0x03"};
final Map<String, String> storage =
Map.of(
"0x01", "0x2233333",
"0x02", "0x4455667");
final String reason = "0x53756e696665642066756e6473";
// Mock TraceFrame behaviors
when(traceFrame.getDepth()).thenReturn(depth);
when(traceFrame.getGasRemaining()).thenReturn(gas);
when(traceFrame.getGasCost()).thenReturn(gasCost);
when(traceFrame.getMemory())
.thenReturn(
Optional.of(
Arrays.stream(memory)
.map(Bytes::fromHexString) // Convert each string to Bytes
.toArray(Bytes[]::new)));
when(traceFrame.getOpcode()).thenReturn(op);
when(traceFrame.getPc()).thenReturn(1);
when(traceFrame.getStack())
.thenReturn(
Optional.of(
Arrays.stream(stack)
.map(Bytes::fromHexString) // Convert each string to Bytes
.toArray(Bytes[]::new)));
Map<UInt256, UInt256> storageMap = new HashMap<>();
for (Map.Entry<String, String> entry : storage.entrySet()) {
storageMap.put(
UInt256.fromHexString(entry.getKey()), UInt256.fromHexString(entry.getValue()));
}
when(traceFrame.getStorage()).thenReturn(Optional.of(storageMap));
when(traceFrame.getRevertReason()).thenReturn(Optional.of(Bytes.fromHexString(reason)));
// When
structLog = new StructLog(traceFrame);
// Use Jackson to serialize the StructLog object to a JSON string
String json = objectMapper.writeValueAsString(structLog);
// Define the expected JSON output
String expectedJson =
"{"
+ "\"pc\":1,"
+ "\"op\":\"PUSH1\","
+ "\"gas\":100,"
+ "\"gasCost\":10,"
+ "\"depth\":1,"
+ "\"stack\":[\"0x0\",\"0x1\",\"0x2\",\"0x3\"],"
+ "\"memory\":[\"0x1\",\"0x2\",\"0x23\",\"0x4\",\"0xe5\",\"0x0\"],"
+ "\"storage\":{\"1\":\"2233333\",\"2\":\"4455667\"},"
+ "\"reason\":\"0x53756e696665642066756e6473\""
+ "}";
// Then
assertThat(json).isEqualTo(expectedJson); // Verify the generated JSON matches the expected JSON
}
@Test
public void testToCompactHexEmptyWithPrefix() {
Bytes emptyBytes = Bytes.EMPTY;
String result = StructLog.toCompactHex(emptyBytes, true);
assertEquals("0x0", result, "Expected '0x0' for an empty byte array with prefix");
}
@Test
public void testToCompactHexEmptyWithoutPrefix() {
Bytes emptyBytes = Bytes.EMPTY;
String result = StructLog.toCompactHex(emptyBytes, false);
assertEquals("0", result, "Expected '0' for an empty byte array without prefix");
}
@Test
public void testToCompactHexSingleByteWithPrefix() {
Bytes bytes = Bytes.fromHexString("0x01");
String result = StructLog.toCompactHex(bytes, true);
assertEquals("0x1", result, "Expected '0x1' for the byte 0x01 with prefix");
}
@Test
public void testToCompactHexSingleByteWithoutPrefix() {
Bytes bytes = Bytes.fromHexString("0x01");
String result = StructLog.toCompactHex(bytes, false);
assertEquals("1", result, "Expected '1' for the byte 0x01 without prefix");
}
@Test
public void testToCompactHexMultipleBytesWithPrefix() {
Bytes bytes = Bytes.fromHexString("0x010203");
String result = StructLog.toCompactHex(bytes, true);
assertEquals("0x10203", result, "Expected '0x10203' for the byte array 0x010203 with prefix");
}
@Test
public void testToCompactHexMultipleBytesWithoutPrefix() {
Bytes bytes = Bytes.fromHexString("0x010203");
String result = StructLog.toCompactHex(bytes, false);
assertEquals("10203", result, "Expected '10203' for the byte array 0x010203 without prefix");
}
@Test
public void testToCompactHexWithLeadingZeros() {
Bytes bytes = Bytes.fromHexString("0x0001");
String result = StructLog.toCompactHex(bytes, true);
assertEquals(
"0x1",
result,
"Expected '0x1' for the byte array 0x0001 with prefix (leading zeros removed)");
}
@Test
public void testToCompactHexWithLargeData() {
Bytes bytes = Bytes.fromHexString("0x0102030405060708090a");
String result = StructLog.toCompactHex(bytes, true);
assertEquals("0x102030405060708090a", result, "Expected correct hex output for large data");
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright contributors to Hyperledger Besu.
* Copyright contributors to Besu.
*
* 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
@@ -58,6 +58,7 @@ import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.nat.NatService;
import org.hyperledger.besu.testutil.DeterministicEthScheduler;
import java.math.BigInteger;
import java.net.URISyntaxException;
@@ -207,7 +208,8 @@ public class WebSocketServiceLoginTest {
vertx,
mock(ApiConfiguration.class),
Optional.empty(),
mock(TransactionSimulator.class)));
mock(TransactionSimulator.class),
new DeterministicEthScheduler()));
websocketMethods.putAll(rpcMethods);
webSocketMessageHandlerSpy =

View File

@@ -28,271 +28,163 @@
"op" : "PUSH1",
"gas" : 16755910,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 1
}, {
"pc" : 2,
"op" : "PUSH1",
"gas" : 16755907,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 1
}, {
"pc" : 4,
"op" : "PUSH1",
"gas" : 16755904,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 1
}, {
"pc" : 6,
"op" : "CALLDATASIZE",
"gas" : 16755901,
"gasCost" : 2,
"depth" : 1,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 1
}, {
"pc" : 7,
"op" : "SUB",
"gas" : 16755899,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 1
}, {
"pc" : 8,
"op" : "DUP1",
"gas" : 16755896,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 1
}, {
"pc" : 9,
"op" : "PUSH1",
"gas" : 16755893,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 1
}, {
"pc" : 11,
"op" : "PUSH1",
"gas" : 16755890,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 1
}, {
"pc" : 13,
"op" : "CALLDATACOPY",
"gas" : 16755887,
"gasCost" : 9,
"depth" : 1,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 1
}, {
"pc" : 14,
"op" : "PUSH1",
"gas" : 16755878,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 1
}, {
"pc" : 16,
"op" : "CALLVALUE",
"gas" : 16755875,
"gasCost" : 2,
"depth" : 1,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 1
}, {
"pc" : 17,
"op" : "PUSH1",
"gas" : 16755873,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 1
}, {
"pc" : 19,
"op" : "CALLDATALOAD",
"gas" : 16755870,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 1
}, {
"pc" : 20,
"op" : "GAS",
"gas" : 16755867,
"gasCost" : 2,
"depth" : 1,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 1
}, {
"pc" : 21,
"op" : "CALLCODE",
"gas" : 16755865,
"gasCost" : 16494066,
"depth" : 1,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 1
}, {
"pc" : 0,
"op" : "PUSH1",
"gas" : 16493366,
"gasCost" : 3,
"depth" : 2,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 2
}, {
"pc" : 2,
"op" : "CALLDATALOAD",
"gas" : 16493363,
"gasCost" : 3,
"depth" : 2,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 2
}, {
"pc" : 3,
"op" : "PUSH1",
"gas" : 16493360,
"gasCost" : 3,
"depth" : 2,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 2
}, {
"pc" : 5,
"op" : "ADD",
"gas" : 16493357,
"gasCost" : 3,
"depth" : 2,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 2
}, {
"pc" : 6,
"op" : "PUSH1",
"gas" : 16493354,
"gasCost" : 3,
"depth" : 2,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 2
}, {
"pc" : 8,
"op" : "MSTORE",
"gas" : 16493351,
"gasCost" : 6,
"depth" : 2,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 2
}, {
"pc" : 9,
"op" : "PUSH1",
"gas" : 16493345,
"gasCost" : 3,
"depth" : 2,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 2
}, {
"pc" : 11,
"op" : "PUSH1",
"gas" : 16493342,
"gasCost" : 3,
"depth" : 2,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 2
}, {
"pc" : 13,
"op" : "RETURN",
"gas" : 16493339,
"gasCost" : 0,
"depth" : 2,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 2
}, {
"pc" : 22,
"op" : "PUSH1",
"gas" : 16755138,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 1
}, {
"pc" : 24,
"op" : "PUSH1",
"gas" : 16755135,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 1
}, {
"pc" : 26,
"op" : "RETURN",
"gas" : 16755132,
"gasCost" : 0,
"depth" : 1,
"stack" : null,
"memory" : null,
"storage" : null,
"reason" : null
"depth" : 1
} ]
}
},

View File

@@ -1,297 +0,0 @@
{
"request" : {
"jsonrpc" : "2.0",
"method" : "debug_traceCall",
"params" : [ {
"from" : "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"to" : "0x0050000000000000000000000000000000000000",
"gas" : "0xfffff2",
"gasPrice" : "0xef",
"value" : "0x0",
"data" : "0x0000000000000000000000000030000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000001",
"nonce" : "0x0"
}, "latest" ],
"id" : 1
},
"response": {
"jsonrpc": "2.0",
"id": 1,
"result": {
"gas" : 22070,
"failed" : false,
"returnValue" : "f000000000000000000000000000000000000000000000000000000000000002",
"structLogs" : [ {
"pc" : 0,
"op" : "PUSH1",
"gas" : 16755910,
"gasCost" : 3,
"depth" : 1,
"stack" : [ ],
"memory" : [ ],
"storage" : { },
"reason" : null
}, {
"pc" : 2,
"op" : "PUSH1",
"gas" : 16755907,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : [ ],
"storage" : { },
"reason" : null
}, {
"pc" : 4,
"op" : "PUSH1",
"gas" : 16755904,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : [ ],
"storage" : { },
"reason" : null
}, {
"pc" : 6,
"op" : "CALLDATASIZE",
"gas" : 16755901,
"gasCost" : 2,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : [ ],
"storage" : { },
"reason" : null
}, {
"pc" : 7,
"op" : "SUB",
"gas" : 16755899,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000040" ],
"memory" : [ ],
"storage" : { },
"reason" : null
}, {
"pc" : 8,
"op" : "DUP1",
"gas" : 16755896,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : [ ],
"storage" : { },
"reason" : null
}, {
"pc" : 9,
"op" : "PUSH1",
"gas" : 16755893,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : [ ],
"storage" : { },
"reason" : null
}, {
"pc" : 11,
"op" : "PUSH1",
"gas" : 16755890,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : [ ],
"storage" : { },
"reason" : null
}, {
"pc" : 13,
"op" : "CALLDATACOPY",
"gas" : 16755887,
"gasCost" : 9,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : { },
"reason" : null
}, {
"pc" : 14,
"op" : "PUSH1",
"gas" : 16755878,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : { },
"reason" : null
}, {
"pc" : 16,
"op" : "CALLVALUE",
"gas" : 16755875,
"gasCost" : 2,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : { },
"reason" : null
}, {
"pc" : 17,
"op" : "PUSH1",
"gas" : 16755873,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : { },
"reason" : null
}, {
"pc" : 19,
"op" : "CALLDATALOAD",
"gas" : 16755870,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : { },
"reason" : null
}, {
"pc" : 20,
"op" : "GAS",
"gas" : 16755867,
"gasCost" : 2,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000030000000000000000000000000000000000000" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : { },
"reason" : null
}, {
"pc" : 21,
"op" : "CALLCODE",
"gas" : 16755865,
"gasCost" : 16494066,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000030000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000ffac99" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : { },
"reason" : null
}, {
"pc" : 0,
"op" : "PUSH1",
"gas" : 16493366,
"gasCost" : 3,
"depth" : 2,
"stack" : [ ],
"memory" : [ ],
"storage" : { },
"reason" : null
}, {
"pc" : 2,
"op" : "CALLDATALOAD",
"gas" : 16493363,
"gasCost" : 3,
"depth" : 2,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : [ ],
"storage" : { },
"reason" : null
}, {
"pc" : 3,
"op" : "PUSH1",
"gas" : 16493360,
"gasCost" : 3,
"depth" : 2,
"stack" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"memory" : [ ],
"storage" : { },
"reason" : null
}, {
"pc" : 5,
"op" : "ADD",
"gas" : 16493357,
"gasCost" : 3,
"depth" : 2,
"stack" : [ "f000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001" ],
"memory" : [ ],
"storage" : { },
"reason" : null
}, {
"pc" : 6,
"op" : "PUSH1",
"gas" : 16493354,
"gasCost" : 3,
"depth" : 2,
"stack" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"memory" : [ ],
"storage" : { },
"reason" : null
}, {
"pc" : 8,
"op" : "MSTORE",
"gas" : 16493351,
"gasCost" : 6,
"depth" : 2,
"stack" : [ "f000000000000000000000000000000000000000000000000000000000000002", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : { },
"reason" : null
}, {
"pc" : 9,
"op" : "PUSH1",
"gas" : 16493345,
"gasCost" : 3,
"depth" : 2,
"stack" : [ ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : { },
"reason" : null
}, {
"pc" : 11,
"op" : "PUSH1",
"gas" : 16493342,
"gasCost" : 3,
"depth" : 2,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : { },
"reason" : null
}, {
"pc" : 13,
"op" : "RETURN",
"gas" : 16493339,
"gasCost" : 0,
"depth" : 2,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : { },
"reason" : null
}, {
"pc" : 22,
"op" : "PUSH1",
"gas" : 16755138,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000001" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : { },
"reason" : null
}, {
"pc" : 24,
"op" : "PUSH1",
"gas" : 16755135,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : { },
"reason" : null
}, {
"pc" : 26,
"op" : "RETURN",
"gas" : 16755132,
"gasCost" : 0,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : { },
"reason" : null
} ]
}
},
"statusCode": 200
}

View File

@@ -0,0 +1,216 @@
{
"request" : {
"jsonrpc" : "2.0",
"method" : "debug_traceCall",
"params" : [ {
"from" : "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"to" : "0x0050000000000000000000000000000000000000",
"gas" : "0xfffff2",
"gasPrice" : "0xef",
"value" : "0x0",
"data" : "0x0000000000000000000000000030000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000001",
"nonce" : "0x0"
}, "latest" ],
"id" : 1
},
"response": {
"jsonrpc": "2.0",
"id": 1,
"result": {
"gas" : 22070,
"failed" : false,
"returnValue" : "f000000000000000000000000000000000000000000000000000000000000002",
"structLogs" : [ {
"pc" : 0,
"op" : "PUSH1",
"gas" : 16755910,
"gasCost" : 3,
"depth" : 1,
"stack" : [ ]
}, {
"pc" : 2,
"op" : "PUSH1",
"gas" : 16755907,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x20" ]
}, {
"pc" : 4,
"op" : "PUSH1",
"gas" : 16755904,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x20", "0x0" ]
}, {
"pc" : 6,
"op" : "CALLDATASIZE",
"gas" : 16755901,
"gasCost" : 2,
"depth" : 1,
"stack" : [ "0x20", "0x0", "0x20" ]
}, {
"pc" : 7,
"op" : "SUB",
"gas" : 16755899,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x20", "0x0", "0x20", "0x40" ]
}, {
"pc" : 8,
"op" : "DUP1",
"gas" : 16755896,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x20", "0x0", "0x20" ]
}, {
"pc" : 9,
"op" : "PUSH1",
"gas" : 16755893,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x20", "0x0", "0x20", "0x20" ]
}, {
"pc" : 11,
"op" : "PUSH1",
"gas" : 16755890,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x20", "0x0", "0x20", "0x20", "0x20" ]
}, {
"pc" : 13,
"op" : "CALLDATACOPY",
"gas" : 16755887,
"gasCost" : 9,
"depth" : 1,
"stack" : [ "0x20", "0x0", "0x20", "0x20", "0x20", "0x0" ]
}, {
"pc" : 14,
"op" : "PUSH1",
"gas" : 16755878,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x20", "0x0", "0x20" ]
}, {
"pc" : 16,
"op" : "CALLVALUE",
"gas" : 16755875,
"gasCost" : 2,
"depth" : 1,
"stack" : [ "0x20", "0x0", "0x20", "0x0" ]
}, {
"pc" : 17,
"op" : "PUSH1",
"gas" : 16755873,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x20", "0x0", "0x20", "0x0", "0x0" ]
}, {
"pc" : 19,
"op" : "CALLDATALOAD",
"gas" : 16755870,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x20", "0x0", "0x20", "0x0", "0x0", "0x0" ]
}, {
"pc" : 20,
"op" : "GAS",
"gas" : 16755867,
"gasCost" : 2,
"depth" : 1,
"stack" : [ "0x20", "0x0", "0x20", "0x0", "0x0", "0x30000000000000000000000000000000000000" ]
}, {
"pc" : 21,
"op" : "CALLCODE",
"gas" : 16755865,
"gasCost" : 16494066,
"depth" : 1,
"stack" : [ "0x20", "0x0", "0x20", "0x0", "0x0", "0x30000000000000000000000000000000000000", "0xffac99" ]
}, {
"pc" : 0,
"op" : "PUSH1",
"gas" : 16493366,
"gasCost" : 3,
"depth" : 2,
"stack" : [ ]
}, {
"pc" : 2,
"op" : "CALLDATALOAD",
"gas" : 16493363,
"gasCost" : 3,
"depth" : 2,
"stack" : [ "0x0" ]
}, {
"pc" : 3,
"op" : "PUSH1",
"gas" : 16493360,
"gasCost" : 3,
"depth" : 2,
"stack" : [ "0xf000000000000000000000000000000000000000000000000000000000000001" ]
}, {
"pc" : 5,
"op" : "ADD",
"gas" : 16493357,
"gasCost" : 3,
"depth" : 2,
"stack" : [ "0xf000000000000000000000000000000000000000000000000000000000000001", "0x1" ]
}, {
"pc" : 6,
"op" : "PUSH1",
"gas" : 16493354,
"gasCost" : 3,
"depth" : 2,
"stack" : [ "0xf000000000000000000000000000000000000000000000000000000000000002" ]
}, {
"pc" : 8,
"op" : "MSTORE",
"gas" : 16493351,
"gasCost" : 6,
"depth" : 2,
"stack" : [ "0xf000000000000000000000000000000000000000000000000000000000000002", "0x0" ]
}, {
"pc" : 9,
"op" : "PUSH1",
"gas" : 16493345,
"gasCost" : 3,
"depth" : 2,
"stack" : [ ]
}, {
"pc" : 11,
"op" : "PUSH1",
"gas" : 16493342,
"gasCost" : 3,
"depth" : 2,
"stack" : [ "0x20" ]
}, {
"pc" : 13,
"op" : "RETURN",
"gas" : 16493339,
"gasCost" : 0,
"depth" : 2,
"stack" : [ "0x20", "0x0" ]
}, {
"pc" : 22,
"op" : "PUSH1",
"gas" : 16755138,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x1" ]
}, {
"pc" : 24,
"op" : "PUSH1",
"gas" : 16755135,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x1", "0x20" ]
}, {
"pc" : 26,
"op" : "RETURN",
"gas" : 16755132,
"gasCost" : 0,
"depth" : 1,
"stack" : [ "0x1", "0x20", "0x0" ]
} ]
}
},
"statusCode": 200
}

View File

@@ -29,270 +29,189 @@
"gas" : 16755910,
"gasCost" : 3,
"depth" : 1,
"stack" : [ ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ ]
}, {
"pc" : 2,
"op" : "PUSH1",
"gas" : 16755907,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0x20" ]
}, {
"pc" : 4,
"op" : "PUSH1",
"gas" : 16755904,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0x20", "0x0" ]
}, {
"pc" : 6,
"op" : "CALLDATASIZE",
"gas" : 16755901,
"gasCost" : 2,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0x20", "0x0", "0x20" ]
}, {
"pc" : 7,
"op" : "SUB",
"gas" : 16755899,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000040" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0x20", "0x0", "0x20", "0x40" ]
}, {
"pc" : 8,
"op" : "DUP1",
"gas" : 16755896,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0x20", "0x0", "0x20" ]
}, {
"pc" : 9,
"op" : "PUSH1",
"gas" : 16755893,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0x20", "0x0", "0x20", "0x20" ]
}, {
"pc" : 11,
"op" : "PUSH1",
"gas" : 16755890,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0x20", "0x0", "0x20", "0x20", "0x20" ]
}, {
"pc" : 13,
"op" : "CALLDATACOPY",
"gas" : 16755887,
"gasCost" : 9,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0x20", "0x0", "0x20", "0x20", "0x20", "0x0" ]
}, {
"pc" : 14,
"op" : "PUSH1",
"gas" : 16755878,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0x20", "0x0", "0x20" ]
}, {
"pc" : 16,
"op" : "CALLVALUE",
"gas" : 16755875,
"gasCost" : 2,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0x20", "0x0", "0x20", "0x0" ]
}, {
"pc" : 17,
"op" : "PUSH1",
"gas" : 16755873,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0x20", "0x0", "0x20", "0x0", "0x0" ]
}, {
"pc" : 19,
"op" : "CALLDATALOAD",
"gas" : 16755870,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0x20", "0x0", "0x20", "0x0", "0x0", "0x0" ]
}, {
"pc" : 20,
"op" : "GAS",
"gas" : 16755867,
"gasCost" : 2,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000030000000000000000000000000000000000000" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0x20", "0x0", "0x20", "0x0", "0x0", "0x30000000000000000000000000000000000000" ]
}, {
"pc" : 21,
"op" : "CALLCODE",
"gas" : 16755865,
"gasCost" : 16494066,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000030000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000ffac99" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0x20", "0x0", "0x20", "0x0", "0x0", "0x30000000000000000000000000000000000000", "0xffac99" ]
}, {
"pc" : 0,
"op" : "PUSH1",
"gas" : 16493366,
"gasCost" : 3,
"depth" : 2,
"stack" : [ ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ ]
}, {
"pc" : 2,
"op" : "CALLDATALOAD",
"gas" : 16493363,
"gasCost" : 3,
"depth" : 2,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0x0" ]
}, {
"pc" : 3,
"op" : "PUSH1",
"gas" : 16493360,
"gasCost" : 3,
"depth" : 2,
"stack" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0xf000000000000000000000000000000000000000000000000000000000000001" ]
}, {
"pc" : 5,
"op" : "ADD",
"gas" : 16493357,
"gasCost" : 3,
"depth" : 2,
"stack" : [ "f000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0xf000000000000000000000000000000000000000000000000000000000000001", "0x1" ]
}, {
"pc" : 6,
"op" : "PUSH1",
"gas" : 16493354,
"gasCost" : 3,
"depth" : 2,
"stack" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0xf000000000000000000000000000000000000000000000000000000000000002" ]
}, {
"pc" : 8,
"op" : "MSTORE",
"gas" : 16493351,
"gasCost" : 6,
"depth" : 2,
"stack" : [ "f000000000000000000000000000000000000000000000000000000000000002", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0xf000000000000000000000000000000000000000000000000000000000000002", "0x0" ]
}, {
"pc" : 9,
"op" : "PUSH1",
"gas" : 16493345,
"gasCost" : 3,
"depth" : 2,
"stack" : [ ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ ]
}, {
"pc" : 11,
"op" : "PUSH1",
"gas" : 16493342,
"gasCost" : 3,
"depth" : 2,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0x20" ]
}, {
"pc" : 13,
"op" : "RETURN",
"gas" : 16493339,
"gasCost" : 0,
"depth" : 2,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0x20", "0x0" ]
}, {
"pc" : 22,
"op" : "PUSH1",
"gas" : 16755138,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000001" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0x1" ]
}, {
"pc" : 24,
"op" : "PUSH1",
"gas" : 16755135,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0x1", "0x20" ]
}, {
"pc" : 26,
"op" : "RETURN",
"gas" : 16755132,
"gasCost" : 0,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : null,
"storage" : { },
"reason" : null
"stack" : [ "0x1", "0x20", "0x0" ]
} ]
}
},

View File

@@ -28,271 +28,177 @@
"op" : "PUSH1",
"gas" : 16755910,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : [ ],
"storage" : { },
"reason" : null
"depth" : 1
}, {
"pc" : 2,
"op" : "PUSH1",
"gas" : 16755907,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : [ ],
"storage" : { },
"reason" : null
"depth" : 1
}, {
"pc" : 4,
"op" : "PUSH1",
"gas" : 16755904,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : [ ],
"storage" : { },
"reason" : null
"depth" : 1
}, {
"pc" : 6,
"op" : "CALLDATASIZE",
"gas" : 16755901,
"gasCost" : 2,
"depth" : 1,
"stack" : null,
"memory" : [ ],
"storage" : { },
"reason" : null
"depth" : 1
}, {
"pc" : 7,
"op" : "SUB",
"gas" : 16755899,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : [ ],
"storage" : { },
"reason" : null
"depth" : 1
}, {
"pc" : 8,
"op" : "DUP1",
"gas" : 16755896,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : [ ],
"storage" : { },
"reason" : null
"depth" : 1
}, {
"pc" : 9,
"op" : "PUSH1",
"gas" : 16755893,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : [ ],
"storage" : { },
"reason" : null
"depth" : 1
}, {
"pc" : 11,
"op" : "PUSH1",
"gas" : 16755890,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : [ ],
"storage" : { },
"reason" : null
"depth" : 1
}, {
"pc" : 13,
"op" : "CALLDATACOPY",
"gas" : 16755887,
"gasCost" : 9,
"depth" : 1,
"stack" : null,
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : { },
"reason" : null
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000001" ]
}, {
"pc" : 14,
"op" : "PUSH1",
"gas" : 16755878,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : { },
"reason" : null
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000001" ]
}, {
"pc" : 16,
"op" : "CALLVALUE",
"gas" : 16755875,
"gasCost" : 2,
"depth" : 1,
"stack" : null,
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : { },
"reason" : null
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000001" ]
}, {
"pc" : 17,
"op" : "PUSH1",
"gas" : 16755873,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : { },
"reason" : null
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000001" ]
}, {
"pc" : 19,
"op" : "CALLDATALOAD",
"gas" : 16755870,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : { },
"reason" : null
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000001" ]
}, {
"pc" : 20,
"op" : "GAS",
"gas" : 16755867,
"gasCost" : 2,
"depth" : 1,
"stack" : null,
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : { },
"reason" : null
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000001" ]
}, {
"pc" : 21,
"op" : "CALLCODE",
"gas" : 16755865,
"gasCost" : 16494066,
"depth" : 1,
"stack" : null,
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : { },
"reason" : null
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000001" ]
}, {
"pc" : 0,
"op" : "PUSH1",
"gas" : 16493366,
"gasCost" : 3,
"depth" : 2,
"stack" : null,
"memory" : [ ],
"storage" : { },
"reason" : null
"depth" : 2
}, {
"pc" : 2,
"op" : "CALLDATALOAD",
"gas" : 16493363,
"gasCost" : 3,
"depth" : 2,
"stack" : null,
"memory" : [ ],
"storage" : { },
"reason" : null
"depth" : 2
}, {
"pc" : 3,
"op" : "PUSH1",
"gas" : 16493360,
"gasCost" : 3,
"depth" : 2,
"stack" : null,
"memory" : [ ],
"storage" : { },
"reason" : null
"depth" : 2
}, {
"pc" : 5,
"op" : "ADD",
"gas" : 16493357,
"gasCost" : 3,
"depth" : 2,
"stack" : null,
"memory" : [ ],
"storage" : { },
"reason" : null
"depth" : 2
}, {
"pc" : 6,
"op" : "PUSH1",
"gas" : 16493354,
"gasCost" : 3,
"depth" : 2,
"stack" : null,
"memory" : [ ],
"storage" : { },
"reason" : null
"depth" : 2
}, {
"pc" : 8,
"op" : "MSTORE",
"gas" : 16493351,
"gasCost" : 6,
"depth" : 2,
"stack" : null,
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : { },
"reason" : null
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000002" ]
}, {
"pc" : 9,
"op" : "PUSH1",
"gas" : 16493345,
"gasCost" : 3,
"depth" : 2,
"stack" : null,
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : { },
"reason" : null
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000002" ]
}, {
"pc" : 11,
"op" : "PUSH1",
"gas" : 16493342,
"gasCost" : 3,
"depth" : 2,
"stack" : null,
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : { },
"reason" : null
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000002" ]
}, {
"pc" : 13,
"op" : "RETURN",
"gas" : 16493339,
"gasCost" : 0,
"depth" : 2,
"stack" : null,
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : { },
"reason" : null
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000002" ]
}, {
"pc" : 22,
"op" : "PUSH1",
"gas" : 16755138,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : { },
"reason" : null
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000002" ]
}, {
"pc" : 24,
"op" : "PUSH1",
"gas" : 16755135,
"gasCost" : 3,
"depth" : 1,
"stack" : null,
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : { },
"reason" : null
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000002" ]
}, {
"pc" : 26,
"op" : "RETURN",
"gas" : 16755132,
"gasCost" : 0,
"depth" : 1,
"stack" : null,
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : { },
"reason" : null
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000002" ]
} ]
}
},

View File

@@ -29,210 +29,155 @@
"gas" : 16755910,
"gasCost" : 3,
"depth" : 1,
"stack" : [ ],
"memory" : [ ],
"storage" : null,
"reason" : null
"stack" : [ ]
}, {
"pc" : 2,
"op" : "PUSH1",
"gas" : 16755907,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : [ ],
"storage" : null,
"reason" : null
"stack" : [ "0x20" ]
}, {
"pc" : 4,
"op" : "PUSH1",
"gas" : 16755904,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : [ ],
"storage" : null,
"reason" : null
"stack" : [ "0x20", "0x0" ]
}, {
"pc" : 6,
"op" : "CALLDATASIZE",
"gas" : 16755901,
"gasCost" : 2,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : [ ],
"storage" : null,
"reason" : null
"stack" : [ "0x20", "0x0", "0x20" ]
}, {
"pc" : 7,
"op" : "SUB",
"gas" : 16755899,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000040" ],
"memory" : [ ],
"storage" : null,
"reason" : null
"stack" : [ "0x20", "0x0", "0x20", "0x40" ]
}, {
"pc" : 8,
"op" : "DUP1",
"gas" : 16755896,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : [ ],
"storage" : null,
"reason" : null
"stack" : [ "0x20", "0x0", "0x20" ]
}, {
"pc" : 9,
"op" : "PUSH1",
"gas" : 16755893,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : [ ],
"storage" : null,
"reason" : null
"stack" : [ "0x20", "0x0", "0x20", "0x20" ]
}, {
"pc" : 11,
"op" : "PUSH1",
"gas" : 16755890,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : [ ],
"storage" : null,
"reason" : null
"stack" : [ "0x20", "0x0", "0x20", "0x20", "0x20" ]
}, {
"pc" : 13,
"op" : "CALLDATACOPY",
"gas" : 16755887,
"gasCost" : 9,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : null,
"reason" : null
"stack" : [ "0x20", "0x0", "0x20", "0x20", "0x20", "0x0" ],
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000001" ]
}, {
"pc" : 14,
"op" : "PUSH1",
"gas" : 16755878,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : null,
"reason" : null
"stack" : [ "0x20", "0x0", "0x20" ],
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000001" ]
}, {
"pc" : 16,
"op" : "CALLVALUE",
"gas" : 16755875,
"gasCost" : 2,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : null,
"reason" : null
"stack" : [ "0x20", "0x0", "0x20", "0x0" ],
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000001" ]
}, {
"pc" : 17,
"op" : "PUSH1",
"gas" : 16755873,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : null,
"reason" : null
"stack" : [ "0x20", "0x0", "0x20", "0x0", "0x0" ],
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000001" ]
}, {
"pc" : 19,
"op" : "CALLDATALOAD",
"gas" : 16755870,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : null,
"reason" : null
"stack" : [ "0x20", "0x0", "0x20", "0x0", "0x0", "0x0" ],
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000001" ]
}, {
"pc" : 20,
"op" : "GAS",
"gas" : 16755867,
"gasCost" : 2,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000030000000000000000000000000000000000000" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : null,
"reason" : null
"stack" : [ "0x20", "0x0", "0x20", "0x0", "0x0", "0x30000000000000000000000000000000000000" ],
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000001" ]
}, {
"pc" : 21,
"op" : "CALLCODE",
"gas" : 16755865,
"gasCost" : 16494066,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000030000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000ffac99" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"storage" : null,
"reason" : null
"stack" : [ "0x20", "0x0", "0x20", "0x0", "0x0", "0x30000000000000000000000000000000000000", "0xffac99" ],
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000001" ]
}, {
"pc" : 0,
"op" : "PUSH1",
"gas" : 16493366,
"gasCost" : 3,
"depth" : 2,
"stack" : [ ],
"memory" : [ ],
"storage" : null,
"reason" : null
"stack" : [ ]
}, {
"pc" : 2,
"op" : "CALLDATALOAD",
"gas" : 16493363,
"gasCost" : 3,
"depth" : 2,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : [ ],
"storage" : null,
"reason" : null
"stack" : [ "0x0" ]
}, {
"pc" : 3,
"op" : "PUSH1",
"gas" : 16493360,
"gasCost" : 3,
"depth" : 2,
"stack" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
"memory" : [ ],
"storage" : null,
"reason" : null
"stack" : [ "0xf000000000000000000000000000000000000000000000000000000000000001" ]
}, {
"pc" : 5,
"op" : "ADD",
"gas" : 16493357,
"gasCost" : 3,
"depth" : 2,
"stack" : [ "f000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001" ],
"memory" : [ ],
"storage" : null,
"reason" : null
"stack" : [ "0xf000000000000000000000000000000000000000000000000000000000000001", "0x1" ]
}, {
"pc" : 6,
"op" : "PUSH1",
"gas" : 16493354,
"gasCost" : 3,
"depth" : 2,
"stack" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"memory" : [ ],
"storage" : null,
"reason" : null
"stack" : [ "0xf000000000000000000000000000000000000000000000000000000000000002" ]
}, {
"pc" : 8,
"op" : "MSTORE",
"gas" : 16493351,
"gasCost" : 6,
"depth" : 2,
"stack" : [ "f000000000000000000000000000000000000000000000000000000000000002", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : null,
"reason" : null
"stack" : [ "0xf000000000000000000000000000000000000000000000000000000000000002", "0x0" ],
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000002" ]
}, {
"pc" : 9,
"op" : "PUSH1",
@@ -240,59 +185,47 @@
"gasCost" : 3,
"depth" : 2,
"stack" : [ ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : null,
"reason" : null
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000002" ]
}, {
"pc" : 11,
"op" : "PUSH1",
"gas" : 16493342,
"gasCost" : 3,
"depth" : 2,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : null,
"reason" : null
"stack" : [ "0x20" ],
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000002" ]
}, {
"pc" : 13,
"op" : "RETURN",
"gas" : 16493339,
"gasCost" : 0,
"depth" : 2,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : null,
"reason" : null
"stack" : [ "0x20", "0x0" ],
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000002" ]
}, {
"pc" : 22,
"op" : "PUSH1",
"gas" : 16755138,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000001" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : null,
"reason" : null
"stack" : [ "0x1" ],
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000002" ]
}, {
"pc" : 24,
"op" : "PUSH1",
"gas" : 16755135,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000020" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : null,
"reason" : null
"stack" : [ "0x1", "0x20" ],
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000002" ]
}, {
"pc" : 26,
"op" : "RETURN",
"gas" : 16755132,
"gasCost" : 0,
"depth" : 1,
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
"storage" : null,
"reason" : null
"stack" : [ "0x1", "0x20", "0x0" ],
"memory" : [ "0xf000000000000000000000000000000000000000000000000000000000000002" ]
} ]
}
},

View File

@@ -20,22 +20,16 @@
"jsonrpc": "2.0",
"id": 1,
"result": {
"gas": 21164,
"failed": false,
"returnValue": "",
"structLogs": [
{
"pc": 0,
"op": "STOP",
"gas": 17592186023252,
"gasCost": 0,
"depth": 1,
"stack": null,
"memory": null,
"storage": null,
"reason": null
}
]
"gas" : 21164,
"failed" : false,
"returnValue" : "",
"structLogs" : [ {
"pc" : 0,
"op" : "STOP",
"gas" : 17592186023252,
"gasCost" : 0,
"depth" : 1
} ]
}
},
"statusCode": 200

View File

@@ -0,0 +1,764 @@
{
"request": {
"id": 1,
"jsonrpc": "2.0",
"method": "debug_traceTransaction",
"params": [
"0xcef53f2311d7c80e9086d661e69ac11a5f3d081e28e02a9ba9b66749407ac310"
]
},
"response": {
"jsonrpc": "2.0",
"id": 1,
"result": {
"gas" : 23705,
"failed" : false,
"returnValue" : "",
"structLogs" : [ {
"pc" : 0,
"op" : "PUSH1",
"gas" : 292887,
"gasCost" : 3,
"depth" : 1,
"stack" : [ ]
}, {
"pc" : 2,
"op" : "CALLDATALOAD",
"gas" : 292884,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x0" ]
}, {
"pc" : 3,
"op" : "PUSH29",
"gas" : 292881,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f500000000000000000000000000000000000000000000000000000000" ]
}, {
"pc" : 33,
"op" : "SWAP1",
"gas" : 292878,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f500000000000000000000000000000000000000000000000000000000", "0x100000000000000000000000000000000000000000000000000000000" ]
}, {
"pc" : 34,
"op" : "DIV",
"gas" : 292875,
"gasCost" : 5,
"depth" : 1,
"stack" : [ "0x100000000000000000000000000000000000000000000000000000000", "0x9dc2c8f500000000000000000000000000000000000000000000000000000000" ]
}, {
"pc" : 35,
"op" : "DUP1",
"gas" : 292870,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5" ]
}, {
"pc" : 36,
"op" : "PUSH4",
"gas" : 292867,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5" ]
}, {
"pc" : 41,
"op" : "EQ",
"gas" : 292864,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5", "0x102accc1" ]
}, {
"pc" : 42,
"op" : "PUSH2",
"gas" : 292861,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0" ]
}, {
"pc" : 45,
"op" : "JUMPI",
"gas" : 292858,
"gasCost" : 10,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0", "0x12c" ]
}, {
"pc" : 46,
"op" : "DUP1",
"gas" : 292848,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5" ]
}, {
"pc" : 47,
"op" : "PUSH4",
"gas" : 292845,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5" ]
}, {
"pc" : 52,
"op" : "EQ",
"gas" : 292842,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5", "0x12a7b914" ]
}, {
"pc" : 53,
"op" : "PUSH2",
"gas" : 292839,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0" ]
}, {
"pc" : 56,
"op" : "JUMPI",
"gas" : 292836,
"gasCost" : 10,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0", "0x13a" ]
}, {
"pc" : 57,
"op" : "DUP1",
"gas" : 292826,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5" ]
}, {
"pc" : 58,
"op" : "PUSH4",
"gas" : 292823,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5" ]
}, {
"pc" : 63,
"op" : "EQ",
"gas" : 292820,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5", "0x1774e646" ]
}, {
"pc" : 64,
"op" : "PUSH2",
"gas" : 292817,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0" ]
}, {
"pc" : 67,
"op" : "JUMPI",
"gas" : 292814,
"gasCost" : 10,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0", "0x14c" ]
}, {
"pc" : 68,
"op" : "DUP1",
"gas" : 292804,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5" ]
}, {
"pc" : 69,
"op" : "PUSH4",
"gas" : 292801,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5" ]
}, {
"pc" : 74,
"op" : "EQ",
"gas" : 292798,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5", "0x1e26fd33" ]
}, {
"pc" : 75,
"op" : "PUSH2",
"gas" : 292795,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0" ]
}, {
"pc" : 78,
"op" : "JUMPI",
"gas" : 292792,
"gasCost" : 10,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0", "0x15d" ]
}, {
"pc" : 79,
"op" : "DUP1",
"gas" : 292782,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5" ]
}, {
"pc" : 80,
"op" : "PUSH4",
"gas" : 292779,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5" ]
}, {
"pc" : 85,
"op" : "EQ",
"gas" : 292776,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5", "0x1f903037" ]
}, {
"pc" : 86,
"op" : "PUSH2",
"gas" : 292773,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0" ]
}, {
"pc" : 89,
"op" : "JUMPI",
"gas" : 292770,
"gasCost" : 10,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0", "0x16e" ]
}, {
"pc" : 90,
"op" : "DUP1",
"gas" : 292760,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5" ]
}, {
"pc" : 91,
"op" : "PUSH4",
"gas" : 292757,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5" ]
}, {
"pc" : 96,
"op" : "EQ",
"gas" : 292754,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5", "0x343a875d" ]
}, {
"pc" : 97,
"op" : "PUSH2",
"gas" : 292751,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0" ]
}, {
"pc" : 100,
"op" : "JUMPI",
"gas" : 292748,
"gasCost" : 10,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0", "0x180" ]
}, {
"pc" : 101,
"op" : "DUP1",
"gas" : 292738,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5" ]
}, {
"pc" : 102,
"op" : "PUSH4",
"gas" : 292735,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5" ]
}, {
"pc" : 107,
"op" : "EQ",
"gas" : 292732,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5", "0x38cc4831" ]
}, {
"pc" : 108,
"op" : "PUSH2",
"gas" : 292729,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0" ]
}, {
"pc" : 111,
"op" : "JUMPI",
"gas" : 292726,
"gasCost" : 10,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0", "0x195" ]
}, {
"pc" : 112,
"op" : "DUP1",
"gas" : 292716,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5" ]
}, {
"pc" : 113,
"op" : "PUSH4",
"gas" : 292713,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5" ]
}, {
"pc" : 118,
"op" : "EQ",
"gas" : 292710,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5", "0x4e7ad367" ]
}, {
"pc" : 119,
"op" : "PUSH2",
"gas" : 292707,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0" ]
}, {
"pc" : 122,
"op" : "JUMPI",
"gas" : 292704,
"gasCost" : 10,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0", "0x1bd" ]
}, {
"pc" : 123,
"op" : "DUP1",
"gas" : 292694,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5" ]
}, {
"pc" : 124,
"op" : "PUSH4",
"gas" : 292691,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5" ]
}, {
"pc" : 129,
"op" : "EQ",
"gas" : 292688,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5", "0x57cb2fc4" ]
}, {
"pc" : 130,
"op" : "PUSH2",
"gas" : 292685,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0" ]
}, {
"pc" : 133,
"op" : "JUMPI",
"gas" : 292682,
"gasCost" : 10,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0", "0x1cb" ]
}, {
"pc" : 134,
"op" : "DUP1",
"gas" : 292672,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5" ]
}, {
"pc" : 135,
"op" : "PUSH4",
"gas" : 292669,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5" ]
}, {
"pc" : 140,
"op" : "EQ",
"gas" : 292666,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5", "0x65538c73" ]
}, {
"pc" : 141,
"op" : "PUSH2",
"gas" : 292663,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0" ]
}, {
"pc" : 144,
"op" : "JUMPI",
"gas" : 292660,
"gasCost" : 10,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0", "0x1e0" ]
}, {
"pc" : 145,
"op" : "DUP1",
"gas" : 292650,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5" ]
}, {
"pc" : 146,
"op" : "PUSH4",
"gas" : 292647,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5" ]
}, {
"pc" : 151,
"op" : "EQ",
"gas" : 292644,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5", "0x68895979" ]
}, {
"pc" : 152,
"op" : "PUSH2",
"gas" : 292641,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0" ]
}, {
"pc" : 155,
"op" : "JUMPI",
"gas" : 292638,
"gasCost" : 10,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0", "0x1ee" ]
}, {
"pc" : 156,
"op" : "DUP1",
"gas" : 292628,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5" ]
}, {
"pc" : 157,
"op" : "PUSH4",
"gas" : 292625,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5" ]
}, {
"pc" : 162,
"op" : "EQ",
"gas" : 292622,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5", "0x76bc21d9" ]
}, {
"pc" : 163,
"op" : "PUSH2",
"gas" : 292619,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0" ]
}, {
"pc" : 166,
"op" : "JUMPI",
"gas" : 292616,
"gasCost" : 10,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0", "0x200" ]
}, {
"pc" : 167,
"op" : "DUP1",
"gas" : 292606,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5" ]
}, {
"pc" : 168,
"op" : "PUSH4",
"gas" : 292603,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5" ]
}, {
"pc" : 173,
"op" : "EQ",
"gas" : 292600,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5", "0x9a19a953" ]
}, {
"pc" : 174,
"op" : "PUSH2",
"gas" : 292597,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0" ]
}, {
"pc" : 177,
"op" : "JUMPI",
"gas" : 292594,
"gasCost" : 10,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0", "0x20e" ]
}, {
"pc" : 178,
"op" : "DUP1",
"gas" : 292584,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5" ]
}, {
"pc" : 179,
"op" : "PUSH4",
"gas" : 292581,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5" ]
}, {
"pc" : 184,
"op" : "EQ",
"gas" : 292578,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x9dc2c8f5", "0x9dc2c8f5" ]
}, {
"pc" : 185,
"op" : "PUSH2",
"gas" : 292575,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x1" ]
}, {
"pc" : 188,
"op" : "JUMPI",
"gas" : 292572,
"gasCost" : 10,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x1", "0x21f" ]
}, {
"pc" : 543,
"op" : "JUMPDEST",
"gas" : 292562,
"gasCost" : 1,
"depth" : 1,
"stack" : [ "0x9dc2c8f5" ]
}, {
"pc" : 544,
"op" : "PUSH2",
"gas" : 292561,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5" ]
}, {
"pc" : 547,
"op" : "PUSH2",
"gas" : 292558,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227" ]
}, {
"pc" : 550,
"op" : "JUMP",
"gas" : 292555,
"gasCost" : 8,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0x693" ]
}, {
"pc" : 1683,
"op" : "JUMPDEST",
"gas" : 292547,
"gasCost" : 1,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227" ]
}, {
"pc" : 1684,
"op" : "PUSH32",
"gas" : 292546,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227" ]
}, {
"pc" : 1717,
"op" : "PUSH1",
"gas" : 292543,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ]
}, {
"pc" : 1719,
"op" : "MUL",
"gas" : 292540,
"gasCost" : 5,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x1" ]
}, {
"pc" : 1720,
"op" : "CALLER",
"gas" : 292535,
"gasCost" : 2,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ]
}, {
"pc" : 1721,
"op" : "PUSH20",
"gas" : 292533,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" ]
}, {
"pc" : 1742,
"op" : "AND",
"gas" : 292530,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0xffffffffffffffffffffffffffffffffffffffff" ]
}, {
"pc" : 1743,
"op" : "PUSH1",
"gas" : 292527,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" ]
}, {
"pc" : 1745,
"op" : "PUSH1",
"gas" : 292524,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x1" ]
}, {
"pc" : 1747,
"op" : "PUSH32",
"gas" : 292521,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x1", "0x0" ]
}, {
"pc" : 1780,
"op" : "DUP2",
"gas" : 292518,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x1", "0x0", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe9" ]
}, {
"pc" : 1781,
"op" : "MSTORE",
"gas" : 292515,
"gasCost" : 6,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x1", "0x0", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe9", "0x0" ]
}, {
"pc" : 1782,
"op" : "PUSH1",
"gas" : 292509,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x1", "0x0" ]
}, {
"pc" : 1784,
"op" : "ADD",
"gas" : 292506,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x1", "0x0", "0x20" ]
}, {
"pc" : 1785,
"op" : "PUSH1",
"gas" : 292503,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x1", "0x20" ]
}, {
"pc" : 1787,
"op" : "DUP2",
"gas" : 292500,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x1", "0x20", "0x2a" ]
}, {
"pc" : 1788,
"op" : "MSTORE",
"gas" : 292497,
"gasCost" : 6,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x1", "0x20", "0x2a", "0x20" ]
}, {
"pc" : 1789,
"op" : "PUSH1",
"gas" : 292491,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x1", "0x20" ]
}, {
"pc" : 1791,
"op" : "ADD",
"gas" : 292488,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x1", "0x20", "0x20" ]
}, {
"pc" : 1792,
"op" : "PUSH1",
"gas" : 292485,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x1", "0x40" ]
}, {
"pc" : 1794,
"op" : "LOG3",
"gas" : 292482,
"gasCost" : 2012,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x1", "0x40", "0x0" ]
}, {
"pc" : 1795,
"op" : "JUMPDEST",
"gas" : 290470,
"gasCost" : 1,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227" ]
}, {
"pc" : 1796,
"op" : "JUMP",
"gas" : 290469,
"gasCost" : 8,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227" ]
}, {
"pc" : 551,
"op" : "JUMPDEST",
"gas" : 290461,
"gasCost" : 1,
"depth" : 1,
"stack" : [ "0x9dc2c8f5" ]
}, {
"pc" : 552,
"op" : "PUSH1",
"gas" : 290460,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5" ]
}, {
"pc" : 554,
"op" : "PUSH1",
"gas" : 290457,
"gasCost" : 3,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0" ]
}, {
"pc" : 556,
"op" : "RETURN",
"gas" : 290454,
"gasCost" : 0,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x0", "0x0" ]
}
]
}
},
"statusCode": 200
}

View File

@@ -5,21 +5,21 @@
"method": "eth_call",
"params": [
{
"to": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"from": "a94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"data": "0x12a7b914"
"comment": "Call to ECREC Precompiled on a different address, expect the original behaviour of ECREC precompile",
"from": "0xc100000000000000000000000000000000000000",
"to": "0x0000000000000000000000000000000000123456",
"input": "0x82f3df49d3645876de6313df2bbe9fbce593f21341a7b03acdb9423bc171fcc9000000000000000000000000000000000000000000000000000000000000001cba13918f50da910f2d55a7ea64cf716ba31dad91856f45908dde900530377d8a112d60f36900d18eb8f9d3b4f85a697b545085614509e3520e4b762e35d0d6bd"
},
"latest",
{
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
"0xc100000000000000000000000000000000000000": {
"balance": "0xde0b6b3a7640000",
"nonce": 88
},
"0xb9741079a300Cb3B8f324CdDB847c0d1d273a05E": {
"stateDiff": {
"0x1cf7945003fc5b59d2f6736f0704557aa805c4f2844084ccd1173b8d56946962": "0x000000000000000000000000000000000000000000000000000000110ed03bf7"
},
"movePrecompileToAddress":null
"0x0000000000000000000000000000000000000001": {
"comment": "Move ECREC Precompiled to address",
"code": "0x60003560010160005260206000f3",
"movePrecompileToAddress": "0x0000000000000000000000000000000000123456"
}
}
]
@@ -27,7 +27,8 @@
"response": {
"jsonrpc": "2.0",
"id": 3,
"result": "0x0000000000000000000000000000000000000000000000000000000000000001"
"comment": "The original ECREC precompile behaviour is expected, not the overridden one",
"result": "0x000000000000000000000000c6e93f4c1920eaeaa1e699f76a7a8c18e3056074"
},
"statusCode": 200
}

View File

@@ -0,0 +1,33 @@
{
"request": {
"id": 3,
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"to": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"from": "a94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"data": "0x12a7b914"
},
"latest",
{
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
"balance": "0xde0b6b3a7640000",
"nonce": 88
},
"0xb9741079a300Cb3B8f324CdDB847c0d1d273a05E": {
"stateDiff": {
"0x1cf7945003fc5b59d2f6736f0704557aa805c4f2844084ccd1173b8d56946962": "0x000000000000000000000000000000000000000000000000000000110ed03bf7"
},
"movePrecompileToAddress":null
}
}
]
},
"response": {
"jsonrpc": "2.0",
"id": 3,
"result": "0x0000000000000000000000000000000000000000000000000000000000000001"
},
"statusCode": 200
}

View File

@@ -0,0 +1,32 @@
{
"request": {
"id": 3,
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "0xc100000000000000000000000000000000000000",
"comment": "Call to precompile ECREC (0x01), but code was modified to add 1 to input",
"to": "0x0000000000000000000000000000000000000001",
"input": "0x0000000000000000000000000000000000000000000000000000000000000001"
},
"latest",
{
"0xc100000000000000000000000000000000000000": {
"balance": "0xde0b6b3a7640000"
},
"0x0000000000000000000000000000000000000001": {
"comment": "The code below adds one to input",
"code": "0x60003560010160005260206000f3",
"movePrecompileToAddress": "0x0000000000000000000000000000000000123456"
}
}
]
},
"response": {
"jsonrpc": "2.0",
"id": 3,
"result": "0x0000000000000000000000000000000000000000000000000000000000000002"
},
"statusCode": 200
}

View File

@@ -153,7 +153,6 @@ public class TraceTransactionIntegrationTest {
// No storage changes before the SSTORE call.
TraceFrame frame = tracer.getTraceFrames().get(170);
assertThat(frame.getOpcode()).isEqualTo("DUP6");
assertStorageContainsExactly(frame);
// Storage changes show up in the SSTORE frame.
frame = tracer.getTraceFrames().get(171);
@@ -201,8 +200,6 @@ public class TraceTransactionIntegrationTest {
assertThat(frame.getOpcode()).isEqualTo("PUSH1");
assertThat(frame.getPc()).isEqualTo(0);
assertStackContainsExactly(frame);
assertMemoryContainsExactly(frame);
assertStorageContainsExactly(frame);
frame = traceFrames.get(1);
assertThat(frame.getDepth()).isEqualTo(expectedDepth);
@@ -211,8 +208,6 @@ public class TraceTransactionIntegrationTest {
assertThat(frame.getOpcode()).isEqualTo("PUSH1");
assertThat(frame.getPc()).isEqualTo(2);
assertStackContainsExactly(frame, "0x80");
assertMemoryContainsExactly(frame);
assertStorageContainsExactly(frame);
frame = traceFrames.get(2);
assertThat(frame.getDepth()).isEqualTo(expectedDepth);
@@ -226,7 +221,6 @@ public class TraceTransactionIntegrationTest {
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000080");
assertStorageContainsExactly(frame);
// Reference implementation actually records the memory after expansion but before the store.
// assertMemoryContainsExactly(frame,
// "0000000000000000000000000000000000000000000000000000000000000000",
@@ -245,7 +239,6 @@ public class TraceTransactionIntegrationTest {
"0000000000000000000000000000000000000000000000000000000000000000",
"0000000000000000000000000000000000000000000000000000000000000000",
"0000000000000000000000000000000000000000000000000000000000000080");
assertStorageContainsExactly(frame);
}
private void assertStackContainsExactly(

View File

@@ -21,6 +21,7 @@ import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.core.encoding.CodeDelegationTransactionEncoder;
import org.hyperledger.besu.ethereum.core.json.ChainIdDeserializer;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import java.math.BigInteger;
@@ -28,10 +29,14 @@ import java.util.Optional;
import java.util.function.Supplier;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.google.common.base.Suppliers;
import org.apache.tuweni.bytes.Bytes;
// ignore `signer` field used in execution-spec-tests
@JsonIgnoreProperties(ignoreUnknown = true)
public class CodeDelegation implements org.hyperledger.besu.datatypes.CodeDelegation {
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
@@ -77,14 +82,23 @@ public class CodeDelegation implements org.hyperledger.besu.datatypes.CodeDelega
*/
@JsonCreator
public static org.hyperledger.besu.datatypes.CodeDelegation createCodeDelegation(
@JsonProperty("chainId") final BigInteger chainId,
@JsonProperty("chainId") @JsonDeserialize(using = ChainIdDeserializer.class)
final BigInteger chainId,
@JsonProperty("address") final Address address,
@JsonProperty("nonce") final long nonce,
@JsonProperty("v") final byte v,
@JsonProperty("r") final BigInteger r,
@JsonProperty("s") final BigInteger s) {
@JsonProperty("nonce") final String nonce,
@JsonProperty("v") final String v,
@JsonProperty("r") final String r,
@JsonProperty("s") final String s) {
return new CodeDelegation(
chainId, address, nonce, SIGNATURE_ALGORITHM.get().createSignature(r, s, v));
chainId,
address,
Bytes.fromHexStringLenient(nonce).toLong(),
SIGNATURE_ALGORITHM
.get()
.createSignature(
Bytes.fromHexStringLenient(r).toUnsignedBigInteger(),
Bytes.fromHexStringLenient(s).toUnsignedBigInteger(),
Bytes.fromHexStringLenient(v).get(0)));
}
@JsonProperty("chainId")

View File

@@ -29,4 +29,13 @@ public record Request(RequestType type, Bytes data)
public Bytes getData() {
return data();
}
/**
* Gets the serialized form of the concatenated type and data.
*
* @return the serialized request as a byte.
*/
public Bytes getEncodedRequest() {
return Bytes.concatenate(Bytes.of(getType().ordinal()), getData());
}
}

View File

@@ -38,8 +38,8 @@ public class ChainIdDeserializer extends StdDeserializer<BigInteger> {
final var chainId =
UInt256.fromHexString(jsonparser.getCodec().readValue(jsonparser, String.class))
.toBigInteger();
if (chainId.signum() <= 0) {
throw new IllegalArgumentException("Non positive chain id: " + chainId);
if (chainId.signum() < 0) {
throw new IllegalArgumentException("Negative chain id: " + chainId);
}
return chainId;
}

View File

@@ -20,7 +20,7 @@ public class TraceOptions {
private final boolean traceMemory;
private final boolean traceStack;
public static final TraceOptions DEFAULT = new TraceOptions(true, true, true);
public static final TraceOptions DEFAULT = new TraceOptions(true, false, true);
public TraceOptions(
final boolean traceStorage, final boolean traceMemory, final boolean traceStack) {

View File

@@ -92,20 +92,18 @@ public final class BodyValidation {
/**
* Generates the requests hash for a list of requests
*
* @param requests list of request
* @param requests list of request (must be sorted by request type ascending)
* @return the requests hash
*/
public static Hash requestsHash(final List<Request> requests) {
List<Bytes> requestHashes = new ArrayList<>();
IntStream.range(0, requests.size())
.forEach(
i -> {
final Request request = requests.get(i);
final Bytes requestBytes =
Bytes.concatenate(
Bytes.of(request.getType().getSerializedType()), request.getData());
requestHashes.add(sha256(requestBytes));
});
requests.forEach(
request -> {
// empty requests are excluded from the hash
if (!request.getData().isEmpty()) {
requestHashes.add(sha256(request.getEncodedRequest()));
}
});
return Hash.wrap(sha256(Bytes.wrap(requestHashes)));
}

View File

@@ -175,16 +175,17 @@ public class ClassicProtocolSpecs {
transactionValidatorFactory,
contractCreationProcessor,
messageCallProcessor) ->
new MainnetTransactionProcessor(
gasCalculator,
transactionValidatorFactory,
contractCreationProcessor,
messageCallProcessor,
true,
false,
evmConfiguration.evmStackSize(),
feeMarket,
CoinbaseFeePriceCalculator.frontier()))
MainnetTransactionProcessor.builder()
.gasCalculator(gasCalculator)
.transactionValidatorFactory(transactionValidatorFactory)
.contractCreationProcessor(contractCreationProcessor)
.messageCallProcessor(messageCallProcessor)
.clearEmptyAccounts(true)
.warmCoinbase(false)
.maxStackSize(evmConfiguration.evmStackSize())
.feeMarket(feeMarket)
.coinbaseFeePriceCalculator(CoinbaseFeePriceCalculator.frontier())
.build())
.name("Atlantis");
}
@@ -357,16 +358,17 @@ public class ClassicProtocolSpecs {
transactionValidatorFactory,
contractCreationProcessor,
messageCallProcessor) ->
new MainnetTransactionProcessor(
gasCalculator,
transactionValidatorFactory,
contractCreationProcessor,
messageCallProcessor,
true,
true,
evmConfiguration.evmStackSize(),
feeMarket,
CoinbaseFeePriceCalculator.frontier()))
MainnetTransactionProcessor.builder()
.gasCalculator(gasCalculator)
.transactionValidatorFactory(transactionValidatorFactory)
.contractCreationProcessor(contractCreationProcessor)
.messageCallProcessor(messageCallProcessor)
.clearEmptyAccounts(true)
.warmCoinbase(true)
.maxStackSize(evmConfiguration.evmStackSize())
.feeMarket(feeMarket)
.coinbaseFeePriceCalculator(CoinbaseFeePriceCalculator.frontier())
.build())
.name("Spiral");
}
}

View File

@@ -136,16 +136,17 @@ public abstract class MainnetProtocolSpecs {
transactionValidatorFactory,
contractCreationProcessor,
messageCallProcessor) ->
new MainnetTransactionProcessor(
gasCalculator,
transactionValidatorFactory,
contractCreationProcessor,
messageCallProcessor,
false,
false,
evmConfiguration.evmStackSize(),
FeeMarket.legacy(),
CoinbaseFeePriceCalculator.frontier()))
MainnetTransactionProcessor.builder()
.gasCalculator(gasCalculator)
.transactionValidatorFactory(transactionValidatorFactory)
.contractCreationProcessor(contractCreationProcessor)
.messageCallProcessor(messageCallProcessor)
.clearEmptyAccounts(false)
.warmCoinbase(false)
.maxStackSize(evmConfiguration.evmStackSize())
.feeMarket(FeeMarket.legacy())
.coinbaseFeePriceCalculator(CoinbaseFeePriceCalculator.frontier())
.build())
.privateTransactionProcessorBuilder(
(transactionValidatorFactory,
contractCreationProcessor,
@@ -297,16 +298,17 @@ public abstract class MainnetProtocolSpecs {
transactionValidator,
contractCreationProcessor,
messageCallProcessor) ->
new MainnetTransactionProcessor(
gasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor,
true,
false,
evmConfiguration.evmStackSize(),
feeMarket,
CoinbaseFeePriceCalculator.frontier()))
MainnetTransactionProcessor.builder()
.gasCalculator(gasCalculator)
.transactionValidatorFactory(transactionValidator)
.contractCreationProcessor(contractCreationProcessor)
.messageCallProcessor(messageCallProcessor)
.clearEmptyAccounts(true)
.warmCoinbase(false)
.maxStackSize(evmConfiguration.evmStackSize())
.feeMarket(feeMarket)
.coinbaseFeePriceCalculator(CoinbaseFeePriceCalculator.frontier())
.build())
.name("SpuriousDragon");
}
@@ -503,16 +505,17 @@ public abstract class MainnetProtocolSpecs {
transactionValidatorFactory,
contractCreationProcessor,
messageCallProcessor) ->
new MainnetTransactionProcessor(
gasCalculator,
transactionValidatorFactory,
contractCreationProcessor,
messageCallProcessor,
true,
false,
evmConfiguration.evmStackSize(),
feeMarket,
CoinbaseFeePriceCalculator.eip1559()))
MainnetTransactionProcessor.builder()
.gasCalculator(gasCalculator)
.transactionValidatorFactory(transactionValidatorFactory)
.contractCreationProcessor(contractCreationProcessor)
.messageCallProcessor(messageCallProcessor)
.clearEmptyAccounts(true)
.warmCoinbase(false)
.maxStackSize(evmConfiguration.evmStackSize())
.feeMarket(feeMarket)
.coinbaseFeePriceCalculator(CoinbaseFeePriceCalculator.eip1559())
.build())
.contractCreationProcessorBuilder(
evm ->
new ContractCreationProcessor(
@@ -635,16 +638,17 @@ public abstract class MainnetProtocolSpecs {
transactionValidatorFactory,
contractCreationProcessor,
messageCallProcessor) ->
new MainnetTransactionProcessor(
gasCalculator,
transactionValidatorFactory,
contractCreationProcessor,
messageCallProcessor,
true,
true,
evmConfiguration.evmStackSize(),
feeMarket,
CoinbaseFeePriceCalculator.eip1559()))
MainnetTransactionProcessor.builder()
.gasCalculator(gasCalculator)
.transactionValidatorFactory(transactionValidatorFactory)
.contractCreationProcessor(contractCreationProcessor)
.messageCallProcessor(messageCallProcessor)
.clearEmptyAccounts(true)
.warmCoinbase(true)
.maxStackSize(evmConfiguration.evmStackSize())
.feeMarket(feeMarket)
.coinbaseFeePriceCalculator(CoinbaseFeePriceCalculator.eip1559())
.build())
// Contract creation rules for EIP-3860 Limit and meter intitcode
.transactionValidatorFactoryBuilder(
(evm, gasLimitCalculator, feeMarket) ->
@@ -722,18 +726,20 @@ public abstract class MainnetProtocolSpecs {
transactionValidator,
contractCreationProcessor,
messageCallProcessor) ->
new MainnetTransactionProcessor(
gasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor,
true,
true,
evmConfiguration.evmStackSize(),
feeMarket,
CoinbaseFeePriceCalculator.eip1559(),
new CodeDelegationProcessor(
chainId, SIGNATURE_ALGORITHM.get().getHalfCurveOrder())))
MainnetTransactionProcessor.builder()
.gasCalculator(gasCalculator)
.transactionValidatorFactory(transactionValidator)
.contractCreationProcessor(contractCreationProcessor)
.messageCallProcessor(messageCallProcessor)
.clearEmptyAccounts(true)
.warmCoinbase(true)
.maxStackSize(evmConfiguration.evmStackSize())
.feeMarket(feeMarket)
.coinbaseFeePriceCalculator(CoinbaseFeePriceCalculator.eip1559())
.codeDelegationProcessor(
new CodeDelegationProcessor(
chainId, SIGNATURE_ALGORITHM.get().getHalfCurveOrder()))
.build())
// change to check for max blob gas per block for EIP-4844
.transactionValidatorFactoryBuilder(
(evm, gasLimitCalculator, feeMarket) ->

View File

@@ -41,6 +41,8 @@ import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.processor.AbstractMessageProcessor;
import org.hyperledger.besu.evm.processor.ContractCreationProcessor;
import org.hyperledger.besu.evm.processor.MessageCallProcessor;
import org.hyperledger.besu.evm.tracing.OperationTracer;
import org.hyperledger.besu.evm.worldstate.EVMWorldUpdater;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
@@ -68,9 +70,9 @@ public class MainnetTransactionProcessor {
protected final TransactionValidatorFactory transactionValidatorFactory;
private final AbstractMessageProcessor contractCreationProcessor;
private final ContractCreationProcessor contractCreationProcessor;
private final AbstractMessageProcessor messageCallProcessor;
private final MessageCallProcessor messageCallProcessor;
private final int maxStackSize;
@@ -83,34 +85,11 @@ public class MainnetTransactionProcessor {
private final Optional<CodeDelegationProcessor> maybeCodeDelegationProcessor;
public MainnetTransactionProcessor(
private MainnetTransactionProcessor(
final GasCalculator gasCalculator,
final TransactionValidatorFactory transactionValidatorFactory,
final AbstractMessageProcessor contractCreationProcessor,
final AbstractMessageProcessor messageCallProcessor,
final boolean clearEmptyAccounts,
final boolean warmCoinbase,
final int maxStackSize,
final FeeMarket feeMarket,
final CoinbaseFeePriceCalculator coinbaseFeePriceCalculator) {
this(
gasCalculator,
transactionValidatorFactory,
contractCreationProcessor,
messageCallProcessor,
clearEmptyAccounts,
warmCoinbase,
maxStackSize,
feeMarket,
coinbaseFeePriceCalculator,
null);
}
public MainnetTransactionProcessor(
final GasCalculator gasCalculator,
final TransactionValidatorFactory transactionValidatorFactory,
final AbstractMessageProcessor contractCreationProcessor,
final AbstractMessageProcessor messageCallProcessor,
final ContractCreationProcessor contractCreationProcessor,
final MessageCallProcessor messageCallProcessor,
final boolean clearEmptyAccounts,
final boolean warmCoinbase,
final int maxStackSize,
@@ -500,11 +479,8 @@ public class MainnetTransactionProcessor {
// Refund the sender by what we should and pay the miner fee (note that we're doing them one
// after the other so that if it is the same account somehow, we end up with the right result)
final long selfDestructRefund =
gasCalculator.getSelfDestructRefundAmount() * initialFrame.getSelfDestructs().size();
final long baseRefundGas =
initialFrame.getGasRefund() + selfDestructRefund + codeDelegationRefund;
final long refundedGas = refunded(transaction, initialFrame.getRemainingGas(), baseRefundGas);
final long refundedGas =
gasCalculator.calculateGasRefund(transaction, initialFrame, codeDelegationRefund);
final Wei refundedWei = transactionGasPrice.multiply(refundedGas);
final Wei balancePriorToRefund = sender.getBalance();
sender.incrementBalance(refundedWei);
@@ -635,13 +611,8 @@ public class MainnetTransactionProcessor {
};
}
protected long refunded(
final Transaction transaction, final long gasRemaining, final long gasRefund) {
// Integer truncation takes care of the floor calculation needed after the divide.
final long maxRefundAllowance =
(transaction.getGasLimit() - gasRemaining) / gasCalculator.getMaxRefundQuotient();
final long refundAllowance = Math.min(maxRefundAllowance, gasRefund);
return gasRemaining + refundAllowance;
public MessageCallProcessor getMessageCallProcessor() {
return messageCallProcessor;
}
private String printableStackTraceFromThrowable(final RuntimeException re) {
@@ -653,4 +624,103 @@ public class MainnetTransactionProcessor {
return builder.toString();
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private GasCalculator gasCalculator;
private TransactionValidatorFactory transactionValidatorFactory;
private ContractCreationProcessor contractCreationProcessor;
private MessageCallProcessor messageCallProcessor;
private boolean clearEmptyAccounts;
private boolean warmCoinbase;
private int maxStackSize;
private FeeMarket feeMarket;
private CoinbaseFeePriceCalculator coinbaseFeePriceCalculator;
private CodeDelegationProcessor codeDelegationProcessor;
public Builder gasCalculator(final GasCalculator gasCalculator) {
this.gasCalculator = gasCalculator;
return this;
}
public Builder transactionValidatorFactory(
final TransactionValidatorFactory transactionValidatorFactory) {
this.transactionValidatorFactory = transactionValidatorFactory;
return this;
}
public Builder contractCreationProcessor(
final ContractCreationProcessor contractCreationProcessor) {
this.contractCreationProcessor = contractCreationProcessor;
return this;
}
public Builder messageCallProcessor(final MessageCallProcessor messageCallProcessor) {
this.messageCallProcessor = messageCallProcessor;
return this;
}
public Builder clearEmptyAccounts(final boolean clearEmptyAccounts) {
this.clearEmptyAccounts = clearEmptyAccounts;
return this;
}
public Builder warmCoinbase(final boolean warmCoinbase) {
this.warmCoinbase = warmCoinbase;
return this;
}
public Builder maxStackSize(final int maxStackSize) {
this.maxStackSize = maxStackSize;
return this;
}
public Builder feeMarket(final FeeMarket feeMarket) {
this.feeMarket = feeMarket;
return this;
}
public Builder coinbaseFeePriceCalculator(
final CoinbaseFeePriceCalculator coinbaseFeePriceCalculator) {
this.coinbaseFeePriceCalculator = coinbaseFeePriceCalculator;
return this;
}
public Builder codeDelegationProcessor(
final CodeDelegationProcessor maybeCodeDelegationProcessor) {
this.codeDelegationProcessor = maybeCodeDelegationProcessor;
return this;
}
public Builder populateFrom(final MainnetTransactionProcessor processor) {
this.gasCalculator = processor.gasCalculator;
this.transactionValidatorFactory = processor.transactionValidatorFactory;
this.contractCreationProcessor = processor.contractCreationProcessor;
this.messageCallProcessor = processor.messageCallProcessor;
this.clearEmptyAccounts = processor.clearEmptyAccounts;
this.warmCoinbase = processor.warmCoinbase;
this.maxStackSize = processor.maxStackSize;
this.feeMarket = processor.feeMarket;
this.coinbaseFeePriceCalculator = processor.coinbaseFeePriceCalculator;
this.codeDelegationProcessor = processor.maybeCodeDelegationProcessor.orElse(null);
return this;
}
public MainnetTransactionProcessor build() {
return new MainnetTransactionProcessor(
gasCalculator,
transactionValidatorFactory,
contractCreationProcessor,
messageCallProcessor,
clearEmptyAccounts,
warmCoinbase,
maxStackSize,
feeMarket,
coinbaseFeePriceCalculator,
codeDelegationProcessor);
}
}
}

View File

@@ -41,6 +41,8 @@ import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.evm.precompile.PrecompileContractRegistry;
import org.hyperledger.besu.evm.processor.AbstractMessageProcessor;
import org.hyperledger.besu.evm.processor.ContractCreationProcessor;
import org.hyperledger.besu.evm.processor.MessageCallProcessor;
import java.util.Optional;
import java.util.function.BiFunction;
@@ -62,10 +64,10 @@ public class ProtocolSpecBuilder {
private Function<FeeMarket, BlockHeaderValidator.Builder> blockHeaderValidatorBuilder;
private Function<FeeMarket, BlockHeaderValidator.Builder> ommerHeaderValidatorBuilder;
private Function<ProtocolSchedule, BlockBodyValidator> blockBodyValidatorBuilder;
private Function<EVM, AbstractMessageProcessor> contractCreationProcessorBuilder;
private Function<EVM, ContractCreationProcessor> contractCreationProcessorBuilder;
private Function<PrecompiledContractConfiguration, PrecompileContractRegistry>
precompileContractRegistryBuilder;
private BiFunction<EVM, PrecompileContractRegistry, AbstractMessageProcessor>
private BiFunction<EVM, PrecompileContractRegistry, MessageCallProcessor>
messageCallProcessorBuilder;
private TransactionProcessorBuilder transactionProcessorBuilder;
@@ -158,7 +160,7 @@ public class ProtocolSpecBuilder {
}
public ProtocolSpecBuilder contractCreationProcessorBuilder(
final Function<EVM, AbstractMessageProcessor> contractCreationProcessorBuilder) {
final Function<EVM, ContractCreationProcessor> contractCreationProcessorBuilder) {
this.contractCreationProcessorBuilder = contractCreationProcessorBuilder;
return this;
}
@@ -180,7 +182,7 @@ public class ProtocolSpecBuilder {
}
public ProtocolSpecBuilder messageCallProcessorBuilder(
final BiFunction<EVM, PrecompileContractRegistry, AbstractMessageProcessor>
final BiFunction<EVM, PrecompileContractRegistry, MessageCallProcessor>
messageCallProcessorBuilder) {
this.messageCallProcessorBuilder = messageCallProcessorBuilder;
return this;
@@ -330,11 +332,11 @@ public class ProtocolSpecBuilder {
new PrecompiledContractConfiguration(gasCalculator, privacyParameters);
final TransactionValidatorFactory transactionValidatorFactory =
transactionValidatorFactoryBuilder.apply(evm, gasLimitCalculator, feeMarket);
final AbstractMessageProcessor contractCreationProcessor =
final ContractCreationProcessor contractCreationProcessor =
contractCreationProcessorBuilder.apply(evm);
final PrecompileContractRegistry precompileContractRegistry =
precompileContractRegistryBuilder.apply(precompiledContractConfiguration);
final AbstractMessageProcessor messageCallProcessor =
final MessageCallProcessor messageCallProcessor =
messageCallProcessorBuilder.apply(evm, precompileContractRegistry);
final MainnetTransactionProcessor transactionProcessor =
transactionProcessorBuilder.apply(
@@ -469,8 +471,8 @@ public class ProtocolSpecBuilder {
GasCalculator gasCalculator,
FeeMarket feeMarket,
TransactionValidatorFactory transactionValidatorFactory,
AbstractMessageProcessor contractCreationProcessor,
AbstractMessageProcessor messageCallProcessor);
ContractCreationProcessor contractCreationProcessor,
MessageCallProcessor messageCallProcessor);
}
public interface PrivateTransactionProcessorBuilder {

View File

@@ -0,0 +1,85 @@
/*
* Copyright contributors to Besu.
*
* 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.ethereum.transaction;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.StateOverrideMap;
import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader;
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.evm.processor.OverriddenPrecompilesMessageCallProcessor;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
public class SimulationTransactionProcessorFactory {
private final ProtocolSchedule protocolSchedule;
/**
* Creates a factory capable of producing transaction processors.
*
* @param protocolSchedule the protocol schedule used for creating processors
*/
public SimulationTransactionProcessorFactory(final ProtocolSchedule protocolSchedule) {
this.protocolSchedule = protocolSchedule;
}
/**
* Creates a transaction processor, optionally applying state overrides.
*
* @param processableHeader the block header to process transactions against
* @param maybeStateOverrides optional state overrides for simulation
* @return a transaction processor, with overrides applied if provided
*/
public MainnetTransactionProcessor getTransactionProcessor(
final ProcessableBlockHeader processableHeader,
final Optional<StateOverrideMap> maybeStateOverrides) {
MainnetTransactionProcessor baseProcessor =
protocolSchedule.getByBlockHeader(processableHeader).getTransactionProcessor();
return maybeStateOverrides
.flatMap(this::extractPrecompileAddressOverrides)
.map(
precompileOverrides -> createProcessorWithOverrides(baseProcessor, precompileOverrides))
.orElse(baseProcessor);
}
private Optional<Map<Address, Address>> extractPrecompileAddressOverrides(
final StateOverrideMap stateOverrides) {
Map<Address, Address> addressOverrides =
stateOverrides.entrySet().stream()
.filter(entry -> entry.getValue().getMovePrecompileToAddress().isPresent())
.collect(
Collectors.toMap(
Map.Entry::getKey,
entry -> entry.getValue().getMovePrecompileToAddress().get()));
return addressOverrides.isEmpty() ? Optional.empty() : Optional.of(addressOverrides);
}
private MainnetTransactionProcessor createProcessorWithOverrides(
final MainnetTransactionProcessor baseProcessor,
final Map<Address, Address> precompileAddressOverrides) {
return MainnetTransactionProcessor.builder()
.populateFrom(baseProcessor)
.messageCallProcessor(
new OverriddenPrecompilesMessageCallProcessor(
baseProcessor.getMessageCallProcessor(), precompileAddressOverrides))
.build();
}
}

View File

@@ -87,6 +87,7 @@ public class TransactionSimulator {
private final WorldStateArchive worldStateArchive;
private final ProtocolSchedule protocolSchedule;
private final MiningConfiguration miningConfiguration;
private final SimulationTransactionProcessorFactory simulationTransactionProcessorFactory;
private final long rpcGasCap;
public TransactionSimulator(
@@ -100,6 +101,8 @@ public class TransactionSimulator {
this.protocolSchedule = protocolSchedule;
this.miningConfiguration = miningConfiguration;
this.rpcGasCap = rpcGasCap;
this.simulationTransactionProcessorFactory =
new SimulationTransactionProcessorFactory(protocolSchedule);
}
public Optional<TransactionSimulatorResult> process(
@@ -402,8 +405,9 @@ public class TransactionSimulator {
final long simulationGasCap =
calculateSimulationGasCap(callParams.getGasLimit(), blockHeaderToProcess.getGasLimit());
final MainnetTransactionProcessor transactionProcessor =
protocolSchedule.getByBlockHeader(blockHeaderToProcess).getTransactionProcessor();
MainnetTransactionProcessor transactionProcessor =
simulationTransactionProcessorFactory.getTransactionProcessor(
processableHeader, maybeStateOverrides);
final Optional<BlockHeader> maybeParentHeader =
blockchain.getBlockHeader(blockHeaderToProcess.getParentHash());

View File

@@ -218,9 +218,10 @@ public class DebugOperationTracer implements OperationTracer {
return Optional.empty();
}
try {
final Map<UInt256, UInt256> storageContents =
new TreeMap<>(
frame.getWorldUpdater().getAccount(frame.getRecipientAddress()).getUpdatedStorage());
Map<UInt256, UInt256> updatedStorage =
frame.getWorldUpdater().getAccount(frame.getRecipientAddress()).getUpdatedStorage();
if (updatedStorage.isEmpty()) return Optional.empty();
final Map<UInt256, UInt256> storageContents = new TreeMap<>(updatedStorage);
return Optional.of(storageContents);
} catch (final ModificationNotAllowedException e) {
@@ -229,7 +230,7 @@ public class DebugOperationTracer implements OperationTracer {
}
private Optional<Bytes[]> captureMemory(final MessageFrame frame) {
if (!options.isMemoryEnabled()) {
if (!options.isMemoryEnabled() || frame.memoryWordSize() == 0) {
return Optional.empty();
}
final Bytes[] memoryContents = new Bytes[frame.memoryWordSize()];

View File

@@ -290,7 +290,7 @@ final class GenesisStateTest {
assertThat(header.getHash())
.isEqualTo(
Hash.fromHexString(
"0x554807b22674e6d335f734485993857bbad7a9543affb0663a10c14d78135ec7"));
"0x5d2d02fce02d1b7ca635ec91a4fe6f7aa36f9b3997ec4304e8c68d8f6f15d266"));
assertThat(header.getGasLimit()).isEqualTo(0x2fefd8);
assertThat(header.getGasUsed()).isZero();
assertThat(header.getNumber()).isZero();
@@ -330,7 +330,7 @@ final class GenesisStateTest {
assertThat(header.getRequestsHash().get())
.isEqualTo(
Hash.fromHexString(
"0x6036c41849da9c076ed79654d434017387a88fb833c2856b32e18218b3341c5f"));
"0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"));
}
@Test

View File

@@ -34,7 +34,8 @@ import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.gascalculator.LondonGasCalculator;
import org.hyperledger.besu.evm.log.Log;
import org.hyperledger.besu.evm.processor.AbstractMessageProcessor;
import org.hyperledger.besu.evm.processor.ContractCreationProcessor;
import org.hyperledger.besu.evm.processor.MessageCallProcessor;
import org.hyperledger.besu.evm.tracing.OperationTracer;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.evm.worldstate.WorldView;
@@ -67,8 +68,8 @@ class MainnetTransactionProcessorTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private TransactionValidatorFactory transactionValidatorFactory;
@Mock private AbstractMessageProcessor contractCreationProcessor;
@Mock private AbstractMessageProcessor messageCallProcessor;
@Mock private ContractCreationProcessor contractCreationProcessor;
@Mock private MessageCallProcessor messageCallProcessor;
@Mock private WorldUpdater worldState;
@Mock private ProcessableBlockHeader blockHeader;
@@ -79,17 +80,19 @@ class MainnetTransactionProcessorTest {
@Mock private MutableAccount receiverAccount;
MainnetTransactionProcessor createTransactionProcessor(final boolean warmCoinbase) {
return new MainnetTransactionProcessor(
gasCalculator,
transactionValidatorFactory,
contractCreationProcessor,
messageCallProcessor,
false,
warmCoinbase,
MAX_STACK_SIZE,
FeeMarket.legacy(),
CoinbaseFeePriceCalculator.frontier(),
new CodeDelegationProcessor(Optional.of(BigInteger.ONE), BigInteger.TEN));
return MainnetTransactionProcessor.builder()
.gasCalculator(gasCalculator)
.transactionValidatorFactory(transactionValidatorFactory)
.contractCreationProcessor(contractCreationProcessor)
.messageCallProcessor(messageCallProcessor)
.clearEmptyAccounts(false)
.warmCoinbase(warmCoinbase)
.maxStackSize(MAX_STACK_SIZE)
.feeMarket(FeeMarket.legacy())
.coinbaseFeePriceCalculator(CoinbaseFeePriceCalculator.frontier())
.codeDelegationProcessor(
new CodeDelegationProcessor(Optional.of(BigInteger.ONE), BigInteger.TEN))
.build();
}
@Test

View File

@@ -0,0 +1,91 @@
/*
* Copyright contributors to Besu.
*
* 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.ethereum.transaction;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.StateOverride;
import org.hyperledger.besu.datatypes.StateOverrideMap;
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.evm.EVM;
import org.hyperledger.besu.evm.precompile.PrecompileContractRegistry;
import org.hyperledger.besu.evm.precompile.PrecompiledContract;
import org.hyperledger.besu.evm.processor.MessageCallProcessor;
import java.util.Optional;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class SimulationTransactionProcessorFactoryTest {
private SimulationTransactionProcessorFactory factory;
private final Address originalPrecompileAddress = Address.fromHexString("0x1");
private final Address newPrecompileAddress = Address.fromHexString("0x2");
@BeforeEach
void setUp() {
ProtocolSpec protocolSpec = mock(ProtocolSpec.class);
ProtocolSchedule protocolSchedule = mock(ProtocolSchedule.class);
when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
PrecompileContractRegistry precompileContractRegistry = new PrecompileContractRegistry();
precompileContractRegistry.put(originalPrecompileAddress, mock(PrecompiledContract.class));
MainnetTransactionProcessor mainnetTransactionProcessor =
MainnetTransactionProcessor.builder()
.messageCallProcessor(
new MessageCallProcessor(mock(EVM.class), precompileContractRegistry))
.build();
when(protocolSpec.getTransactionProcessor()).thenReturn(mainnetTransactionProcessor);
factory = new SimulationTransactionProcessorFactory(protocolSchedule);
}
@Test
void shouldReturnProcessorWithOriginalPrecompileAddressesIfNoOverrides() {
MainnetTransactionProcessor simulationTransactionProcessor =
factory.getTransactionProcessor(null, Optional.empty());
Set<Address> precompileAddresses =
simulationTransactionProcessor.getMessageCallProcessor().getPrecompileAddresses();
assertThat(precompileAddresses).containsExactlyInAnyOrder(originalPrecompileAddress);
}
@Test
void shouldReturnProcessorWithNewPrecompileAddressesWithOverrides() {
StateOverrideMap stateOverrideMap = new StateOverrideMap();
stateOverrideMap.put(
originalPrecompileAddress,
new StateOverride.Builder().withMovePrecompileToAddress(newPrecompileAddress).build());
MainnetTransactionProcessor simulationTransactionProcessor =
factory.getTransactionProcessor(null, Optional.of(stateOverrideMap));
Set<Address> precompileAddresses =
simulationTransactionProcessor.getMessageCallProcessor().getPrecompileAddresses();
assertThat(precompileAddresses).containsExactlyInAnyOrder(newPrecompileAddress);
}
}

View File

@@ -546,7 +546,12 @@ public class T8nExecutor {
ArrayNode requests = resultObject.putArray("requests");
maybeRequests
.orElseGet(List::of)
.forEach(request -> requests.add(request.getData().toHexString()));
.forEach(
request -> {
if (!request.data().isEmpty()) {
requests.add(request.getEncodedRequest().toHexString());
}
});
}
worldState.persist(blockHeader);

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Configuration level="WARN">
<Properties>
<Property name="root.log.level">INFO</Property>
</Properties>

File diff suppressed because one or more lines are too long

View File

@@ -189,14 +189,6 @@
"balance": "0x0",
"nonce": "0x1"
},
"0x0f792be4b0c0cb4dae440ef133e90c0ecd48cccc":{
"code":"0x3373fffffffffffffffffffffffffffffffffffffffe14604657602036036042575f35600143038111604257611fff81430311604257611fff9006545f5260205ff35b5f5ffd5b5f35611fff60014303065500",
"storage":{
"0x0000000000000000000000000000000000000000000000000000000000000000":"0x10715cfbefdb8a0cb2f7d7ca5ee6d1ea65515ecb41cff0a22d1e11716a9d27fb"
},
"balance":"0x0",
"nonce":"0x1"
},
"0x0c15f14308530b7cdb8460094bbb9cc28b9aaaaa": {
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe1460cb5760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146101f457600182026001905f5b5f82111560685781019083028483029004916001019190604d565b909390049250505036603814608857366101f457346101f4575f5260205ff35b34106101f457600154600101600155600354806003026004013381556001015f35815560010160203590553360601b5f5260385f601437604c5fa0600101600355005b6003546002548082038060101160df575060105b5f5b8181146101835782810160030260040181604c02815460601b8152601401816001015481526020019060020154807fffffffffffffffffffffffffffffffff00000000000000000000000000000000168252906010019060401c908160381c81600701538160301c81600601538160281c81600501538160201c81600401538160181c81600301538160101c81600201538160081c81600101535360010160e1565b910180921461019557906002556101a0565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14156101cd57505f5b6001546002828201116101e25750505f6101e8565b01600290035b5f555f600155604c025ff35b5f5ffd",
"storage": {
@@ -206,6 +198,14 @@
"balance": "0x1",
"nonce": "0x1"
},
"0x0f792be4b0c0cb4dae440ef133e90c0ecd48cccc": {
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604657602036036042575f35600143038111604257611fff81430311604257611fff9006545f5260205ff35b5f5ffd5b5f35611fff60014303065500",
"storage": {
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x10715cfbefdb8a0cb2f7d7ca5ee6d1ea65515ecb41cff0a22d1e11716a9d27fb"
},
"balance": "0x0",
"nonce": "0x1"
},
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
"balance": "0xad78ebc5ac61f2b034",
"nonce": "0x1"
@@ -213,11 +213,9 @@
},
"body": "0xf89bf8998007830f424094000000000000000000000000000000000000100080b838000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000026a0d050db98a60dbe4bbbc6ce154c607f28f1cf803a8882f369b28a5eb4ef1a600fa07512ca5133bcb887a41f6136cd645839c1bcf0f300325948387a70f3ad9ced1c",
"result": {
"requestsHash": "0xab205d558af6253557180e19e89356ed4c7d4b13615ee9560840af3df75ddb12",
"requestsHash": "0x16a372318fd60f169dd3e1e2e528d1fb17edc62e741feebcb0896f950018769a",
"requests": [
"0x",
"0x00000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000",
"0x"
"0x0100000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000"
],
"stateRoot": "0xc7b49e4aef4229962b94ec0a7c83a6fc0b4015f2573b9a85446ed434c823164e",
"txRoot": "0x0d36638e52999b7beafa00eb94f7ca23139774cd14229c011d0edc1fc66125c9",

View File

@@ -29,12 +29,15 @@ import java.util.Optional;
import com.google.common.net.InetAddresses;
import org.apache.tuweni.bytes.Bytes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Encapsulates the network coordinates of a {@link DiscoveryPeer} as well as serialization logic
* used in various Discovery messages.
*/
public class Endpoint {
private static final Logger LOG = LoggerFactory.getLogger(Endpoint.class);
private final Optional<String> host;
private final int udpPort;
private final Optional<Integer> tcpPort;
@@ -49,15 +52,16 @@ public class Endpoint {
}
public static Endpoint fromEnode(final EnodeURL enode) {
final int discoveryPort =
enode
.getDiscoveryPort()
.orElseThrow(
() ->
new IllegalArgumentException(
"Attempt to create a discovery endpoint for an enode with discovery disabled."));
Optional<Integer> discoveryPort = enode.getDiscoveryPort();
if (discoveryPort.isEmpty()) {
int defaultPort = EnodeURLImpl.DEFAULT_LISTENING_PORT;
LOG.debug("Discovery disabled for enode {}. Using default port {}.", enode, defaultPort);
return new Endpoint(enode.getIp().getHostAddress(), defaultPort, Optional.empty());
}
final Optional<Integer> listeningPort = enode.getListeningPort();
return new Endpoint(enode.getIp().getHostAddress(), discoveryPort, listeningPort);
return new Endpoint(enode.getIp().getHostAddress(), discoveryPort.get(), listeningPort);
}
public EnodeURL toEnode(final Bytes nodeId) {

View File

@@ -18,6 +18,7 @@ import static java.util.stream.Collectors.toList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
@@ -45,6 +46,8 @@ import org.hyperledger.besu.ethereum.p2p.permissions.PeerPermissions.Action;
import org.hyperledger.besu.ethereum.p2p.permissions.PeerPermissionsDenylist;
import org.hyperledger.besu.plugin.data.EnodeURL;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@@ -898,6 +901,23 @@ public class PeerDiscoveryAgentTest {
assertThat(PeerDiscoveryAgent.deriveHost(source, mockWellFormed)).isEqualTo(routableHost);
}
@Test
void testFromEnodeWithDiscoveryDisabled() throws UnknownHostException {
EnodeURL enodeWithNoDiscovery = mock(EnodeURL.class);
when(enodeWithNoDiscovery.getDiscoveryPort()).thenReturn(Optional.empty());
when(enodeWithNoDiscovery.getListeningPort()).thenReturn(Optional.of(8545));
when(enodeWithNoDiscovery.getIp()).thenReturn(InetAddress.getLoopbackAddress());
Endpoint result = Endpoint.fromEnode(enodeWithNoDiscovery);
assertEquals("127.0.0.1", result.getHost());
assertEquals(EnodeURLImpl.DEFAULT_LISTENING_PORT, result.getUdpPort());
assertEquals(Optional.empty(), result.getTcpPort());
}
protected void bondViaIncomingPing(
final MockPeerDiscoveryAgent agent, final MockPeerDiscoveryAgent otherNode) {
final Packet pingPacket = helper.createPingPacket(otherNode, agent);

View File

@@ -22,7 +22,6 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMer
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.NoOpBonsaiCachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiPreImageProxy;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateLayerStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.common.cache.DiffBasedCachedWorldStorageManager;
@@ -38,6 +37,8 @@ import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.plugin.services.trielogs.TrieLog;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;
@@ -47,13 +48,18 @@ import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BonsaiReferenceTestWorldState extends BonsaiWorldState
implements ReferenceTestWorldState {
private static final Logger LOG = LoggerFactory.getLogger(BonsaiReferenceTestWorldState.class);
private final BonsaiReferenceTestWorldStateStorage refTestStorage;
private final BonsaiPreImageProxy preImageProxy;
private final EvmConfiguration evmConfiguration;
private final Collection<Exception> exceptionCollector = new ArrayList<>();
protected BonsaiReferenceTestWorldState(
final BonsaiReferenceTestWorldStateStorage worldStateKeyValueStorage,
@@ -110,7 +116,8 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
}
@Override
public void processExtraStateStorageFormatValidation(final BlockHeader blockHeader) {
public Collection<Exception> processExtraStateStorageFormatValidation(
final BlockHeader blockHeader) {
if (blockHeader != null) {
final Hash parentStateRoot = getWorldStateRootHash();
final BonsaiReferenceTestUpdateAccumulator originalUpdater =
@@ -121,6 +128,7 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
// validate trielog generation with frozen state
validateStateRolling(parentStateRoot, originalUpdater, blockHeader, true);
}
return exceptionCollector;
}
/**
@@ -156,9 +164,12 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
bonsaiWorldState.persist(blockHeader);
Hash generatedRootHash = bonsaiWorldState.rootHash();
if (!bonsaiWorldState.rootHash().equals(blockHeader.getStateRoot())) {
throw new RuntimeException(
final String msg =
"state root becomes invalid following a rollForward %s != %s"
.formatted(blockHeader.getStateRoot(), generatedRootHash));
.formatted(blockHeader.getStateRoot(), generatedRootHash);
final RuntimeException e = new RuntimeException(msg);
exceptionCollector.add(e);
LOG.atError().setMessage(msg).setCause(e).log();
}
updaterForState = (BonsaiWorldStateUpdateAccumulator) bonsaiWorldState.updater();
@@ -167,9 +178,12 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
bonsaiWorldState.persist(null);
generatedRootHash = bonsaiWorldState.rootHash();
if (!bonsaiWorldState.rootHash().equals(parentStateRoot)) {
throw new RuntimeException(
final String msg =
"state root becomes invalid following a rollBackward %s != %s"
.formatted(parentStateRoot, generatedRootHash));
.formatted(parentStateRoot, generatedRootHash);
final RuntimeException e = new RuntimeException(msg);
exceptionCollector.add(e);
LOG.atError().setMessage(msg).setCause(e).log();
}
}
}
@@ -189,19 +203,11 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
}
private BonsaiWorldState createBonsaiWorldState(final boolean isFrozen) {
BonsaiWorldState bonsaiWorldState =
new BonsaiWorldState(
new BonsaiWorldStateLayerStorage(
(BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage),
bonsaiCachedMerkleTrieLoader,
cachedWorldStorageManager,
trieLogManager,
evmConfiguration,
new DiffBasedWorldStateConfig());
final BonsaiReferenceTestWorldState copy = (BonsaiReferenceTestWorldState) this.copy();
if (isFrozen) {
bonsaiWorldState.freeze(); // freeze state
copy.freeze();
}
return bonsaiWorldState;
return copy;
}
@JsonCreator

View File

@@ -24,6 +24,8 @@ import org.hyperledger.besu.evm.worldstate.WorldState;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonCreator;
@@ -56,8 +58,10 @@ public class ForestReferenceTestWorldState extends ForestMutableWorldState
* root has been validated, to ensure the integrity of other aspects of the state.
*/
@Override
public void processExtraStateStorageFormatValidation(final BlockHeader blockHeader) {
public Collection<Exception> processExtraStateStorageFormatValidation(
final BlockHeader blockHeader) {
// nothing more to verify with forest
return Collections.emptyList();
}
@JsonCreator

View File

@@ -22,6 +22,7 @@ import org.hyperledger.besu.evm.account.MutableAccount;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@@ -91,7 +92,7 @@ public interface ReferenceTestWorldState extends MutableWorldState {
ReferenceTestWorldState copy();
void processExtraStateStorageFormatValidation(final BlockHeader blockHeader);
Collection<Exception> processExtraStateStorageFormatValidation(final BlockHeader blockHeader);
@JsonCreator
static ReferenceTestWorldState create(final Map<String, AccountMock> accounts) {

View File

@@ -75,6 +75,9 @@ public class StateTestVersionedTransaction {
// String instead of VersionedHash because reference tests intentionally use bad hashes.
private final List<String> blobVersionedHashes;
@JsonDeserialize(contentAs = org.hyperledger.besu.ethereum.core.CodeDelegation.class)
private final List<org.hyperledger.besu.datatypes.CodeDelegation> authorizationList;
/**
* Constructor for populating a mock transaction with json data.
*
@@ -103,7 +106,9 @@ public class StateTestVersionedTransaction {
@JsonDeserialize(using = StateTestAccessListDeserializer.class) @JsonProperty("accessLists")
final List<List<AccessListEntry>> maybeAccessLists,
@JsonProperty("maxFeePerBlobGas") final String maxFeePerBlobGas,
@JsonProperty("blobVersionedHashes") final List<String> blobVersionedHashes) {
@JsonProperty("blobVersionedHashes") final List<String> blobVersionedHashes,
@JsonProperty("authorizationList")
final List<org.hyperledger.besu.datatypes.CodeDelegation> authorizationList) {
this.nonce = Bytes.fromHexStringLenient(nonce).toLong();
this.gasPrice = Optional.ofNullable(gasPrice).map(Wei::fromHexString).orElse(null);
@@ -124,6 +129,7 @@ public class StateTestVersionedTransaction {
this.maxFeePerBlobGas =
Optional.ofNullable(maxFeePerBlobGas).map(Wei::fromHexString).orElse(null);
this.blobVersionedHashes = blobVersionedHashes;
this.authorizationList = authorizationList;
}
private static <T> List<T> parseArray(final String[] array, final Function<String, T> parseFct) {
@@ -170,6 +176,7 @@ public class StateTestVersionedTransaction {
// versioned hash string was bad, so this is an invalid transaction
return null;
}
Optional.ofNullable(authorizationList).ifPresent(transactionBuilder::codeDelegations);
transactionBuilder.guessType();
if (transactionBuilder.getTransactionType().requiresChainId()) {

View File

@@ -22,6 +22,13 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
import org.assertj.core.api.SoftAssertions;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
@@ -42,8 +49,12 @@ import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.log.Log;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.testutil.JsonTestParameters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class GeneralStateReferenceTestTools {
private static final Logger LOG = LoggerFactory.getLogger(GeneralStateReferenceTestTools.class);
private static final List<String> SPECS_PRIOR_TO_DELETING_EMPTY_ACCOUNTS =
Arrays.asList("Frontier", "Homestead", "EIP150");
@@ -179,16 +190,26 @@ public class GeneralStateReferenceTestTools {
worldStateUpdater.deleteAccount(coinbase.getAddress());
}
worldStateUpdater.commit();
worldState.processExtraStateStorageFormatValidation(blockHeader);
Collection<Exception> additionalExceptions = worldState.processExtraStateStorageFormatValidation(blockHeader);
worldState.persist(blockHeader);
// Check the world state root hash.
final Hash expectedRootHash = spec.getExpectedRootHash();
assertThat(worldState.rootHash())
.withFailMessage(
"Unexpected world state root hash; expected state: %s, computed state: %s",
spec.getExpectedRootHash(), worldState.rootHash())
.isEqualTo(expectedRootHash);
// If the root hash doesn't match, first dump the world state for debugging.
if (!expectedRootHash.equals(worldState.rootHash())) {
logWorldState(worldState);
}
SoftAssertions.assertSoftly(
softly -> {
softly.assertThat(worldState.rootHash())
.withFailMessage(
"Unexpected world state root hash; expected state: %s, computed state: %s",
spec.getExpectedRootHash(), worldState.rootHash())
.isEqualTo(expectedRootHash);
additionalExceptions.forEach(
e -> softly.fail("Additional exception during state validation: " + e.getMessage()));
});
// Check the logs.
final Hash expectedLogsHash = spec.getExpectedLogsHash();
@@ -206,4 +227,33 @@ public class GeneralStateReferenceTestTools {
private static boolean shouldClearEmptyAccounts(final String eip) {
return !SPECS_PRIOR_TO_DELETING_EMPTY_ACCOUNTS.contains(eip);
}
private static void logWorldState(final ReferenceTestWorldState worldState) {
ObjectMapper mapper = new ObjectMapper();
ObjectNode worldStateJson = mapper.createObjectNode();
worldState.streamAccounts(Bytes32.ZERO, Integer.MAX_VALUE)
.forEach(
account -> {
ObjectNode accountJson = mapper.createObjectNode();
accountJson.put("nonce", Bytes.ofUnsignedLong(account.getNonce()).toShortHexString());
accountJson.put("balance", account.getBalance().toShortHexString());
accountJson.put("code", account.getCode().toHexString());
ObjectNode storageJson = mapper.createObjectNode();
var storageEntries = account.storageEntriesFrom(Bytes32.ZERO, Integer.MAX_VALUE);
storageEntries.values().stream()
.map(
e ->
Map.entry(
e.getKey().orElse(UInt256.fromBytes(Bytes.EMPTY)),
account.getStorageValue(UInt256.fromBytes(e.getKey().get()))))
.sorted(Map.Entry.comparingByKey())
.forEach(e -> storageJson.put(e.getKey().toQuantityHexString(), e.getValue().toQuantityHexString()));
if (!storageEntries.isEmpty()) {
accountJson.set("storage", storageJson);
}
worldStateJson.set(account.getAddress().orElse(Address.wrap(Bytes.EMPTY)).toHexString(), accountJson);
});
LOG.error("Calculated world state: \n{}", worldStateJson.toPrettyString());
}
}

View File

@@ -21,6 +21,7 @@ import static org.hyperledger.besu.evm.internal.Words.clampedToLong;
import static org.hyperledger.besu.evm.internal.Words.numWords;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Transaction;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.frame.MessageFrame;
@@ -566,4 +567,25 @@ public class FrontierGasCalculator implements GasCalculator {
public long getMinimumTransactionCost() {
return TX_BASE_COST;
}
@Override
public long calculateGasRefund(
final Transaction transaction,
final MessageFrame initialFrame,
final long codeDelegationRefund) {
final long selfDestructRefund =
getSelfDestructRefundAmount() * initialFrame.getSelfDestructs().size();
final long baseRefundGas =
initialFrame.getGasRefund() + selfDestructRefund + codeDelegationRefund;
return refunded(transaction, initialFrame.getRemainingGas(), baseRefundGas);
}
private long refunded(
final Transaction transaction, final long gasRemaining, final long gasRefund) {
// Integer truncation takes care of the floor calculation needed after the divide.
final long maxRefundAllowance =
(transaction.getGasLimit() - gasRemaining) / getMaxRefundQuotient();
final long refundAllowance = Math.min(maxRefundAllowance, gasRefund);
return gasRemaining + refundAllowance;
}
}

View File

@@ -16,6 +16,7 @@ package org.hyperledger.besu.evm.gascalculator;
import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Transaction;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.frame.MessageFrame;
@@ -664,4 +665,15 @@ public interface GasCalculator {
default long calculateDelegateCodeGasRefund(final long alreadyExistingAccountSize) {
return 0L;
}
/**
* Calculate the gas refund for a transaction.
*
* @param transaction the transaction
* @param initialFrame the initial frame
* @param codeDelegationRefund the code delegation refund
* @return the gas refund
*/
long calculateGasRefund(
Transaction transaction, MessageFrame initialFrame, long codeDelegationRefund);
}

View File

@@ -16,8 +16,10 @@ package org.hyperledger.besu.evm.precompile;
import org.hyperledger.besu.datatypes.Address;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/** Encapsulates a group of {@link PrecompiledContract}s used together. */
public class PrecompileContractRegistry {
@@ -48,4 +50,13 @@ public class PrecompileContractRegistry {
public void put(final Address address, final PrecompiledContract precompile) {
precompiles.put(address, precompile);
}
/**
* Gets the addresses of the precompiled contracts.
*
* @return the addresses
*/
public Set<Address> getPrecompileAddresses() {
return Collections.unmodifiableSet(precompiles.keySet());
}
}

View File

@@ -30,6 +30,7 @@ import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import com.google.common.annotations.VisibleForTesting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,7 +38,8 @@ import org.slf4j.LoggerFactory;
public class MessageCallProcessor extends AbstractMessageProcessor {
private static final Logger LOG = LoggerFactory.getLogger(MessageCallProcessor.class);
private final PrecompileContractRegistry precompiles;
/** The precompiles. */
protected final PrecompileContractRegistry precompiles;
/**
* Instantiates a new Message call processor.
@@ -171,4 +173,14 @@ public class MessageCallProcessor extends AbstractMessageProcessor {
frame.setExceptionalHaltReason(result.getHaltReason());
}
}
/**
* Gets the precompile addresses.
*
* @return the precompile addresses
*/
@VisibleForTesting
public Set<Address> getPrecompileAddresses() {
return precompiles.getPrecompileAddresses();
}
}

Some files were not shown because too many files have changed in this diff Show More