mirror of
https://github.com/vacp2p/status-linea-besu.git
synced 2026-01-07 22:44:05 -05:00
Merge branch 'main' into zkbesu
# Conflicts: # .circleci/config.yml # gradle.properties
This commit is contained in:
16
CHANGELOG.md
16
CHANGELOG.md
@@ -1,8 +1,20 @@
|
||||
# Changelog
|
||||
|
||||
## 23.10.3
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
### Deprecations
|
||||
|
||||
### Additions and Improvements
|
||||
- Implement debug_traceCall [#5885](https://github.com/hyperledger/besu/pull/5885)
|
||||
- Transactions that takes too long to evaluate, during block creation, are dropped from the txpool [#6163](https://github.com/hyperledger/besu/pull/6163)
|
||||
- New option `tx-pool-min-gas-price` to set a lower bound when accepting txs to the pool [#6098](https://github.com/hyperledger/besu/pull/6098)
|
||||
|
||||
## 23.10.2
|
||||
|
||||
### Breaking Changes
|
||||
- TX pool eviction in the legacy TX pool now favours keeping oldest transactions (more likely to evict higher nonces, less likely to introduce nonce gaps) [#6106](https://github.com/hyperledger/besu/pull/6106) and [#6146](https://github.com/hyperledger/besu/pull/6146)
|
||||
|
||||
### Deprecations
|
||||
|
||||
@@ -19,6 +31,7 @@
|
||||
- Add `yParity` to GraphQL and JSON-RPC for relevant querise. [6119](https://github.com/hyperledger/besu/pull/6119)
|
||||
- Force tx replacement price bump to zero when zero base fee market is configured or `--min-gas-price` is set to 0. This allows for easier tx replacement in networks where there is not gas price. [#6079](https://github.com/hyperledger/besu/pull/6079)
|
||||
- Introduce the possibility to limit the time spent selecting pending transactions during block creation, using the new experimental option `Xblock-txs-selection-max-time` on PoS and PoW networks (by default set to 5000ms) or `Xpoa-block-txs-selection-max-time` on PoA networks (by default 75% of the min block time) [#6044](https://github.com/hyperledger/besu/pull/6044)
|
||||
- Remove LowestInvalidNonceCache from `legacy` transaction pool to make it more private networks friendly [#6148](https://github.com/hyperledger/besu/pull/6148)
|
||||
|
||||
### Bug fixes
|
||||
- Upgrade netty to address CVE-2023-44487, CVE-2023-34462 [#6100](https://github.com/hyperledger/besu/pull/6100)
|
||||
@@ -29,6 +42,9 @@
|
||||
---
|
||||
|
||||
### Download Links
|
||||
https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/23.10.2/besu-23.10.2.zip / sha256: 597ab71898d379180106baf24878239ed49acefea5772344fd359b0ff13fe19f
|
||||
|
||||
https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/23.10.2/besu-23.10.2.tar.gz / sha256: 255818a5c6067a38aa8b565d8f32a49a172a7536a1d370673bbb75f548263c2c
|
||||
|
||||
## 23.10.1
|
||||
|
||||
|
||||
@@ -192,10 +192,11 @@ public class OpenTelemetryAcceptanceTest extends AcceptanceTestBase {
|
||||
assertThat(internalSpan.getKind()).isEqualTo(Span.SpanKind.SPAN_KIND_INTERNAL);
|
||||
final ByteString parent = internalSpan.getParentSpanId();
|
||||
assertThat(parent.isEmpty()).isFalse();
|
||||
final Span serverSpan = spans.get(0).getScopeSpans(0).getSpans(1);
|
||||
assertThat(serverSpan.getKind()).isEqualTo(Span.SpanKind.SPAN_KIND_SERVER);
|
||||
final ByteString rootSpanId = serverSpan.getParentSpanId();
|
||||
assertThat(rootSpanId.isEmpty()).isTrue();
|
||||
// this part of the test is flaky
|
||||
// final Span serverSpan = spans.get(0).getScopeSpans(0).getSpans(1);
|
||||
// assertThat(serverSpan.getKind()).isEqualTo(Span.SpanKind.SPAN_KIND_SERVER);
|
||||
// final ByteString rootSpanId = serverSpan.getParentSpanId();
|
||||
// assertThat(rootSpanId.isEmpty()).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -83,10 +83,10 @@ public class ExecutionEngineCancunBlockBuildingAcceptanceTest extends AbstractJs
|
||||
assertThat(blobsBundle.get("blobs").getNodeType()).isEqualTo(JsonNodeType.ARRAY);
|
||||
final ArrayNode blobs = (ArrayNode) blobsBundle.get("blobs");
|
||||
final ArrayNode proofs = (ArrayNode) blobsBundle.get("proofs");
|
||||
assertThat(2).isEqualTo(transactions.size());
|
||||
assertThat(6).isEqualTo(commitments.size());
|
||||
assertThat(6).isEqualTo(blobs.size());
|
||||
assertThat(6).isEqualTo(proofs.size());
|
||||
assertThat(3).isEqualTo(transactions.size());
|
||||
assertThat(3).isEqualTo(commitments.size());
|
||||
assertThat(3).isEqualTo(blobs.size());
|
||||
assertThat(3).isEqualTo(proofs.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,95 +1,5 @@
|
||||
{
|
||||
"request": {
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"method": "engine_forkchoiceUpdatedV3",
|
||||
"params": [
|
||||
{
|
||||
"headBlockHash": "0x33235e7b7a78302cdb54e5ddba66c7ae49b01c1f5498bb00cd0c8ed5206784bf",
|
||||
"safeBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"timestamp": "0x1235",
|
||||
"prevRandao": "0x31a3b9b03c64172b39b7fa7d35d86eaa0f9cbac30e2abbf9895a32b80ae1cd76",
|
||||
"suggestedFeeRecipient": "0x0000000000000000000000000000000000000000",
|
||||
"withdrawals": [
|
||||
{
|
||||
"index": "0x1",
|
||||
"validatorIndex": "0x0",
|
||||
"address": "0x0000000000000000000000000000000000000000",
|
||||
"amount": "0x64"
|
||||
},
|
||||
{
|
||||
"index": "0x2",
|
||||
"validatorIndex": "0x1",
|
||||
"address": "0x0100000000000000000000000000000000000000",
|
||||
"amount": "0x64"
|
||||
},
|
||||
{
|
||||
"index": "0x3",
|
||||
"validatorIndex": "0x2",
|
||||
"address": "0x0200000000000000000000000000000000000000",
|
||||
"amount": "0x64"
|
||||
},
|
||||
{
|
||||
"index": "0x4",
|
||||
"validatorIndex": "0x3",
|
||||
"address": "0x0300000000000000000000000000000000000000",
|
||||
"amount": "0x64"
|
||||
},
|
||||
{
|
||||
"index": "0x5",
|
||||
"validatorIndex": "0x4",
|
||||
"address": "0x0400000000000000000000000000000000000000",
|
||||
"amount": "0x64"
|
||||
},
|
||||
{
|
||||
"index": "0x6",
|
||||
"validatorIndex": "0x5",
|
||||
"address": "0x0500000000000000000000000000000000000000",
|
||||
"amount": "0x64"
|
||||
},
|
||||
{
|
||||
"index": "0x7",
|
||||
"validatorIndex": "0x6",
|
||||
"address": "0x0600000000000000000000000000000000000000",
|
||||
"amount": "0x64"
|
||||
},
|
||||
{
|
||||
"index": "0x8",
|
||||
"validatorIndex": "0x7",
|
||||
"address": "0x0700000000000000000000000000000000000000",
|
||||
"amount": "0x64"
|
||||
},
|
||||
{
|
||||
"index": "0x9",
|
||||
"validatorIndex": "0x8",
|
||||
"address": "0x0800000000000000000000000000000000000000",
|
||||
"amount": "0x64"
|
||||
},
|
||||
{
|
||||
"index": "0xa",
|
||||
"validatorIndex": "0x9",
|
||||
"address": "0x0900000000000000000000000000000000000000",
|
||||
"amount": "0x64"
|
||||
}
|
||||
],
|
||||
"parentBeaconBlockRoot": "0x169630f535b4a41330164c6e5c92b1224c0c407f582d407d0ac3d206cd32fd52"
|
||||
}
|
||||
]
|
||||
},
|
||||
"response": {
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"result": {
|
||||
"payloadStatus": {
|
||||
"status": "VALID",
|
||||
"latestValidHash": "0x33235e7b7a78302cdb54e5ddba66c7ae49b01c1f5498bb00cd0c8ed5206784bf",
|
||||
"validationError": null
|
||||
},
|
||||
"payloadId": "0x78d3b312ed5adeb5"
|
||||
}
|
||||
},
|
||||
"statusCode": 200
|
||||
"request" : {"jsonrpc":"2.0","id":5,"method":"engine_forkchoiceUpdatedV3","params":[{"headBlockHash":"0x33235e7b7a78302cdb54e5ddba66c7ae49b01c1f5498bb00cd0c8ed5206784bf","safeBlockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","finalizedBlockHash":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"timestamp":"0x1236","prevRandao":"0xc13da06dc53836ca0766057413b9683eb9a8773bbb8fcc5691e41c25b56dda1d","suggestedFeeRecipient":"0x0000000000000000000000000000000000000000","withdrawals":[{"index":"0xb","validatorIndex":"0x0","address":"0x0000000000000000000000000000000000000000","amount":"0x64"},{"index":"0xc","validatorIndex":"0x1","address":"0x0100000000000000000000000000000000000000","amount":"0x64"},{"index":"0xd","validatorIndex":"0x2","address":"0x0200000000000000000000000000000000000000","amount":"0x64"},{"index":"0xe","validatorIndex":"0x3","address":"0x0300000000000000000000000000000000000000","amount":"0x64"},{"index":"0xf","validatorIndex":"0x4","address":"0x0400000000000000000000000000000000000000","amount":"0x64"},{"index":"0x10","validatorIndex":"0x5","address":"0x0500000000000000000000000000000000000000","amount":"0x64"},{"index":"0x11","validatorIndex":"0x6","address":"0x0600000000000000000000000000000000000000","amount":"0x64"},{"index":"0x12","validatorIndex":"0x7","address":"0x0700000000000000000000000000000000000000","amount":"0x64"},{"index":"0x13","validatorIndex":"0x8","address":"0x0800000000000000000000000000000000000000","amount":"0x64"},{"index":"0x14","validatorIndex":"0x9","address":"0x0900000000000000000000000000000000000000","amount":"0x64"}],"parentBeaconBlockRoot":"0x062367f0b23e2d49ad5e770d9ad17b83c0c1c625c3f9a290cd9572b3fc6cfc9e"}]},
|
||||
"response" : {"jsonrpc":"2.0","id":5,"result":{"payloadStatus":{"status":"VALID","latestValidHash":"0x33235e7b7a78302cdb54e5ddba66c7ae49b01c1f5498bb00cd0c8ed5206784bf","validationError":null},"payloadId":"0x29e12df730769ab6"}},
|
||||
"statusCode" : 200
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -156,7 +156,13 @@ public class RlpBlockImporter implements Closeable {
|
||||
previousBlockFuture =
|
||||
validationFuture.runAfterBothAsync(
|
||||
calculationFutures,
|
||||
() -> evaluateBlock(context, block, header, protocolSpec, skipPowValidation),
|
||||
() ->
|
||||
evaluateBlock(
|
||||
context,
|
||||
block,
|
||||
header,
|
||||
protocolSchedule.getByBlockHeader(header),
|
||||
skipPowValidation),
|
||||
importExecutor);
|
||||
previousBlockFuture.exceptionally(
|
||||
exception -> {
|
||||
|
||||
@@ -294,7 +294,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
private final ChainPruningOptions unstableChainPruningOptions = ChainPruningOptions.create();
|
||||
|
||||
// stable CLI options
|
||||
private final DataStorageOptions dataStorageOptions = DataStorageOptions.create();
|
||||
final DataStorageOptions dataStorageOptions = DataStorageOptions.create();
|
||||
private final EthstatsOptions ethstatsOptions = EthstatsOptions.create();
|
||||
private final NodePrivateKeyFileOption nodePrivateKeyFileOption =
|
||||
NodePrivateKeyFileOption.create();
|
||||
@@ -1786,6 +1786,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
validateChainDataPruningParams();
|
||||
validatePostMergeCheckpointBlockRequirements();
|
||||
validateTransactionPoolOptions();
|
||||
validateDataStorageOptions();
|
||||
p2pTLSConfigOptions.checkP2PTLSOptionsDependencies(logger, commandLine);
|
||||
pkiBlockCreationOptions.checkPkiBlockCreationOptionsDependencies(logger, commandLine);
|
||||
}
|
||||
@@ -1794,6 +1795,10 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
transactionPoolOptions.validate(commandLine, getActualGenesisConfigOptions());
|
||||
}
|
||||
|
||||
private void validateDataStorageOptions() {
|
||||
dataStorageOptions.validate(commandLine);
|
||||
}
|
||||
|
||||
private void validateRequiredOptions() {
|
||||
commandLine
|
||||
.getCommandSpec()
|
||||
@@ -2826,6 +2831,23 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
txPoolConfBuilder.priceBump(Percentage.ZERO);
|
||||
}
|
||||
|
||||
if (getMiningParameters().getMinTransactionGasPrice().lessThan(txPoolConf.getMinGasPrice())) {
|
||||
if (transactionPoolOptions.isMinGasPriceSet(commandLine)) {
|
||||
throw new ParameterException(
|
||||
commandLine, "tx-pool-min-gas-price cannot be greater than the value of min-gas-price");
|
||||
|
||||
} else {
|
||||
// for backward compatibility, if tx-pool-min-gas-price is not set, we adjust its value
|
||||
// to be the same as min-gas-price, so the behavior is as before this change, and we notify
|
||||
// the user of the change
|
||||
logger.warn(
|
||||
"Forcing tx-pool-min-gas-price="
|
||||
+ getMiningParameters().getMinTransactionGasPrice().toDecimalString()
|
||||
+ ", since it cannot be greater than the value of min-gas-price");
|
||||
txPoolConfBuilder.minGasPrice(getMiningParameters().getMinTransactionGasPrice());
|
||||
}
|
||||
}
|
||||
|
||||
return txPoolConfBuilder.build();
|
||||
}
|
||||
|
||||
@@ -3467,6 +3489,14 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
builder.setHighSpecEnabled();
|
||||
}
|
||||
|
||||
if (dataStorageOptions.toDomainObject().getUnstable().getBonsaiTrieLogPruningEnabled()) {
|
||||
builder.setTrieLogPruningEnabled();
|
||||
builder.setTrieLogRetentionThreshold(
|
||||
dataStorageOptions.toDomainObject().getUnstable().getBonsaiTrieLogRetentionThreshold());
|
||||
builder.setTrieLogPruningLimit(
|
||||
dataStorageOptions.toDomainObject().getUnstable().getBonsaiTrieLogPruningLimit());
|
||||
}
|
||||
|
||||
builder.setTxPoolImplementation(buildTransactionPoolConfiguration().getTxPoolImplementation());
|
||||
builder.setWorldStateUpdateMode(unstableEvmOptions.toDomainObject().worldUpdaterMode());
|
||||
|
||||
|
||||
@@ -50,6 +50,9 @@ public class ConfigurationOverviewBuilder {
|
||||
private Collection<String> engineApis;
|
||||
private String engineJwtFilePath;
|
||||
private boolean isHighSpec = false;
|
||||
private boolean isTrieLogPruningEnabled = false;
|
||||
private long trieLogRetentionThreshold = 0;
|
||||
private Integer trieLogPruningLimit = null;
|
||||
private TransactionPoolConfiguration.Implementation txPoolImplementation;
|
||||
private EvmConfiguration.WorldUpdaterMode worldStateUpdateMode;
|
||||
private Map<String, String> environment;
|
||||
@@ -171,6 +174,38 @@ public class ConfigurationOverviewBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets trie log pruning enabled
|
||||
*
|
||||
* @return the builder
|
||||
*/
|
||||
public ConfigurationOverviewBuilder setTrieLogPruningEnabled() {
|
||||
isTrieLogPruningEnabled = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets trie log retention threshold
|
||||
*
|
||||
* @param threshold the number of blocks to retain trie logs for
|
||||
* @return the builder
|
||||
*/
|
||||
public ConfigurationOverviewBuilder setTrieLogRetentionThreshold(final long threshold) {
|
||||
trieLogRetentionThreshold = threshold;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets trie log pruning limit
|
||||
*
|
||||
* @param limit the max number of blocks to load and prune trie logs for at startup
|
||||
* @return the builder
|
||||
*/
|
||||
public ConfigurationOverviewBuilder setTrieLogPruningLimit(final int limit) {
|
||||
trieLogPruningLimit = limit;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the txpool implementation in use.
|
||||
*
|
||||
@@ -266,13 +301,25 @@ public class ConfigurationOverviewBuilder {
|
||||
lines.add("Engine JWT: " + engineJwtFilePath);
|
||||
}
|
||||
|
||||
lines.add("Using " + txPoolImplementation + " transaction pool implementation");
|
||||
|
||||
if (isHighSpec) {
|
||||
lines.add("Experimental high spec configuration enabled");
|
||||
}
|
||||
|
||||
lines.add("Using " + txPoolImplementation + " transaction pool implementation");
|
||||
lines.add("Using " + worldStateUpdateMode + " worldstate update mode");
|
||||
|
||||
if (isTrieLogPruningEnabled) {
|
||||
final StringBuilder trieLogPruningString = new StringBuilder();
|
||||
trieLogPruningString
|
||||
.append("Trie log pruning enabled: retention: ")
|
||||
.append(trieLogRetentionThreshold);
|
||||
if (trieLogPruningLimit != null) {
|
||||
trieLogPruningString.append("; prune limit: ").append(trieLogPruningLimit);
|
||||
}
|
||||
lines.add(trieLogPruningString.toString());
|
||||
}
|
||||
|
||||
lines.add("");
|
||||
lines.add("Host:");
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
|
||||
private static final String STRICT_TX_REPLAY_PROTECTION_ENABLED_FLAG =
|
||||
"--strict-tx-replay-protection-enabled";
|
||||
private static final String TX_POOL_PRIORITY_SENDERS = "--tx-pool-priority-senders";
|
||||
private static final String TX_POOL_MIN_GAS_PRICE = "--tx-pool-min-gas-price";
|
||||
|
||||
@CommandLine.Option(
|
||||
names = {TX_POOL_IMPLEMENTATION},
|
||||
@@ -122,6 +123,15 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
|
||||
arity = "1..*")
|
||||
private Set<Address> prioritySenders = TransactionPoolConfiguration.DEFAULT_PRIORITY_SENDERS;
|
||||
|
||||
@CommandLine.Option(
|
||||
names = {TX_POOL_MIN_GAS_PRICE},
|
||||
paramLabel = "<Wei>",
|
||||
description =
|
||||
"Transactions with gas price (in Wei) lower than this minimum will not be accepted into the txpool"
|
||||
+ "(not to be confused with min-gas-price, that is applied on block creation) (default: ${DEFAULT-VALUE})",
|
||||
arity = "1")
|
||||
private Wei minGasPrice = TransactionPoolConfiguration.DEFAULT_TX_POOL_MIN_GAS_PRICE;
|
||||
|
||||
@CommandLine.ArgGroup(
|
||||
validate = false,
|
||||
heading = "@|bold Tx Pool Layered Implementation Options|@%n")
|
||||
@@ -257,6 +267,7 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
|
||||
options.saveFile = config.getSaveFile();
|
||||
options.strictTxReplayProtectionEnabled = config.getStrictTransactionReplayProtectionEnabled();
|
||||
options.prioritySenders = config.getPrioritySenders();
|
||||
options.minGasPrice = config.getMinGasPrice();
|
||||
options.layeredOptions.txPoolLayerMaxCapacity =
|
||||
config.getPendingTransactionsLayerMaxCapacityBytes();
|
||||
options.layeredOptions.txPoolMaxPrioritized = config.getMaxPrioritizedTransactions();
|
||||
@@ -312,6 +323,7 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
|
||||
.saveFile(saveFile)
|
||||
.strictTransactionReplayProtectionEnabled(strictTxReplayProtectionEnabled)
|
||||
.prioritySenders(prioritySenders)
|
||||
.minGasPrice(minGasPrice)
|
||||
.pendingTransactionsLayerMaxCapacityBytes(layeredOptions.txPoolLayerMaxCapacity)
|
||||
.maxPrioritizedTransactions(layeredOptions.txPoolMaxPrioritized)
|
||||
.maxFutureBySender(layeredOptions.txPoolMaxFutureBySender)
|
||||
@@ -340,4 +352,14 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
|
||||
public boolean isPriceBumpSet(final CommandLine commandLine) {
|
||||
return CommandLineUtils.isOptionSet(commandLine, TransactionPoolOptions.TX_POOL_PRICE_BUMP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is min gas price option set?
|
||||
*
|
||||
* @param commandLine the command line
|
||||
* @return true if tx-pool-min-gas-price is set
|
||||
*/
|
||||
public boolean isMinGasPriceSet(final CommandLine commandLine) {
|
||||
return CommandLineUtils.isOptionSet(commandLine, TransactionPoolOptions.TX_POOL_MIN_GAS_PRICE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,13 @@
|
||||
package org.hyperledger.besu.cli.options.stable;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD;
|
||||
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.DEFAULT_BONSAI_TRIE_LOG_PRUNING_ENABLED;
|
||||
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.DEFAULT_BONSAI_TRIE_LOG_PRUNING_LIMIT;
|
||||
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.DEFAULT_BONSAI_TRIE_LOG_RETENTION_THRESHOLD;
|
||||
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.MINIMUM_BONSAI_TRIE_LOG_RETENTION_THRESHOLD;
|
||||
|
||||
import org.hyperledger.besu.cli.options.CLIOptions;
|
||||
import org.hyperledger.besu.cli.util.CommandLineUtils;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
|
||||
import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration;
|
||||
@@ -26,6 +31,7 @@ import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguratio
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import picocli.CommandLine;
|
||||
import picocli.CommandLine.Option;
|
||||
|
||||
/** The Data storage CLI options. */
|
||||
@@ -42,7 +48,7 @@ public class DataStorageOptions implements CLIOptions<DataStorageConfiguration>
|
||||
description =
|
||||
"Format to store trie data in. Either FOREST or BONSAI (default: ${DEFAULT-VALUE}).",
|
||||
arity = "1")
|
||||
private final DataStorageFormat dataStorageFormat = DataStorageFormat.FOREST;
|
||||
private DataStorageFormat dataStorageFormat = DataStorageFormat.FOREST;
|
||||
|
||||
@Option(
|
||||
names = {BONSAI_STORAGE_FORMAT_MAX_LAYERS_TO_LOAD, "--bonsai-maximum-back-layers-to-load"},
|
||||
@@ -50,8 +56,33 @@ public class DataStorageOptions implements CLIOptions<DataStorageConfiguration>
|
||||
description =
|
||||
"Limit of historical layers that can be loaded with BONSAI (default: ${DEFAULT-VALUE}).",
|
||||
arity = "1")
|
||||
private final Long bonsaiMaxLayersToLoad = DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD;
|
||||
private Long bonsaiMaxLayersToLoad = DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD;
|
||||
|
||||
@CommandLine.ArgGroup(validate = false)
|
||||
private final DataStorageOptions.Unstable unstableOptions = new Unstable();
|
||||
|
||||
static class Unstable {
|
||||
|
||||
@CommandLine.Option(
|
||||
hidden = true,
|
||||
names = {"--Xbonsai-trie-log-pruning-enabled"},
|
||||
description = "Enable trie log pruning. (default: ${DEFAULT-VALUE})")
|
||||
private boolean bonsaiTrieLogPruningEnabled = DEFAULT_BONSAI_TRIE_LOG_PRUNING_ENABLED;
|
||||
|
||||
@CommandLine.Option(
|
||||
hidden = true,
|
||||
names = {"--Xbonsai-trie-log-retention-threshold"},
|
||||
description =
|
||||
"The number of blocks for which to retain trie logs. (default: ${DEFAULT-VALUE})")
|
||||
private long bonsaiTrieLogRetentionThreshold = DEFAULT_BONSAI_TRIE_LOG_RETENTION_THRESHOLD;
|
||||
|
||||
@CommandLine.Option(
|
||||
hidden = true,
|
||||
names = {"--Xbonsai-trie-log-pruning-limit"},
|
||||
description =
|
||||
"The max number of blocks to load and prune trie logs for at startup. (default: ${DEFAULT-VALUE})")
|
||||
private int bonsaiTrieLogPruningLimit = DEFAULT_BONSAI_TRIE_LOG_PRUNING_LIMIT;
|
||||
}
|
||||
/**
|
||||
* Create data storage options.
|
||||
*
|
||||
@@ -61,21 +92,62 @@ public class DataStorageOptions implements CLIOptions<DataStorageConfiguration>
|
||||
return new DataStorageOptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the data storage options
|
||||
*
|
||||
* @param commandLine the full commandLine to check all the options specified by the user
|
||||
*/
|
||||
public void validate(final CommandLine commandLine) {
|
||||
if (unstableOptions.bonsaiTrieLogPruningEnabled) {
|
||||
if (unstableOptions.bonsaiTrieLogRetentionThreshold
|
||||
< MINIMUM_BONSAI_TRIE_LOG_RETENTION_THRESHOLD) {
|
||||
throw new CommandLine.ParameterException(
|
||||
commandLine,
|
||||
String.format(
|
||||
"--Xbonsai-trie-log-retention-threshold minimum value is %d",
|
||||
MINIMUM_BONSAI_TRIE_LOG_RETENTION_THRESHOLD));
|
||||
}
|
||||
if (unstableOptions.bonsaiTrieLogPruningLimit <= 0) {
|
||||
throw new CommandLine.ParameterException(
|
||||
commandLine,
|
||||
String.format(
|
||||
"--Xbonsai-trie-log-pruning-limit=%d must be greater than 0",
|
||||
unstableOptions.bonsaiTrieLogPruningLimit));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DataStorageOptions fromConfig(final DataStorageConfiguration domainObject) {
|
||||
final DataStorageOptions dataStorageOptions = DataStorageOptions.create();
|
||||
dataStorageOptions.dataStorageFormat = domainObject.getDataStorageFormat();
|
||||
dataStorageOptions.bonsaiMaxLayersToLoad = domainObject.getBonsaiMaxLayersToLoad();
|
||||
dataStorageOptions.unstableOptions.bonsaiTrieLogPruningEnabled =
|
||||
domainObject.getUnstable().getBonsaiTrieLogPruningEnabled();
|
||||
dataStorageOptions.unstableOptions.bonsaiTrieLogRetentionThreshold =
|
||||
domainObject.getUnstable().getBonsaiTrieLogRetentionThreshold();
|
||||
dataStorageOptions.unstableOptions.bonsaiTrieLogPruningLimit =
|
||||
domainObject.getUnstable().getBonsaiTrieLogPruningLimit();
|
||||
|
||||
return dataStorageOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataStorageConfiguration toDomainObject() {
|
||||
return ImmutableDataStorageConfiguration.builder()
|
||||
.dataStorageFormat(dataStorageFormat)
|
||||
.bonsaiMaxLayersToLoad(bonsaiMaxLayersToLoad)
|
||||
.unstable(
|
||||
ImmutableDataStorageConfiguration.Unstable.builder()
|
||||
.bonsaiTrieLogPruningEnabled(unstableOptions.bonsaiTrieLogPruningEnabled)
|
||||
.bonsaiTrieLogRetentionThreshold(unstableOptions.bonsaiTrieLogRetentionThreshold)
|
||||
.bonsaiTrieLogPruningLimit(unstableOptions.bonsaiTrieLogPruningLimit)
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getCLIOptions() {
|
||||
return List.of(
|
||||
DATA_STORAGE_FORMAT,
|
||||
dataStorageFormat.toString(),
|
||||
BONSAI_STORAGE_FORMAT_MAX_LAYERS_TO_LOAD,
|
||||
bonsaiMaxLayersToLoad.toString());
|
||||
return CommandLineUtils.getCLIOptions(this, new DataStorageOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,6 +19,8 @@ package org.hyperledger.besu.components;
|
||||
import org.hyperledger.besu.cli.BesuCommand;
|
||||
import org.hyperledger.besu.ethereum.bonsai.cache.CachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.bonsai.cache.CachedMerkleTrieLoaderModule;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.BlobCache;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.BlobCacheModule;
|
||||
import org.hyperledger.besu.metrics.MetricsSystemModule;
|
||||
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
|
||||
import org.hyperledger.besu.services.BesuPluginContextImpl;
|
||||
@@ -36,7 +38,8 @@ import org.slf4j.Logger;
|
||||
BesuCommandModule.class,
|
||||
MetricsSystemModule.class,
|
||||
CachedMerkleTrieLoaderModule.class,
|
||||
BesuPluginContextModule.class
|
||||
BesuPluginContextModule.class,
|
||||
BlobCacheModule.class
|
||||
})
|
||||
public interface BesuComponent {
|
||||
|
||||
@@ -72,8 +75,15 @@ public interface BesuComponent {
|
||||
/**
|
||||
* Besu plugin context for doing plugin service discovery.
|
||||
*
|
||||
* @return BesuComponent
|
||||
* @return BesuPluginContextImpl
|
||||
*/
|
||||
@Named("besuPluginContext")
|
||||
BesuPluginContextImpl getBesuPluginContext();
|
||||
|
||||
/**
|
||||
* Cache to store blobs in for re-use after reorgs.
|
||||
*
|
||||
* @return BlobCache
|
||||
*/
|
||||
BlobCache getBlobCache();
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
|
||||
import org.hyperledger.besu.ethereum.bonsai.BonsaiWorldStateProvider;
|
||||
import org.hyperledger.besu.ethereum.bonsai.cache.CachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.bonsai.trielog.TrieLogPruner;
|
||||
import org.hyperledger.besu.ethereum.chain.Blockchain;
|
||||
import org.hyperledger.besu.ethereum.chain.BlockchainStorage;
|
||||
import org.hyperledger.besu.ethereum.chain.ChainDataPruner;
|
||||
@@ -73,6 +74,7 @@ import org.hyperledger.besu.ethereum.eth.sync.fastsync.checkpoint.Checkpoint;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.fastsync.checkpoint.ImmutableCheckpoint;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.fullsync.SyncTerminationCondition;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.BlobCache;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolFactory;
|
||||
@@ -720,9 +722,9 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
|
||||
clock,
|
||||
metricsSystem,
|
||||
syncState,
|
||||
miningParameters,
|
||||
transactionPoolConfiguration,
|
||||
pluginTransactionValidatorFactory);
|
||||
pluginTransactionValidatorFactory,
|
||||
besuComponent.map(BesuComponent::getBlobCache).orElse(new BlobCache()));
|
||||
|
||||
final List<PeerValidator> peerValidators = createPeerValidators(protocolSchedule);
|
||||
|
||||
@@ -1064,14 +1066,30 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
|
||||
final Blockchain blockchain,
|
||||
final CachedMerkleTrieLoader cachedMerkleTrieLoader) {
|
||||
return switch (dataStorageConfiguration.getDataStorageFormat()) {
|
||||
case BONSAI -> new BonsaiWorldStateProvider(
|
||||
(BonsaiWorldStateKeyValueStorage) worldStateStorage,
|
||||
blockchain,
|
||||
Optional.of(dataStorageConfiguration.getBonsaiMaxLayersToLoad()),
|
||||
cachedMerkleTrieLoader,
|
||||
metricsSystem,
|
||||
besuComponent.map(BesuComponent::getBesuPluginContext).orElse(null),
|
||||
evmConfiguration);
|
||||
case BONSAI -> {
|
||||
final GenesisConfigOptions genesisConfigOptions = configOptionsSupplier.get();
|
||||
final boolean isProofOfStake =
|
||||
genesisConfigOptions.getTerminalTotalDifficulty().isPresent();
|
||||
final TrieLogPruner trieLogPruner =
|
||||
dataStorageConfiguration.getUnstable().getBonsaiTrieLogPruningEnabled()
|
||||
? new TrieLogPruner(
|
||||
(BonsaiWorldStateKeyValueStorage) worldStateStorage,
|
||||
blockchain,
|
||||
dataStorageConfiguration.getUnstable().getBonsaiTrieLogRetentionThreshold(),
|
||||
dataStorageConfiguration.getUnstable().getBonsaiTrieLogPruningLimit(),
|
||||
isProofOfStake)
|
||||
: TrieLogPruner.noOpTrieLogPruner();
|
||||
trieLogPruner.initialize();
|
||||
yield new BonsaiWorldStateProvider(
|
||||
(BonsaiWorldStateKeyValueStorage) worldStateStorage,
|
||||
blockchain,
|
||||
Optional.of(dataStorageConfiguration.getBonsaiMaxLayersToLoad()),
|
||||
cachedMerkleTrieLoader,
|
||||
metricsSystem,
|
||||
besuComponent.map(BesuComponent::getBesuPluginContext).orElse(null),
|
||||
evmConfiguration,
|
||||
trieLogPruner);
|
||||
}
|
||||
case FOREST -> {
|
||||
final WorldStatePreimageStorage preimageStorage =
|
||||
storageProvider.createWorldStatePreimageStorage();
|
||||
|
||||
@@ -5248,6 +5248,31 @@ public class BesuCommandTest extends CommandTestAbstract {
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void txpoolWhenNotSetForceTxPoolMinGasPriceToZeroWhenMinGasPriceZero() {
|
||||
parseCommand("--min-gas-price", "0");
|
||||
verify(mockControllerBuilder)
|
||||
.transactionPoolConfiguration(transactionPoolConfigCaptor.capture());
|
||||
|
||||
final Wei txPoolMinGasPrice = transactionPoolConfigCaptor.getValue().getMinGasPrice();
|
||||
assertThat(txPoolMinGasPrice).isEqualTo(Wei.ZERO);
|
||||
|
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty();
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
|
||||
verify(mockLogger, atLeast(1))
|
||||
.warn(
|
||||
contains(
|
||||
"Forcing tx-pool-min-gas-price=0, since it cannot be greater than the value of min-gas-price"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void txpoolTxPoolMinGasPriceMustNotBeGreaterThanMinGasPriceZero() {
|
||||
parseCommand("--min-gas-price", "100", "--tx-pool-min-gas-price", "101");
|
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty();
|
||||
assertThat(commandErrorOutput.toString(UTF_8))
|
||||
.contains("tx-pool-min-gas-price cannot be greater than the value of min-gas-price");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void snapsyncHealingOptionShouldBeDisabledByDefault() {
|
||||
final TestBesuCommand besuCommand = parseCommand();
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.hyperledger.besu.chainimport.RlpBlockImporter;
|
||||
import org.hyperledger.besu.cli.config.EthNetworkConfig;
|
||||
import org.hyperledger.besu.cli.options.MiningOptions;
|
||||
import org.hyperledger.besu.cli.options.TransactionPoolOptions;
|
||||
import org.hyperledger.besu.cli.options.stable.DataStorageOptions;
|
||||
import org.hyperledger.besu.cli.options.stable.EthstatsOptions;
|
||||
import org.hyperledger.besu.cli.options.unstable.EthProtocolOptions;
|
||||
import org.hyperledger.besu.cli.options.unstable.MetricsCLIOptions;
|
||||
@@ -568,6 +569,10 @@ public abstract class CommandTestAbstract {
|
||||
return transactionPoolOptions;
|
||||
}
|
||||
|
||||
public DataStorageOptions getDataStorageOptions() {
|
||||
return dataStorageOptions;
|
||||
}
|
||||
|
||||
public MetricsCLIOptions getMetricsCLIOptions() {
|
||||
return unstableMetricsCLIOptions;
|
||||
}
|
||||
|
||||
@@ -148,6 +148,24 @@ class ConfigurationOverviewBuilderTest {
|
||||
assertThat(highSpecEnabled).contains("Experimental high spec configuration enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
void setTrieLogPruningEnabled() {
|
||||
final String noTrieLogRetentionThresholdSet = builder.build();
|
||||
assertThat(noTrieLogRetentionThresholdSet).doesNotContain("Trie log pruning enabled");
|
||||
|
||||
builder.setTrieLogPruningEnabled();
|
||||
builder.setTrieLogRetentionThreshold(42);
|
||||
String trieLogRetentionThresholdSet = builder.build();
|
||||
assertThat(trieLogRetentionThresholdSet)
|
||||
.contains("Trie log pruning enabled")
|
||||
.contains("retention: 42");
|
||||
assertThat(trieLogRetentionThresholdSet).doesNotContain("prune limit");
|
||||
|
||||
builder.setTrieLogPruningLimit(1000);
|
||||
trieLogRetentionThresholdSet = builder.build();
|
||||
assertThat(trieLogRetentionThresholdSet).contains("prune limit: 1000");
|
||||
}
|
||||
|
||||
@Test
|
||||
void setTxPoolImplementationLayered() {
|
||||
builder.setTxPoolImplementation(LAYERED);
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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.cli.options.stable;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.MINIMUM_BONSAI_TRIE_LOG_RETENTION_THRESHOLD;
|
||||
|
||||
import org.hyperledger.besu.cli.options.AbstractCLIOptionsTest;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
|
||||
import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class DataStorageOptionsTest
|
||||
extends AbstractCLIOptionsTest<DataStorageConfiguration, DataStorageOptions> {
|
||||
|
||||
@Test
|
||||
public void bonsaiTrieLogPruningLimitOption() {
|
||||
internalTestSuccess(
|
||||
dataStorageConfiguration ->
|
||||
assertThat(dataStorageConfiguration.getUnstable().getBonsaiTrieLogPruningLimit())
|
||||
.isEqualTo(1),
|
||||
"--Xbonsai-trie-log-pruning-enabled",
|
||||
"--Xbonsai-trie-log-pruning-limit",
|
||||
"1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bonsaiTrieLogPruningLimitShouldBePositive() {
|
||||
internalTestFailure(
|
||||
"--Xbonsai-trie-log-pruning-limit=0 must be greater than 0",
|
||||
"--Xbonsai-trie-log-pruning-enabled",
|
||||
"--Xbonsai-trie-log-pruning-limit",
|
||||
"0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bonsaiTrieLogRetentionThresholdOption() {
|
||||
internalTestSuccess(
|
||||
dataStorageConfiguration ->
|
||||
assertThat(dataStorageConfiguration.getUnstable().getBonsaiTrieLogRetentionThreshold())
|
||||
.isEqualTo(MINIMUM_BONSAI_TRIE_LOG_RETENTION_THRESHOLD + 1),
|
||||
"--Xbonsai-trie-log-pruning-enabled",
|
||||
"--Xbonsai-trie-log-retention-threshold",
|
||||
"513");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bonsaiTrieLogRetentionThresholdOption_boundaryTest() {
|
||||
internalTestSuccess(
|
||||
dataStorageConfiguration ->
|
||||
assertThat(dataStorageConfiguration.getUnstable().getBonsaiTrieLogRetentionThreshold())
|
||||
.isEqualTo(MINIMUM_BONSAI_TRIE_LOG_RETENTION_THRESHOLD),
|
||||
"--Xbonsai-trie-log-pruning-enabled",
|
||||
"--Xbonsai-trie-log-retention-threshold",
|
||||
"512");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bonsaiTrieLogRetentionThresholdShouldBeAboveMinimum() {
|
||||
internalTestFailure(
|
||||
"--Xbonsai-trie-log-retention-threshold minimum value is 512",
|
||||
"--Xbonsai-trie-log-pruning-enabled",
|
||||
"--Xbonsai-trie-log-retention-threshold",
|
||||
"511");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataStorageConfiguration createDefaultDomainObject() {
|
||||
return DataStorageConfiguration.DEFAULT_CONFIG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataStorageConfiguration createCustomizedDomainObject() {
|
||||
return ImmutableDataStorageConfiguration.builder()
|
||||
.dataStorageFormat(DataStorageFormat.BONSAI)
|
||||
.bonsaiMaxLayersToLoad(100L)
|
||||
.unstable(
|
||||
ImmutableDataStorageConfiguration.Unstable.builder()
|
||||
.bonsaiTrieLogPruningEnabled(true)
|
||||
.bonsaiTrieLogRetentionThreshold(1000L)
|
||||
.bonsaiTrieLogPruningLimit(20)
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataStorageOptions optionsFromDomainObject(
|
||||
final DataStorageConfiguration domainObject) {
|
||||
return DataStorageOptions.fromConfig(domainObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataStorageOptions getOptionsFromBesuCommand(final TestBesuCommand besuCommand) {
|
||||
return besuCommand.getDataStorageOptions();
|
||||
}
|
||||
}
|
||||
@@ -33,8 +33,6 @@ import org.hyperledger.besu.ethereum.core.BlockBody;
|
||||
import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.Difficulty;
|
||||
import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters;
|
||||
import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues;
|
||||
import org.hyperledger.besu.ethereum.core.MutableWorldState;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionTestFixture;
|
||||
@@ -45,6 +43,7 @@ import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.BlockBroadcaster;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.BlobCache;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
|
||||
@@ -146,7 +145,10 @@ public class BesuEventsImplTest {
|
||||
blockBroadcaster = new BlockBroadcaster(mockEthContext);
|
||||
syncState = new SyncState(blockchain, mockEthPeers);
|
||||
TransactionPoolConfiguration txPoolConfig =
|
||||
ImmutableTransactionPoolConfiguration.builder().txPoolMaxSize(1).build();
|
||||
ImmutableTransactionPoolConfiguration.builder()
|
||||
.txPoolMaxSize(1)
|
||||
.minGasPrice(Wei.ZERO)
|
||||
.build();
|
||||
|
||||
transactionPool =
|
||||
TransactionPoolFactory.createTransactionPool(
|
||||
@@ -156,12 +158,9 @@ public class BesuEventsImplTest {
|
||||
TestClock.system(ZoneId.systemDefault()),
|
||||
new NoOpMetricsSystem(),
|
||||
syncState,
|
||||
ImmutableMiningParameters.builder()
|
||||
.mutableInitValues(
|
||||
MutableInitValues.builder().minTransactionGasPrice(Wei.ZERO).build())
|
||||
.build(),
|
||||
txPoolConfig,
|
||||
null);
|
||||
null,
|
||||
new BlobCache());
|
||||
|
||||
serviceImpl = new BesuEventsImpl(blockchain, blockBroadcaster, transactionPool, syncState);
|
||||
}
|
||||
|
||||
@@ -188,6 +188,7 @@ tx-pool-max-future-by-sender=321
|
||||
tx-pool-retention-hours=999
|
||||
tx-pool-max-size=1234
|
||||
tx-pool-limit-by-account-percentage=0.017
|
||||
tx-pool-min-gas-price=1000
|
||||
|
||||
# Revert Reason
|
||||
revert-reason-enabled=false
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
* Copyright Hyperledger Besu contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -238,7 +238,6 @@ public class CliqueBlockCreatorTest {
|
||||
protocolContext,
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
mock(MiningParameters.class),
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
conf,
|
||||
null);
|
||||
|
||||
@@ -222,7 +222,6 @@ public class CliqueMinerExecutorTest {
|
||||
cliqueProtocolContext,
|
||||
mock(TransactionBroadcaster.class),
|
||||
cliqueEthContext,
|
||||
mock(MiningParameters.class),
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
conf,
|
||||
null);
|
||||
|
||||
@@ -362,7 +362,6 @@ public class TestContextBuilder {
|
||||
protocolContext,
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
miningParams,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf,
|
||||
null);
|
||||
|
||||
@@ -146,7 +146,6 @@ public class BftBlockCreatorTest {
|
||||
protContext,
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
mock(MiningParameters.class),
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf,
|
||||
null);
|
||||
|
||||
@@ -491,7 +491,7 @@ public class MergeCoordinator implements MergeMiningCoordinator, BadChainListene
|
||||
|
||||
if (maybeHeadHeader.isPresent()) {
|
||||
LOG.atDebug()
|
||||
.setMessage("BlockHeader {} is already present")
|
||||
.setMessage("BlockHeader {} is already present in blockchain")
|
||||
.addArgument(maybeHeadHeader.get()::toLogString)
|
||||
.log();
|
||||
} else {
|
||||
|
||||
@@ -227,7 +227,6 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
|
||||
protocolContext,
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
miningParameters,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf,
|
||||
null);
|
||||
|
||||
@@ -450,7 +450,6 @@ public class TestContextBuilder {
|
||||
protocolContext,
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
miningParams,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf,
|
||||
null);
|
||||
|
||||
@@ -17,6 +17,8 @@ package org.hyperledger.besu.datatypes;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPInput;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
|
||||
/** Arbitrary data for use in the KZG scheme. */
|
||||
@@ -61,4 +63,17 @@ public class Blob {
|
||||
public Bytes getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Blob blob = (Blob) o;
|
||||
return Objects.equals(getData(), blob.getData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getData());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,15 +15,18 @@
|
||||
package org.hyperledger.besu.datatypes;
|
||||
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/** A class to hold the blobs, commitments, proofs and versioned hashes for a set of blobs. */
|
||||
public class BlobsWithCommitments {
|
||||
private final List<KZGCommitment> kzgCommitments;
|
||||
private final List<Blob> blobs;
|
||||
private final List<KZGProof> kzgProofs;
|
||||
|
||||
private final List<VersionedHash> versionedHashes;
|
||||
/** A record to hold the blob, commitment, proof and versioned hash for a blob. */
|
||||
public record BlobQuad(
|
||||
Blob blob, KZGCommitment kzgCommitment, KZGProof kzgProof, VersionedHash versionedHash) {}
|
||||
|
||||
private final List<BlobQuad> blobQuads;
|
||||
|
||||
/**
|
||||
* A class to hold the blobs, commitments and proofs for a set of blobs.
|
||||
@@ -38,7 +41,7 @@ public class BlobsWithCommitments {
|
||||
final List<Blob> blobs,
|
||||
final List<KZGProof> kzgProofs,
|
||||
final List<VersionedHash> versionedHashes) {
|
||||
if (blobs.size() == 0) {
|
||||
if (blobs.isEmpty()) {
|
||||
throw new InvalidParameterException(
|
||||
"There needs to be a minimum of one blob in a blob transaction with commitments");
|
||||
}
|
||||
@@ -48,10 +51,22 @@ public class BlobsWithCommitments {
|
||||
throw new InvalidParameterException(
|
||||
"There must be an equal number of blobs, commitments, proofs, and versioned hashes");
|
||||
}
|
||||
this.kzgCommitments = kzgCommitments;
|
||||
this.blobs = blobs;
|
||||
this.kzgProofs = kzgProofs;
|
||||
this.versionedHashes = versionedHashes;
|
||||
List<BlobQuad> toBuild = new ArrayList<>(blobs.size());
|
||||
for (int i = 0; i < blobs.size(); i++) {
|
||||
toBuild.add(
|
||||
new BlobQuad(
|
||||
blobs.get(i), kzgCommitments.get(i), kzgProofs.get(i), versionedHashes.get(i)));
|
||||
}
|
||||
this.blobQuads = toBuild;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the class from a list of BlobQuads.
|
||||
*
|
||||
* @param quads the list of blob quads to be attached to the transaction
|
||||
*/
|
||||
public BlobsWithCommitments(final List<BlobQuad> quads) {
|
||||
this.blobQuads = quads;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,7 +75,7 @@ public class BlobsWithCommitments {
|
||||
* @return the blobs
|
||||
*/
|
||||
public List<Blob> getBlobs() {
|
||||
return blobs;
|
||||
return blobQuads.stream().map(BlobQuad::blob).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,7 +84,7 @@ public class BlobsWithCommitments {
|
||||
* @return the commitments
|
||||
*/
|
||||
public List<KZGCommitment> getKzgCommitments() {
|
||||
return kzgCommitments;
|
||||
return blobQuads.stream().map(BlobQuad::kzgCommitment).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,7 +93,7 @@ public class BlobsWithCommitments {
|
||||
* @return the proofs
|
||||
*/
|
||||
public List<KZGProof> getKzgProofs() {
|
||||
return kzgProofs;
|
||||
return blobQuads.stream().map(BlobQuad::kzgProof).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,6 +102,28 @@ public class BlobsWithCommitments {
|
||||
* @return the hashes
|
||||
*/
|
||||
public List<VersionedHash> getVersionedHashes() {
|
||||
return versionedHashes;
|
||||
return blobQuads.stream().map(BlobQuad::versionedHash).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of BlobQuads.
|
||||
*
|
||||
* @return blob quads
|
||||
*/
|
||||
public List<BlobQuad> getBlobQuads() {
|
||||
return blobQuads;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
BlobsWithCommitments that = (BlobsWithCommitments) o;
|
||||
return Objects.equals(getBlobQuads(), that.getBlobQuads());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getBlobQuads());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ package org.hyperledger.besu.datatypes;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPInput;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes48;
|
||||
|
||||
/** This class contains the data for a KZG commitment. */
|
||||
@@ -60,4 +62,17 @@ public class KZGCommitment {
|
||||
public Bytes48 getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
KZGCommitment that = (KZGCommitment) o;
|
||||
return Objects.equals(getData(), that.getData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getData());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ package org.hyperledger.besu.datatypes;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPInput;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes48;
|
||||
|
||||
/** This class contains the data for a KZG proof for a KZG commitment. */
|
||||
@@ -60,4 +62,17 @@ public class KZGProof {
|
||||
public Bytes48 getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
KZGProof kzgProof = (KZGProof) o;
|
||||
return Objects.equals(getData(), kzgProof.getData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getData());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@ 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.ExecutionContextTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
@@ -119,7 +118,6 @@ public class EthGetFilterChangesIntegrationTest {
|
||||
protocolContext,
|
||||
batchAddedListener,
|
||||
ethContext,
|
||||
MiningParameters.newDefault(),
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
TransactionPoolConfiguration.DEFAULT,
|
||||
null);
|
||||
|
||||
@@ -44,7 +44,6 @@ 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.ExecutionContextTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
@@ -119,7 +118,6 @@ public class EthGetFilterChangesIntegrationTest {
|
||||
protocolContext,
|
||||
batchAddedListener,
|
||||
ethContext,
|
||||
MiningParameters.newDefault(),
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
TransactionPoolConfiguration.DEFAULT,
|
||||
null);
|
||||
|
||||
@@ -71,14 +71,14 @@ public class JsonRpcErrorConverter {
|
||||
return RpcErrorType.ETH_SEND_TX_REPLACEMENT_UNDERPRICED;
|
||||
case NONCE_TOO_FAR_IN_FUTURE_FOR_SENDER:
|
||||
return RpcErrorType.NONCE_TOO_FAR_IN_FUTURE_FOR_SENDER;
|
||||
case LOWER_NONCE_INVALID_TRANSACTION_EXISTS:
|
||||
return RpcErrorType.LOWER_NONCE_INVALID_TRANSACTION_EXISTS;
|
||||
case TOTAL_BLOB_GAS_TOO_HIGH:
|
||||
return RpcErrorType.TOTAL_BLOB_GAS_TOO_HIGH;
|
||||
case TX_POOL_DISABLED:
|
||||
return RpcErrorType.TX_POOL_DISABLED;
|
||||
case PLUGIN_TX_VALIDATOR:
|
||||
return RpcErrorType.PLUGIN_TX_VALIDATOR;
|
||||
case INVALID_BLOBS:
|
||||
return RpcErrorType.INVALID_BLOBS;
|
||||
default:
|
||||
return RpcErrorType.INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ public enum RpcMethod {
|
||||
DEBUG_STANDARD_TRACE_BLOCK_TO_FILE("debug_standardTraceBlockToFile"),
|
||||
DEBUG_STANDARD_TRACE_BAD_BLOCK_TO_FILE("debug_standardTraceBadBlockToFile"),
|
||||
DEBUG_TRACE_TRANSACTION("debug_traceTransaction"),
|
||||
DEBUG_TRACE_CALL("debug_traceCall"),
|
||||
DEBUG_BATCH_RAW_TRANSACTION("debug_batchSendRawTransaction"),
|
||||
DEBUG_GET_BAD_BLOCKS("debug_getBadBlocks"),
|
||||
DEBUG_GET_RAW_HEADER("debug_getRawHeader"),
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 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 static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType.BLOCK_NOT_FOUND;
|
||||
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType.INTERNAL_ERROR;
|
||||
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonCallParameter;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
|
||||
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.debug.TraceOptions;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.transaction.PreCloseStateHandler;
|
||||
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
|
||||
import org.hyperledger.besu.ethereum.vm.DebugOperationTracer;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class AbstractTraceCall extends AbstractTraceByBlock {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AbstractTraceCall.class);
|
||||
|
||||
public AbstractTraceCall(
|
||||
final BlockchainQueries blockchainQueries,
|
||||
final ProtocolSchedule protocolSchedule,
|
||||
final TransactionSimulator transactionSimulator) {
|
||||
super(blockchainQueries, protocolSchedule, transactionSimulator);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object resultByBlockNumber(
|
||||
final JsonRpcRequestContext requestContext, final long blockNumber) {
|
||||
final JsonCallParameter callParams =
|
||||
JsonCallParameterUtil.validateAndGetCallParams(requestContext);
|
||||
final TraceOptions traceOptions = getTraceOptions(requestContext);
|
||||
final String blockNumberString = String.valueOf(blockNumber);
|
||||
LOG.atTrace()
|
||||
.setMessage("Received RPC rpcName={} callParams={} block={} traceTypes={}")
|
||||
.addArgument(this::getName)
|
||||
.addArgument(callParams)
|
||||
.addArgument(blockNumberString)
|
||||
.addArgument(traceOptions)
|
||||
.log();
|
||||
|
||||
final Optional<BlockHeader> maybeBlockHeader =
|
||||
blockchainQueriesSupplier.get().getBlockHeaderByNumber(blockNumber);
|
||||
|
||||
if (maybeBlockHeader.isEmpty()) {
|
||||
return new JsonRpcErrorResponse(requestContext.getRequest().getId(), BLOCK_NOT_FOUND);
|
||||
}
|
||||
|
||||
final DebugOperationTracer tracer = new DebugOperationTracer(traceOptions);
|
||||
return transactionSimulator
|
||||
.process(
|
||||
callParams,
|
||||
buildTransactionValidationParams(),
|
||||
tracer,
|
||||
getSimulatorResultHandler(requestContext, tracer),
|
||||
maybeBlockHeader.get())
|
||||
.orElseGet(
|
||||
() -> new JsonRpcErrorResponse(requestContext.getRequest().getId(), INTERNAL_ERROR));
|
||||
}
|
||||
|
||||
protected abstract TraceOptions getTraceOptions(final JsonRpcRequestContext requestContext);
|
||||
|
||||
protected abstract PreCloseStateHandler<Object> getSimulatorResultHandler(
|
||||
final JsonRpcRequestContext requestContext, final DebugOperationTracer tracer);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 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 static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType.INTERNAL_ERROR;
|
||||
|
||||
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.parameters.TransactionTraceParams;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.TransactionTrace;
|
||||
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.DebugTraceTransactionResult;
|
||||
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
|
||||
import org.hyperledger.besu.ethereum.debug.TraceOptions;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.transaction.PreCloseStateHandler;
|
||||
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
|
||||
import org.hyperledger.besu.ethereum.vm.DebugOperationTracer;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class DebugTraceCall extends AbstractTraceCall {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DebugTraceCall.class);
|
||||
|
||||
public DebugTraceCall(
|
||||
final BlockchainQueries blockchainQueries,
|
||||
final ProtocolSchedule protocolSchedule,
|
||||
final TransactionSimulator transactionSimulator) {
|
||||
super(blockchainQueries, protocolSchedule, transactionSimulator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return RpcMethod.DEBUG_TRACE_CALL.getMethodName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TraceOptions getTraceOptions(final JsonRpcRequestContext requestContext) {
|
||||
return requestContext
|
||||
.getOptionalParameter(2, TransactionTraceParams.class)
|
||||
.map(TransactionTraceParams::traceOptions)
|
||||
.orElse(TraceOptions.DEFAULT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockParameter blockParameter(final JsonRpcRequestContext request) {
|
||||
final Optional<BlockParameter> maybeBlockParameter =
|
||||
request.getOptionalParameter(1, BlockParameter.class);
|
||||
|
||||
return maybeBlockParameter.orElse(BlockParameter.LATEST);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PreCloseStateHandler<Object> getSimulatorResultHandler(
|
||||
final JsonRpcRequestContext requestContext, final DebugOperationTracer tracer) {
|
||||
return (mutableWorldState, maybeSimulatorResult) ->
|
||||
maybeSimulatorResult.map(
|
||||
result -> {
|
||||
if (result.isInvalid()) {
|
||||
LOG.error("Invalid simulator result {}", result);
|
||||
final JsonRpcError error =
|
||||
new JsonRpcError(
|
||||
INTERNAL_ERROR, result.getValidationResult().getErrorMessage());
|
||||
return new JsonRpcErrorResponse(requestContext.getRequest().getId(), error);
|
||||
}
|
||||
|
||||
final TransactionTrace transactionTrace =
|
||||
new TransactionTrace(
|
||||
result.getTransaction(), result.getResult(), tracer.getTraceFrames());
|
||||
|
||||
return new DebugTraceTransactionResult(transactionTrace);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -47,6 +47,7 @@ import java.util.stream.Stream;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.Streams;
|
||||
|
||||
public class EthFeeHistory implements JsonRpcMethod {
|
||||
@@ -187,7 +188,8 @@ public class EthFeeHistory implements JsonRpcMethod {
|
||||
.build()));
|
||||
}
|
||||
|
||||
private List<Wei> computeRewards(final List<Double> rewardPercentiles, final Block block) {
|
||||
@VisibleForTesting
|
||||
public List<Wei> computeRewards(final List<Double> rewardPercentiles, final Block block) {
|
||||
final List<Transaction> transactions = block.getBody().getTransactions();
|
||||
if (transactions.isEmpty()) {
|
||||
// all 0's for empty block
|
||||
@@ -201,13 +203,11 @@ public class EthFeeHistory implements JsonRpcMethod {
|
||||
// we need to get the gas used for the individual transactions and can't use the cumulative gas
|
||||
// used because we're going to be reordering the transactions
|
||||
final List<Long> transactionsGasUsed = new ArrayList<>();
|
||||
long cumulativeGasUsed = 0L;
|
||||
for (final TransactionReceipt transactionReceipt :
|
||||
blockchain.getTxReceipts(block.getHash()).get()) {
|
||||
transactionsGasUsed.add(
|
||||
transactionsGasUsed.isEmpty()
|
||||
? transactionReceipt.getCumulativeGasUsed()
|
||||
: transactionReceipt.getCumulativeGasUsed()
|
||||
- transactionsGasUsed.get(transactionsGasUsed.size() - 1));
|
||||
transactionsGasUsed.add(transactionReceipt.getCumulativeGasUsed() - cumulativeGasUsed);
|
||||
cumulativeGasUsed = transactionReceipt.getCumulativeGasUsed();
|
||||
}
|
||||
|
||||
record TransactionInfo(Transaction transaction, Long gasUsed, Wei effectivePriorityFeePerGas) {}
|
||||
@@ -226,23 +226,26 @@ public class EthFeeHistory implements JsonRpcMethod {
|
||||
.sorted(Comparator.comparing(TransactionInfo::effectivePriorityFeePerGas))
|
||||
.collect(toUnmodifiableList());
|
||||
|
||||
// We need to weight the percentile of rewards by the gas used in the transaction.
|
||||
// That's why we're keeping track of the cumulative gas used and checking to see which
|
||||
// percentile markers we've passed
|
||||
final ArrayList<Wei> rewards = new ArrayList<>();
|
||||
int rewardPercentileIndex = 0;
|
||||
long gasUsed = 0;
|
||||
for (final TransactionInfo transactionAndGasUsed :
|
||||
transactionsAndGasUsedAscendingEffectiveGasFee) {
|
||||
// Start with the gas used by the first transaction
|
||||
double totalGasUsed = transactionsAndGasUsedAscendingEffectiveGasFee.get(0).gasUsed();
|
||||
var transactionIndex = 0;
|
||||
for (var rewardPercentile : rewardPercentiles) {
|
||||
// Calculate the threshold gas used for the current reward percentile. This is the amount of
|
||||
// gas that needs to be used to reach this percentile
|
||||
var thresholdGasUsed = rewardPercentile * block.getHeader().getGasUsed() / 100;
|
||||
|
||||
gasUsed += transactionAndGasUsed.gasUsed();
|
||||
|
||||
while (rewardPercentileIndex < rewardPercentiles.size()
|
||||
&& 100.0 * gasUsed / block.getHeader().getGasUsed()
|
||||
>= rewardPercentiles.get(rewardPercentileIndex)) {
|
||||
rewards.add(transactionAndGasUsed.effectivePriorityFeePerGas);
|
||||
rewardPercentileIndex++;
|
||||
// Stop when totalGasUsed reaches the threshold or there are no more transactions
|
||||
while (totalGasUsed < thresholdGasUsed
|
||||
&& transactionIndex < transactionsAndGasUsedAscendingEffectiveGasFee.size() - 1) {
|
||||
transactionIndex++;
|
||||
totalGasUsed +=
|
||||
transactionsAndGasUsedAscendingEffectiveGasFee.get(transactionIndex).gasUsed();
|
||||
}
|
||||
// Add the effective priority fee per gas of the transaction that reached the percentile value
|
||||
rewards.add(
|
||||
transactionsAndGasUsedAscendingEffectiveGasFee.get(transactionIndex)
|
||||
.effectivePriorityFeePerGas);
|
||||
}
|
||||
// Put the computed rewards in the cache
|
||||
cache.put(new RewardCacheKey(block.getHeader().getBlockHash(), rewardPercentiles), rewards);
|
||||
|
||||
@@ -14,29 +14,27 @@
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType.BLOCK_NOT_FOUND;
|
||||
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType.INTERNAL_ERROR;
|
||||
|
||||
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.JsonCallParameter;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.TraceTypeParameter;
|
||||
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.query.BlockchainQueries;
|
||||
import org.hyperledger.besu.ethereum.core.Block;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.debug.TraceOptions;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.transaction.PreCloseStateHandler;
|
||||
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
|
||||
import org.hyperledger.besu.ethereum.vm.DebugOperationTracer;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class TraceCall extends AbstractTraceByBlock implements JsonRpcMethod {
|
||||
public class TraceCall extends AbstractTraceCall {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TraceCall.class);
|
||||
|
||||
public TraceCall(
|
||||
@@ -52,56 +50,35 @@ public class TraceCall extends AbstractTraceByBlock implements JsonRpcMethod {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object resultByBlockNumber(
|
||||
final JsonRpcRequestContext requestContext, final long blockNumber) {
|
||||
final JsonCallParameter callParams =
|
||||
JsonCallParameterUtil.validateAndGetCallParams(requestContext);
|
||||
final TraceTypeParameter traceTypeParameter =
|
||||
requestContext.getRequiredParameter(1, TraceTypeParameter.class);
|
||||
final String blockNumberString = String.valueOf(blockNumber);
|
||||
LOG.atTrace()
|
||||
.setMessage("Received RPC rpcName={} callParams={} block={} traceTypes={}")
|
||||
.addArgument(this::getName)
|
||||
.addArgument(callParams)
|
||||
.addArgument(blockNumberString)
|
||||
.addArgument(traceTypeParameter)
|
||||
.log();
|
||||
protected TraceOptions getTraceOptions(final JsonRpcRequestContext requestContext) {
|
||||
return buildTraceOptions(getTraceTypes(requestContext));
|
||||
}
|
||||
|
||||
final Optional<BlockHeader> maybeBlockHeader =
|
||||
blockchainQueriesSupplier.get().getBlockHeaderByNumber(blockNumber);
|
||||
private Set<TraceTypeParameter.TraceType> getTraceTypes(
|
||||
final JsonRpcRequestContext requestContext) {
|
||||
return requestContext.getRequiredParameter(1, TraceTypeParameter.class).getTraceTypes();
|
||||
}
|
||||
|
||||
if (maybeBlockHeader.isEmpty()) {
|
||||
return new JsonRpcErrorResponse(requestContext.getRequest().getId(), BLOCK_NOT_FOUND);
|
||||
}
|
||||
@Override
|
||||
protected PreCloseStateHandler<Object> getSimulatorResultHandler(
|
||||
final JsonRpcRequestContext requestContext, final DebugOperationTracer tracer) {
|
||||
return (mutableWorldState, maybeSimulatorResult) ->
|
||||
maybeSimulatorResult.map(
|
||||
result -> {
|
||||
if (result.isInvalid()) {
|
||||
LOG.error("Invalid simulator result {}", result);
|
||||
return new JsonRpcErrorResponse(
|
||||
requestContext.getRequest().getId(), INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
final Set<TraceTypeParameter.TraceType> traceTypes = traceTypeParameter.getTraceTypes();
|
||||
final TransactionTrace transactionTrace =
|
||||
new TransactionTrace(
|
||||
result.getTransaction(), result.getResult(), tracer.getTraceFrames());
|
||||
|
||||
final DebugOperationTracer tracer = new DebugOperationTracer(buildTraceOptions(traceTypes));
|
||||
return transactionSimulator
|
||||
.process(
|
||||
callParams,
|
||||
buildTransactionValidationParams(),
|
||||
tracer,
|
||||
(mutableWorldState, maybeSimulatorResult) ->
|
||||
maybeSimulatorResult.map(
|
||||
result -> {
|
||||
if (result.isInvalid()) {
|
||||
LOG.error(String.format("Invalid simulator result %s", result));
|
||||
return new JsonRpcErrorResponse(
|
||||
requestContext.getRequest().getId(), INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
final TransactionTrace transactionTrace =
|
||||
new TransactionTrace(
|
||||
result.getTransaction(), result.getResult(), tracer.getTraceFrames());
|
||||
|
||||
final Block block =
|
||||
blockchainQueriesSupplier.get().getBlockchain().getChainHeadBlock();
|
||||
|
||||
return getTraceCallResult(
|
||||
protocolSchedule, traceTypes, result, transactionTrace, block);
|
||||
}),
|
||||
maybeBlockHeader.get())
|
||||
.orElse(new JsonRpcErrorResponse(requestContext.getRequest().getId(), INTERNAL_ERROR));
|
||||
final Block block =
|
||||
blockchainQueriesSupplier.get().getBlockchain().getChainHeadBlock();
|
||||
return getTraceCallResult(
|
||||
protocolSchedule, getTraceTypes(requestContext), result, transactionTrace, block);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,7 +213,9 @@ public enum RpcErrorType {
|
||||
BLOCK_RLP_IMPORT_ERROR(-32000, "Could not decode RLP for Block"),
|
||||
BLOCK_IMPORT_ERROR(-32000, "Could not import Block"),
|
||||
|
||||
UNKNOWN(-32603, "Unknown internal error");
|
||||
UNKNOWN(-32603, "Unknown internal error"),
|
||||
|
||||
INVALID_BLOBS(-32603, "blobs failed kzg validation");
|
||||
|
||||
private final int code;
|
||||
private final String message;
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.TreeMap;
|
||||
import com.fasterxml.jackson.annotation.JsonGetter;
|
||||
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"})
|
||||
@@ -38,6 +39,7 @@ 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;
|
||||
@@ -53,12 +55,25 @@ public class StructLog {
|
||||
stack =
|
||||
traceFrame
|
||||
.getStack()
|
||||
.map(a -> Arrays.stream(a).map(Bytes::toUnprefixedHexString).toArray(String[]::new))
|
||||
.map(
|
||||
a ->
|
||||
Arrays.stream(a)
|
||||
.map(Bytes::toUnprefixedHexString)
|
||||
.map(this::stringLeftPadTo64)
|
||||
.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();
|
||||
}
|
||||
|
||||
private static Map<String, String> formatStorage(final Map<UInt256, UInt256> storage) {
|
||||
final Map<String, String> formattedStorage = new TreeMap<>();
|
||||
storage.forEach(
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugStorageRa
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugTraceBlock;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugTraceBlockByHash;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugTraceBlockByNumber;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugTraceCall;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugTraceTransaction;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockReplay;
|
||||
@@ -45,6 +46,7 @@ import org.hyperledger.besu.ethereum.core.Synchronizer;
|
||||
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;
|
||||
|
||||
import java.nio.file.Path;
|
||||
@@ -113,6 +115,13 @@ public class DebugJsonRpcMethods extends ApiGroupJsonRpcMethods {
|
||||
new DebugGetRawHeader(blockchainQueries),
|
||||
new DebugGetRawBlock(blockchainQueries),
|
||||
new DebugGetRawReceipts(blockchainQueries),
|
||||
new DebugGetRawTransaction(blockchainQueries));
|
||||
new DebugGetRawTransaction(blockchainQueries),
|
||||
new DebugTraceCall(
|
||||
blockchainQueries,
|
||||
protocolSchedule,
|
||||
new TransactionSimulator(
|
||||
blockchainQueries.getBlockchain(),
|
||||
blockchainQueries.getWorldStateArchive(),
|
||||
protocolSchedule)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,9 +28,9 @@ public class DebugJsonRpcHttpBySpecTest extends AbstractJsonRpcHttpBySpecTest {
|
||||
}
|
||||
|
||||
public static Object[][] specs() {
|
||||
return findSpecFiles(
|
||||
new String[] {"debug"},
|
||||
"storageRange",
|
||||
"accountRange"); // storageRange and accountRange are not working with bonsai trie
|
||||
return AbstractJsonRpcHttpBySpecTest.findSpecFiles(
|
||||
new String[] {
|
||||
"debug/account-at", "debug/batch-send-raw-transaction", "debug/trace-transaction"
|
||||
}); // storageRange and accountRange are not working with bonsai trie
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.bonsai;
|
||||
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.AbstractJsonRpcHttpBySpecTest;
|
||||
import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
public class DebugTraceJsonRpcHttpBySpecTest extends AbstractJsonRpcHttpBySpecTest {
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
public void setup() throws Exception {
|
||||
setupBonsaiBlockchain();
|
||||
startService();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockchainSetupUtil getBlockchainSetupUtil(final DataStorageFormat storageFormat) {
|
||||
return createBlockchainSetupUtil(
|
||||
"trace/chain-data/genesis.json", "trace/chain-data/blocks.bin", storageFormat);
|
||||
}
|
||||
|
||||
public static Object[][] specs() {
|
||||
return AbstractJsonRpcHttpBySpecTest.findSpecFiles(new String[] {"debug/trace-call"});
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,13 @@ public class DebugJsonRpcHttpBySpecTest extends AbstractJsonRpcHttpBySpecTest {
|
||||
}
|
||||
|
||||
public static Object[][] specs() {
|
||||
return findSpecFiles(new String[] {"debug"});
|
||||
return AbstractJsonRpcHttpBySpecTest.findSpecFiles(
|
||||
new String[] {
|
||||
"debug/account-at",
|
||||
"debug/batch-send-raw-transaction",
|
||||
"debug/trace-transaction",
|
||||
"debug/account-range",
|
||||
"debug/storage-range"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.forest;
|
||||
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.AbstractJsonRpcHttpBySpecTest;
|
||||
import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
public class DebugTraceJsonRpcHttpBySpecTest extends AbstractJsonRpcHttpBySpecTest {
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
public void setup() throws Exception {
|
||||
setupBlockchain();
|
||||
startService();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockchainSetupUtil getBlockchainSetupUtil(final DataStorageFormat storageFormat) {
|
||||
return createBlockchainSetupUtil(
|
||||
"trace/chain-data/genesis.json", "trace/chain-data/blocks.bin", storageFormat);
|
||||
}
|
||||
|
||||
public static Object[][] specs() {
|
||||
return AbstractJsonRpcHttpBySpecTest.findSpecFiles(new String[] {"debug/trace-call"});
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
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;
|
||||
@@ -34,15 +35,27 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.FeeHistory;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.ImmutableFeeHistory;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.ImmutableFeeHistoryResult;
|
||||
import org.hyperledger.besu.ethereum.chain.Blockchain;
|
||||
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
|
||||
import org.hyperledger.besu.ethereum.core.Block;
|
||||
import org.hyperledger.besu.ethereum.core.BlockBody;
|
||||
import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
|
||||
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -104,6 +117,68 @@ public class EthFeeHistoryTest {
|
||||
.build()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldComputeRewardsCorrectly() {
|
||||
// Define the percentiles of rewards we want to compute
|
||||
List<Double> rewardPercentiles =
|
||||
Arrays.asList(0.0, 5.0, 10.0, 30.0, 31.0, 59.0, 60.0, 61.0, 100.0);
|
||||
|
||||
// Define the expected rewards for each percentile
|
||||
// The expected rewards match the fees of the transactions at each percentile in the
|
||||
// rewardPercentiles list
|
||||
List<Wei> expectedRewards = Stream.of(1, 1, 2, 5, 5, 6, 6, 7, 7).map(Wei::of).toList();
|
||||
|
||||
// Define a list of gas used and fee pairs. Each pair represents a transaction in the block.
|
||||
// The first number is the gas used by the transaction, and the second number the fee.
|
||||
// The comments indicate the cumulative gas used up as a percentage of the total gas limit.
|
||||
List<Object[]> gasUsedAndFee = new ArrayList<>();
|
||||
gasUsedAndFee.add(new Object[] {100, 1L}); // 5%
|
||||
gasUsedAndFee.add(new Object[] {150, 2L}); // 12.5%
|
||||
gasUsedAndFee.add(new Object[] {200, 3L}); // 22.5%
|
||||
gasUsedAndFee.add(new Object[] {100, 4L}); // 27.5%
|
||||
gasUsedAndFee.add(new Object[] {200, 5L}); // 37.5%
|
||||
gasUsedAndFee.add(new Object[] {450, 6L}); // 60.0%
|
||||
gasUsedAndFee.add(new Object[] {800, 7L}); // 100.0%
|
||||
Collections.shuffle(gasUsedAndFee);
|
||||
|
||||
Block block = mock(Block.class);
|
||||
Blockchain blockchain = mockBlockchainTransactionsWithPriorityFee(gasUsedAndFee, block);
|
||||
EthFeeHistory ethFeeHistory = new EthFeeHistory(null, blockchain);
|
||||
|
||||
List<Wei> rewards = ethFeeHistory.computeRewards(rewardPercentiles, block);
|
||||
|
||||
// Check that the number of computed rewards is equal to the number of requested percentiles
|
||||
assertThat(rewards.size()).isEqualTo(rewardPercentiles.size());
|
||||
assertThat(rewards).isEqualTo(expectedRewards);
|
||||
}
|
||||
|
||||
private Blockchain mockBlockchainTransactionsWithPriorityFee(
|
||||
final List<Object[]> gasUsedAndFee, final Block block) {
|
||||
final Blockchain blockchain = mock(Blockchain.class);
|
||||
|
||||
when(block.getHash()).thenReturn(Hash.wrap(Bytes32.wrap(Bytes.random(32))));
|
||||
BlockBody body = mock(BlockBody.class);
|
||||
BlockHeader blockHeader = mock(BlockHeader.class);
|
||||
when(block.getHeader()).thenReturn(blockHeader);
|
||||
when(block.getBody()).thenReturn(body);
|
||||
long cumulativeGasUsed = 0;
|
||||
List<Transaction> transactions = new ArrayList<>();
|
||||
List<TransactionReceipt> receipts = new ArrayList<>();
|
||||
for (Object[] objects : gasUsedAndFee) {
|
||||
Transaction transaction = mock(Transaction.class);
|
||||
when(transaction.getEffectivePriorityFeePerGas(any())).thenReturn(Wei.of((Long) objects[1]));
|
||||
cumulativeGasUsed += (int) objects[0];
|
||||
transactions.add(transaction);
|
||||
TransactionReceipt receipt = mock(TransactionReceipt.class);
|
||||
when(receipt.getCumulativeGasUsed()).thenReturn(cumulativeGasUsed);
|
||||
receipts.add(receipt);
|
||||
}
|
||||
when(blockHeader.getGasUsed()).thenReturn(cumulativeGasUsed);
|
||||
when(blockchain.getTxReceipts(any())).thenReturn(Optional.of(receipts));
|
||||
when(body.getTransactions()).thenReturn(transactions);
|
||||
return blockchain;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cantGetBlockHigherThanChainHead() {
|
||||
assertThat(
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -71,7 +72,8 @@ class EthGetTransactionByHashTest {
|
||||
|
||||
@Test
|
||||
void shouldReturnErrorResponseIfMissingRequiredParameter() {
|
||||
final JsonRpcRequest request = new JsonRpcRequest("2.0", method.getName(), new Object[] {});
|
||||
final JsonRpcRequest request =
|
||||
new JsonRpcRequest(JSON_RPC_VERSION, method.getName(), new Object[] {});
|
||||
final JsonRpcRequestContext context = new JsonRpcRequestContext(request);
|
||||
|
||||
final JsonRpcErrorResponse expectedResponse =
|
||||
@@ -92,7 +94,7 @@ class EthGetTransactionByHashTest {
|
||||
.thenReturn(Optional.empty());
|
||||
|
||||
final JsonRpcRequest request =
|
||||
new JsonRpcRequest("2.0", method.getName(), new Object[] {transactionHash});
|
||||
new JsonRpcRequest(JSON_RPC_VERSION, method.getName(), new Object[] {transactionHash});
|
||||
final JsonRpcRequestContext context = new JsonRpcRequestContext(request);
|
||||
|
||||
final JsonRpcSuccessResponse expectedResponse =
|
||||
@@ -115,7 +117,7 @@ class EthGetTransactionByHashTest {
|
||||
|
||||
final JsonRpcRequest request =
|
||||
new JsonRpcRequest(
|
||||
"2.0", method.getName(), new Object[] {transaction.getHash().toHexString()});
|
||||
JSON_RPC_VERSION, method.getName(), new Object[] {transaction.getHash().toHexString()});
|
||||
final JsonRpcRequestContext context = new JsonRpcRequestContext(request);
|
||||
|
||||
final JsonRpcSuccessResponse expectedResponse =
|
||||
@@ -141,7 +143,7 @@ class EthGetTransactionByHashTest {
|
||||
|
||||
final JsonRpcRequest request =
|
||||
new JsonRpcRequest(
|
||||
"2.0", method.getName(), new Object[] {transaction.getHash().toHexString()});
|
||||
JSON_RPC_VERSION, method.getName(), new Object[] {transaction.getHash().toHexString()});
|
||||
final JsonRpcRequestContext context = new JsonRpcRequestContext(request);
|
||||
|
||||
final JsonRpcSuccessResponse expectedResponse =
|
||||
@@ -181,8 +183,23 @@ class EthGetTransactionByHashTest {
|
||||
assertThat(result.getRaw()).isNotNull();
|
||||
assertThat(result.getTo()).isNotNull();
|
||||
assertThat(result.getValue()).isNotNull();
|
||||
assertThat(result.getYParity()).isNotNull();
|
||||
assertThat(result.getV()).isNotNull();
|
||||
switch (result.getType()) {
|
||||
case "0x0":
|
||||
assertThat(result.getYParity()).isNull();
|
||||
assertThat(result.getV()).isNotNull();
|
||||
break;
|
||||
case "0x1":
|
||||
case "0x2":
|
||||
assertThat(result.getYParity()).isNotNull();
|
||||
assertThat(result.getV()).isNotNull();
|
||||
break;
|
||||
case "0x3":
|
||||
assertThat(result.getYParity()).isNotNull();
|
||||
assertThat(result.getV()).isNull();
|
||||
break;
|
||||
default:
|
||||
fail("unknownType " + result.getType());
|
||||
}
|
||||
assertThat(result.getR()).isNotNull();
|
||||
assertThat(result.getS()).isNotNull();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,300 @@
|
||||
{
|
||||
"request" : {
|
||||
"jsonrpc" : "2.0",
|
||||
"method" : "debug_traceCall",
|
||||
"params" : [ {
|
||||
"from" : "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
|
||||
"to" : "0x0050000000000000000000000000000000000000",
|
||||
"gas" : "0xfffff2",
|
||||
"gasPrice" : "0xef",
|
||||
"value" : "0x0",
|
||||
"data" : "0x0000000000000000000000000030000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000001",
|
||||
"nonce" : "0x0"
|
||||
}, "latest",
|
||||
{
|
||||
"disableMemory": true, "disableStack": true, "disableStorage": true
|
||||
} ],
|
||||
"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" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 2,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755907,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 4,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755904,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 6,
|
||||
"op" : "CALLDATASIZE",
|
||||
"gas" : 16755901,
|
||||
"gasCost" : 2,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 7,
|
||||
"op" : "SUB",
|
||||
"gas" : 16755899,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 8,
|
||||
"op" : "DUP1",
|
||||
"gas" : 16755896,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 9,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755893,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 11,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755890,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 13,
|
||||
"op" : "CALLDATACOPY",
|
||||
"gas" : 16755887,
|
||||
"gasCost" : 9,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 14,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755878,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 16,
|
||||
"op" : "CALLVALUE",
|
||||
"gas" : 16755875,
|
||||
"gasCost" : 2,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 17,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755873,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 19,
|
||||
"op" : "CALLDATALOAD",
|
||||
"gas" : 16755870,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 20,
|
||||
"op" : "GAS",
|
||||
"gas" : 16755867,
|
||||
"gasCost" : 2,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 21,
|
||||
"op" : "CALLCODE",
|
||||
"gas" : 16755865,
|
||||
"gasCost" : 700,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 0,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16493366,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 2,
|
||||
"op" : "CALLDATALOAD",
|
||||
"gas" : 16493363,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 3,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16493360,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 5,
|
||||
"op" : "ADD",
|
||||
"gas" : 16493357,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 6,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16493354,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 8,
|
||||
"op" : "MSTORE",
|
||||
"gas" : 16493351,
|
||||
"gasCost" : 6,
|
||||
"depth" : 2,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 9,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16493345,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 11,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16493342,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 13,
|
||||
"op" : "RETURN",
|
||||
"gas" : 16493339,
|
||||
"gasCost" : 0,
|
||||
"depth" : 2,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 22,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755138,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 24,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755135,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 26,
|
||||
"op" : "RETURN",
|
||||
"gas" : 16755132,
|
||||
"gasCost" : 0,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : null,
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
} ]
|
||||
}
|
||||
},
|
||||
"statusCode": 200
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
{
|
||||
"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" : 700,
|
||||
"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
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
{
|
||||
"request" : {
|
||||
"jsonrpc" : "2.0",
|
||||
"method" : "debug_traceCall",
|
||||
"params" : [ {
|
||||
"from" : "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
|
||||
"to" : "0x0050000000000000000000000000000000000000",
|
||||
"gas" : "0xfffff2",
|
||||
"gasPrice" : "0xef",
|
||||
"value" : "0x0",
|
||||
"data" : "0x0000000000000000000000000030000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000001",
|
||||
"nonce" : "0x0"
|
||||
}, "latest",
|
||||
{
|
||||
"disableMemory":true
|
||||
} ],
|
||||
"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" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 2,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755907,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 4,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755904,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 6,
|
||||
"op" : "CALLDATASIZE",
|
||||
"gas" : 16755901,
|
||||
"gasCost" : 2,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 7,
|
||||
"op" : "SUB",
|
||||
"gas" : 16755899,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000040" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 8,
|
||||
"op" : "DUP1",
|
||||
"gas" : 16755896,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 9,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755893,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 11,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755890,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 13,
|
||||
"op" : "CALLDATACOPY",
|
||||
"gas" : 16755887,
|
||||
"gasCost" : 9,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 14,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755878,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 16,
|
||||
"op" : "CALLVALUE",
|
||||
"gas" : 16755875,
|
||||
"gasCost" : 2,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 17,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755873,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 19,
|
||||
"op" : "CALLDATALOAD",
|
||||
"gas" : 16755870,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 20,
|
||||
"op" : "GAS",
|
||||
"gas" : 16755867,
|
||||
"gasCost" : 2,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000030000000000000000000000000000000000000" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 21,
|
||||
"op" : "CALLCODE",
|
||||
"gas" : 16755865,
|
||||
"gasCost" : 700,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000030000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000ffac99" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 0,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16493366,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : [ ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 2,
|
||||
"op" : "CALLDATALOAD",
|
||||
"gas" : 16493363,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000000" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 3,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16493360,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 5,
|
||||
"op" : "ADD",
|
||||
"gas" : 16493357,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : [ "f000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 6,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16493354,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 8,
|
||||
"op" : "MSTORE",
|
||||
"gas" : 16493351,
|
||||
"gasCost" : 6,
|
||||
"depth" : 2,
|
||||
"stack" : [ "f000000000000000000000000000000000000000000000000000000000000002", "0000000000000000000000000000000000000000000000000000000000000000" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 9,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16493345,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : [ ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 11,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16493342,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 13,
|
||||
"op" : "RETURN",
|
||||
"gas" : 16493339,
|
||||
"gasCost" : 0,
|
||||
"depth" : 2,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 22,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755138,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000001" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 24,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755135,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000020" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 26,
|
||||
"op" : "RETURN",
|
||||
"gas" : 16755132,
|
||||
"gasCost" : 0,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
|
||||
"memory" : null,
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
} ]
|
||||
}
|
||||
},
|
||||
"statusCode": 200
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
{
|
||||
"request" : {
|
||||
"jsonrpc" : "2.0",
|
||||
"method" : "debug_traceCall",
|
||||
"params" : [ {
|
||||
"from" : "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
|
||||
"to" : "0x0050000000000000000000000000000000000000",
|
||||
"gas" : "0xfffff2",
|
||||
"gasPrice" : "0xef",
|
||||
"value" : "0x0",
|
||||
"data" : "0x0000000000000000000000000030000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000001",
|
||||
"nonce" : "0x0"
|
||||
}, "latest",
|
||||
{
|
||||
"disableStack": true
|
||||
} ],
|
||||
"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" : null,
|
||||
"memory" : [ ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 2,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755907,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : [ ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 4,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755904,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : [ ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 6,
|
||||
"op" : "CALLDATASIZE",
|
||||
"gas" : 16755901,
|
||||
"gasCost" : 2,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : [ ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 7,
|
||||
"op" : "SUB",
|
||||
"gas" : 16755899,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : [ ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 8,
|
||||
"op" : "DUP1",
|
||||
"gas" : 16755896,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : [ ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 9,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755893,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : [ ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 11,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755890,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : [ ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 13,
|
||||
"op" : "CALLDATACOPY",
|
||||
"gas" : 16755887,
|
||||
"gasCost" : 9,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 14,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755878,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 16,
|
||||
"op" : "CALLVALUE",
|
||||
"gas" : 16755875,
|
||||
"gasCost" : 2,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 17,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755873,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 19,
|
||||
"op" : "CALLDATALOAD",
|
||||
"gas" : 16755870,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 20,
|
||||
"op" : "GAS",
|
||||
"gas" : 16755867,
|
||||
"gasCost" : 2,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 21,
|
||||
"op" : "CALLCODE",
|
||||
"gas" : 16755865,
|
||||
"gasCost" : 700,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 0,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16493366,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : null,
|
||||
"memory" : [ ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 2,
|
||||
"op" : "CALLDATALOAD",
|
||||
"gas" : 16493363,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : null,
|
||||
"memory" : [ ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 3,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16493360,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : null,
|
||||
"memory" : [ ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 5,
|
||||
"op" : "ADD",
|
||||
"gas" : 16493357,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : null,
|
||||
"memory" : [ ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 6,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16493354,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : null,
|
||||
"memory" : [ ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 8,
|
||||
"op" : "MSTORE",
|
||||
"gas" : 16493351,
|
||||
"gasCost" : 6,
|
||||
"depth" : 2,
|
||||
"stack" : null,
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 9,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16493345,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : null,
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 11,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16493342,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : null,
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 13,
|
||||
"op" : "RETURN",
|
||||
"gas" : 16493339,
|
||||
"gasCost" : 0,
|
||||
"depth" : 2,
|
||||
"stack" : null,
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 22,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755138,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 24,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755135,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 26,
|
||||
"op" : "RETURN",
|
||||
"gas" : 16755132,
|
||||
"gasCost" : 0,
|
||||
"depth" : 1,
|
||||
"stack" : null,
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
|
||||
"storage" : { },
|
||||
"reason" : null
|
||||
} ]
|
||||
}
|
||||
},
|
||||
"statusCode": 200
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
{
|
||||
"request" : {
|
||||
"jsonrpc" : "2.0",
|
||||
"method" : "debug_traceCall",
|
||||
"params" : [ {
|
||||
"from" : "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
|
||||
"to" : "0x0050000000000000000000000000000000000000",
|
||||
"gas" : "0xfffff2",
|
||||
"gasPrice" : "0xef",
|
||||
"value" : "0x0",
|
||||
"data" : "0x0000000000000000000000000030000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000001",
|
||||
"nonce" : "0x0"
|
||||
}, "latest",
|
||||
{
|
||||
"disableStorage": true
|
||||
} ],
|
||||
"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" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 2,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755907,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020" ],
|
||||
"memory" : [ ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 4,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755904,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
|
||||
"memory" : [ ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 6,
|
||||
"op" : "CALLDATASIZE",
|
||||
"gas" : 16755901,
|
||||
"gasCost" : 2,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020" ],
|
||||
"memory" : [ ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 7,
|
||||
"op" : "SUB",
|
||||
"gas" : 16755899,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000040" ],
|
||||
"memory" : [ ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 8,
|
||||
"op" : "DUP1",
|
||||
"gas" : 16755896,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020" ],
|
||||
"memory" : [ ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 9,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755893,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020" ],
|
||||
"memory" : [ ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 11,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755890,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020" ],
|
||||
"memory" : [ ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 13,
|
||||
"op" : "CALLDATACOPY",
|
||||
"gas" : 16755887,
|
||||
"gasCost" : 9,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 14,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755878,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020" ],
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 16,
|
||||
"op" : "CALLVALUE",
|
||||
"gas" : 16755875,
|
||||
"gasCost" : 2,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 17,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755873,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000" ],
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 19,
|
||||
"op" : "CALLDATALOAD",
|
||||
"gas" : 16755870,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000" ],
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 20,
|
||||
"op" : "GAS",
|
||||
"gas" : 16755867,
|
||||
"gasCost" : 2,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000030000000000000000000000000000000000000" ],
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 21,
|
||||
"op" : "CALLCODE",
|
||||
"gas" : 16755865,
|
||||
"gasCost" : 700,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000030000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000ffac99" ],
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 0,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16493366,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : [ ],
|
||||
"memory" : [ ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 2,
|
||||
"op" : "CALLDATALOAD",
|
||||
"gas" : 16493363,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000000" ],
|
||||
"memory" : [ ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 3,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16493360,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : [ "f000000000000000000000000000000000000000000000000000000000000001" ],
|
||||
"memory" : [ ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 5,
|
||||
"op" : "ADD",
|
||||
"gas" : 16493357,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : [ "f000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001" ],
|
||||
"memory" : [ ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 6,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16493354,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
|
||||
"memory" : [ ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 8,
|
||||
"op" : "MSTORE",
|
||||
"gas" : 16493351,
|
||||
"gasCost" : 6,
|
||||
"depth" : 2,
|
||||
"stack" : [ "f000000000000000000000000000000000000000000000000000000000000002", "0000000000000000000000000000000000000000000000000000000000000000" ],
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 9,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16493345,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : [ ],
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 11,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16493342,
|
||||
"gasCost" : 3,
|
||||
"depth" : 2,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020" ],
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 13,
|
||||
"op" : "RETURN",
|
||||
"gas" : 16493339,
|
||||
"gasCost" : 0,
|
||||
"depth" : 2,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 22,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755138,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000001" ],
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 24,
|
||||
"op" : "PUSH1",
|
||||
"gas" : 16755135,
|
||||
"gasCost" : 3,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000020" ],
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
}, {
|
||||
"pc" : 26,
|
||||
"op" : "RETURN",
|
||||
"gas" : 16755132,
|
||||
"gasCost" : 0,
|
||||
"depth" : 1,
|
||||
"stack" : [ "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000020", "0000000000000000000000000000000000000000000000000000000000000000" ],
|
||||
"memory" : [ "f000000000000000000000000000000000000000000000000000000000000002" ],
|
||||
"storage" : null,
|
||||
"reason" : null
|
||||
} ]
|
||||
}
|
||||
},
|
||||
"statusCode": 200
|
||||
}
|
||||
@@ -16,6 +16,7 @@ package org.hyperledger.besu.ethereum.blockcreation.txselection;
|
||||
|
||||
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.BLOCK_SELECTION_TIMEOUT;
|
||||
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.SELECTED;
|
||||
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.TX_EVALUATION_TOO_LONG;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
@@ -95,6 +96,7 @@ public class BlockTransactionSelector {
|
||||
private final BlockAwareOperationTracer pluginOperationTracer;
|
||||
private final EthScheduler ethScheduler;
|
||||
private final AtomicBoolean isTimeout = new AtomicBoolean(false);
|
||||
private final long blockTxsSelectionMaxTime;
|
||||
private WorldUpdater blockWorldStateUpdater;
|
||||
|
||||
public BlockTransactionSelector(
|
||||
@@ -133,6 +135,7 @@ public class BlockTransactionSelector {
|
||||
this.pluginTransactionSelector = pluginTransactionSelector;
|
||||
this.pluginOperationTracer = pluginTransactionSelector.getOperationTracer();
|
||||
blockWorldStateUpdater = worldState.updater();
|
||||
blockTxsSelectionMaxTime = miningParameters.getUnstable().getBlockTxsSelectionMaxTime();
|
||||
}
|
||||
|
||||
private List<AbstractTransactionSelector> createTransactionSelectors(
|
||||
@@ -168,8 +171,6 @@ public class BlockTransactionSelector {
|
||||
}
|
||||
|
||||
private void timeLimitedSelection() {
|
||||
final long blockTxsSelectionMaxTime =
|
||||
blockSelectionContext.miningParameters().getUnstable().getBlockTxsSelectionMaxTime();
|
||||
final var txSelection =
|
||||
ethScheduler.scheduleBlockCreationTask(
|
||||
() ->
|
||||
@@ -226,9 +227,11 @@ public class BlockTransactionSelector {
|
||||
final PendingTransaction pendingTransaction) {
|
||||
checkCancellation();
|
||||
|
||||
final long evaluationStartedAt = System.currentTimeMillis();
|
||||
|
||||
TransactionSelectionResult selectionResult = evaluatePreProcessing(pendingTransaction);
|
||||
if (!selectionResult.selected()) {
|
||||
return handleTransactionNotSelected(pendingTransaction, selectionResult);
|
||||
return handleTransactionNotSelected(pendingTransaction, selectionResult, evaluationStartedAt);
|
||||
}
|
||||
|
||||
final WorldUpdater txWorldStateUpdater = blockWorldStateUpdater.updater();
|
||||
@@ -239,10 +242,14 @@ public class BlockTransactionSelector {
|
||||
evaluatePostProcessing(pendingTransaction, processingResult);
|
||||
|
||||
if (postProcessingSelectionResult.selected()) {
|
||||
return handleTransactionSelected(pendingTransaction, processingResult, txWorldStateUpdater);
|
||||
return handleTransactionSelected(
|
||||
pendingTransaction, processingResult, txWorldStateUpdater, evaluationStartedAt);
|
||||
}
|
||||
return handleTransactionNotSelected(
|
||||
pendingTransaction, postProcessingSelectionResult, txWorldStateUpdater);
|
||||
pendingTransaction,
|
||||
postProcessingSelectionResult,
|
||||
txWorldStateUpdater,
|
||||
evaluationStartedAt);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -326,12 +333,14 @@ public class BlockTransactionSelector {
|
||||
* @param pendingTransaction The pending transaction.
|
||||
* @param processingResult The result of the transaction processing.
|
||||
* @param txWorldStateUpdater The world state updater.
|
||||
* @param evaluationStartedAt when the evaluation of this tx started
|
||||
* @return The result of the transaction selection process.
|
||||
*/
|
||||
private TransactionSelectionResult handleTransactionSelected(
|
||||
final PendingTransaction pendingTransaction,
|
||||
final TransactionProcessingResult processingResult,
|
||||
final WorldUpdater txWorldStateUpdater) {
|
||||
final WorldUpdater txWorldStateUpdater,
|
||||
final long evaluationStartedAt) {
|
||||
final Transaction transaction = pendingTransaction.getTransaction();
|
||||
|
||||
final long gasUsedByTransaction =
|
||||
@@ -347,7 +356,8 @@ public class BlockTransactionSelector {
|
||||
// this need to be done synchronously to avoid that a concurrent timeout
|
||||
// could start packing a block while we are updating the state here
|
||||
synchronized (isTimeout) {
|
||||
if (!isTimeout.get()) {
|
||||
tooLate = isTimeout.get();
|
||||
if (!tooLate) {
|
||||
txWorldStateUpdater.commit();
|
||||
blockWorldStateUpdater.commit();
|
||||
final TransactionReceipt receipt =
|
||||
@@ -356,30 +366,47 @@ public class BlockTransactionSelector {
|
||||
|
||||
transactionSelectionResults.updateSelected(
|
||||
pendingTransaction.getTransaction(), receipt, gasUsedByTransaction, blobGasUsed);
|
||||
tooLate = false;
|
||||
} else {
|
||||
tooLate = true;
|
||||
}
|
||||
}
|
||||
|
||||
final long evaluationTime = System.currentTimeMillis() - evaluationStartedAt;
|
||||
if (tooLate) {
|
||||
// even if this tx passed all the checks, it is too late to include it in this block,
|
||||
// so we need to treat it as not selected
|
||||
LOG.atTrace()
|
||||
.setMessage("{} processed too late for block creation")
|
||||
.addArgument(transaction::toTraceLog)
|
||||
.log();
|
||||
|
||||
// check if this tx took too much to evaluate, and in case remove it from the pool
|
||||
final TransactionSelectionResult timeoutSelectionResult;
|
||||
if (evaluationTime > blockTxsSelectionMaxTime) {
|
||||
LOG.atWarn()
|
||||
.setMessage(
|
||||
"Transaction {} is too late for inclusion, evaluated in {}ms that is over the max limit of {}"
|
||||
+ ", removing it from the pool")
|
||||
.addArgument(transaction::toTraceLog)
|
||||
.addArgument(evaluationTime)
|
||||
.addArgument(blockTxsSelectionMaxTime)
|
||||
.log();
|
||||
timeoutSelectionResult = TX_EVALUATION_TOO_LONG;
|
||||
} else {
|
||||
LOG.atTrace()
|
||||
.setMessage("Transaction {} is too late for inclusion")
|
||||
.addArgument(transaction::toTraceLog)
|
||||
.addArgument(evaluationTime)
|
||||
.log();
|
||||
timeoutSelectionResult = BLOCK_SELECTION_TIMEOUT;
|
||||
}
|
||||
|
||||
// do not rely on the presence of this result, since by the time it is added, the code
|
||||
// reading it could have been already executed by another thread
|
||||
return handleTransactionNotSelected(
|
||||
pendingTransaction, BLOCK_SELECTION_TIMEOUT, txWorldStateUpdater);
|
||||
pendingTransaction, timeoutSelectionResult, txWorldStateUpdater, evaluationStartedAt);
|
||||
}
|
||||
|
||||
pluginTransactionSelector.onTransactionSelected(pendingTransaction, processingResult);
|
||||
blockWorldStateUpdater = worldState.updater();
|
||||
LOG.atTrace()
|
||||
.setMessage("Selected {} for block creation")
|
||||
.setMessage("Selected {} for block creation, evaluated in {}ms")
|
||||
.addArgument(transaction::toTraceLog)
|
||||
.addArgument(evaluationTime)
|
||||
.log();
|
||||
return SELECTED;
|
||||
}
|
||||
@@ -391,24 +418,34 @@ public class BlockTransactionSelector {
|
||||
*
|
||||
* @param pendingTransaction The unselected pending transaction.
|
||||
* @param selectionResult The result of the transaction selection process.
|
||||
* @param evaluationStartedAt when the evaluation of this tx started
|
||||
* @return The result of the transaction selection process.
|
||||
*/
|
||||
private TransactionSelectionResult handleTransactionNotSelected(
|
||||
final PendingTransaction pendingTransaction,
|
||||
final TransactionSelectionResult selectionResult) {
|
||||
final TransactionSelectionResult selectionResult,
|
||||
final long evaluationStartedAt) {
|
||||
|
||||
transactionSelectionResults.updateNotSelected(
|
||||
pendingTransaction.getTransaction(), selectionResult);
|
||||
pluginTransactionSelector.onTransactionNotSelected(pendingTransaction, selectionResult);
|
||||
LOG.atTrace()
|
||||
.setMessage("Not selected {} for block creation with result {}, evaluated in {}ms")
|
||||
.addArgument(pendingTransaction::toTraceLog)
|
||||
.addArgument(selectionResult)
|
||||
.addArgument(() -> System.currentTimeMillis() - evaluationStartedAt)
|
||||
.log();
|
||||
|
||||
return selectionResult;
|
||||
}
|
||||
|
||||
private TransactionSelectionResult handleTransactionNotSelected(
|
||||
final PendingTransaction pendingTransaction,
|
||||
final TransactionSelectionResult selectionResult,
|
||||
final WorldUpdater txWorldStateUpdater) {
|
||||
final WorldUpdater txWorldStateUpdater,
|
||||
final long evaluationStartedAt) {
|
||||
txWorldStateUpdater.revert();
|
||||
return handleTransactionNotSelected(pendingTransaction, selectionResult);
|
||||
return handleTransactionNotSelected(pendingTransaction, selectionResult, evaluationStartedAt);
|
||||
}
|
||||
|
||||
private void checkCancellation() {
|
||||
|
||||
@@ -383,7 +383,6 @@ abstract class AbstractBlockCreatorTest {
|
||||
executionContextTestFixture.getProtocolContext(),
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
mock(MiningParameters.class),
|
||||
new TransactionPoolMetrics(new NoOpMetricsSystem()),
|
||||
poolConf,
|
||||
null);
|
||||
|
||||
@@ -18,6 +18,10 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.entry;
|
||||
import static org.awaitility.Awaitility.await;
|
||||
import static org.hyperledger.besu.ethereum.core.MiningParameters.Unstable.DEFAULT_NON_POA_BLOCK_TXS_SELECTION_MAX_TIME;
|
||||
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.BLOCK_SELECTION_TIMEOUT;
|
||||
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.PRIORITY_FEE_PER_GAS_BELOW_CURRENT_MIN;
|
||||
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.SELECTED;
|
||||
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.TX_EVALUATION_TOO_LONG;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@@ -177,7 +181,7 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
|
||||
protected abstract ProtocolSchedule createProtocolSchedule();
|
||||
|
||||
protected abstract TransactionPool createTransactionPool(final MiningParameters miningParameters);
|
||||
protected abstract TransactionPool createTransactionPool();
|
||||
|
||||
private Boolean isCancelled() {
|
||||
return false;
|
||||
@@ -586,7 +590,7 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
return TransactionSelectionResult.invalidTransient("transient");
|
||||
if (pendingTransaction.getTransaction().equals(notSelectedInvalid))
|
||||
return TransactionSelectionResult.invalid("invalid");
|
||||
return TransactionSelectionResult.SELECTED;
|
||||
return SELECTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -594,7 +598,7 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
final PendingTransaction pendingTransaction,
|
||||
final org.hyperledger.besu.plugin.data.TransactionProcessingResult
|
||||
processingResult) {
|
||||
return TransactionSelectionResult.SELECTED;
|
||||
return SELECTED;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -644,7 +648,7 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
@Override
|
||||
public TransactionSelectionResult evaluateTransactionPreProcessing(
|
||||
final PendingTransaction pendingTransaction) {
|
||||
return TransactionSelectionResult.SELECTED;
|
||||
return SELECTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -656,7 +660,7 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
if (processingResult.getEstimateGasUsedByTransaction() > maxGasUsedByTransaction) {
|
||||
return TransactionSelectionResult.invalidTransient("Invalid");
|
||||
}
|
||||
return TransactionSelectionResult.SELECTED;
|
||||
return SELECTED;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -873,9 +877,7 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
|
||||
assertThat(results.getSelectedTransactions()).containsOnly(txSelected);
|
||||
assertThat(results.getNotSelectedTransactions())
|
||||
.containsOnly(
|
||||
entry(
|
||||
txNotSelected, TransactionSelectionResult.PRIORITY_FEE_PER_GAS_BELOW_CURRENT_MIN));
|
||||
.containsOnly(entry(txNotSelected, PRIORITY_FEE_PER_GAS_BELOW_CURRENT_MIN));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@@ -886,47 +888,84 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
final boolean processingTooLate,
|
||||
final boolean postProcessingTooLate) {
|
||||
|
||||
final Supplier<Answer<TransactionSelectionResult>> inTime =
|
||||
() -> invocation -> TransactionSelectionResult.SELECTED;
|
||||
internalBlockSelectionTimeoutSimulation(
|
||||
isPoa,
|
||||
preProcessingTooLate,
|
||||
processingTooLate,
|
||||
postProcessingTooLate,
|
||||
500,
|
||||
BLOCK_SELECTION_TIMEOUT,
|
||||
false);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("subsetOfPendingTransactionsIncludedWhenTxSelectionMaxTimeIsOver")
|
||||
public void pendingTransactionsThatTakesTooLongToEvaluateIsDroppedFromThePool(
|
||||
final boolean isPoa,
|
||||
final boolean preProcessingTooLate,
|
||||
final boolean processingTooLate,
|
||||
final boolean postProcessingTooLate) {
|
||||
|
||||
internalBlockSelectionTimeoutSimulation(
|
||||
isPoa,
|
||||
preProcessingTooLate,
|
||||
processingTooLate,
|
||||
postProcessingTooLate,
|
||||
900,
|
||||
TX_EVALUATION_TOO_LONG,
|
||||
true);
|
||||
}
|
||||
|
||||
private void internalBlockSelectionTimeoutSimulation(
|
||||
final boolean isPoa,
|
||||
final boolean preProcessingTooLate,
|
||||
final boolean processingTooLate,
|
||||
final boolean postProcessingTooLate,
|
||||
final long longProcessingTxTime,
|
||||
final TransactionSelectionResult longProcessingTxResult,
|
||||
final boolean isLongProcessingTxDropped) {
|
||||
|
||||
final long fastProcessingTxTime = 200;
|
||||
|
||||
final Supplier<Answer<TransactionSelectionResult>> inTime = () -> invocation -> SELECTED;
|
||||
|
||||
final BiFunction<Transaction, Long, Answer<TransactionSelectionResult>> tooLate =
|
||||
(p, t) ->
|
||||
invocation -> {
|
||||
if (((PendingTransaction) invocation.getArgument(0)).getTransaction().equals(p)) {
|
||||
final org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction ptx =
|
||||
invocation.getArgument(0);
|
||||
if (ptx.getTransaction().equals(p)) {
|
||||
Thread.sleep(t);
|
||||
} else {
|
||||
Thread.sleep(fastProcessingTxTime);
|
||||
}
|
||||
return TransactionSelectionResult.SELECTED;
|
||||
return SELECTED;
|
||||
};
|
||||
|
||||
final ProcessableBlockHeader blockHeader = createBlock(301_000);
|
||||
final Address miningBeneficiary = AddressHelpers.ofValue(1);
|
||||
final int poaMinBlockTime = 1;
|
||||
final long blockTxsSelectionMaxTime = 750;
|
||||
final long longProcessingTxTime = 500;
|
||||
|
||||
final List<Transaction> transactionsToInject = new ArrayList<>(3);
|
||||
for (int i = 0; i < 2; i++) {
|
||||
final Transaction tx = createTransaction(i, Wei.of(7), 100_000);
|
||||
transactionsToInject.add(tx);
|
||||
ensureTransactionIsValid(tx);
|
||||
ensureTransactionIsValid(tx, 0, 0, processingTooLate ? fastProcessingTxTime : 0);
|
||||
}
|
||||
|
||||
final Transaction lateTx = createTransaction(2, Wei.of(7), 100_000);
|
||||
transactionsToInject.add(lateTx);
|
||||
ensureTransactionIsValid(
|
||||
lateTx, 0, 0, processingTooLate ? blockTxsSelectionMaxTime + longProcessingTxTime : 0);
|
||||
ensureTransactionIsValid(lateTx, 0, 0, processingTooLate ? longProcessingTxTime : 0);
|
||||
|
||||
PluginTransactionSelector transactionSelector = mock(PluginTransactionSelector.class);
|
||||
when(transactionSelector.evaluateTransactionPreProcessing(any()))
|
||||
.thenAnswer(
|
||||
preProcessingTooLate
|
||||
? inTime.get()
|
||||
: tooLate.apply(lateTx, blockTxsSelectionMaxTime + longProcessingTxTime));
|
||||
preProcessingTooLate ? tooLate.apply(lateTx, longProcessingTxTime) : inTime.get());
|
||||
|
||||
when(transactionSelector.evaluateTransactionPostProcessing(any(), any()))
|
||||
.thenAnswer(
|
||||
postProcessingTooLate
|
||||
? inTime.get()
|
||||
: tooLate.apply(lateTx, blockTxsSelectionMaxTime + longProcessingTxTime));
|
||||
postProcessingTooLate ? tooLate.apply(lateTx, longProcessingTxTime) : inTime.get());
|
||||
|
||||
final PluginTransactionSelectorFactory transactionSelectorFactory =
|
||||
mock(PluginTransactionSelectorFactory.class);
|
||||
@@ -966,7 +1005,9 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
// given enough time we can check the not selected tx
|
||||
await().until(() -> !results.getNotSelectedTransactions().isEmpty());
|
||||
assertThat(results.getNotSelectedTransactions())
|
||||
.containsOnly(entry(lateTx, TransactionSelectionResult.BLOCK_SELECTION_TIMEOUT));
|
||||
.containsOnly(entry(lateTx, longProcessingTxResult));
|
||||
assertThat(transactionPool.getTransactionByHash(lateTx.getHash()).isEmpty())
|
||||
.isEqualTo(isLongProcessingTxDropped ? true : false);
|
||||
}
|
||||
|
||||
private static Stream<Arguments>
|
||||
@@ -989,7 +1030,7 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
final Wei blobGasPrice,
|
||||
final PluginTransactionSelectorFactory transactionSelectorFactory) {
|
||||
|
||||
transactionPool = createTransactionPool(miningParameters);
|
||||
transactionPool = createTransactionPool();
|
||||
|
||||
return createBlockSelector(
|
||||
miningParameters,
|
||||
|
||||
@@ -20,7 +20,7 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.config.GenesisConfigFile;
|
||||
import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
|
||||
@@ -62,11 +62,12 @@ public class LegacyFeeMarketBlockTransactionSelectorTest
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TransactionPool createTransactionPool(final MiningParameters miningParameters) {
|
||||
protected TransactionPool createTransactionPool() {
|
||||
final TransactionPoolConfiguration poolConf =
|
||||
ImmutableTransactionPoolConfiguration.builder()
|
||||
.txPoolMaxSize(5)
|
||||
.txPoolLimitByAccountPercentage(Fraction.fromFloat(1f))
|
||||
.minGasPrice(Wei.ONE)
|
||||
.build();
|
||||
|
||||
final PendingTransactions pendingTransactions =
|
||||
@@ -86,7 +87,6 @@ public class LegacyFeeMarketBlockTransactionSelectorTest
|
||||
protocolContext,
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
miningParameters,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf,
|
||||
null);
|
||||
|
||||
@@ -74,11 +74,12 @@ public class LondonFeeMarketBlockTransactionSelectorTest
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TransactionPool createTransactionPool(final MiningParameters miningParameters) {
|
||||
protected TransactionPool createTransactionPool() {
|
||||
final TransactionPoolConfiguration poolConf =
|
||||
ImmutableTransactionPoolConfiguration.builder()
|
||||
.txPoolMaxSize(5)
|
||||
.txPoolLimitByAccountPercentage(Fraction.fromFloat(1f))
|
||||
.minGasPrice(Wei.ONE)
|
||||
.build();
|
||||
final PendingTransactions pendingTransactions =
|
||||
new BaseFeePendingTransactionsSorter(
|
||||
@@ -94,7 +95,6 @@ public class LondonFeeMarketBlockTransactionSelectorTest
|
||||
protocolContext,
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
miningParameters,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf,
|
||||
null);
|
||||
|
||||
@@ -332,7 +332,6 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest {
|
||||
executionContextTestFixture.getProtocolContext(),
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
mock(MiningParameters.class),
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf,
|
||||
null);
|
||||
|
||||
@@ -52,7 +52,7 @@ public class PoWMinerExecutorTest {
|
||||
public void startingMiningWithoutCoinbaseThrowsException() {
|
||||
final MiningParameters miningParameters = MiningParameters.newDefault();
|
||||
|
||||
final TransactionPool transactionPool = createTransactionPool(miningParameters);
|
||||
final TransactionPool transactionPool = createTransactionPool();
|
||||
|
||||
final PoWMinerExecutor executor =
|
||||
new PoWMinerExecutor(
|
||||
@@ -73,7 +73,7 @@ public class PoWMinerExecutorTest {
|
||||
public void settingCoinbaseToNullThrowsException() {
|
||||
final MiningParameters miningParameters = MiningParameters.newDefault();
|
||||
|
||||
final TransactionPool transactionPool = createTransactionPool(miningParameters);
|
||||
final TransactionPool transactionPool = createTransactionPool();
|
||||
|
||||
final PoWMinerExecutor executor =
|
||||
new PoWMinerExecutor(
|
||||
@@ -96,7 +96,7 @@ public class PoWMinerExecutorTest {
|
||||
return blockHeader;
|
||||
}
|
||||
|
||||
private TransactionPool createTransactionPool(final MiningParameters miningParameters) {
|
||||
private TransactionPool createTransactionPool() {
|
||||
final TransactionPoolConfiguration poolConf =
|
||||
ImmutableTransactionPoolConfiguration.builder().txPoolMaxSize(1).build();
|
||||
final GasPricePendingTransactionsSorter pendingTransactions =
|
||||
@@ -116,7 +116,6 @@ public class PoWMinerExecutorTest {
|
||||
mock(ProtocolContext.class),
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
miningParameters,
|
||||
new TransactionPoolMetrics(new NoOpMetricsSystem()),
|
||||
poolConf,
|
||||
null);
|
||||
|
||||
@@ -206,8 +206,7 @@ public class TraceTransactionIntegrationTest {
|
||||
assertThat(frame.getGasCost()).isEqualTo(OptionalLong.of(3L));
|
||||
assertThat(frame.getOpcode()).isEqualTo("PUSH1");
|
||||
assertThat(frame.getPc()).isEqualTo(2);
|
||||
assertStackContainsExactly(
|
||||
frame, "0000000000000000000000000000000000000000000000000000000000000080");
|
||||
assertStackContainsExactly(frame, "0x80");
|
||||
assertMemoryContainsExactly(frame);
|
||||
assertStorageContainsExactly(frame);
|
||||
|
||||
@@ -217,10 +216,7 @@ public class TraceTransactionIntegrationTest {
|
||||
assertThat(frame.getGasCost()).isEqualTo(OptionalLong.of(12L));
|
||||
assertThat(frame.getOpcode()).isEqualTo("MSTORE");
|
||||
assertThat(frame.getPc()).isEqualTo(4);
|
||||
assertStackContainsExactly(
|
||||
frame,
|
||||
"0000000000000000000000000000000000000000000000000000000000000080",
|
||||
"0000000000000000000000000000000000000000000000000000000000000040");
|
||||
assertStackContainsExactly(frame, "80", "40");
|
||||
assertMemoryContainsExactly(
|
||||
frame,
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
@@ -251,8 +247,8 @@ public class TraceTransactionIntegrationTest {
|
||||
private void assertStackContainsExactly(
|
||||
final TraceFrame frame, final String... stackEntriesAsHex) {
|
||||
assertThat(frame.getStack()).isPresent();
|
||||
final Bytes32[] stackEntries =
|
||||
Stream.of(stackEntriesAsHex).map(Bytes32::fromHexString).toArray(Bytes32[]::new);
|
||||
final Bytes[] stackEntries =
|
||||
Stream.of(stackEntriesAsHex).map(Bytes::fromHexString).toArray(Bytes[]::new);
|
||||
assertThat(frame.getStack().get()).containsExactly(stackEntries);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.bonsai.cache.CachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.bonsai.cache.CachedWorldStorageManager;
|
||||
import org.hyperledger.besu.ethereum.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.bonsai.trielog.TrieLogManager;
|
||||
import org.hyperledger.besu.ethereum.bonsai.trielog.TrieLogPruner;
|
||||
import org.hyperledger.besu.ethereum.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.chain.Blockchain;
|
||||
@@ -74,14 +75,19 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
|
||||
final CachedMerkleTrieLoader cachedMerkleTrieLoader,
|
||||
final ObservableMetricsSystem metricsSystem,
|
||||
final BesuContext pluginContext,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
final EvmConfiguration evmConfiguration,
|
||||
final TrieLogPruner trieLogPruner) {
|
||||
|
||||
this.cachedWorldStorageManager =
|
||||
new CachedWorldStorageManager(this, worldStateStorage, metricsSystem);
|
||||
// TODO: de-dup constructors
|
||||
this.trieLogManager =
|
||||
new TrieLogManager(
|
||||
blockchain, worldStateStorage, maxLayersToLoad.orElse(RETAINED_LAYERS), pluginContext);
|
||||
blockchain,
|
||||
worldStateStorage,
|
||||
maxLayersToLoad.orElse(RETAINED_LAYERS),
|
||||
pluginContext,
|
||||
trieLogPruner);
|
||||
this.blockchain = blockchain;
|
||||
this.worldStateStorage = worldStateStorage;
|
||||
this.cachedMerkleTrieLoader = cachedMerkleTrieLoader;
|
||||
|
||||
@@ -47,6 +47,7 @@ import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
@@ -203,6 +204,10 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateStorage, AutoC
|
||||
return trieLogStorage.get(blockHash.toArrayUnsafe());
|
||||
}
|
||||
|
||||
public Stream<byte[]> streamTrieLogKeys(final int limit) {
|
||||
return trieLogStorage.streamKeys().limit(limit);
|
||||
}
|
||||
|
||||
public Optional<Bytes> getStateTrieNode(final Bytes location) {
|
||||
return composedWorldStateStorage
|
||||
.get(TRIE_BRANCH_STORAGE, location.toArrayUnsafe())
|
||||
@@ -335,6 +340,15 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateStorage, AutoC
|
||||
throw new RuntimeException("Bonsai Tries do not work with pruning.");
|
||||
}
|
||||
|
||||
public boolean pruneTrieLog(final Hash blockHash) {
|
||||
try {
|
||||
return trieLogStorage.tryDelete(blockHash.toArrayUnsafe());
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error pruning trie log for block hash {}", blockHash, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long addNodeAddedListener(final NodesAddedListener listener) {
|
||||
throw new RuntimeException("addNodeAddedListener not available");
|
||||
|
||||
@@ -47,16 +47,19 @@ public class TrieLogManager {
|
||||
protected final Subscribers<TrieLogEvent.TrieLogObserver> trieLogObservers = Subscribers.create();
|
||||
|
||||
protected final TrieLogFactory trieLogFactory;
|
||||
private final TrieLogPruner trieLogPruner;
|
||||
|
||||
public TrieLogManager(
|
||||
final Blockchain blockchain,
|
||||
final BonsaiWorldStateKeyValueStorage worldStateStorage,
|
||||
final long maxLayersToLoad,
|
||||
final BesuContext pluginContext) {
|
||||
final BesuContext pluginContext,
|
||||
final TrieLogPruner trieLogPruner) {
|
||||
this.blockchain = blockchain;
|
||||
this.rootWorldStateStorage = worldStateStorage;
|
||||
this.maxLayersToLoad = maxLayersToLoad;
|
||||
this.trieLogFactory = setupTrieLogFactory(pluginContext);
|
||||
this.trieLogPruner = trieLogPruner;
|
||||
}
|
||||
|
||||
public synchronized void saveTrieLog(
|
||||
@@ -82,6 +85,8 @@ public class TrieLogManager {
|
||||
} finally {
|
||||
if (success) {
|
||||
stateUpdater.commit();
|
||||
trieLogPruner.addToPruneQueue(forBlockHeader.getNumber(), forBlockHeader.getBlockHash());
|
||||
trieLogPruner.pruneFromQueue();
|
||||
} else {
|
||||
stateUpdater.rollback();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* 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.bonsai.trielog;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.chain.Blockchain;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.TreeMultimap;
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class TrieLogPruner {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TrieLogPruner.class);
|
||||
|
||||
private final int pruningLimit;
|
||||
private final int loadingLimit;
|
||||
private final BonsaiWorldStateKeyValueStorage rootWorldStateStorage;
|
||||
private final Blockchain blockchain;
|
||||
private final long numBlocksToRetain;
|
||||
private final boolean requireFinalizedBlock;
|
||||
|
||||
private final Multimap<Long, Hash> trieLogBlocksAndForksByDescendingBlockNumber =
|
||||
TreeMultimap.create(Comparator.reverseOrder(), Comparator.naturalOrder());
|
||||
|
||||
public TrieLogPruner(
|
||||
final BonsaiWorldStateKeyValueStorage rootWorldStateStorage,
|
||||
final Blockchain blockchain,
|
||||
final long numBlocksToRetain,
|
||||
final int pruningLimit,
|
||||
final boolean requireFinalizedBlock) {
|
||||
this.rootWorldStateStorage = rootWorldStateStorage;
|
||||
this.blockchain = blockchain;
|
||||
this.numBlocksToRetain = numBlocksToRetain;
|
||||
this.pruningLimit = pruningLimit;
|
||||
this.loadingLimit = pruningLimit; // same as pruningLimit for now
|
||||
this.requireFinalizedBlock = requireFinalizedBlock;
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
preloadQueue();
|
||||
}
|
||||
|
||||
private void preloadQueue() {
|
||||
LOG.atInfo()
|
||||
.setMessage("Loading first {} trie logs from database...")
|
||||
.addArgument(loadingLimit)
|
||||
.log();
|
||||
try (final Stream<byte[]> trieLogKeys = rootWorldStateStorage.streamTrieLogKeys(loadingLimit)) {
|
||||
final AtomicLong count = new AtomicLong();
|
||||
trieLogKeys.forEach(
|
||||
blockHashAsBytes -> {
|
||||
final Hash blockHash = Hash.wrap(Bytes32.wrap(blockHashAsBytes));
|
||||
final Optional<BlockHeader> header = blockchain.getBlockHeader(blockHash);
|
||||
if (header.isPresent()) {
|
||||
trieLogBlocksAndForksByDescendingBlockNumber.put(header.get().getNumber(), blockHash);
|
||||
count.getAndIncrement();
|
||||
} else {
|
||||
// prune orphaned blocks (sometimes created during block production)
|
||||
rootWorldStateStorage.pruneTrieLog(blockHash);
|
||||
}
|
||||
});
|
||||
LOG.atInfo().log("Loaded {} trie logs from database", count);
|
||||
pruneFromQueue();
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error loading trie logs from database, nothing pruned", e);
|
||||
}
|
||||
}
|
||||
|
||||
void addToPruneQueue(final long blockNumber, final Hash blockHash) {
|
||||
LOG.atTrace()
|
||||
.setMessage("adding trie log to queue for later pruning blockNumber {}; blockHash {}")
|
||||
.addArgument(blockNumber)
|
||||
.addArgument(blockHash)
|
||||
.log();
|
||||
trieLogBlocksAndForksByDescendingBlockNumber.put(blockNumber, blockHash);
|
||||
}
|
||||
|
||||
int pruneFromQueue() {
|
||||
final long retainAboveThisBlock = blockchain.getChainHeadBlockNumber() - numBlocksToRetain;
|
||||
final Optional<Hash> finalized = blockchain.getFinalized();
|
||||
if (requireFinalizedBlock && finalized.isEmpty()) {
|
||||
LOG.debug("No finalized block present, skipping pruning");
|
||||
return 0;
|
||||
}
|
||||
|
||||
final long retainAboveThisBlockOrFinalized =
|
||||
finalized
|
||||
.flatMap(blockchain::getBlockHeader)
|
||||
.map(ProcessableBlockHeader::getNumber)
|
||||
.map(finalizedBlock -> Math.min(finalizedBlock, retainAboveThisBlock))
|
||||
.orElse(retainAboveThisBlock);
|
||||
|
||||
LOG.atTrace()
|
||||
.setMessage(
|
||||
"min((chainHeadNumber: {} - numBlocksToRetain: {}) = {}, finalized: {})) = retainAboveThisBlockOrFinalized: {}")
|
||||
.addArgument(blockchain::getChainHeadBlockNumber)
|
||||
.addArgument(numBlocksToRetain)
|
||||
.addArgument(retainAboveThisBlock)
|
||||
.addArgument(
|
||||
() ->
|
||||
finalized
|
||||
.flatMap(blockchain::getBlockHeader)
|
||||
.map(ProcessableBlockHeader::getNumber)
|
||||
.orElse(null))
|
||||
.addArgument(retainAboveThisBlockOrFinalized)
|
||||
.log();
|
||||
|
||||
final var pruneWindowEntries =
|
||||
trieLogBlocksAndForksByDescendingBlockNumber.asMap().entrySet().stream()
|
||||
.dropWhile((e) -> e.getKey() > retainAboveThisBlockOrFinalized)
|
||||
.limit(pruningLimit);
|
||||
|
||||
final Multimap<Long, Hash> wasPruned = ArrayListMultimap.create();
|
||||
|
||||
pruneWindowEntries.forEach(
|
||||
(e) -> {
|
||||
for (Hash blockHash : e.getValue()) {
|
||||
if (rootWorldStateStorage.pruneTrieLog(blockHash)) {
|
||||
wasPruned.put(e.getKey(), blockHash);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
wasPruned.keySet().forEach(trieLogBlocksAndForksByDescendingBlockNumber::removeAll);
|
||||
|
||||
LOG.atTrace()
|
||||
.setMessage("pruned {} trie logs for blocks {}")
|
||||
.addArgument(wasPruned::size)
|
||||
.addArgument(wasPruned)
|
||||
.log();
|
||||
LOG.atDebug()
|
||||
.setMessage("pruned {} trie logs from {} blocks")
|
||||
.addArgument(wasPruned::size)
|
||||
.addArgument(() -> wasPruned.keySet().size())
|
||||
.log();
|
||||
|
||||
return wasPruned.size();
|
||||
}
|
||||
|
||||
public static TrieLogPruner noOpTrieLogPruner() {
|
||||
return new NoOpTrieLogPruner(null, null, 0, 0);
|
||||
}
|
||||
|
||||
public static class NoOpTrieLogPruner extends TrieLogPruner {
|
||||
private NoOpTrieLogPruner(
|
||||
final BonsaiWorldStateKeyValueStorage rootWorldStateStorage,
|
||||
final Blockchain blockchain,
|
||||
final long numBlocksToRetain,
|
||||
final int pruningLimit) {
|
||||
super(rootWorldStateStorage, blockchain, numBlocksToRetain, pruningLimit, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
void addToPruneQueue(final long blockNumber, final Hash blockHash) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
int pruneFromQueue() {
|
||||
// no-op
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,6 +148,15 @@ public interface Blockchain {
|
||||
*/
|
||||
Optional<BlockHeader> getBlockHeader(Hash blockHeaderHash);
|
||||
|
||||
/**
|
||||
* Safe version of {@code getBlockHeader} (it should take any locks necessary to ensure any block
|
||||
* updates that might be taking place have been completed first)
|
||||
*
|
||||
* @param blockHeaderHash The hash of the block whose header we want to retrieve.
|
||||
* @return The block header corresponding to this block hash.
|
||||
*/
|
||||
Optional<BlockHeader> getBlockHeaderSafe(Hash blockHeaderHash);
|
||||
|
||||
/**
|
||||
* Returns the block body corresponding to the given block header hash. Associated block is not
|
||||
* necessarily on the canonical chain.
|
||||
|
||||
@@ -302,6 +302,16 @@ public class DefaultBlockchain implements MutableBlockchain {
|
||||
.orElseGet(() -> blockchainStorage.getBlockHeader(blockHeaderHash));
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Optional<BlockHeader> getBlockHeaderSafe(final Hash blockHeaderHash) {
|
||||
return blockHeadersCache
|
||||
.map(
|
||||
cache ->
|
||||
Optional.ofNullable(cache.getIfPresent(blockHeaderHash))
|
||||
.or(() -> blockchainStorage.getBlockHeader(blockHeaderHash)))
|
||||
.orElseGet(() -> blockchainStorage.getBlockHeader(blockHeaderHash));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<BlockBody> getBlockBody(final Hash blockHeaderHash) {
|
||||
return blockBodiesCache
|
||||
|
||||
@@ -1096,6 +1096,26 @@ public class Transaction
|
||||
protected List<VersionedHash> versionedHashes = null;
|
||||
private BlobsWithCommitments blobsWithCommitments;
|
||||
|
||||
public Builder copiedFrom(final Transaction toCopy) {
|
||||
this.transactionType = toCopy.transactionType;
|
||||
this.nonce = toCopy.nonce;
|
||||
this.gasPrice = toCopy.gasPrice.orElse(null);
|
||||
this.maxPriorityFeePerGas = toCopy.maxPriorityFeePerGas.orElse(null);
|
||||
this.maxFeePerGas = toCopy.maxFeePerGas.orElse(null);
|
||||
this.maxFeePerBlobGas = toCopy.maxFeePerBlobGas.orElse(null);
|
||||
this.gasLimit = toCopy.gasLimit;
|
||||
this.to = toCopy.to;
|
||||
this.value = toCopy.value;
|
||||
this.signature = toCopy.signature;
|
||||
this.payload = toCopy.payload;
|
||||
this.accessList = toCopy.maybeAccessList;
|
||||
this.sender = toCopy.sender;
|
||||
this.chainId = toCopy.chainId;
|
||||
this.versionedHashes = toCopy.versionedHashes.orElse(null);
|
||||
this.blobsWithCommitments = toCopy.blobsWithCommitments.orElse(null);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder type(final TransactionType transactionType) {
|
||||
this.transactionType = transactionType;
|
||||
return this;
|
||||
@@ -1260,5 +1280,10 @@ public class Transaction
|
||||
new BlobsWithCommitments(kzgCommitments, blobs, kzgProofs, versionedHashes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder blobsWithCommitments(final BlobsWithCommitments blobsWithCommitments) {
|
||||
this.blobsWithCommitments = blobsWithCommitments;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,10 @@ import java.util.List;
|
||||
*/
|
||||
public class BlobPooledTransactionDecoder {
|
||||
|
||||
private BlobPooledTransactionDecoder() {
|
||||
// no instances
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a blob transaction from the provided RLP input.
|
||||
*
|
||||
@@ -44,7 +48,6 @@ public class BlobPooledTransactionDecoder {
|
||||
List<KZGCommitment> commitments = input.readList(KZGCommitment::readFrom);
|
||||
List<KZGProof> proofs = input.readList(KZGProof::readFrom);
|
||||
input.leaveList();
|
||||
builder.kzgBlobs(commitments, blobs, proofs);
|
||||
return builder.build();
|
||||
return builder.kzgBlobs(commitments, blobs, proofs).build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import java.util.OptionalLong;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.apache.tuweni.units.bigints.UInt256;
|
||||
|
||||
public class TraceFrame {
|
||||
@@ -44,7 +43,7 @@ public class TraceFrame {
|
||||
private final Wei value;
|
||||
private final Bytes inputData;
|
||||
private final Bytes outputData;
|
||||
private final Optional<Bytes32[]> stack;
|
||||
private final Optional<Bytes[]> stack;
|
||||
private final Optional<Bytes[]> memory;
|
||||
private final Optional<Map<UInt256, UInt256>> storage;
|
||||
|
||||
@@ -53,7 +52,7 @@ public class TraceFrame {
|
||||
private final Optional<Map<Address, Wei>> maybeRefunds;
|
||||
private final Optional<Code> maybeCode;
|
||||
private final int stackItemsProduced;
|
||||
private final Optional<Bytes32[]> stackPostExecution;
|
||||
private final Optional<Bytes[]> stackPostExecution;
|
||||
|
||||
private long gasRemainingPostExecution;
|
||||
private final boolean virtualOperation;
|
||||
@@ -73,7 +72,7 @@ public class TraceFrame {
|
||||
final Wei value,
|
||||
final Bytes inputData,
|
||||
final Bytes outputData,
|
||||
final Optional<Bytes32[]> stack,
|
||||
final Optional<Bytes[]> stack,
|
||||
final Optional<Bytes[]> memory,
|
||||
final Optional<Map<UInt256, UInt256>> storage,
|
||||
final WorldUpdater worldUpdater,
|
||||
@@ -81,7 +80,7 @@ public class TraceFrame {
|
||||
final Optional<Map<Address, Wei>> maybeRefunds,
|
||||
final Optional<Code> maybeCode,
|
||||
final int stackItemsProduced,
|
||||
final Optional<Bytes32[]> stackPostExecution,
|
||||
final Optional<Bytes[]> stackPostExecution,
|
||||
final boolean virtualOperation,
|
||||
final Optional<MemoryEntry> maybeUpdatedMemory,
|
||||
final Optional<StorageEntry> maybeUpdatedStorage) {
|
||||
@@ -159,7 +158,7 @@ public class TraceFrame {
|
||||
return outputData;
|
||||
}
|
||||
|
||||
public Optional<Bytes32[]> getStack() {
|
||||
public Optional<Bytes[]> getStack() {
|
||||
return stack;
|
||||
}
|
||||
|
||||
@@ -206,7 +205,7 @@ public class TraceFrame {
|
||||
return stackItemsProduced;
|
||||
}
|
||||
|
||||
public Optional<Bytes32[]> getStackPostExecution() {
|
||||
public Optional<Bytes[]> getStackPostExecution() {
|
||||
return stackPostExecution;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Responsible for ensuring the timestamp of a block is not more than "acceptableClockDriftSeconds'
|
||||
* Responsible for ensuring the timestamp of a block is not more than "acceptableClockDriftSeconds"
|
||||
* into the future.
|
||||
*/
|
||||
public class TimestampBoundedByFutureParameter implements DetachedBlockHeaderValidationRule {
|
||||
|
||||
@@ -40,7 +40,6 @@ public enum TransactionInvalidReason {
|
||||
INITCODE_TOO_LARGE,
|
||||
CALLDATA_TOO_LARGE,
|
||||
NONCE_TOO_FAR_IN_FUTURE_FOR_SENDER,
|
||||
LOWER_NONCE_INVALID_TRANSACTION_EXISTS,
|
||||
TOTAL_BLOB_GAS_TOO_HIGH,
|
||||
GAS_PRICE_TOO_LOW,
|
||||
GAS_PRICE_BELOW_CURRENT_BASE_FEE,
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.vm;
|
||||
|
||||
import static org.apache.tuweni.bytes.Bytes32.leftPad;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.debug.TraceFrame;
|
||||
@@ -36,7 +34,6 @@ import java.util.OptionalLong;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.apache.tuweni.units.bigints.UInt256;
|
||||
|
||||
public class DebugOperationTracer implements OperationTracer {
|
||||
@@ -45,7 +42,7 @@ public class DebugOperationTracer implements OperationTracer {
|
||||
private List<TraceFrame> traceFrames = new ArrayList<>();
|
||||
private TraceFrame lastFrame;
|
||||
|
||||
private Optional<Bytes32[]> preExecutionStack;
|
||||
private Optional<Bytes[]> preExecutionStack;
|
||||
private long gasRemaining;
|
||||
private Bytes inputData;
|
||||
private int pc;
|
||||
@@ -73,7 +70,7 @@ public class DebugOperationTracer implements OperationTracer {
|
||||
final WorldUpdater worldUpdater = frame.getWorldUpdater();
|
||||
final Bytes outputData = frame.getOutputData();
|
||||
final Optional<Bytes[]> memory = captureMemory(frame);
|
||||
final Optional<Bytes32[]> stackPostExecution = captureStack(frame);
|
||||
final Optional<Bytes[]> stackPostExecution = captureStack(frame);
|
||||
|
||||
if (lastFrame != null) {
|
||||
lastFrame.setGasRemainingPostExecution(gasRemaining);
|
||||
@@ -218,15 +215,15 @@ public class DebugOperationTracer implements OperationTracer {
|
||||
return Optional.of(memoryContents);
|
||||
}
|
||||
|
||||
private Optional<Bytes32[]> captureStack(final MessageFrame frame) {
|
||||
private Optional<Bytes[]> captureStack(final MessageFrame frame) {
|
||||
if (!options.isStackEnabled()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
final Bytes32[] stackContents = new Bytes32[frame.stackSize()];
|
||||
final Bytes[] stackContents = new Bytes[frame.stackSize()];
|
||||
for (int i = 0; i < stackContents.length; i++) {
|
||||
// Record stack contents in reverse
|
||||
stackContents[i] = leftPad(frame.getStackItem(stackContents.length - i - 1));
|
||||
stackContents[i] = frame.getStackItem(stackContents.length - i - 1);
|
||||
}
|
||||
return Optional.of(stackContents);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.hyperledger.besu.ethereum.worldstate;
|
||||
import org.immutables.value.Value;
|
||||
|
||||
@Value.Immutable
|
||||
@Value.Enclosing
|
||||
public interface DataStorageConfiguration {
|
||||
|
||||
long DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD = 512;
|
||||
@@ -27,9 +28,42 @@ public interface DataStorageConfiguration {
|
||||
ImmutableDataStorageConfiguration.builder()
|
||||
.dataStorageFormat(DataStorageFormat.FOREST)
|
||||
.bonsaiMaxLayersToLoad(DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD)
|
||||
.unstable(Unstable.DEFAULT)
|
||||
.build();
|
||||
|
||||
DataStorageFormat getDataStorageFormat();
|
||||
|
||||
Long getBonsaiMaxLayersToLoad();
|
||||
|
||||
@Value.Default
|
||||
default Unstable getUnstable() {
|
||||
return Unstable.DEFAULT;
|
||||
}
|
||||
|
||||
@Value.Immutable
|
||||
interface Unstable {
|
||||
|
||||
boolean DEFAULT_BONSAI_TRIE_LOG_PRUNING_ENABLED = false;
|
||||
long DEFAULT_BONSAI_TRIE_LOG_RETENTION_THRESHOLD = 512L;
|
||||
long MINIMUM_BONSAI_TRIE_LOG_RETENTION_THRESHOLD = DEFAULT_BONSAI_TRIE_LOG_RETENTION_THRESHOLD;
|
||||
int DEFAULT_BONSAI_TRIE_LOG_PRUNING_LIMIT = 30_000;
|
||||
|
||||
DataStorageConfiguration.Unstable DEFAULT =
|
||||
ImmutableDataStorageConfiguration.Unstable.builder().build();
|
||||
|
||||
@Value.Default
|
||||
default boolean getBonsaiTrieLogPruningEnabled() {
|
||||
return DEFAULT_BONSAI_TRIE_LOG_PRUNING_ENABLED;
|
||||
}
|
||||
|
||||
@Value.Default
|
||||
default long getBonsaiTrieLogRetentionThreshold() {
|
||||
return DEFAULT_BONSAI_TRIE_LOG_RETENTION_THRESHOLD;
|
||||
}
|
||||
|
||||
@Value.Default
|
||||
default int getBonsaiTrieLogPruningLimit() {
|
||||
return DEFAULT_BONSAI_TRIE_LOG_PRUNING_LIMIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public class BlobTestFixture {
|
||||
// and ignore errors in case no trusted setup was already loaded
|
||||
}
|
||||
try {
|
||||
CKZG4844JNI.loadNativeLibrary(CKZG4844JNI.Preset.MAINNET);
|
||||
CKZG4844JNI.loadNativeLibrary();
|
||||
CKZG4844JNI.loadTrustedSetupFromResource(
|
||||
"/kzg-trusted-setups/mainnet.txt", BlobTestFixture.class);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user