mirror of
https://github.com/vacp2p/linea-besu.git
synced 2026-01-09 21:17:54 -05:00
Add support for movePrecompileToAddress in State Overrides (eth_call) (#8115)
Signed-off-by: Gabriel-Trintinalia <gabriel.trintinalia@consensys.net>
This commit is contained in:
committed by
GitHub
parent
9c12ed19df
commit
5cc309a26e
@@ -24,6 +24,7 @@
|
||||
- Allow gasPrice (legacy) and 1559 gasPrice params to be specified simultaneously for `eth_call`, `eth_createAccessList`, and `eth_estimateGas` [#8059](https://github.com/hyperledger/besu/pull/8059)
|
||||
- Improve debug_traceBlock calls performance and reduce output size [#8076](https://github.com/hyperledger/besu/pull/8076)
|
||||
- Add support for EIP-7702 transaction in the txpool [#8018](https://github.com/hyperledger/besu/pull/8018) [#7984](https://github.com/hyperledger/besu/pull/7984)
|
||||
- Add support for `movePrecompileToAddress` in `StateOverrides` (`eth_call`)[8115](https://github.com/hyperledger/besu/pull/8115)
|
||||
|
||||
### Bug fixes
|
||||
- Fix serialization of state overrides when `movePrecompileToAddress` is present [#8204](https://github.com/hyperledger/besu/pull/8024)
|
||||
|
||||
@@ -36,16 +36,19 @@ public class StateOverride {
|
||||
private final Optional<Long> nonce;
|
||||
private final Optional<String> code;
|
||||
private final Optional<Map<String, String>> stateDiff;
|
||||
private final Optional<Address> movePrecompileToAddress;
|
||||
|
||||
private StateOverride(
|
||||
final Optional<Wei> balance,
|
||||
final Optional<Long> nonce,
|
||||
final Optional<String> code,
|
||||
final Optional<Map<String, String>> stateDiff) {
|
||||
final Optional<Map<String, String>> stateDiff,
|
||||
final Optional<Address> movePrecompileToAddress) {
|
||||
this.balance = balance;
|
||||
this.nonce = nonce;
|
||||
this.code = code;
|
||||
this.stateDiff = stateDiff;
|
||||
this.movePrecompileToAddress = movePrecompileToAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,6 +87,15 @@ public class StateOverride {
|
||||
return stateDiff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the new address for the pre-compiled contract
|
||||
*
|
||||
* @return the new address for the pre-compiled contract if present
|
||||
*/
|
||||
public Optional<Address> getMovePrecompileToAddress() {
|
||||
return movePrecompileToAddress;
|
||||
}
|
||||
|
||||
/** Builder class for Account overrides */
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public static class Builder {
|
||||
@@ -91,6 +103,7 @@ public class StateOverride {
|
||||
private Optional<Long> nonce = Optional.empty();
|
||||
private Optional<String> code = Optional.empty();
|
||||
private Optional<Map<String, String>> stateDiff = Optional.empty();
|
||||
private Optional<Address> movePrecompileToAddress = Optional.empty();
|
||||
|
||||
/** Default constructor. */
|
||||
public Builder() {}
|
||||
@@ -139,13 +152,24 @@ public class StateOverride {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new address for the pre-compiled contract
|
||||
*
|
||||
* @param newPrecompileAddress the new address for the pre-compile contract
|
||||
* @return the builder
|
||||
*/
|
||||
public Builder withMovePrecompileToAddress(final Address newPrecompileAddress) {
|
||||
this.movePrecompileToAddress = Optional.ofNullable(newPrecompileAddress);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* build the account override from the builder
|
||||
*
|
||||
* @return account override
|
||||
*/
|
||||
public StateOverride build() {
|
||||
return new StateOverride(balance, nonce, code, stateDiff);
|
||||
return new StateOverride(balance, nonce, code, stateDiff, movePrecompileToAddress);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,6 +219,8 @@ public class StateOverride {
|
||||
+ code
|
||||
+ ", stateDiff="
|
||||
+ stateDiff
|
||||
+ ", movePrecompileToAddress="
|
||||
+ movePrecompileToAddress
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ import org.hyperledger.besu.ethereum.transaction.PreCloseStateHandler;
|
||||
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
|
||||
import org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
@@ -123,6 +124,33 @@ public class EthCallTest {
|
||||
assertThat(overrideMap).containsValue(override);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fullStateOverrides() {
|
||||
StateOverrideMap suppliedOverrides = new StateOverrideMap();
|
||||
StateOverride override =
|
||||
new StateOverride.Builder()
|
||||
.withNonce(new UnsignedLongParameter("0x9e"))
|
||||
.withBalance(Wei.of(100))
|
||||
.withCode("0x1234")
|
||||
.withStateDiff(Map.of("0x1234", "0x5678"))
|
||||
.withMovePrecompileToAddress(Address.fromHexString("0x1234"))
|
||||
.build();
|
||||
final Address address = Address.fromHexString("0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3");
|
||||
suppliedOverrides.put(address, override);
|
||||
|
||||
final JsonRpcRequestContext request =
|
||||
ethCallRequestWithStateOverrides(callParameter(), "latest", suppliedOverrides);
|
||||
|
||||
Optional<StateOverrideMap> maybeOverrideMap = method.getAddressStateOverrideMap(request);
|
||||
assertThat(maybeOverrideMap.isPresent()).isTrue();
|
||||
StateOverrideMap actualOverrideMap = maybeOverrideMap.get();
|
||||
assertThat(actualOverrideMap.keySet()).hasSize(1);
|
||||
assertThat(actualOverrideMap.values()).hasSize(1);
|
||||
|
||||
assertThat(actualOverrideMap).containsKey(address);
|
||||
assertThat(actualOverrideMap).containsValue(override);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnInternalErrorWhenProcessorReturnsEmpty() {
|
||||
final JsonRpcRequestContext request = ethCallRequest(callParameter(), "latest");
|
||||
|
||||
@@ -5,21 +5,21 @@
|
||||
"method": "eth_call",
|
||||
"params": [
|
||||
{
|
||||
"to": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f",
|
||||
"from": "a94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"data": "0x12a7b914"
|
||||
"comment": "Call to ECREC Precompiled on a different address, expect the original behaviour of ECREC precompile",
|
||||
"from": "0xc100000000000000000000000000000000000000",
|
||||
"to": "0x0000000000000000000000000000000000123456",
|
||||
"input": "0x82f3df49d3645876de6313df2bbe9fbce593f21341a7b03acdb9423bc171fcc9000000000000000000000000000000000000000000000000000000000000001cba13918f50da910f2d55a7ea64cf716ba31dad91856f45908dde900530377d8a112d60f36900d18eb8f9d3b4f85a697b545085614509e3520e4b762e35d0d6bd"
|
||||
},
|
||||
"latest",
|
||||
{
|
||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
|
||||
"0xc100000000000000000000000000000000000000": {
|
||||
"balance": "0xde0b6b3a7640000",
|
||||
"nonce": 88
|
||||
},
|
||||
"0xb9741079a300Cb3B8f324CdDB847c0d1d273a05E": {
|
||||
"stateDiff": {
|
||||
"0x1cf7945003fc5b59d2f6736f0704557aa805c4f2844084ccd1173b8d56946962": "0x000000000000000000000000000000000000000000000000000000110ed03bf7"
|
||||
},
|
||||
"movePrecompileToAddress":null
|
||||
"0x0000000000000000000000000000000000000001": {
|
||||
"comment": "Move ECREC Precompiled to address",
|
||||
"code": "0x60003560010160005260206000f3",
|
||||
"movePrecompileToAddress": "0x0000000000000000000000000000000000123456"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -27,7 +27,8 @@
|
||||
"response": {
|
||||
"jsonrpc": "2.0",
|
||||
"id": 3,
|
||||
"result": "0x0000000000000000000000000000000000000000000000000000000000000001"
|
||||
"comment": "The original ECREC precompile behaviour is expected, not the overridden one",
|
||||
"result": "0x000000000000000000000000c6e93f4c1920eaeaa1e699f76a7a8c18e3056074"
|
||||
},
|
||||
"statusCode": 200
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"request": {
|
||||
"id": 3,
|
||||
"jsonrpc": "2.0",
|
||||
"method": "eth_call",
|
||||
"params": [
|
||||
{
|
||||
"to": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f",
|
||||
"from": "a94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"data": "0x12a7b914"
|
||||
},
|
||||
"latest",
|
||||
{
|
||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
|
||||
"balance": "0xde0b6b3a7640000",
|
||||
"nonce": 88
|
||||
},
|
||||
"0xb9741079a300Cb3B8f324CdDB847c0d1d273a05E": {
|
||||
"stateDiff": {
|
||||
"0x1cf7945003fc5b59d2f6736f0704557aa805c4f2844084ccd1173b8d56946962": "0x000000000000000000000000000000000000000000000000000000110ed03bf7"
|
||||
},
|
||||
"movePrecompileToAddress":null
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"response": {
|
||||
"jsonrpc": "2.0",
|
||||
"id": 3,
|
||||
"result": "0x0000000000000000000000000000000000000000000000000000000000000001"
|
||||
},
|
||||
"statusCode": 200
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"request": {
|
||||
"id": 3,
|
||||
"jsonrpc": "2.0",
|
||||
"method": "eth_call",
|
||||
"params": [
|
||||
{
|
||||
"from": "0xc100000000000000000000000000000000000000",
|
||||
"comment": "Call to precompile ECREC (0x01), but code was modified to add 1 to input",
|
||||
"to": "0x0000000000000000000000000000000000000001",
|
||||
"input": "0x0000000000000000000000000000000000000000000000000000000000000001"
|
||||
},
|
||||
"latest",
|
||||
{
|
||||
"0xc100000000000000000000000000000000000000": {
|
||||
"balance": "0xde0b6b3a7640000"
|
||||
},
|
||||
"0x0000000000000000000000000000000000000001": {
|
||||
"comment": "The code below adds one to input",
|
||||
"code": "0x60003560010160005260206000f3",
|
||||
"movePrecompileToAddress": "0x0000000000000000000000000000000000123456"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"response": {
|
||||
"jsonrpc": "2.0",
|
||||
"id": 3,
|
||||
"result": "0x0000000000000000000000000000000000000000000000000000000000000002"
|
||||
},
|
||||
"statusCode": 200
|
||||
}
|
||||
@@ -175,16 +175,17 @@ public class ClassicProtocolSpecs {
|
||||
transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor) ->
|
||||
new MainnetTransactionProcessor(
|
||||
gasCalculator,
|
||||
transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor,
|
||||
true,
|
||||
false,
|
||||
evmConfiguration.evmStackSize(),
|
||||
feeMarket,
|
||||
CoinbaseFeePriceCalculator.frontier()))
|
||||
MainnetTransactionProcessor.builder()
|
||||
.gasCalculator(gasCalculator)
|
||||
.transactionValidatorFactory(transactionValidatorFactory)
|
||||
.contractCreationProcessor(contractCreationProcessor)
|
||||
.messageCallProcessor(messageCallProcessor)
|
||||
.clearEmptyAccounts(true)
|
||||
.warmCoinbase(false)
|
||||
.maxStackSize(evmConfiguration.evmStackSize())
|
||||
.feeMarket(feeMarket)
|
||||
.coinbaseFeePriceCalculator(CoinbaseFeePriceCalculator.frontier())
|
||||
.build())
|
||||
.name("Atlantis");
|
||||
}
|
||||
|
||||
@@ -357,16 +358,17 @@ public class ClassicProtocolSpecs {
|
||||
transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor) ->
|
||||
new MainnetTransactionProcessor(
|
||||
gasCalculator,
|
||||
transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor,
|
||||
true,
|
||||
true,
|
||||
evmConfiguration.evmStackSize(),
|
||||
feeMarket,
|
||||
CoinbaseFeePriceCalculator.frontier()))
|
||||
MainnetTransactionProcessor.builder()
|
||||
.gasCalculator(gasCalculator)
|
||||
.transactionValidatorFactory(transactionValidatorFactory)
|
||||
.contractCreationProcessor(contractCreationProcessor)
|
||||
.messageCallProcessor(messageCallProcessor)
|
||||
.clearEmptyAccounts(true)
|
||||
.warmCoinbase(true)
|
||||
.maxStackSize(evmConfiguration.evmStackSize())
|
||||
.feeMarket(feeMarket)
|
||||
.coinbaseFeePriceCalculator(CoinbaseFeePriceCalculator.frontier())
|
||||
.build())
|
||||
.name("Spiral");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,16 +136,17 @@ public abstract class MainnetProtocolSpecs {
|
||||
transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor) ->
|
||||
new MainnetTransactionProcessor(
|
||||
gasCalculator,
|
||||
transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor,
|
||||
false,
|
||||
false,
|
||||
evmConfiguration.evmStackSize(),
|
||||
FeeMarket.legacy(),
|
||||
CoinbaseFeePriceCalculator.frontier()))
|
||||
MainnetTransactionProcessor.builder()
|
||||
.gasCalculator(gasCalculator)
|
||||
.transactionValidatorFactory(transactionValidatorFactory)
|
||||
.contractCreationProcessor(contractCreationProcessor)
|
||||
.messageCallProcessor(messageCallProcessor)
|
||||
.clearEmptyAccounts(false)
|
||||
.warmCoinbase(false)
|
||||
.maxStackSize(evmConfiguration.evmStackSize())
|
||||
.feeMarket(FeeMarket.legacy())
|
||||
.coinbaseFeePriceCalculator(CoinbaseFeePriceCalculator.frontier())
|
||||
.build())
|
||||
.privateTransactionProcessorBuilder(
|
||||
(transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
@@ -297,16 +298,17 @@ public abstract class MainnetProtocolSpecs {
|
||||
transactionValidator,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor) ->
|
||||
new MainnetTransactionProcessor(
|
||||
gasCalculator,
|
||||
transactionValidator,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor,
|
||||
true,
|
||||
false,
|
||||
evmConfiguration.evmStackSize(),
|
||||
feeMarket,
|
||||
CoinbaseFeePriceCalculator.frontier()))
|
||||
MainnetTransactionProcessor.builder()
|
||||
.gasCalculator(gasCalculator)
|
||||
.transactionValidatorFactory(transactionValidator)
|
||||
.contractCreationProcessor(contractCreationProcessor)
|
||||
.messageCallProcessor(messageCallProcessor)
|
||||
.clearEmptyAccounts(true)
|
||||
.warmCoinbase(false)
|
||||
.maxStackSize(evmConfiguration.evmStackSize())
|
||||
.feeMarket(feeMarket)
|
||||
.coinbaseFeePriceCalculator(CoinbaseFeePriceCalculator.frontier())
|
||||
.build())
|
||||
.name("SpuriousDragon");
|
||||
}
|
||||
|
||||
@@ -503,16 +505,17 @@ public abstract class MainnetProtocolSpecs {
|
||||
transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor) ->
|
||||
new MainnetTransactionProcessor(
|
||||
gasCalculator,
|
||||
transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor,
|
||||
true,
|
||||
false,
|
||||
evmConfiguration.evmStackSize(),
|
||||
feeMarket,
|
||||
CoinbaseFeePriceCalculator.eip1559()))
|
||||
MainnetTransactionProcessor.builder()
|
||||
.gasCalculator(gasCalculator)
|
||||
.transactionValidatorFactory(transactionValidatorFactory)
|
||||
.contractCreationProcessor(contractCreationProcessor)
|
||||
.messageCallProcessor(messageCallProcessor)
|
||||
.clearEmptyAccounts(true)
|
||||
.warmCoinbase(false)
|
||||
.maxStackSize(evmConfiguration.evmStackSize())
|
||||
.feeMarket(feeMarket)
|
||||
.coinbaseFeePriceCalculator(CoinbaseFeePriceCalculator.eip1559())
|
||||
.build())
|
||||
.contractCreationProcessorBuilder(
|
||||
evm ->
|
||||
new ContractCreationProcessor(
|
||||
@@ -635,16 +638,17 @@ public abstract class MainnetProtocolSpecs {
|
||||
transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor) ->
|
||||
new MainnetTransactionProcessor(
|
||||
gasCalculator,
|
||||
transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor,
|
||||
true,
|
||||
true,
|
||||
evmConfiguration.evmStackSize(),
|
||||
feeMarket,
|
||||
CoinbaseFeePriceCalculator.eip1559()))
|
||||
MainnetTransactionProcessor.builder()
|
||||
.gasCalculator(gasCalculator)
|
||||
.transactionValidatorFactory(transactionValidatorFactory)
|
||||
.contractCreationProcessor(contractCreationProcessor)
|
||||
.messageCallProcessor(messageCallProcessor)
|
||||
.clearEmptyAccounts(true)
|
||||
.warmCoinbase(true)
|
||||
.maxStackSize(evmConfiguration.evmStackSize())
|
||||
.feeMarket(feeMarket)
|
||||
.coinbaseFeePriceCalculator(CoinbaseFeePriceCalculator.eip1559())
|
||||
.build())
|
||||
// Contract creation rules for EIP-3860 Limit and meter intitcode
|
||||
.transactionValidatorFactoryBuilder(
|
||||
(evm, gasLimitCalculator, feeMarket) ->
|
||||
@@ -722,18 +726,20 @@ public abstract class MainnetProtocolSpecs {
|
||||
transactionValidator,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor) ->
|
||||
new MainnetTransactionProcessor(
|
||||
gasCalculator,
|
||||
transactionValidator,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor,
|
||||
true,
|
||||
true,
|
||||
evmConfiguration.evmStackSize(),
|
||||
feeMarket,
|
||||
CoinbaseFeePriceCalculator.eip1559(),
|
||||
new CodeDelegationProcessor(
|
||||
chainId, SIGNATURE_ALGORITHM.get().getHalfCurveOrder())))
|
||||
MainnetTransactionProcessor.builder()
|
||||
.gasCalculator(gasCalculator)
|
||||
.transactionValidatorFactory(transactionValidator)
|
||||
.contractCreationProcessor(contractCreationProcessor)
|
||||
.messageCallProcessor(messageCallProcessor)
|
||||
.clearEmptyAccounts(true)
|
||||
.warmCoinbase(true)
|
||||
.maxStackSize(evmConfiguration.evmStackSize())
|
||||
.feeMarket(feeMarket)
|
||||
.coinbaseFeePriceCalculator(CoinbaseFeePriceCalculator.eip1559())
|
||||
.codeDelegationProcessor(
|
||||
new CodeDelegationProcessor(
|
||||
chainId, SIGNATURE_ALGORITHM.get().getHalfCurveOrder()))
|
||||
.build())
|
||||
// change to check for max blob gas per block for EIP-4844
|
||||
.transactionValidatorFactoryBuilder(
|
||||
(evm, gasLimitCalculator, feeMarket) ->
|
||||
|
||||
@@ -41,6 +41,8 @@ import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
|
||||
import org.hyperledger.besu.evm.frame.MessageFrame;
|
||||
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
||||
import org.hyperledger.besu.evm.processor.AbstractMessageProcessor;
|
||||
import org.hyperledger.besu.evm.processor.ContractCreationProcessor;
|
||||
import org.hyperledger.besu.evm.processor.MessageCallProcessor;
|
||||
import org.hyperledger.besu.evm.tracing.OperationTracer;
|
||||
import org.hyperledger.besu.evm.worldstate.EVMWorldUpdater;
|
||||
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
|
||||
@@ -68,9 +70,9 @@ public class MainnetTransactionProcessor {
|
||||
|
||||
protected final TransactionValidatorFactory transactionValidatorFactory;
|
||||
|
||||
private final AbstractMessageProcessor contractCreationProcessor;
|
||||
private final ContractCreationProcessor contractCreationProcessor;
|
||||
|
||||
private final AbstractMessageProcessor messageCallProcessor;
|
||||
private final MessageCallProcessor messageCallProcessor;
|
||||
|
||||
private final int maxStackSize;
|
||||
|
||||
@@ -83,34 +85,11 @@ public class MainnetTransactionProcessor {
|
||||
|
||||
private final Optional<CodeDelegationProcessor> maybeCodeDelegationProcessor;
|
||||
|
||||
public MainnetTransactionProcessor(
|
||||
private MainnetTransactionProcessor(
|
||||
final GasCalculator gasCalculator,
|
||||
final TransactionValidatorFactory transactionValidatorFactory,
|
||||
final AbstractMessageProcessor contractCreationProcessor,
|
||||
final AbstractMessageProcessor messageCallProcessor,
|
||||
final boolean clearEmptyAccounts,
|
||||
final boolean warmCoinbase,
|
||||
final int maxStackSize,
|
||||
final FeeMarket feeMarket,
|
||||
final CoinbaseFeePriceCalculator coinbaseFeePriceCalculator) {
|
||||
this(
|
||||
gasCalculator,
|
||||
transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor,
|
||||
clearEmptyAccounts,
|
||||
warmCoinbase,
|
||||
maxStackSize,
|
||||
feeMarket,
|
||||
coinbaseFeePriceCalculator,
|
||||
null);
|
||||
}
|
||||
|
||||
public MainnetTransactionProcessor(
|
||||
final GasCalculator gasCalculator,
|
||||
final TransactionValidatorFactory transactionValidatorFactory,
|
||||
final AbstractMessageProcessor contractCreationProcessor,
|
||||
final AbstractMessageProcessor messageCallProcessor,
|
||||
final ContractCreationProcessor contractCreationProcessor,
|
||||
final MessageCallProcessor messageCallProcessor,
|
||||
final boolean clearEmptyAccounts,
|
||||
final boolean warmCoinbase,
|
||||
final int maxStackSize,
|
||||
@@ -632,6 +611,10 @@ public class MainnetTransactionProcessor {
|
||||
};
|
||||
}
|
||||
|
||||
public MessageCallProcessor getMessageCallProcessor() {
|
||||
return messageCallProcessor;
|
||||
}
|
||||
|
||||
private String printableStackTraceFromThrowable(final RuntimeException re) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
|
||||
@@ -641,4 +624,103 @@ public class MainnetTransactionProcessor {
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private GasCalculator gasCalculator;
|
||||
private TransactionValidatorFactory transactionValidatorFactory;
|
||||
private ContractCreationProcessor contractCreationProcessor;
|
||||
private MessageCallProcessor messageCallProcessor;
|
||||
private boolean clearEmptyAccounts;
|
||||
private boolean warmCoinbase;
|
||||
private int maxStackSize;
|
||||
private FeeMarket feeMarket;
|
||||
private CoinbaseFeePriceCalculator coinbaseFeePriceCalculator;
|
||||
private CodeDelegationProcessor codeDelegationProcessor;
|
||||
|
||||
public Builder gasCalculator(final GasCalculator gasCalculator) {
|
||||
this.gasCalculator = gasCalculator;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder transactionValidatorFactory(
|
||||
final TransactionValidatorFactory transactionValidatorFactory) {
|
||||
this.transactionValidatorFactory = transactionValidatorFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder contractCreationProcessor(
|
||||
final ContractCreationProcessor contractCreationProcessor) {
|
||||
this.contractCreationProcessor = contractCreationProcessor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder messageCallProcessor(final MessageCallProcessor messageCallProcessor) {
|
||||
this.messageCallProcessor = messageCallProcessor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder clearEmptyAccounts(final boolean clearEmptyAccounts) {
|
||||
this.clearEmptyAccounts = clearEmptyAccounts;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder warmCoinbase(final boolean warmCoinbase) {
|
||||
this.warmCoinbase = warmCoinbase;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder maxStackSize(final int maxStackSize) {
|
||||
this.maxStackSize = maxStackSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder feeMarket(final FeeMarket feeMarket) {
|
||||
this.feeMarket = feeMarket;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder coinbaseFeePriceCalculator(
|
||||
final CoinbaseFeePriceCalculator coinbaseFeePriceCalculator) {
|
||||
this.coinbaseFeePriceCalculator = coinbaseFeePriceCalculator;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder codeDelegationProcessor(
|
||||
final CodeDelegationProcessor maybeCodeDelegationProcessor) {
|
||||
this.codeDelegationProcessor = maybeCodeDelegationProcessor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder populateFrom(final MainnetTransactionProcessor processor) {
|
||||
this.gasCalculator = processor.gasCalculator;
|
||||
this.transactionValidatorFactory = processor.transactionValidatorFactory;
|
||||
this.contractCreationProcessor = processor.contractCreationProcessor;
|
||||
this.messageCallProcessor = processor.messageCallProcessor;
|
||||
this.clearEmptyAccounts = processor.clearEmptyAccounts;
|
||||
this.warmCoinbase = processor.warmCoinbase;
|
||||
this.maxStackSize = processor.maxStackSize;
|
||||
this.feeMarket = processor.feeMarket;
|
||||
this.coinbaseFeePriceCalculator = processor.coinbaseFeePriceCalculator;
|
||||
this.codeDelegationProcessor = processor.maybeCodeDelegationProcessor.orElse(null);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MainnetTransactionProcessor build() {
|
||||
return new MainnetTransactionProcessor(
|
||||
gasCalculator,
|
||||
transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor,
|
||||
clearEmptyAccounts,
|
||||
warmCoinbase,
|
||||
maxStackSize,
|
||||
feeMarket,
|
||||
coinbaseFeePriceCalculator,
|
||||
codeDelegationProcessor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@ import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||
import org.hyperledger.besu.evm.precompile.PrecompileContractRegistry;
|
||||
import org.hyperledger.besu.evm.processor.AbstractMessageProcessor;
|
||||
import org.hyperledger.besu.evm.processor.ContractCreationProcessor;
|
||||
import org.hyperledger.besu.evm.processor.MessageCallProcessor;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiFunction;
|
||||
@@ -62,10 +64,10 @@ public class ProtocolSpecBuilder {
|
||||
private Function<FeeMarket, BlockHeaderValidator.Builder> blockHeaderValidatorBuilder;
|
||||
private Function<FeeMarket, BlockHeaderValidator.Builder> ommerHeaderValidatorBuilder;
|
||||
private Function<ProtocolSchedule, BlockBodyValidator> blockBodyValidatorBuilder;
|
||||
private Function<EVM, AbstractMessageProcessor> contractCreationProcessorBuilder;
|
||||
private Function<EVM, ContractCreationProcessor> contractCreationProcessorBuilder;
|
||||
private Function<PrecompiledContractConfiguration, PrecompileContractRegistry>
|
||||
precompileContractRegistryBuilder;
|
||||
private BiFunction<EVM, PrecompileContractRegistry, AbstractMessageProcessor>
|
||||
private BiFunction<EVM, PrecompileContractRegistry, MessageCallProcessor>
|
||||
messageCallProcessorBuilder;
|
||||
private TransactionProcessorBuilder transactionProcessorBuilder;
|
||||
|
||||
@@ -158,7 +160,7 @@ public class ProtocolSpecBuilder {
|
||||
}
|
||||
|
||||
public ProtocolSpecBuilder contractCreationProcessorBuilder(
|
||||
final Function<EVM, AbstractMessageProcessor> contractCreationProcessorBuilder) {
|
||||
final Function<EVM, ContractCreationProcessor> contractCreationProcessorBuilder) {
|
||||
this.contractCreationProcessorBuilder = contractCreationProcessorBuilder;
|
||||
return this;
|
||||
}
|
||||
@@ -180,7 +182,7 @@ public class ProtocolSpecBuilder {
|
||||
}
|
||||
|
||||
public ProtocolSpecBuilder messageCallProcessorBuilder(
|
||||
final BiFunction<EVM, PrecompileContractRegistry, AbstractMessageProcessor>
|
||||
final BiFunction<EVM, PrecompileContractRegistry, MessageCallProcessor>
|
||||
messageCallProcessorBuilder) {
|
||||
this.messageCallProcessorBuilder = messageCallProcessorBuilder;
|
||||
return this;
|
||||
@@ -330,11 +332,11 @@ public class ProtocolSpecBuilder {
|
||||
new PrecompiledContractConfiguration(gasCalculator, privacyParameters);
|
||||
final TransactionValidatorFactory transactionValidatorFactory =
|
||||
transactionValidatorFactoryBuilder.apply(evm, gasLimitCalculator, feeMarket);
|
||||
final AbstractMessageProcessor contractCreationProcessor =
|
||||
final ContractCreationProcessor contractCreationProcessor =
|
||||
contractCreationProcessorBuilder.apply(evm);
|
||||
final PrecompileContractRegistry precompileContractRegistry =
|
||||
precompileContractRegistryBuilder.apply(precompiledContractConfiguration);
|
||||
final AbstractMessageProcessor messageCallProcessor =
|
||||
final MessageCallProcessor messageCallProcessor =
|
||||
messageCallProcessorBuilder.apply(evm, precompileContractRegistry);
|
||||
final MainnetTransactionProcessor transactionProcessor =
|
||||
transactionProcessorBuilder.apply(
|
||||
@@ -469,8 +471,8 @@ public class ProtocolSpecBuilder {
|
||||
GasCalculator gasCalculator,
|
||||
FeeMarket feeMarket,
|
||||
TransactionValidatorFactory transactionValidatorFactory,
|
||||
AbstractMessageProcessor contractCreationProcessor,
|
||||
AbstractMessageProcessor messageCallProcessor);
|
||||
ContractCreationProcessor contractCreationProcessor,
|
||||
MessageCallProcessor messageCallProcessor);
|
||||
}
|
||||
|
||||
public interface PrivateTransactionProcessorBuilder {
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright contributors to Besu.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.transaction;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.StateOverrideMap;
|
||||
import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader;
|
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.evm.processor.OverriddenPrecompilesMessageCallProcessor;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SimulationTransactionProcessorFactory {
|
||||
|
||||
private final ProtocolSchedule protocolSchedule;
|
||||
|
||||
/**
|
||||
* Creates a factory capable of producing transaction processors.
|
||||
*
|
||||
* @param protocolSchedule the protocol schedule used for creating processors
|
||||
*/
|
||||
public SimulationTransactionProcessorFactory(final ProtocolSchedule protocolSchedule) {
|
||||
this.protocolSchedule = protocolSchedule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a transaction processor, optionally applying state overrides.
|
||||
*
|
||||
* @param processableHeader the block header to process transactions against
|
||||
* @param maybeStateOverrides optional state overrides for simulation
|
||||
* @return a transaction processor, with overrides applied if provided
|
||||
*/
|
||||
public MainnetTransactionProcessor getTransactionProcessor(
|
||||
final ProcessableBlockHeader processableHeader,
|
||||
final Optional<StateOverrideMap> maybeStateOverrides) {
|
||||
|
||||
MainnetTransactionProcessor baseProcessor =
|
||||
protocolSchedule.getByBlockHeader(processableHeader).getTransactionProcessor();
|
||||
|
||||
return maybeStateOverrides
|
||||
.flatMap(this::extractPrecompileAddressOverrides)
|
||||
.map(
|
||||
precompileOverrides -> createProcessorWithOverrides(baseProcessor, precompileOverrides))
|
||||
.orElse(baseProcessor);
|
||||
}
|
||||
|
||||
private Optional<Map<Address, Address>> extractPrecompileAddressOverrides(
|
||||
final StateOverrideMap stateOverrides) {
|
||||
Map<Address, Address> addressOverrides =
|
||||
stateOverrides.entrySet().stream()
|
||||
.filter(entry -> entry.getValue().getMovePrecompileToAddress().isPresent())
|
||||
.collect(
|
||||
Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
entry -> entry.getValue().getMovePrecompileToAddress().get()));
|
||||
|
||||
return addressOverrides.isEmpty() ? Optional.empty() : Optional.of(addressOverrides);
|
||||
}
|
||||
|
||||
private MainnetTransactionProcessor createProcessorWithOverrides(
|
||||
final MainnetTransactionProcessor baseProcessor,
|
||||
final Map<Address, Address> precompileAddressOverrides) {
|
||||
return MainnetTransactionProcessor.builder()
|
||||
.populateFrom(baseProcessor)
|
||||
.messageCallProcessor(
|
||||
new OverriddenPrecompilesMessageCallProcessor(
|
||||
baseProcessor.getMessageCallProcessor(), precompileAddressOverrides))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -87,6 +87,7 @@ public class TransactionSimulator {
|
||||
private final WorldStateArchive worldStateArchive;
|
||||
private final ProtocolSchedule protocolSchedule;
|
||||
private final MiningConfiguration miningConfiguration;
|
||||
private final SimulationTransactionProcessorFactory simulationTransactionProcessorFactory;
|
||||
private final long rpcGasCap;
|
||||
|
||||
public TransactionSimulator(
|
||||
@@ -100,6 +101,8 @@ public class TransactionSimulator {
|
||||
this.protocolSchedule = protocolSchedule;
|
||||
this.miningConfiguration = miningConfiguration;
|
||||
this.rpcGasCap = rpcGasCap;
|
||||
this.simulationTransactionProcessorFactory =
|
||||
new SimulationTransactionProcessorFactory(protocolSchedule);
|
||||
}
|
||||
|
||||
public Optional<TransactionSimulatorResult> process(
|
||||
@@ -402,8 +405,9 @@ public class TransactionSimulator {
|
||||
final long simulationGasCap =
|
||||
calculateSimulationGasCap(callParams.getGasLimit(), blockHeaderToProcess.getGasLimit());
|
||||
|
||||
final MainnetTransactionProcessor transactionProcessor =
|
||||
protocolSchedule.getByBlockHeader(blockHeaderToProcess).getTransactionProcessor();
|
||||
MainnetTransactionProcessor transactionProcessor =
|
||||
simulationTransactionProcessorFactory.getTransactionProcessor(
|
||||
processableHeader, maybeStateOverrides);
|
||||
|
||||
final Optional<BlockHeader> maybeParentHeader =
|
||||
blockchain.getBlockHeader(blockHeaderToProcess.getParentHash());
|
||||
|
||||
@@ -34,7 +34,8 @@ import org.hyperledger.besu.evm.frame.MessageFrame;
|
||||
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
||||
import org.hyperledger.besu.evm.gascalculator.LondonGasCalculator;
|
||||
import org.hyperledger.besu.evm.log.Log;
|
||||
import org.hyperledger.besu.evm.processor.AbstractMessageProcessor;
|
||||
import org.hyperledger.besu.evm.processor.ContractCreationProcessor;
|
||||
import org.hyperledger.besu.evm.processor.MessageCallProcessor;
|
||||
import org.hyperledger.besu.evm.tracing.OperationTracer;
|
||||
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
|
||||
import org.hyperledger.besu.evm.worldstate.WorldView;
|
||||
@@ -67,8 +68,8 @@ class MainnetTransactionProcessorTest {
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private TransactionValidatorFactory transactionValidatorFactory;
|
||||
|
||||
@Mock private AbstractMessageProcessor contractCreationProcessor;
|
||||
@Mock private AbstractMessageProcessor messageCallProcessor;
|
||||
@Mock private ContractCreationProcessor contractCreationProcessor;
|
||||
@Mock private MessageCallProcessor messageCallProcessor;
|
||||
|
||||
@Mock private WorldUpdater worldState;
|
||||
@Mock private ProcessableBlockHeader blockHeader;
|
||||
@@ -79,17 +80,19 @@ class MainnetTransactionProcessorTest {
|
||||
@Mock private MutableAccount receiverAccount;
|
||||
|
||||
MainnetTransactionProcessor createTransactionProcessor(final boolean warmCoinbase) {
|
||||
return new MainnetTransactionProcessor(
|
||||
gasCalculator,
|
||||
transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor,
|
||||
false,
|
||||
warmCoinbase,
|
||||
MAX_STACK_SIZE,
|
||||
FeeMarket.legacy(),
|
||||
CoinbaseFeePriceCalculator.frontier(),
|
||||
new CodeDelegationProcessor(Optional.of(BigInteger.ONE), BigInteger.TEN));
|
||||
return MainnetTransactionProcessor.builder()
|
||||
.gasCalculator(gasCalculator)
|
||||
.transactionValidatorFactory(transactionValidatorFactory)
|
||||
.contractCreationProcessor(contractCreationProcessor)
|
||||
.messageCallProcessor(messageCallProcessor)
|
||||
.clearEmptyAccounts(false)
|
||||
.warmCoinbase(warmCoinbase)
|
||||
.maxStackSize(MAX_STACK_SIZE)
|
||||
.feeMarket(FeeMarket.legacy())
|
||||
.coinbaseFeePriceCalculator(CoinbaseFeePriceCalculator.frontier())
|
||||
.codeDelegationProcessor(
|
||||
new CodeDelegationProcessor(Optional.of(BigInteger.ONE), BigInteger.TEN))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright contributors to Besu.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.transaction;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.StateOverride;
|
||||
import org.hyperledger.besu.datatypes.StateOverrideMap;
|
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
|
||||
import org.hyperledger.besu.evm.EVM;
|
||||
import org.hyperledger.besu.evm.precompile.PrecompileContractRegistry;
|
||||
import org.hyperledger.besu.evm.precompile.PrecompiledContract;
|
||||
import org.hyperledger.besu.evm.processor.MessageCallProcessor;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class SimulationTransactionProcessorFactoryTest {
|
||||
|
||||
private SimulationTransactionProcessorFactory factory;
|
||||
private final Address originalPrecompileAddress = Address.fromHexString("0x1");
|
||||
private final Address newPrecompileAddress = Address.fromHexString("0x2");
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
ProtocolSpec protocolSpec = mock(ProtocolSpec.class);
|
||||
ProtocolSchedule protocolSchedule = mock(ProtocolSchedule.class);
|
||||
when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
|
||||
|
||||
PrecompileContractRegistry precompileContractRegistry = new PrecompileContractRegistry();
|
||||
precompileContractRegistry.put(originalPrecompileAddress, mock(PrecompiledContract.class));
|
||||
|
||||
MainnetTransactionProcessor mainnetTransactionProcessor =
|
||||
MainnetTransactionProcessor.builder()
|
||||
.messageCallProcessor(
|
||||
new MessageCallProcessor(mock(EVM.class), precompileContractRegistry))
|
||||
.build();
|
||||
when(protocolSpec.getTransactionProcessor()).thenReturn(mainnetTransactionProcessor);
|
||||
|
||||
factory = new SimulationTransactionProcessorFactory(protocolSchedule);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnProcessorWithOriginalPrecompileAddressesIfNoOverrides() {
|
||||
MainnetTransactionProcessor simulationTransactionProcessor =
|
||||
factory.getTransactionProcessor(null, Optional.empty());
|
||||
Set<Address> precompileAddresses =
|
||||
simulationTransactionProcessor.getMessageCallProcessor().getPrecompileAddresses();
|
||||
|
||||
assertThat(precompileAddresses).containsExactlyInAnyOrder(originalPrecompileAddress);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnProcessorWithNewPrecompileAddressesWithOverrides() {
|
||||
StateOverrideMap stateOverrideMap = new StateOverrideMap();
|
||||
stateOverrideMap.put(
|
||||
originalPrecompileAddress,
|
||||
new StateOverride.Builder().withMovePrecompileToAddress(newPrecompileAddress).build());
|
||||
|
||||
MainnetTransactionProcessor simulationTransactionProcessor =
|
||||
factory.getTransactionProcessor(null, Optional.of(stateOverrideMap));
|
||||
Set<Address> precompileAddresses =
|
||||
simulationTransactionProcessor.getMessageCallProcessor().getPrecompileAddresses();
|
||||
|
||||
assertThat(precompileAddresses).containsExactlyInAnyOrder(newPrecompileAddress);
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,10 @@ package org.hyperledger.besu.evm.precompile;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/** Encapsulates a group of {@link PrecompiledContract}s used together. */
|
||||
public class PrecompileContractRegistry {
|
||||
@@ -48,4 +50,13 @@ public class PrecompileContractRegistry {
|
||||
public void put(final Address address, final PrecompiledContract precompile) {
|
||||
precompiles.put(address, precompile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the addresses of the precompiled contracts.
|
||||
*
|
||||
* @return the addresses
|
||||
*/
|
||||
public Set<Address> getPrecompileAddresses() {
|
||||
return Collections.unmodifiableSet(precompiles.keySet());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -37,7 +38,8 @@ import org.slf4j.LoggerFactory;
|
||||
public class MessageCallProcessor extends AbstractMessageProcessor {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MessageCallProcessor.class);
|
||||
|
||||
private final PrecompileContractRegistry precompiles;
|
||||
/** The precompiles. */
|
||||
protected final PrecompileContractRegistry precompiles;
|
||||
|
||||
/**
|
||||
* Instantiates a new Message call processor.
|
||||
@@ -171,4 +173,14 @@ public class MessageCallProcessor extends AbstractMessageProcessor {
|
||||
frame.setExceptionalHaltReason(result.getHaltReason());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the precompile addresses.
|
||||
*
|
||||
* @return the precompile addresses
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public Set<Address> getPrecompileAddresses() {
|
||||
return precompiles.getPrecompileAddresses();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright contributors to Besu.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.evm.processor;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.evm.precompile.PrecompileContractRegistry;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A message call processor designed specifically for simulation purposes that allows for overriding
|
||||
* precompile addresses.
|
||||
*/
|
||||
public class OverriddenPrecompilesMessageCallProcessor extends MessageCallProcessor {
|
||||
|
||||
/**
|
||||
* Instantiates a new Modifiable precompiles message call processor for simulation.
|
||||
*
|
||||
* @param originalProcessor the original processor
|
||||
* @param precompileOverrides the address overrides
|
||||
*/
|
||||
public OverriddenPrecompilesMessageCallProcessor(
|
||||
final MessageCallProcessor originalProcessor,
|
||||
final Map<Address, Address> precompileOverrides) {
|
||||
super(
|
||||
originalProcessor.evm,
|
||||
createRegistryWithPrecompileOverrides(originalProcessor.precompiles, precompileOverrides));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new PrecompileContractRegistry with the specified address overrides.
|
||||
*
|
||||
* @param originalRegistry the original precompile contract registry
|
||||
* @param precompileOverrides the address overrides
|
||||
* @return a new PrecompileContractRegistry with the overrides applied
|
||||
*/
|
||||
private static PrecompileContractRegistry createRegistryWithPrecompileOverrides(
|
||||
final PrecompileContractRegistry originalRegistry,
|
||||
final Map<Address, Address> precompileOverrides) {
|
||||
PrecompileContractRegistry newRegistry = new PrecompileContractRegistry();
|
||||
for (Address originalAddress : originalRegistry.getPrecompileAddresses()) {
|
||||
Address effectiveAddress = precompileOverrides.getOrDefault(originalAddress, originalAddress);
|
||||
newRegistry.put(effectiveAddress, originalRegistry.get(originalAddress));
|
||||
}
|
||||
return newRegistry;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user