Skip to content

Commit b5d507d

Browse files
authored
Extend simulate transaction on pending block plugin API (hyperledger#8174)
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
1 parent b3192a5 commit b5d507d

File tree

6 files changed

+87
-90
lines changed

6 files changed

+87
-90
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
### Upcoming Breaking Changes
66
### Additions and Improvements
77
- Adds timestamps to enable Prague hardfork on Sepolia and Holesky test networks. [#8163](https://github.com/hyperledger/besu/pull/8163)
8+
- Extend simulate transaction on pending block plugin API [#8174](https://github.com/hyperledger/besu/pull/8174)
9+
810
### Bug fixes
911

1012

besu/src/main/java/org/hyperledger/besu/services/TransactionSimulationServiceImpl.java

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,23 @@
1414
*/
1515
package org.hyperledger.besu.services;
1616

17+
import static org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams.transactionSimulator;
18+
import static org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams.transactionSimulatorAllowExceedingBalance;
19+
import static org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams.transactionSimulatorAllowExceedingBalanceAndFutureNonce;
20+
import static org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams.transactionSimulatorAllowFutureNonce;
21+
1722
import org.hyperledger.besu.datatypes.Hash;
1823
import org.hyperledger.besu.datatypes.StateOverrideMap;
1924
import org.hyperledger.besu.datatypes.Transaction;
2025
import org.hyperledger.besu.ethereum.chain.Blockchain;
21-
import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
2226
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
2327
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
2428
import org.hyperledger.besu.ethereum.transaction.CallParameter;
2529
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
2630
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
2731
import org.hyperledger.besu.evm.tracing.OperationTracer;
2832
import org.hyperledger.besu.plugin.Unstable;
33+
import org.hyperledger.besu.plugin.data.ProcessableBlockHeader;
2934
import org.hyperledger.besu.plugin.data.TransactionSimulationResult;
3035
import org.hyperledger.besu.plugin.services.TransactionSimulationService;
3136

@@ -51,50 +56,67 @@ public void init(final Blockchain blockchain, final TransactionSimulator transac
5156
this.transactionSimulator = transactionSimulator;
5257
}
5358

59+
@Override
60+
public ProcessableBlockHeader simulatePendingBlockHeader() {
61+
return transactionSimulator.simulatePendingBlockHeader();
62+
}
63+
5464
@Override
5565
public Optional<TransactionSimulationResult> simulate(
5666
final Transaction transaction,
5767
final Optional<StateOverrideMap> maybeStateOverrides,
58-
final Optional<Hash> maybeBlockHash,
68+
final Hash blockHash,
5969
final OperationTracer operationTracer,
6070
final boolean isAllowExceedingBalance) {
6171

6272
final CallParameter callParameter = CallParameter.fromTransaction(transaction);
6373

64-
if (maybeBlockHash.isPresent()) {
65-
final Hash blockHash = maybeBlockHash.get();
74+
final var maybeBlockHeader =
75+
blockchain.getBlockHeader(blockHash).or(() -> blockchain.getBlockHeaderSafe(blockHash));
6676

67-
final var maybeBlockHeader =
68-
blockchain.getBlockHeader(blockHash).or(() -> blockchain.getBlockHeaderSafe(blockHash));
77+
if (maybeBlockHeader.isEmpty()) {
78+
return Optional.of(
79+
new TransactionSimulationResult(
80+
transaction,
81+
TransactionProcessingResult.invalid(
82+
ValidationResult.invalid(TransactionInvalidReason.BLOCK_NOT_FOUND))));
83+
}
6984

70-
if (maybeBlockHeader.isEmpty()) {
71-
return Optional.of(
72-
new TransactionSimulationResult(
73-
transaction,
74-
TransactionProcessingResult.invalid(
75-
ValidationResult.invalid(TransactionInvalidReason.BLOCK_NOT_FOUND))));
76-
}
85+
return transactionSimulator
86+
.process(
87+
callParameter,
88+
isAllowExceedingBalance
89+
? transactionSimulatorAllowExceedingBalance()
90+
: transactionSimulator(),
91+
operationTracer,
92+
maybeBlockHeader.get())
93+
.map(res -> new TransactionSimulationResult(transaction, res.result()));
94+
}
7795

78-
return transactionSimulator
79-
.process(
80-
callParameter,
81-
isAllowExceedingBalance
82-
? TransactionValidationParams.transactionSimulatorAllowExceedingBalance()
83-
: TransactionValidationParams.transactionSimulator(),
84-
operationTracer,
85-
maybeBlockHeader.get())
86-
.map(res -> new TransactionSimulationResult(transaction, res.result()));
87-
}
96+
@Override
97+
public Optional<TransactionSimulationResult> simulate(
98+
final Transaction transaction,
99+
final Optional<StateOverrideMap> maybeStateOverrides,
100+
final ProcessableBlockHeader pendingBlockHeader,
101+
final OperationTracer operationTracer,
102+
final boolean isAllowExceedingBalance,
103+
final boolean isAllowFutureNonce) {
104+
105+
final CallParameter callParameter = CallParameter.fromTransaction(transaction);
88106

89107
return transactionSimulator
90108
.processOnPending(
91109
callParameter,
92110
maybeStateOverrides,
93111
isAllowExceedingBalance
94-
? TransactionValidationParams.transactionSimulatorAllowExceedingBalance()
95-
: TransactionValidationParams.transactionSimulator(),
112+
? isAllowFutureNonce
113+
? transactionSimulatorAllowExceedingBalanceAndFutureNonce()
114+
: transactionSimulatorAllowExceedingBalance()
115+
: isAllowFutureNonce
116+
? transactionSimulatorAllowFutureNonce()
117+
: transactionSimulator(),
96118
operationTracer,
97-
transactionSimulator.simulatePendingBlockHeader())
119+
(org.hyperledger.besu.ethereum.core.ProcessableBlockHeader) pendingBlockHeader)
98120
.map(res -> new TransactionSimulationResult(transaction, res.result()));
99121
}
100122
}

ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/TransactionValidationParams.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,15 @@ public interface TransactionValidationParams {
3535
TransactionValidationParams transactionSimulatorParams =
3636
ImmutableTransactionValidationParams.of(false, false, false, false, false, true);
3737

38+
TransactionValidationParams transactionSimulatorParamsAllowFutureNonce =
39+
ImmutableTransactionValidationParams.of(true, false, false, false, false, true);
40+
3841
TransactionValidationParams transactionSimulatorAllowExceedingBalanceParams =
3942
ImmutableTransactionValidationParams.of(false, true, false, false, false, true);
4043

44+
TransactionValidationParams transactionSimulatorAllowExceedingBalanceAndFutureNonceParams =
45+
ImmutableTransactionValidationParams.of(true, true, false, false, false, true);
46+
4147
@Value.Default
4248
default boolean isAllowFutureNonce() {
4349
return false;
@@ -72,10 +78,18 @@ static TransactionValidationParams transactionSimulator() {
7278
return transactionSimulatorParams;
7379
}
7480

81+
static TransactionValidationParams transactionSimulatorAllowFutureNonce() {
82+
return transactionSimulatorParamsAllowFutureNonce;
83+
}
84+
7585
static TransactionValidationParams transactionSimulatorAllowExceedingBalance() {
7686
return transactionSimulatorAllowExceedingBalanceParams;
7787
}
7888

89+
static TransactionValidationParams transactionSimulatorAllowExceedingBalanceAndFutureNonce() {
90+
return transactionSimulatorAllowExceedingBalanceAndFutureNonceParams;
91+
}
92+
7993
static TransactionValidationParams processingBlock() {
8094
return processingBlockParams;
8195
}

ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ public Optional<TransactionSimulatorResult> processOnPending(
174174
operationTracer,
175175
pendingBlockHeader,
176176
updater,
177-
Address.ZERO);
177+
pendingBlockHeader.getCoinbase());
178178
} catch (Exception e) {
179179
throw new RuntimeException(e);
180180
}

plugin-api/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ Calculated : ${currentHash}
7171
tasks.register('checkAPIChanges', FileStateChecker) {
7272
description = "Checks that the API for the Plugin-API project does not change without deliberate thought"
7373
files = sourceSets.main.allJava.files
74-
knownHash = 'E2b/W+IKnNxo6L7cHuijBMBUewHHRrkQ8dEVlcql5KE='
74+
knownHash = 'gZIQWjSStog+2qxsbGPPp0OwpYjl8QDM5pv9QWdtADA='
7575
}
7676
check.dependsOn('checkAPIChanges')
7777

plugin-api/src/main/java/org/hyperledger/besu/plugin/services/TransactionSimulationService.java

Lines changed: 21 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.hyperledger.besu.datatypes.Transaction;
2020
import org.hyperledger.besu.evm.tracing.OperationTracer;
2121
import org.hyperledger.besu.plugin.Unstable;
22+
import org.hyperledger.besu.plugin.data.ProcessableBlockHeader;
2223
import org.hyperledger.besu.plugin.data.TransactionSimulationResult;
2324

2425
import java.util.Optional;
@@ -27,91 +28,49 @@
2728
@Unstable
2829
public interface TransactionSimulationService extends BesuService {
2930

31+
/**
32+
* Return a simulation of what could be current pending block, it can also be passed to {@link
33+
* #simulate(Transaction, Optional, ProcessableBlockHeader, OperationTracer, boolean, boolean)}
34+
*
35+
* @return the simulated pending block header
36+
*/
37+
ProcessableBlockHeader simulatePendingBlockHeader();
38+
3039
/**
3140
* Simulate transaction execution at the block identified by the hash if present, otherwise on the
3241
* pending block, with optional state overrides that can be applied before the simulation.
3342
*
3443
* @param transaction tx
3544
* @param stateOverrides state overrides to apply to this simulation
36-
* @param maybeBlockHash optional hash of the block, empty to simulate on pending block
45+
* @param blockHash hash of the block
3746
* @param operationTracer the tracer
3847
* @param isAllowExceedingBalance should ignore the sender balance during the simulation?
3948
* @return the result of the simulation
4049
*/
4150
Optional<TransactionSimulationResult> simulate(
4251
Transaction transaction,
4352
Optional<StateOverrideMap> stateOverrides,
44-
Optional<Hash> maybeBlockHash,
53+
Hash blockHash,
4554
OperationTracer operationTracer,
4655
boolean isAllowExceedingBalance);
4756

4857
/**
4958
* Simulate transaction execution at the block identified by the hash if present, otherwise on the
50-
* pending block
51-
*
52-
* @param transaction tx
53-
* @param maybeBlockHash optional hash of the block, empty to simulate on pending block
54-
* @param operationTracer the tracer
55-
* @param isAllowExceedingBalance should ignore the sender balance during the simulation?
56-
* @return the result of the simulation
57-
*/
58-
default Optional<TransactionSimulationResult> simulate(
59-
final Transaction transaction,
60-
final Optional<Hash> maybeBlockHash,
61-
final OperationTracer operationTracer,
62-
final boolean isAllowExceedingBalance) {
63-
return simulate(
64-
transaction, Optional.empty(), maybeBlockHash, operationTracer, isAllowExceedingBalance);
65-
}
66-
67-
/**
68-
* Simulate transaction execution at the block identified by the hash
69-
*
70-
* @param transaction tx
71-
* @param blockHash then hash of the block
72-
* @param operationTracer the tracer
73-
* @param isAllowExceedingBalance should ignore the sender balance during the simulation?
74-
* @return the result of the simulation
75-
* @deprecated use {@link #simulate(Transaction, Optional, OperationTracer, boolean)}
76-
*/
77-
@Deprecated(since = "24.12", forRemoval = true)
78-
default Optional<TransactionSimulationResult> simulate(
79-
final Transaction transaction,
80-
final Hash blockHash,
81-
final OperationTracer operationTracer,
82-
final boolean isAllowExceedingBalance) {
83-
return simulate(
84-
transaction,
85-
Optional.empty(),
86-
Optional.of(blockHash),
87-
operationTracer,
88-
isAllowExceedingBalance);
89-
}
90-
91-
/**
92-
* Simulate transaction execution at the block identified by the hash, with optional state
93-
* overrides that can be applied before the simulation.
59+
* pending block, with optional state overrides that can be applied before the simulation.
9460
*
9561
* @param transaction tx
9662
* @param stateOverrides state overrides to apply to this simulation
97-
* @param blockHash the hash of the block
63+
* @param processableBlockHeader block header to simulate on pending block
9864
* @param operationTracer the tracer
9965
* @param isAllowExceedingBalance should ignore the sender balance during the simulation?
66+
* @param isAllowFutureNonce should skip strict check on sequential nonce?
10067
* @return the result of the simulation
101-
* @deprecated use {@link #simulate(Transaction, Optional, Optional, OperationTracer, boolean)}
10268
*/
103-
@Deprecated(since = "24.12", forRemoval = true)
104-
default Optional<TransactionSimulationResult> simulate(
105-
final Transaction transaction,
106-
final Optional<StateOverrideMap> stateOverrides,
107-
final Hash blockHash,
108-
final OperationTracer operationTracer,
109-
final boolean isAllowExceedingBalance) {
110-
return simulate(
111-
transaction,
112-
stateOverrides,
113-
Optional.of(blockHash),
114-
operationTracer,
115-
isAllowExceedingBalance);
116-
}
69+
Optional<TransactionSimulationResult> simulate(
70+
Transaction transaction,
71+
Optional<StateOverrideMap> stateOverrides,
72+
ProcessableBlockHeader processableBlockHeader,
73+
OperationTracer operationTracer,
74+
boolean isAllowExceedingBalance,
75+
boolean isAllowFutureNonce);
11776
}

0 commit comments

Comments
 (0)