Add new JSON_RPC endpoints to get miner data by block number and block hash. (#1538)

* #1066 Switched to use unprefixed hex strings for memory and stack values

Signed-off-by: David Mechler <david.mechler@consensys.net>

* Disable flaky tests per Ben Burns(Yeti) request

Signed-off-by: David Mechler <david.mechler@consensys.net>

* Revert last commit and enable ignored tests.

Signed-off-by: David Mechler <david.mechler@consensys.net>

* #1157 - updated to create 2 agents so that proper bonding can occur

Signed-off-by: David Mechler <david.mechler@consensys.net>

* #1162 - Updated test to mock the local peer PING packet creation so that the hash can be managed.

Signed-off-by: David Mechler <david.mechler@consensys.net>

* Added admin_logsRepairCache end point

Signed-off-by: David Mechler <david.mechler@consensys.net>

* Added admin_logsRepairCache end point

Signed-off-by: David Mechler <david.mechler@consensys.net>

* Remove p2p network code per PR comments

Signed-off-by: David Mechler <david.mechler@consensys.net>

* Updates from PR comments

Signed-off-by: David Mechler <david.mechler@consensys.net>

* Spotless Apply fixes

Signed-off-by: David Mechler <david.mechler@consensys.net>

* PR updates

Signed-off-by: David Mechler <david.mechler@consensys.net>

* Admin force cache refresh when called through end point per PR comments

Signed-off-by: David Mechler <david.mechler@consensys.net>

* Pr updates

Signed-off-by: David Mechler <david.mechler@consensys.net>

* Update changelog for 1.5.1

Signed-off-by: David Mechler <david.mechler@consensys.net>

* Remove check for 0x prefix on addresses to match expectations

Signed-off-by: David Mechler <david.mechler@consensys.net>

* Update graphql pending to allow for sorting of transactions

Signed-off-by: David Mechler <david.mechler@consensys.net>

* #1408 Add Miner data endpoints

Signed-off-by: David Mechler <david.mechler@consensys.net>

* #1408 Add Miner data endpoints

Signed-off-by: David Mechler <david.mechler@consensys.net>

* #1408 Add Miner data endpoints

Signed-off-by: David Mechler <david.mechler@consensys.net>

* #1408 Added tests for new miner endpoints

Signed-off-by: David Mechler <david.mechler@consensys.net>

* #1408 - PR updates

Signed-off-by: David Mechler <david.mechler@consensys.net>

* SpotlessApply updtes

Signed-off-by: David Mechler <david.mechler@consensys.net>

* SpotlessApply updtes

Signed-off-by: David Mechler <david.mechler@consensys.net>

Co-authored-by: David Mechler <davemec@users.noreply.github.com>
pull/1553/head
David Mechler 4 years ago committed by GitHub
parent b9364ed243
commit 67191aac76
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 10
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java
  3. 4
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java
  4. 2
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java
  5. 10
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfiguration.java
  6. 8
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java
  7. 6
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java
  8. 2
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/NodeConfiguration.java
  9. 2
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java
  10. 2
      acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/RevertReasonAcceptanceTest.java
  11. 8
      besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
  12. 6
      besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java
  13. 2
      besu/src/main/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilder.java
  14. 2
      besu/src/main/java/org/hyperledger/besu/controller/IbftBesuControllerBuilder.java
  15. 2
      besu/src/main/java/org/hyperledger/besu/controller/IbftLegacyBesuControllerBuilder.java
  16. 2
      besu/src/main/java/org/hyperledger/besu/controller/MainnetBesuControllerBuilder.java
  17. 2
      besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java
  18. 10
      consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/CliqueProtocolSchedule.java
  19. 8
      consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/IbftProtocolSchedule.java
  20. 8
      consensus/ibftlegacy/src/main/java/org/hyperledger/besu/consensus/ibftlegacy/IbftProtocolSchedule.java
  21. 2
      ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthGetFilterChangesIntegrationTest.java
  22. 2
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java
  23. 8
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractBlockParameterMethod.java
  24. 136
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetMinerDataByBlockHash.java
  25. 71
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetMinerDataByBlockNumber.java
  26. 119
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/MinerDataResult.java
  27. 6
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java
  28. 2
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/StateBackupService.java
  29. 158
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetMinerDataByBlockHashTest.java
  30. 149
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetMinerDataByBlockNumberTest.java
  31. 4
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionReceiptTest.java
  32. 2
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/subscription/logs/LogsSubscriptionServiceTest.java
  33. 3
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_getTransactionReceipt_contractAddress.json
  34. 3
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_getTransactionReceipt_logs.json
  35. 3
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_getTransactionReceipt_nullContractAddress.json
  36. 2
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/BlockTransactionSelectorTest.java
  37. 61
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/TransactionReceipt.java
  38. 8
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/difficulty/fixed/FixedDifficultyProtocolSchedule.java
  39. 12
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicProtocolSpecs.java
  40. 15
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSchedule.java
  41. 15
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java
  42. 54
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java
  43. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStoragePrefixedKeyBlockchainStorage.java
  44. 20
      ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockDataGenerator.java
  45. 2
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchainTest.java
  46. 8
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/TransactionReceiptTest.java
  47. 2
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessorTest.java
  48. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/ReceiptsMessageTest.java
  49. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolTest.java
  50. 4
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/CliqueGenesisFileModule.java
  51. 13
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommandOptionsModule.java
  52. 2
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/GenesisFileModule.java
  53. 2
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/IBFTGenesisFileModule.java
  54. 2
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/MainnetGenesisFileModule.java

@ -11,6 +11,7 @@
* Added EvmTool binary to the distribution. EvmTool is a CLI that can execute EVM bytecode and execute ethereum state tests. [\#1465](https://github.com/hyperledger/besu/pull/1465)
* Updated the libraries for secp256k1 and AltBN series precompiles. These updates provide significant performance improvements to those areas. [\#1499](https://github.com/hyperledger/besu/pull/1499)
* Provide MegaGas/second measurements in the log when doing a full block import, such as the catch up phase of a fast sync. [\#1512](https://github.com/hyperledger/besu/pull/1512)
* Added new endpoints to get miner data, `eth_getMinerDataByBlockHash` and `eth_getMinerDataByBlockNumber`. [\#1538](https://github.com/hyperledger/besu/pull/1538)
### Bug Fixes

@ -84,7 +84,7 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
private final Properties portsProperties = new Properties();
private final Boolean p2pEnabled;
private final NetworkingConfiguration networkingConfiguration;
private final boolean revertReasonEnabled;
private final boolean isMetadataEnabled;
private final String name;
private final MiningParameters miningParameters;
@ -127,7 +127,7 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
final NetworkingConfiguration networkingConfiguration,
final boolean discoveryEnabled,
final boolean bootnodeEligible,
final boolean revertReasonEnabled,
final boolean isMetadataEnabled,
final boolean secp256k1Native,
final boolean altbn128Native,
final List<String> plugins,
@ -159,7 +159,7 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
this.networkingConfiguration = networkingConfiguration;
this.discoveryEnabled = discoveryEnabled;
this.bootnodeEligible = bootnodeEligible;
this.revertReasonEnabled = revertReasonEnabled;
this.isMetadataEnabled = isMetadataEnabled;
this.secp256k1Native = secp256k1Native;
this.altbn128Native = altbn128Native;
this.runCommand = runCommand;
@ -603,8 +603,8 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
}
@Override
public boolean isRevertReasonEnabled() {
return revertReasonEnabled;
public boolean isMetadataEnabled() {
return isMetadataEnabled;
}
@Override

@ -229,8 +229,8 @@ public class ProcessBesuNodeRunner implements BesuNodeRunner {
params.addAll(networkConfigParams);
}
if (node.isRevertReasonEnabled()) {
params.add("--revert-reason-enabled");
if (node.isMetadataEnabled()) {
params.add("--receipt-metadata-enabled");
}
params.add("--Xsecp256k1-native-enabled=" + node.isSecp256k1Native());

@ -159,7 +159,7 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
.transactionPoolConfiguration(TransactionPoolConfiguration.builder().build())
.ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig())
.clock(Clock.systemUTC())
.isRevertReasonEnabled(node.isRevertReasonEnabled())
.isMetadataEnabled(node.isMetadataEnabled())
.storageProvider(storageProvider)
.gasLimitCalculator(GasLimitCalculator.constant())
.build();

@ -43,7 +43,7 @@ public class BesuNodeConfiguration {
private final NetworkingConfiguration networkingConfiguration;
private final boolean discoveryEnabled;
private final boolean bootnodeEligible;
private final boolean revertReasonEnabled;
private final boolean metadataEnabled;
private final boolean secp256k1Native;
private final boolean altbn128Native;
private final List<String> plugins;
@ -68,7 +68,7 @@ public class BesuNodeConfiguration {
final NetworkingConfiguration networkingConfiguration,
final boolean discoveryEnabled,
final boolean bootnodeEligible,
final boolean revertReasonEnabled,
final boolean metadataEnabled,
final boolean secp256k1Native,
final boolean altbn128Native,
final List<String> plugins,
@ -91,7 +91,7 @@ public class BesuNodeConfiguration {
this.networkingConfiguration = networkingConfiguration;
this.discoveryEnabled = discoveryEnabled;
this.bootnodeEligible = bootnodeEligible;
this.revertReasonEnabled = revertReasonEnabled;
this.metadataEnabled = metadataEnabled;
this.secp256k1Native = secp256k1Native;
this.altbn128Native = altbn128Native;
this.plugins = plugins;
@ -166,8 +166,8 @@ public class BesuNodeConfiguration {
return extraCLIOptions;
}
public boolean isRevertReasonEnabled() {
return revertReasonEnabled;
public boolean isMetadataEnabled() {
return metadataEnabled;
}
public boolean isSecp256k1Native() {

@ -54,7 +54,7 @@ public class BesuNodeConfigurationBuilder {
private final NetworkingConfiguration networkingConfiguration = NetworkingConfiguration.create();
private boolean discoveryEnabled = true;
private boolean bootnodeEligible = true;
private boolean revertReasonEnabled = false;
private boolean metadataEnabled = false;
private boolean secp256K1Native = false;
private boolean altbn128Native = false;
private final List<String> plugins = new ArrayList<>();
@ -249,8 +249,8 @@ public class BesuNodeConfigurationBuilder {
return this;
}
public BesuNodeConfigurationBuilder revertReasonEnabled() {
this.revertReasonEnabled = true;
public BesuNodeConfigurationBuilder metadataEnabled() {
this.metadataEnabled = true;
return this;
}
@ -300,7 +300,7 @@ public class BesuNodeConfigurationBuilder {
networkingConfiguration,
discoveryEnabled,
bootnodeEligible,
revertReasonEnabled,
metadataEnabled,
secp256K1Native,
altbn128Native,
plugins,

@ -65,7 +65,7 @@ public class BesuNodeFactory {
config.getNetworkingConfiguration(),
config.isDiscoveryEnabled(),
config.isBootnodeEligible(),
config.isRevertReasonEnabled(),
config.isMetadataEnabled(),
config.isSecp256k1Native(),
config.isAltbn128Native(),
config.getPlugins(),
@ -86,14 +86,14 @@ public class BesuNodeFactory {
.build());
}
public BesuNode createMinerNodeWithRevertReasonEnabled(final String name) throws IOException {
public BesuNode createMinerNodeWithMetadataEnabled(final String name) throws IOException {
return create(
new BesuNodeConfigurationBuilder()
.name(name)
.miningEnabled()
.jsonRpcEnabled()
.webSocketEnabled()
.revertReasonEnabled()
.metadataEnabled()
.build());
}

@ -50,7 +50,7 @@ public interface NodeConfiguration {
List<String> getExtraCLIOptions();
boolean isRevertReasonEnabled();
boolean isMetadataEnabled();
List<String> getStaticNodes();
}

@ -99,7 +99,7 @@ public class PrivacyNode implements AutoCloseable {
besuConfig.getNetworkingConfiguration(),
besuConfig.isDiscoveryEnabled(),
besuConfig.isBootnodeEligible(),
besuConfig.isRevertReasonEnabled(),
besuConfig.isMetadataEnabled(),
besuConfig.isSecp256k1Native(),
besuConfig.isAltbn128Native(),
besuConfig.getPlugins(),

@ -31,7 +31,7 @@ public class RevertReasonAcceptanceTest extends AcceptanceTestBase {
@Before
public void setUp() throws Exception {
minerNode = besu.createMinerNodeWithRevertReasonEnabled("miner-node-withRevertReason");
minerNode = besu.createMinerNodeWithMetadataEnabled("miner-node-withMetadata");
cluster.start(minerNode);
}

@ -865,10 +865,10 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private final Boolean isPrivacyMultiTenancyEnabled = false;
@Option(
names = {"--revert-reason-enabled"},
names = {"--receipt-metadata-enabled", "--revert-reason-enabled"},
description =
"Enable passing the revert reason back through TransactionReceipts (default: ${DEFAULT-VALUE})")
private final Boolean isRevertReasonEnabled = false;
"Enable passing metadata back through TransactionReceipts (default: ${DEFAULT-VALUE})")
private final Boolean isMetadataEnabled = false;
@Option(
names = {"--required-blocks", "--required-block"},
@ -1497,7 +1497,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.metricsSystem(metricsSystem.get())
.privacyParameters(privacyParameters())
.clock(Clock.systemUTC())
.isRevertReasonEnabled(isRevertReasonEnabled)
.isMetadataEnabled(isMetadataEnabled)
.storageProvider(keyStorageProvider(keyValueStorageName))
.isPruningEnabled(isPruningEnabled())
.pruningConfiguration(

@ -90,7 +90,7 @@ public abstract class BesuControllerBuilder {
protected Path dataDirectory;
protected Clock clock;
protected NodeKey nodeKey;
protected boolean isRevertReasonEnabled;
protected boolean isMetadataEnabled;
GasLimitCalculator gasLimitCalculator;
private StorageProvider storageProvider;
private boolean isPruningEnabled;
@ -162,8 +162,8 @@ public abstract class BesuControllerBuilder {
return this;
}
public BesuControllerBuilder isRevertReasonEnabled(final boolean isRevertReasonEnabled) {
this.isRevertReasonEnabled = isRevertReasonEnabled;
public BesuControllerBuilder isMetadataEnabled(final boolean isMetadataEnabled) {
this.isMetadataEnabled = isMetadataEnabled;
return this;
}

@ -112,7 +112,7 @@ public class CliqueBesuControllerBuilder extends BesuControllerBuilder {
genesisConfig.getConfigOptions(genesisConfigOverrides),
nodeKey,
privacyParameters,
isRevertReasonEnabled);
isMetadataEnabled);
}
@Override

@ -215,7 +215,7 @@ public class IbftBesuControllerBuilder extends BesuControllerBuilder {
return IbftProtocolSchedule.create(
genesisConfig.getConfigOptions(genesisConfigOverrides),
privacyParameters,
isRevertReasonEnabled);
isMetadataEnabled);
}
@Override

@ -77,7 +77,7 @@ public class IbftLegacyBesuControllerBuilder extends BesuControllerBuilder {
return IbftProtocolSchedule.create(
genesisConfig.getConfigOptions(genesisConfigOverrides),
privacyParameters,
isRevertReasonEnabled);
isMetadataEnabled);
}
@Override

@ -89,7 +89,7 @@ public class MainnetBesuControllerBuilder extends BesuControllerBuilder {
return MainnetProtocolSchedule.fromConfig(
genesisConfig.getConfigOptions(genesisConfigOverrides),
privacyParameters,
isRevertReasonEnabled);
isMetadataEnabled);
}
@Override

@ -179,7 +179,7 @@ public abstract class CommandTestAbstract {
when(mockControllerBuilder.metricsSystem(any())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.privacyParameters(any())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.clock(any())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.isRevertReasonEnabled(false)).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.isMetadataEnabled(false)).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.storageProvider(any())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.isPruningEnabled(anyBoolean())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.pruningConfiguration(any())).thenReturn(mockControllerBuilder);

@ -44,7 +44,7 @@ public class CliqueProtocolSchedule {
final GenesisConfigOptions config,
final NodeKey nodeKey,
final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) {
final boolean isMetadataEnabled) {
final CliqueConfigOptions cliqueConfig = config.getCliqueConfigOptions();
@ -72,15 +72,13 @@ public class CliqueProtocolSchedule {
builder,
eip1559),
privacyParameters,
isRevertReasonEnabled)
isMetadataEnabled)
.createProtocolSchedule();
}
public static ProtocolSchedule create(
final GenesisConfigOptions config,
final NodeKey nodeKey,
final boolean isRevertReasonEnabled) {
return create(config, nodeKey, PrivacyParameters.DEFAULT, isRevertReasonEnabled);
final GenesisConfigOptions config, final NodeKey nodeKey, final boolean isMetadataEnabled) {
return create(config, nodeKey, PrivacyParameters.DEFAULT, isMetadataEnabled);
}
private static ProtocolSpecBuilder applyCliqueSpecificModifications(

@ -38,20 +38,20 @@ public class IbftProtocolSchedule {
public static ProtocolSchedule create(
final GenesisConfigOptions config,
final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) {
final boolean isMetadataEnabled) {
return new ProtocolScheduleBuilder(
config,
DEFAULT_CHAIN_ID,
builder -> applyIbftChanges(config.getIbft2ConfigOptions(), builder),
privacyParameters,
isRevertReasonEnabled)
isMetadataEnabled)
.createProtocolSchedule();
}
public static ProtocolSchedule create(
final GenesisConfigOptions config, final boolean isRevertReasonEnabled) {
return create(config, PrivacyParameters.DEFAULT, isRevertReasonEnabled);
final GenesisConfigOptions config, final boolean isMetadataEnabled) {
return create(config, PrivacyParameters.DEFAULT, isMetadataEnabled);
}
public static ProtocolSchedule create(final GenesisConfigOptions config) {

@ -37,7 +37,7 @@ public class IbftProtocolSchedule {
public static ProtocolSchedule create(
final GenesisConfigOptions config,
final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) {
final boolean isMetadataEnabled) {
final IbftConfigOptions ibftConfig = config.getIbftLegacyConfigOptions();
final long blockPeriod = ibftConfig.getBlockPeriodSeconds();
@ -46,13 +46,13 @@ public class IbftProtocolSchedule {
DEFAULT_CHAIN_ID,
builder -> applyIbftChanges(blockPeriod, builder),
privacyParameters,
isRevertReasonEnabled)
isMetadataEnabled)
.createProtocolSchedule();
}
public static ProtocolSchedule create(
final GenesisConfigOptions config, final boolean isRevertReasonEnabled) {
return create(config, PrivacyParameters.DEFAULT, isRevertReasonEnabled);
final GenesisConfigOptions config, final boolean isMetadataEnabled) {
return create(config, PrivacyParameters.DEFAULT, isMetadataEnabled);
}
private static ProtocolSpecBuilder applyIbftChanges(

@ -294,7 +294,7 @@ public class EthGetFilterChangesIntegrationTest {
new BlockBody(transactionList, emptyList()));
final List<TransactionReceipt> transactionReceipts =
transactionList.stream()
.map(transaction -> new TransactionReceipt(1, 1, emptyList(), Optional.empty()))
.map(transaction -> new TransactionReceipt(1, 1, emptyList(), Optional.empty(), -1L))
.collect(toList());
blockchain.appendBlock(block, transactionReceipts);
return block;

@ -79,6 +79,8 @@ public enum RpcMethod {
ETH_GET_FILTER_CHANGES("eth_getFilterChanges"),
ETH_GET_FILTER_LOGS("eth_getFilterLogs"),
ETH_GET_LOGS("eth_getLogs"),
ETH_GET_MINER_DATA_BY_BLOCK_HASH("eth_getMinerDataByBlockHash"),
ETH_GET_MINER_DATA_BY_BLOCK_NUMBER("eth_getMinerDataByBlockNumber"),
ETH_GET_PROOF("eth_getProof"),
ETH_GET_STORAGE_AT("eth_getStorageAt"),
ETH_GET_TRANSACTION_BY_BLOCK_HASH_AND_INDEX("eth_getTransactionByBlockHashAndIndex"),

@ -16,6 +16,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.BlockParameter;
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.query.BlockchainQueries;
@ -74,6 +75,13 @@ public abstract class AbstractBlockParameterMethod implements JsonRpcMethod {
@Override
public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
Object response = findResultByParamType(requestContext);
if (response instanceof JsonRpcErrorResponse) {
return new JsonRpcErrorResponse(
requestContext.getRequest().getId(), ((JsonRpcErrorResponse) response).getError());
}
return new JsonRpcSuccessResponse(
requestContext.getRequest().getId(), findResultByParamType(requestContext));
}

@ -0,0 +1,136 @@
/*
* Copyright ConsenSys AG.
*
* 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.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
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.results.MinerDataResult;
import org.hyperledger.besu.ethereum.api.query.BlockWithMetadata;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.api.query.TransactionReceiptWithMetadata;
import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;
import com.google.common.base.Suppliers;
import org.apache.tuweni.units.bigints.BaseUInt256Value;
public class EthGetMinerDataByBlockHash implements JsonRpcMethod {
private final Supplier<BlockchainQueries> blockchain;
private final ProtocolSchedule protocolSchedule;
public EthGetMinerDataByBlockHash(
final BlockchainQueries blockchain, final ProtocolSchedule protocolSchedule) {
this(Suppliers.ofInstance(blockchain), protocolSchedule);
}
public EthGetMinerDataByBlockHash(
final Supplier<BlockchainQueries> blockchain, final ProtocolSchedule protocolSchedule) {
this.blockchain = blockchain;
this.protocolSchedule = protocolSchedule;
}
@Override
public String getName() {
return RpcMethod.ETH_GET_MINER_DATA_BY_BLOCK_HASH.getMethodName();
}
@Override
public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
final Hash hash = requestContext.getRequest().getRequiredParameter(0, Hash.class);
BlockWithMetadata<TransactionWithMetadata, Hash> block =
blockchain.get().blockByHash(hash).orElse(null);
MinerDataResult minerDataResult = null;
if (block != null) {
if (!blockchain
.get()
.getWorldStateArchive()
.isWorldStateAvailable(block.getHeader().getStateRoot())) {
return new JsonRpcErrorResponse(
requestContext.getRequest().getId(), JsonRpcError.WORLD_STATE_UNAVAILABLE);
}
minerDataResult = createMinerDataResult(block, protocolSchedule, blockchain.get());
}
return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), minerDataResult);
}
public static MinerDataResult createMinerDataResult(
final BlockWithMetadata<TransactionWithMetadata, Hash> block,
final ProtocolSchedule protocolSchedule,
final BlockchainQueries blockchainQueries) {
final BlockHeader blockHeader = block.getHeader();
final ProtocolSpec protocolSpec = protocolSchedule.getByBlockNumber(blockHeader.getNumber());
final Wei staticBlockReward = protocolSpec.getBlockReward();
final Wei transactionFee =
block.getTransactions().stream()
.map(
t -> {
Transaction transaction = t.getTransaction();
Optional<TransactionReceiptWithMetadata> transactionReceiptWithMetadata =
blockchainQueries.transactionReceiptByTransactionHash(transaction.getHash());
Wei refundAmount =
Wei.of(
transactionReceiptWithMetadata
.flatMap(tr -> tr.getReceipt().getGasRemaining())
.orElse(0L))
.multiply(transaction.getGasPrice());
return t.getTransaction().getUpfrontCost().subtract(refundAmount);
})
.reduce(Wei.ZERO, BaseUInt256Value::add);
final Wei uncleInclusionReward =
staticBlockReward.multiply(block.getOmmers().size()).divide(32);
final Wei netBlockReward = staticBlockReward.add(transactionFee).add(uncleInclusionReward);
final Map<Hash, Address> uncleRewards = new HashMap<>();
blockchainQueries
.getBlockchain()
.getBlockByNumber(block.getHeader().getNumber())
.ifPresent(
blockBody ->
blockBody
.getBody()
.getOmmers()
.forEach(header -> uncleRewards.put(header.getHash(), header.getCoinbase())));
return new MinerDataResult(
netBlockReward,
staticBlockReward,
transactionFee,
uncleInclusionReward,
uncleRewards,
blockHeader.getCoinbase(),
blockHeader.getExtraData(),
blockHeader.getDifficulty(),
block.getTotalDifficulty());
}
}

@ -0,0 +1,71 @@
/*
* Copyright ConsenSys AG.
*
* 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.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.BlockParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.MinerDataResult;
import org.hyperledger.besu.ethereum.api.query.BlockWithMetadata;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
public class EthGetMinerDataByBlockNumber extends AbstractBlockParameterMethod {
private final ProtocolSchedule protocolSchedule;
public EthGetMinerDataByBlockNumber(
final BlockchainQueries blockchain, final ProtocolSchedule protocolSchedule) {
super(blockchain);
this.protocolSchedule = protocolSchedule;
}
@Override
public String getName() {
return RpcMethod.ETH_GET_MINER_DATA_BY_BLOCK_NUMBER.getMethodName();
}
@Override
protected BlockParameter blockParameter(final JsonRpcRequestContext request) {
return request.getRequiredParameter(0, BlockParameter.class);
}
@Override
protected Object resultByBlockNumber(
final JsonRpcRequestContext request, final long blockNumber) {
BlockWithMetadata<TransactionWithMetadata, Hash> block =
getBlockchainQueries().blockByNumber(blockNumber).orElse(null);
MinerDataResult minerDataResult = null;
if (block != null) {
if (!getBlockchainQueries()
.getWorldStateArchive()
.isWorldStateAvailable(block.getHeader().getStateRoot())) {
return new JsonRpcErrorResponse(
request.getRequest().getId(), JsonRpcError.WORLD_STATE_UNAVAILABLE);
}
minerDataResult =
EthGetMinerDataByBlockHash.createMinerDataResult(
block, protocolSchedule, getBlockchainQueries());
}
return minerDataResult;
}
}

@ -0,0 +1,119 @@
/*
* Copyright ConsenSys AG.
*
* 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 org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.Wei;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.tuweni.bytes.Bytes;
public class MinerDataResult implements JsonRpcResult {
private final String netBlockReward;
private final String staticBlockReward;
private final String transactionFee;
private final String uncleInclusionReward;
private final List<UncleRewardResult> uncleRewards;
private final String coinbase;
private final String extraData;
private final String difficulty;
private final String totalDifficulty;
public MinerDataResult(
final Wei netBlockReward,
final Wei staticBlockReward,
final Wei transactionFee,
final Wei uncleInclusionReward,
final Map<Hash, Address> uncleRewards,
final Address coinbase,
final Bytes extraData,
final Difficulty difficulty,
final Difficulty totalDifficulty) {
this.netBlockReward = Quantity.create(netBlockReward);
this.staticBlockReward = Quantity.create(staticBlockReward);
this.transactionFee = Quantity.create(transactionFee);
this.uncleInclusionReward = Quantity.create(uncleInclusionReward);
this.uncleRewards = setUncleRewards(uncleRewards);
this.coinbase = coinbase.toString();
this.extraData = extraData.toString();
this.difficulty = Quantity.create(difficulty);
this.totalDifficulty = Quantity.create(totalDifficulty);
}
public String getNetBlockReward() {
return netBlockReward;
}
public String getStaticBlockReward() {
return staticBlockReward;
}
public String getTransactionFee() {
return transactionFee;
}
public String getUncleInclusionReward() {
return uncleInclusionReward;
}
public List<UncleRewardResult> getUncleRewards() {
return uncleRewards;
}
public String getCoinbase() {
return coinbase;
}
public String getExtraData() {
return extraData;
}
public String getDifficulty() {
return difficulty;
}
public String getTotalDifficulty() {
return totalDifficulty;
}
private List<UncleRewardResult> setUncleRewards(final Map<Hash, Address> uncleRewards) {
return uncleRewards.entrySet().stream()
.map(b -> new UncleRewardResult(b.getKey().toString(), b.getValue().toString()))
.collect(Collectors.toList());
}
private static class UncleRewardResult {
private final String hash;
private final String coinbase;
private UncleRewardResult(final String hash, final String coinbase) {
this.hash = hash;
this.coinbase = coinbase;
}
public String getHash() {
return hash;
}
public String getCoinbase() {
return coinbase;
}
}
}

@ -33,6 +33,8 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetCode;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetFilterChanges;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetFilterLogs;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetLogs;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetMinerDataByBlockHash;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetMinerDataByBlockNumber;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetProof;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetStorageAt;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetTransactionByBlockHashAndIndex;
@ -156,6 +158,8 @@ public class EthJsonRpcMethods extends ApiGroupJsonRpcMethods {
new EthSubmitWork(miningCoordinator),
new EthHashrate(miningCoordinator),
new EthSubmitHashRate(miningCoordinator),
new EthChainId(protocolSchedule.getChainId()));
new EthChainId(protocolSchedule.getChainId()),
new EthGetMinerDataByBlockHash(blockchainQueries, protocolSchedule),
new EthGetMinerDataByBlockNumber(blockchainQueries, protocolSchedule));
}
}

@ -322,7 +322,7 @@ public class StateBackupService {
bodyWriter.writeBytes(bodyOutput.encoded().toArrayUnsafe());
final BytesValueRLPOutput receiptsOutput = new BytesValueRLPOutput();
receiptsOutput.writeList(receipts.get(), TransactionReceipt::writeToWithRevertReason);
receiptsOutput.writeList(receipts.get(), TransactionReceipt::writeToWithMetadata);
receiptsWriter.writeBytes(receiptsOutput.encoded().toArrayUnsafe());
backupStatus.storedBlock = blockNumber;

@ -0,0 +1,158 @@
/*
* Copyright ConsenSys AG.
*
* 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.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError.WORLD_STATE_UNAVAILABLE;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
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.exception.InvalidJsonRpcParameters;
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.query.BlockWithMetadata;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import java.util.Collections;
import java.util.Optional;
import com.google.common.base.Suppliers;
import org.assertj.core.util.Arrays;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class EthGetMinerDataByBlockHashTest {
@Mock private BlockchainQueries blockchainQueries;
@Mock private ProtocolSchedule protocolSchedule;
@Mock private WorldStateArchive worldStateArchive;
@Mock private ProtocolSpec protocolSpec;
@Mock private Blockchain blockChain;
private EthGetMinerDataByBlockHash method;
private final String ETH_METHOD = "eth_getMinerDataByBlockHash";
private final BlockHeaderTestFixture blockHeaderTestFixture = new BlockHeaderTestFixture();
@Before
public void before() {
this.method =
new EthGetMinerDataByBlockHash(Suppliers.ofInstance(blockchainQueries), protocolSchedule);
}
@Test
public void shouldReturnExpectedMethodNameTest() {
assertThat(method.getName()).isEqualTo(ETH_METHOD);
}
@Test
public void successTest() {
final BlockHeader header = blockHeaderTestFixture.buildHeader();
final BlockWithMetadata<TransactionWithMetadata, Hash> blockWithMetadata =
new BlockWithMetadata<>(
header, Collections.emptyList(), Collections.emptyList(), Difficulty.of(100L), 5);
when(blockchainQueries.blockByHash(any())).thenReturn(Optional.of(blockWithMetadata));
when(blockchainQueries.getWorldStateArchive()).thenReturn(worldStateArchive);
when(blockchainQueries.getWorldStateArchive().isWorldStateAvailable(any())).thenReturn(true);
when(protocolSchedule.getByBlockNumber(header.getNumber())).thenReturn(protocolSpec);
when(protocolSpec.getBlockReward()).thenReturn(Wei.fromEth(2));
when(blockchainQueries.getBlockchain()).thenReturn(blockChain);
JsonRpcRequest request =
new JsonRpcRequest(
"2.0",
ETH_METHOD,
Arrays.array("0x1349e5d4002e72615ae371dc173ba530bf98a7bef886d5b3b00ca5f217565039"));
JsonRpcRequestContext requestContext = new JsonRpcRequestContext(request);
JsonRpcResponse response = method.response(requestContext);
assertThat(response).isNotNull().isInstanceOf(JsonRpcSuccessResponse.class);
assertThat(((JsonRpcSuccessResponse) response).getResult()).isNotNull();
assertThat(((JsonRpcSuccessResponse) response).getResult())
.hasFieldOrProperty("netBlockReward")
.hasFieldOrProperty("staticBlockReward")
.hasFieldOrProperty("transactionFee")
.hasFieldOrProperty("uncleInclusionReward")
.hasFieldOrProperty("uncleRewards")
.hasFieldOrProperty("coinbase")
.hasFieldOrProperty("extraData")
.hasFieldOrProperty("difficulty")
.hasFieldOrProperty("totalDifficulty");
}
@Test
public void worldStateMissingTest() {
final BlockHeader header = blockHeaderTestFixture.buildHeader();
final BlockWithMetadata<TransactionWithMetadata, Hash> blockWithMetadata =
new BlockWithMetadata<>(
header, Collections.emptyList(), Collections.emptyList(), Difficulty.of(100L), 5);
when(blockchainQueries.blockByHash(any())).thenReturn(Optional.of(blockWithMetadata));
when(blockchainQueries.getWorldStateArchive()).thenReturn(worldStateArchive);
when(blockchainQueries.getWorldStateArchive().isWorldStateAvailable(any())).thenReturn(false);
JsonRpcRequest request =
new JsonRpcRequest(
"2.0",
ETH_METHOD,
Arrays.array("0x1349e5d4002e72615ae371dc173ba530bf98a7bef886d5b3b00ca5f217565039"));
JsonRpcRequestContext requestContext = new JsonRpcRequestContext(request);
JsonRpcResponse response = method.response(requestContext);
assertThat(response).isNotNull().isInstanceOf(JsonRpcErrorResponse.class);
assertThat(((JsonRpcErrorResponse) response).getError()).isNotNull();
assertThat(((JsonRpcErrorResponse) response).getError()).isEqualTo(WORLD_STATE_UNAVAILABLE);
}
@Test
public void exceptionWhenNoHashSuppliedTest() {
JsonRpcRequest request = new JsonRpcRequest("2.0", ETH_METHOD, Arrays.array());
JsonRpcRequestContext requestContext = new JsonRpcRequestContext(request);
assertThatThrownBy(() -> method.response(requestContext))
.isInstanceOf(InvalidJsonRpcParameters.class)
.hasMessage("Missing required json rpc parameter at index 0");
verifyNoMoreInteractions(blockchainQueries);
}
@Test
public void exceptionWhenHashParamInvalidTest() {
JsonRpcRequest request = new JsonRpcRequest("2.0", ETH_METHOD, Arrays.array("hash"));
JsonRpcRequestContext requestContext = new JsonRpcRequestContext(request);
assertThatThrownBy(() -> method.response(requestContext))
.isInstanceOf(InvalidJsonRpcParameters.class)
.hasMessage("Invalid json rpc parameter at index 0");
verifyNoMoreInteractions(blockchainQueries);
}
}

@ -0,0 +1,149 @@
/*
* Copyright ConsenSys AG.
*
* 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.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError.WORLD_STATE_UNAVAILABLE;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
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.exception.InvalidJsonRpcParameters;
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.query.BlockWithMetadata;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import java.util.Collections;
import java.util.Optional;
import org.assertj.core.util.Arrays;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class EthGetMinerDataByBlockNumberTest {
@Mock private BlockchainQueries blockchainQueries;
@Mock private ProtocolSchedule protocolSchedule;
@Mock private WorldStateArchive worldStateArchive;
@Mock private ProtocolSpec protocolSpec;
@Mock private Blockchain blockChain;
private EthGetMinerDataByBlockNumber method;
private final String ETH_METHOD = "eth_getMinerDataByBlockNumber";
private final BlockHeaderTestFixture blockHeaderTestFixture = new BlockHeaderTestFixture();
@Before
public void before() {
this.method = new EthGetMinerDataByBlockNumber(blockchainQueries, protocolSchedule);
}
@Test
public void shouldReturnExpectedMethodNameTest() {
assertThat(method.getName()).isEqualTo(ETH_METHOD);
}
@Test
public void successTest() {
final BlockHeader header = blockHeaderTestFixture.buildHeader();
final BlockWithMetadata<TransactionWithMetadata, Hash> blockWithMetadata =
new BlockWithMetadata<>(
header, Collections.emptyList(), Collections.emptyList(), Difficulty.of(100L), 5);
when(blockchainQueries.blockByNumber(anyLong())).thenReturn(Optional.of(blockWithMetadata));
when(blockchainQueries.getWorldStateArchive()).thenReturn(worldStateArchive);
when(blockchainQueries.getWorldStateArchive().isWorldStateAvailable(any())).thenReturn(true);
when(protocolSchedule.getByBlockNumber(header.getNumber())).thenReturn(protocolSpec);
when(protocolSpec.getBlockReward()).thenReturn(Wei.fromEth(2));
when(blockchainQueries.getBlockchain()).thenReturn(blockChain);
JsonRpcRequest request = new JsonRpcRequest("2.0", ETH_METHOD, Arrays.array("5094833"));
JsonRpcRequestContext requestContext = new JsonRpcRequestContext(request);
JsonRpcResponse response = method.response(requestContext);
assertThat(response).isNotNull().isInstanceOf(JsonRpcSuccessResponse.class);
assertThat(((JsonRpcSuccessResponse) response).getResult()).isNotNull();
assertThat(((JsonRpcSuccessResponse) response).getResult())
.hasFieldOrProperty("netBlockReward")
.hasFieldOrProperty("staticBlockReward")
.hasFieldOrProperty("transactionFee")
.hasFieldOrProperty("uncleInclusionReward")
.hasFieldOrProperty("uncleRewards")
.hasFieldOrProperty("coinbase")
.hasFieldOrProperty("extraData")
.hasFieldOrProperty("difficulty")
.hasFieldOrProperty("totalDifficulty");
}
@Test
public void worldStateMissingTest() {
final BlockHeader header = blockHeaderTestFixture.buildHeader();
final BlockWithMetadata<TransactionWithMetadata, Hash> blockWithMetadata =
new BlockWithMetadata<>(
header, Collections.emptyList(), Collections.emptyList(), Difficulty.of(100L), 5);
when(blockchainQueries.blockByNumber(anyLong())).thenReturn(Optional.of(blockWithMetadata));
when(blockchainQueries.getWorldStateArchive()).thenReturn(worldStateArchive);
when(blockchainQueries.getWorldStateArchive().isWorldStateAvailable(any())).thenReturn(false);
JsonRpcRequest request = new JsonRpcRequest("2.0", ETH_METHOD, Arrays.array("5094833"));
JsonRpcRequestContext requestContext = new JsonRpcRequestContext(request);
JsonRpcResponse response = method.response(requestContext);
assertThat(response).isNotNull().isInstanceOf(JsonRpcErrorResponse.class);
assertThat(((JsonRpcErrorResponse) response).getError()).isNotNull();
assertThat(((JsonRpcErrorResponse) response).getError()).isEqualTo(WORLD_STATE_UNAVAILABLE);
}
@Test
public void exceptionWhenNoNumberSuppliedTest() {
JsonRpcRequest request = new JsonRpcRequest("2.0", ETH_METHOD, Arrays.array());
JsonRpcRequestContext requestContext = new JsonRpcRequestContext(request);
assertThatThrownBy(() -> method.response(requestContext))
.isInstanceOf(InvalidJsonRpcParameters.class)
.hasMessage("Missing required json rpc parameter at index 0");
verifyNoMoreInteractions(blockchainQueries);
}
@Test
public void exceptionWhenNumberParamInvalidTest() {
JsonRpcRequest request = new JsonRpcRequest("2.0", ETH_METHOD, Arrays.array("number"));
JsonRpcRequestContext requestContext = new JsonRpcRequestContext(request);
assertThatThrownBy(() -> method.response(requestContext))
.isInstanceOf(InvalidJsonRpcParameters.class)
.hasMessage("Invalid json rpc parameter at index 0");
verifyNoMoreInteractions(blockchainQueries);
}
}

@ -47,11 +47,11 @@ import org.junit.Test;
public class EthGetTransactionReceiptTest {
private final TransactionReceipt stateReceipt =
new TransactionReceipt(1, 12, Collections.emptyList(), Optional.empty());
new TransactionReceipt(1, 12, Collections.emptyList(), Optional.empty(), -1L);
private final Hash stateRoot =
Hash.fromHexString("0000000000000000000000000000000000000000000000000000000000000000");
private final TransactionReceipt rootReceipt =
new TransactionReceipt(stateRoot, 12, Collections.emptyList(), Optional.empty());
new TransactionReceipt(stateRoot, 12, Collections.emptyList(), Optional.empty(), -1L);
private final Signature signature = Signature.create(BigInteger.ONE, BigInteger.TEN, (byte) 1);
private final Address sender =

@ -377,7 +377,7 @@ public class LogsSubscriptionServiceTest {
final BlockOptions blockOptions = BlockOptions.create();
for (int i = 0; i < txCount; i++) {
final Transaction tx = gen.transaction();
final TransactionReceipt receipt = gen.receipt(logsSupplier.get());
final TransactionReceipt receipt = gen.receipt(logsSupplier.get(), -1L);
receipts.add(receipt);
receipt.getLogs().forEach(logs::add);

@ -22,7 +22,8 @@
"root": "0x6a59608add7cee26032d1c5c3923b91d0b50e6103f61b2137b68229bcdc87395",
"to": null,
"transactionHash": "0x812742182a79a8e67733edc58cfa3767aa2d7ad06439d156ddbbb33e3403b4ed",
"transactionIndex": "0x0"
"transactionIndex": "0x0",
"revertReason" : "0x"
}
},
"statusCode": 200

@ -39,7 +39,8 @@
"root": "0xb55d027526b3f56953584db678b5c3d1a418812c0106b0cfbc3c912c7898dfe5",
"to": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"transactionHash": "0x185a9154a0acc4e0ffc84029aee0f3dbf57ff0b84ec7624cb80e7373a03e8aeb",
"transactionIndex": "0x0"
"transactionIndex": "0x0",
"revertReason" : "0x"
}
},
"statusCode": 200

@ -22,7 +22,8 @@
"root": "0x947228066df6272aac99931a1a639621d4ac7dc461ce9fd93dfcaad933e299ee",
"to": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"transactionHash": "0xb1a62356d1433202cdef0ef9030f8abdfbb3aef549fab0867cf0eaee70b09d81",
"transactionIndex": "0x0"
"transactionIndex": "0x0",
"revertReason" : "0x"
}
},
"statusCode": 200

@ -571,6 +571,6 @@ public class BlockTransactionSelectorTest {
private TransactionReceipt createReceipt(
final TransactionProcessor.Result result, final WorldState worldState, final long gasUsed) {
return new TransactionReceipt(
worldState.rootHash(), gasUsed, Lists.newArrayList(), Optional.empty());
worldState.rootHash(), gasUsed, Lists.newArrayList(), Optional.empty(), -1L);
}
}

@ -48,6 +48,7 @@ public class TransactionReceipt implements org.hyperledger.besu.plugin.data.Tran
private final int status;
private final TransactionReceiptType transactionReceiptType;
private final Optional<Bytes> revertReason;
private final long gasRemaining;
/**
* Creates an instance of a state root-encoded transaction receipt.
@ -56,19 +57,22 @@ public class TransactionReceipt implements org.hyperledger.besu.plugin.data.Tran
* @param cumulativeGasUsed the total amount of gas consumed in the block after this transaction
* @param logs the logs generated within the transaction
* @param revertReason the revert reason for a failed transaction (if applicable)
* @param gasRemaining the gas remaining from the processed transaction
*/
public TransactionReceipt(
final Hash stateRoot,
final long cumulativeGasUsed,
final List<Log> logs,
final Optional<Bytes> revertReason) {
final Optional<Bytes> revertReason,
final long gasRemaining) {
this(
stateRoot,
NONEXISTENT,
cumulativeGasUsed,
logs,
LogsBloomFilter.builder().insertLogs(logs).build(),
revertReason);
revertReason,
gasRemaining);
}
private TransactionReceipt(
@ -76,8 +80,9 @@ public class TransactionReceipt implements org.hyperledger.besu.plugin.data.Tran
final long cumulativeGasUsed,
final List<Log> logs,
final LogsBloomFilter bloomFilter,
final Optional<Bytes> revertReason) {
this(stateRoot, NONEXISTENT, cumulativeGasUsed, logs, bloomFilter, revertReason);
final Optional<Bytes> revertReason,
final long gasRemaining) {
this(stateRoot, NONEXISTENT, cumulativeGasUsed, logs, bloomFilter, revertReason, gasRemaining);
}
/**
@ -87,19 +92,22 @@ public class TransactionReceipt implements org.hyperledger.besu.plugin.data.Tran
* @param cumulativeGasUsed the total amount of gas consumed in the block after this transaction
* @param logs the logs generated within the transaction
* @param revertReason the revert reason for a failed transaction (if applicable)
* @param gasRemaining the remaining gas from the transaction (if applicable)
*/
public TransactionReceipt(
final int status,
final long cumulativeGasUsed,
final List<Log> logs,
final Optional<Bytes> revertReason) {
final Optional<Bytes> revertReason,
final long gasRemaining) {
this(
null,
status,
cumulativeGasUsed,
logs,
LogsBloomFilter.builder().insertLogs(logs).build(),
revertReason);
revertReason,
gasRemaining);
}
private TransactionReceipt(
@ -107,8 +115,9 @@ public class TransactionReceipt implements org.hyperledger.besu.plugin.data.Tran
final long cumulativeGasUsed,
final List<Log> logs,
final LogsBloomFilter bloomFilter,
final Optional<Bytes> revertReason) {
this(null, status, cumulativeGasUsed, logs, bloomFilter, revertReason);
final Optional<Bytes> revertReason,
final long gasRemaining) {
this(null, status, cumulativeGasUsed, logs, bloomFilter, revertReason, gasRemaining);
}
private TransactionReceipt(
@ -117,7 +126,8 @@ public class TransactionReceipt implements org.hyperledger.besu.plugin.data.Tran
final long cumulativeGasUsed,
final List<Log> logs,
final LogsBloomFilter bloomFilter,
final Optional<Bytes> revertReason) {
final Optional<Bytes> revertReason,
final long gasRemaining) {
this.stateRoot = stateRoot;
this.cumulativeGasUsed = cumulativeGasUsed;
this.status = status;
@ -126,6 +136,7 @@ public class TransactionReceipt implements org.hyperledger.besu.plugin.data.Tran
transactionReceiptType =
stateRoot == null ? TransactionReceiptType.STATUS : TransactionReceiptType.ROOT;
this.revertReason = revertReason;
this.gasRemaining = gasRemaining;
}
/**
@ -137,11 +148,11 @@ public class TransactionReceipt implements org.hyperledger.besu.plugin.data.Tran
writeTo(out, false);
}
public void writeToWithRevertReason(final RLPOutput out) {
public void writeToWithMetadata(final RLPOutput out) {
writeTo(out, true);
}
private void writeTo(final RLPOutput out, final boolean withRevertReason) {
private void writeTo(final RLPOutput out, final boolean withMetadata) {
out.startList();
// Determine whether it's a state root-encoded transaction receipt
@ -154,8 +165,11 @@ public class TransactionReceipt implements org.hyperledger.besu.plugin.data.Tran
out.writeLongScalar(cumulativeGasUsed);
out.writeBytes(bloomFilter);
out.writeList(logs, Log::writeTo);
if (withRevertReason && revertReason.isPresent()) {
out.writeBytes(revertReason.get());
if (withMetadata) {
out.writeBytes(
revertReason.orElse(
Bytes.EMPTY)); // writing Bytes.EMPTY is the same as calling RLPOutput.writeNull
out.writeLong(gasRemaining);
}
out.endList();
}
@ -174,11 +188,10 @@ public class TransactionReceipt implements org.hyperledger.besu.plugin.data.Tran
* Creates a transaction receipt for the given RLP
*
* @param input the RLP-encoded transaction receipt
* @param revertReasonAllowed whether the rlp input is allowed to have a revert reason
* @param metadataAllowed whether the rlp input is allowed to have a metadata
* @return the transaction receipt
*/
public static TransactionReceipt readFrom(
final RLPInput input, final boolean revertReasonAllowed) {
public static TransactionReceipt readFrom(final RLPInput input, final boolean metadataAllowed) {
input.enterList();
try {
@ -191,23 +204,29 @@ public class TransactionReceipt implements org.hyperledger.besu.plugin.data.Tran
final LogsBloomFilter bloomFilter = LogsBloomFilter.readFrom(input);
final List<Log> logs = input.readList(Log::readFrom);
final Optional<Bytes> revertReason;
long gasRemaining = -1L;
if (input.isEndOfCurrentList()) {
revertReason = Optional.empty();
} else {
if (!revertReasonAllowed) {
if (!metadataAllowed) {
throw new RLPException("Unexpected value at end of TransactionReceipt");
}
revertReason = Optional.of(input.readBytes());
if (!input.isEndOfCurrentList()) {
gasRemaining = input.readLong();
}
}
// Status code-encoded transaction receipts have a single
// byte for success (0x01) or failure (0x80).
if (firstElement.raw().size() == 1) {
final int status = firstElement.readIntScalar();
return new TransactionReceipt(status, cumulativeGas, logs, bloomFilter, revertReason);
return new TransactionReceipt(
status, cumulativeGas, logs, bloomFilter, revertReason, gasRemaining);
} else {
final Hash stateRoot = Hash.wrap(firstElement.readBytes32());
return new TransactionReceipt(stateRoot, cumulativeGas, logs, bloomFilter, revertReason);
return new TransactionReceipt(
stateRoot, cumulativeGas, logs, bloomFilter, revertReason, gasRemaining);
}
} finally {
input.leaveList();
@ -272,6 +291,10 @@ public class TransactionReceipt implements org.hyperledger.besu.plugin.data.Tran
return revertReason;
}
public Optional<Long> getGasRemaining() {
return Optional.of(gasRemaining);
}
@Override
public boolean equals(final Object obj) {
if (obj == this) {

@ -25,18 +25,18 @@ public class FixedDifficultyProtocolSchedule {
public static ProtocolSchedule create(
final GenesisConfigOptions config,
final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) {
final boolean isMetadataEnabled) {
return new ProtocolScheduleBuilder(
config,
builder -> builder.difficultyCalculator(FixedDifficultyCalculators.calculator(config)),
privacyParameters,
isRevertReasonEnabled)
isMetadataEnabled)
.createProtocolSchedule();
}
public static ProtocolSchedule create(
final GenesisConfigOptions config, final boolean isRevertReasonEnabled) {
return create(config, PrivacyParameters.DEFAULT, isRevertReasonEnabled);
final GenesisConfigOptions config, final boolean isMetadataEnabled) {
return create(config, PrivacyParameters.DEFAULT, isMetadataEnabled);
}
public static ProtocolSchedule create(final GenesisConfigOptions config) {

@ -209,12 +209,20 @@ public class ClassicProtocolSpecs {
private static TransactionReceipt byzantiumTransactionReceiptFactory(
final TransactionProcessor.Result result, final WorldState worldState, final long gasUsed) {
return new TransactionReceipt(
result.isSuccessful() ? 1 : 0, gasUsed, result.getLogs(), Optional.empty());
result.isSuccessful() ? 1 : 0,
gasUsed,
result.getLogs(),
Optional.empty(),
result.getGasRemaining());
}
private static TransactionReceipt byzantiumTransactionReceiptFactoryWithReasonEnabled(
final TransactionProcessor.Result result, final WorldState worldState, final long gasUsed) {
return new TransactionReceipt(
result.isSuccessful() ? 1 : 0, gasUsed, result.getLogs(), result.getRevertReason());
result.isSuccessful() ? 1 : 0,
gasUsed,
result.getLogs(),
result.getRevertReason(),
result.getGasRemaining());
}
}

@ -39,19 +39,18 @@ public class MainnetProtocolSchedule {
* @param config {@link GenesisConfigOptions} containing the config options for the milestone
* starting points
* @param privacyParameters the parameters set for private transactions
* @param isRevertReasonEnabled whether storing the revert reason is for failed transactions
* @param isMetadataEnabled whether storing metadata for failed transactions
* @return A configured mainnet protocol schedule
*/
public static ProtocolSchedule fromConfig(
final GenesisConfigOptions config,
final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) {
final boolean isMetadataEnabled) {
if (FixedDifficultyCalculators.isFixedDifficultyInConfig(config)) {
return FixedDifficultyProtocolSchedule.create(
config, privacyParameters, isRevertReasonEnabled);
return FixedDifficultyProtocolSchedule.create(config, privacyParameters, isMetadataEnabled);
}
return new ProtocolScheduleBuilder(
config, DEFAULT_CHAIN_ID, Function.identity(), privacyParameters, isRevertReasonEnabled)
config, DEFAULT_CHAIN_ID, Function.identity(), privacyParameters, isMetadataEnabled)
.createProtocolSchedule();
}
@ -60,12 +59,12 @@ public class MainnetProtocolSchedule {
*
* @param config {@link GenesisConfigOptions} containing the config options for the milestone
* starting points
* @param isRevertReasonEnabled whether storing the revert reason is for failed transactions
* @param isMetadataEnabled whether storing metadata for failed transactions
* @return A configured mainnet protocol schedule
*/
public static ProtocolSchedule fromConfig(
final GenesisConfigOptions config, final boolean isRevertReasonEnabled) {
return fromConfig(config, PrivacyParameters.DEFAULT, isRevertReasonEnabled);
final GenesisConfigOptions config, final boolean isMetadataEnabled) {
return fromConfig(config, PrivacyParameters.DEFAULT, isMetadataEnabled);
}
/**

@ -408,19 +408,28 @@ public abstract class MainnetProtocolSpecs {
worldState.rootHash(),
gasUsed,
result.getLogs(),
Optional.empty()); // No revert reason in frontier
Optional.empty(), // No revert reason in frontier
result.getGasRemaining());
}
private static TransactionReceipt byzantiumTransactionReceiptFactory(
final TransactionProcessor.Result result, final WorldState worldState, final long gasUsed) {
return new TransactionReceipt(
result.isSuccessful() ? 1 : 0, gasUsed, result.getLogs(), Optional.empty());
result.isSuccessful() ? 1 : 0,
gasUsed,
result.getLogs(),
Optional.empty(),
result.getGasRemaining());
}
private static TransactionReceipt byzantiumTransactionReceiptFactoryWithReasonEnabled(
final TransactionProcessor.Result result, final WorldState worldState, final long gasUsed) {
return new TransactionReceipt(
result.isSuccessful() ? 1 : 0, gasUsed, result.getLogs(), result.getRevertReason());
result.isSuccessful() ? 1 : 0,
gasUsed,
result.getLogs(),
result.getRevertReason(),
result.getGasRemaining());
}
private static class DaoBlockProcessor implements BlockProcessor {

@ -36,7 +36,7 @@ public class ProtocolScheduleBuilder {
private final Function<ProtocolSpecBuilder, ProtocolSpecBuilder> protocolSpecAdapter;
private final Optional<BigInteger> defaultChainId;
private final PrivacyParameters privacyParameters;
private final boolean isRevertReasonEnabled;
private final boolean isMetadataEnabled;
private final BadBlockManager badBlockManager = new BadBlockManager();
public ProtocolScheduleBuilder(
@ -44,21 +44,21 @@ public class ProtocolScheduleBuilder {
final BigInteger defaultChainId,
final Function<ProtocolSpecBuilder, ProtocolSpecBuilder> protocolSpecAdapter,
final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) {
final boolean isMetadataEnabled) {
this(
config,
Optional.of(defaultChainId),
protocolSpecAdapter,
privacyParameters,
isRevertReasonEnabled);
isMetadataEnabled);
}
public ProtocolScheduleBuilder(
final GenesisConfigOptions config,
final Function<ProtocolSpecBuilder, ProtocolSpecBuilder> protocolSpecAdapter,
final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) {
this(config, Optional.empty(), protocolSpecAdapter, privacyParameters, isRevertReasonEnabled);
final boolean isMetadataEnabled) {
this(config, Optional.empty(), protocolSpecAdapter, privacyParameters, isMetadataEnabled);
}
private ProtocolScheduleBuilder(
@ -66,12 +66,12 @@ public class ProtocolScheduleBuilder {
final Optional<BigInteger> defaultChainId,
final Function<ProtocolSpecBuilder, ProtocolSpecBuilder> protocolSpecAdapter,
final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) {
final boolean isMetadataEnabled) {
this.config = config;
this.defaultChainId = defaultChainId;
this.protocolSpecAdapter = protocolSpecAdapter;
this.privacyParameters = privacyParameters;
this.isRevertReasonEnabled = isRevertReasonEnabled;
this.isMetadataEnabled = isMetadataEnabled;
}
public ProtocolSchedule createProtocolSchedule() {
@ -127,52 +127,34 @@ public class ProtocolScheduleBuilder {
protocolSchedule,
config.getByzantiumBlockNumber(),
MainnetProtocolSpecs.byzantiumDefinition(
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isRevertReasonEnabled));
chainId, config.getContractSizeLimit(), config.getEvmStackSize(), isMetadataEnabled));
addProtocolSpec(
protocolSchedule,
config.getConstantinopleBlockNumber(),
MainnetProtocolSpecs.constantinopleDefinition(
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isRevertReasonEnabled));
chainId, config.getContractSizeLimit(), config.getEvmStackSize(), isMetadataEnabled));
addProtocolSpec(
protocolSchedule,
config.getConstantinopleFixBlockNumber(),
MainnetProtocolSpecs.constantinopleFixDefinition(
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isRevertReasonEnabled));
chainId, config.getContractSizeLimit(), config.getEvmStackSize(), isMetadataEnabled));
addProtocolSpec(
protocolSchedule,
config.getIstanbulBlockNumber(),
MainnetProtocolSpecs.istanbulDefinition(
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isRevertReasonEnabled));
chainId, config.getContractSizeLimit(), config.getEvmStackSize(), isMetadataEnabled));
addProtocolSpec(
protocolSchedule,
config.getMuirGlacierBlockNumber(),
MainnetProtocolSpecs.muirGlacierDefinition(
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isRevertReasonEnabled));
chainId, config.getContractSizeLimit(), config.getEvmStackSize(), isMetadataEnabled));
if (ExperimentalEIPs.berlinEnabled) {
addProtocolSpec(
protocolSchedule,
config.getBerlinBlockNumber(),
MainnetProtocolSpecs.berlinDefinition(
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isRevertReasonEnabled));
chainId, config.getContractSizeLimit(), config.getEvmStackSize(), isMetadataEnabled));
}
if (ExperimentalEIPs.eip1559Enabled) {
@ -186,7 +168,7 @@ public class ProtocolScheduleBuilder {
transactionPriceCalculator,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isRevertReasonEnabled,
isMetadataEnabled,
config));
}
@ -238,7 +220,7 @@ public class ProtocolScheduleBuilder {
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isRevertReasonEnabled,
isMetadataEnabled,
config.getEcip1017EraRounds()));
addProtocolSpec(
protocolSchedule,
@ -247,7 +229,7 @@ public class ProtocolScheduleBuilder {
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isRevertReasonEnabled,
isMetadataEnabled,
config.getEcip1017EraRounds()));
addProtocolSpec(
protocolSchedule,
@ -256,7 +238,7 @@ public class ProtocolScheduleBuilder {
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isRevertReasonEnabled,
isMetadataEnabled,
config.getEcip1017EraRounds()));
addProtocolSpec(
protocolSchedule,
@ -265,7 +247,7 @@ public class ProtocolScheduleBuilder {
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isRevertReasonEnabled,
isMetadataEnabled,
config.getEcip1017EraRounds()));
LOG.info("Protocol schedule created with milestones: {}", protocolSchedule.listMilestones());

@ -203,7 +203,7 @@ public class KeyValueStoragePrefixedKeyBlockchainStorage implements BlockchainSt
}
private Bytes rlpEncode(final List<TransactionReceipt> receipts) {
return RLP.encode(o -> o.writeList(receipts, TransactionReceipt::writeToWithRevertReason));
return RLP.encode(o -> o.writeList(receipts, TransactionReceipt::writeToWithMetadata));
}
}
}

@ -362,22 +362,26 @@ public class BlockDataGenerator {
return txs;
}
public TransactionReceipt receipt(final long cumulativeGasUsed) {
public TransactionReceipt receipt(final long cumulativeGasUsed, final Long gasRemaining) {
return new TransactionReceipt(
hash(), cumulativeGasUsed, Arrays.asList(log(), log()), Optional.empty());
hash(), cumulativeGasUsed, Arrays.asList(log(), log()), Optional.empty(), gasRemaining);
}
public TransactionReceipt receipt(final Bytes revertReason) {
public TransactionReceipt receipt(final Bytes revertReason, final Long gasRemaining) {
return new TransactionReceipt(
hash(), positiveLong(), Arrays.asList(log(), log()), Optional.of(revertReason));
hash(),
positiveLong(),
Arrays.asList(log(), log()),
Optional.of(revertReason),
gasRemaining);
}
public TransactionReceipt receipt() {
return receipt(positiveLong());
public TransactionReceipt receipt(final Long gasRemaining) {
return receipt(positiveLong(), gasRemaining);
}
public TransactionReceipt receipt(final List<Log> logs) {
return new TransactionReceipt(hash(), positiveLong(), logs, Optional.empty());
public TransactionReceipt receipt(final List<Log> logs, final Long gasRemaining) {
return new TransactionReceipt(hash(), positiveLong(), logs, Optional.empty(), gasRemaining);
}
public UInt256 storageKey() {

@ -241,7 +241,7 @@ public class DefaultBlockchainTest {
.setParentHash(genesisBlock.getHash());
final Block newBlock = gen.block(options);
final List<TransactionReceipt> receipts = gen.receipts(newBlock);
receipts.add(gen.receipt());
receipts.add(gen.receipt(100L));
blockchain.appendBlock(newBlock, receipts);
}

@ -26,18 +26,18 @@ public class TransactionReceiptTest {
@Test
public void toFromRlp() {
final BlockDataGenerator gen = new BlockDataGenerator();
final TransactionReceipt receipt = gen.receipt();
final TransactionReceipt receipt = gen.receipt(100L);
final TransactionReceipt copy =
TransactionReceipt.readFrom(RLP.input(RLP.encode(receipt::writeToWithRevertReason)), false);
TransactionReceipt.readFrom(RLP.input(RLP.encode(receipt::writeTo)), false);
assertThat(copy).isEqualTo(receipt);
}
@Test
public void toFromRlpWithReason() {
final BlockDataGenerator gen = new BlockDataGenerator();
final TransactionReceipt receipt = gen.receipt(Bytes.fromHexString("0x1122334455667788"));
final TransactionReceipt receipt = gen.receipt(Bytes.fromHexString("0x1122334455667788"), 100L);
final TransactionReceipt copy =
TransactionReceipt.readFrom(RLP.input(RLP.encode(receipt::writeToWithRevertReason)));
TransactionReceipt.readFrom(RLP.input(RLP.encode(receipt::writeToWithMetadata)));
assertThat(copy).isEqualTo(receipt);
}
}

@ -208,7 +208,7 @@ public class PrivacyBlockProcessorTest {
final AbstractBlockProcessor.TransactionReceiptFactory mockTransactionReceiptFactory =
mock(AbstractBlockProcessor.TransactionReceiptFactory.class);
when(mockTransactionReceiptFactory.create(any(), any(), anyLong()))
.thenReturn(new TransactionReceipt(0, 0, Collections.emptyList(), Optional.empty()));
.thenReturn(new TransactionReceipt(0, 0, Collections.emptyList(), Optional.empty(), -1L));
when(protocolSpec.getTransactionReceiptFactory()).thenReturn(mockTransactionReceiptFactory);
when(protocolSpec.getBlockReward()).thenReturn(Wei.ZERO);
when(protocolSpec.getMiningBeneficiaryCalculator())

@ -38,7 +38,7 @@ public final class ReceiptsMessageTest {
for (int i = 0; i < dataCount; ++i) {
final List<TransactionReceipt> receiptSet = new ArrayList<>();
for (int j = 0; j < receiptsPerSet; j++) {
receiptSet.add(gen.receipt());
receiptSet.add(gen.receipt(-1L));
}
receipts.add(receiptSet);
}

@ -767,7 +767,7 @@ public class TransactionPoolTest {
new BlockBody(transactionList, emptyList()));
final List<TransactionReceipt> transactionReceipts =
transactionList.stream()
.map(transaction -> new TransactionReceipt(1, 1, emptyList(), Optional.empty()))
.map(transaction -> new TransactionReceipt(1, 1, emptyList(), Optional.empty(), -1L))
.collect(toList());
blockchain.appendBlock(block, transactionReceipts);
return block;

@ -38,9 +38,9 @@ class CliqueGenesisFileModule extends GenesisFileModule {
@Override
ProtocolSchedule provideProtocolSchedule(
final GenesisConfigOptions configOptions,
@Named("RevertReasonEnabled") final boolean revertReasonEnabled) {
@Named("MetadataEnabled") final boolean metadataEnabled) {
// dagger can handle this magic one day
return CliqueProtocolSchedule.create(configOptions, nodeKey, revertReasonEnabled);
return CliqueProtocolSchedule.create(configOptions, nodeKey, metadataEnabled);
}
@Override

@ -34,19 +34,18 @@ import picocli.CommandLine.Option;
@SuppressWarnings("WeakerAccess")
@Module
public class EvmToolCommandOptionsModule {
@Option(
names = {"--revert-reason-enabled"},
names = {"--receipt-metadata-enabled", "--revert-reason-enabled"},
paramLabel = "<Boolean>",
description = "Should revert reasons be persisted. (default: ${FALLBACK-VALUE})",
description = "Should metadata be persisted. (default: ${FALLBACK-VALUE})",
arity = "0..1",
fallbackValue = "true")
final Boolean revertReasonEnabled = true;
final Boolean metadataEnabled = true;
@Provides
@Named("RevertReasonEnabled")
boolean provideRevertReasonEnabled() {
return revertReasonEnabled;
@Named("MetadataEnabled")
boolean provideMetadataEnabled() {
return metadataEnabled;
}
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings.

@ -64,7 +64,7 @@ public class GenesisFileModule {
@Provides
ProtocolSchedule provideProtocolSchedule(
final GenesisConfigOptions configOptions,
@Named("RevertReasonEnabled") final boolean revertReasonEnabled) {
@Named("MetadataEnabled") final boolean metadataEnabled) {
throw new RuntimeException("Abstract");
}

@ -32,7 +32,7 @@ class IBFTGenesisFileModule extends GenesisFileModule {
@Override
ProtocolSchedule provideProtocolSchedule(
final GenesisConfigOptions configOptions,
@Named("RevertReasonEnabled") final boolean revertReasonEnabled) {
@Named("MetadataEnabled") final boolean metadataEnabled) {
return IbftProtocolSchedule.create(configOptions);
}

@ -32,7 +32,7 @@ class MainnetGenesisFileModule extends GenesisFileModule {
@Override
ProtocolSchedule provideProtocolSchedule(
final GenesisConfigOptions configOptions,
@Named("RevertReasonEnabled") final boolean revertReasonEnabled) {
@Named("MetadataEnabled") final boolean metadataEnabled) {
return MainnetProtocolSchedule.fromConfig(configOptions);
}

Loading…
Cancel
Save