mirror of
https://github.com/vacp2p/status-linea-besu.git
synced 2026-01-09 13:58:02 -05:00
Merge branch 'main' into zkbesu
This commit is contained in:
20
CHANGELOG.md
20
CHANGELOG.md
@@ -1,15 +1,24 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
- Add `--ephemery` network support for Ephemery Testnet [#7563](https://github.com/hyperledger/besu/pull/7563) thanks to [@gconnect](https://github.com/gconnect)
|
|
||||||
- Add configuration of Consolidation Request Contract Address via genesis configuration [#7647](https://github.com/hyperledger/besu/pull/7647)
|
### Breaking Changes
|
||||||
|
|
||||||
### Upcoming Breaking Changes
|
### Upcoming Breaking Changes
|
||||||
- k8s (KUBERNETES) Nat method is now deprecated and will be removed in a future release
|
|
||||||
|
### Additions and Improvements
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
- Fix eth_feeHistory rewards when bounded by configuration [#7750](https://github.com/hyperledger/besu/pull/7750)
|
||||||
|
|
||||||
|
## 24.10.0
|
||||||
|
|
||||||
### Breaking Changes
|
### Breaking Changes
|
||||||
- Besu will now fail to start if any plugins encounter errors during initialization. To allow Besu to continue running despite plugin errors, use the `--plugin-continue-on-error` option. [#7662](https://github.com/hyperledger/besu/pull/7662)
|
- Besu will now fail to start if any plugins encounter errors during initialization. To allow Besu to continue running despite plugin errors, use the `--plugin-continue-on-error` option. [#7662](https://github.com/hyperledger/besu/pull/7662)
|
||||||
|
|
||||||
|
### Upcoming Breaking Changes
|
||||||
|
- k8s (KUBERNETES) Nat method is now deprecated and will be removed in a future release
|
||||||
|
|
||||||
### Additions and Improvements
|
### Additions and Improvements
|
||||||
- Remove privacy test classes support [#7569](https://github.com/hyperledger/besu/pull/7569)
|
- Remove privacy test classes support [#7569](https://github.com/hyperledger/besu/pull/7569)
|
||||||
- Add Blob Transaction Metrics [#7622](https://github.com/hyperledger/besu/pull/7622)
|
- Add Blob Transaction Metrics [#7622](https://github.com/hyperledger/besu/pull/7622)
|
||||||
@@ -21,6 +30,8 @@
|
|||||||
- Expose chainId in the `BlockchainService` [7702](https://github.com/hyperledger/besu/pull/7702)
|
- Expose chainId in the `BlockchainService` [7702](https://github.com/hyperledger/besu/pull/7702)
|
||||||
- Use head block instead of safe block for snap sync [7536](https://github.com/hyperledger/besu/issues/7536)
|
- Use head block instead of safe block for snap sync [7536](https://github.com/hyperledger/besu/issues/7536)
|
||||||
- Add support for `chainId` in `CallParameters` [#7720](https://github.com/hyperledger/besu/pull/7720)
|
- Add support for `chainId` in `CallParameters` [#7720](https://github.com/hyperledger/besu/pull/7720)
|
||||||
|
- Add `--ephemery` network support for Ephemery Testnet [#7563](https://github.com/hyperledger/besu/pull/7563) thanks to [@gconnect](https://github.com/gconnect)
|
||||||
|
- Add configuration of Consolidation Request Contract Address via genesis configuration [#7647](https://github.com/hyperledger/besu/pull/7647)
|
||||||
|
|
||||||
### Bug fixes
|
### Bug fixes
|
||||||
- Fix mounted data path directory permissions for besu user [#7575](https://github.com/hyperledger/besu/pull/7575)
|
- Fix mounted data path directory permissions for besu user [#7575](https://github.com/hyperledger/besu/pull/7575)
|
||||||
@@ -28,6 +39,9 @@
|
|||||||
- Corrects a regression where custom plugin services are not initialized correctly. [#7625](https://github.com/hyperledger/besu/pull/7625)
|
- Corrects a regression where custom plugin services are not initialized correctly. [#7625](https://github.com/hyperledger/besu/pull/7625)
|
||||||
- Fix for IBFT2 chains using the BONSAI DB format [#7631](https://github.com/hyperledger/besu/pull/7631)
|
- Fix for IBFT2 chains using the BONSAI DB format [#7631](https://github.com/hyperledger/besu/pull/7631)
|
||||||
- Fix reading `tx-pool-min-score` option from configuration file [#7623](https://github.com/hyperledger/besu/pull/7623)
|
- Fix reading `tx-pool-min-score` option from configuration file [#7623](https://github.com/hyperledger/besu/pull/7623)
|
||||||
|
- Fix an unhandled PeerTable exception [#7733](https://github.com/hyperledger/besu/issues/7733)
|
||||||
|
- Fix RocksDBException: Busy leading to MerkleTrieException: Unable to load trie node value [#7745](https://github.com/hyperledger/besu/pull/7745)
|
||||||
|
- If a BFT validator node is syncing, pause block production until sync has completed [#7657](https://github.com/hyperledger/besu/pull/7657)
|
||||||
|
|
||||||
## 24.9.1
|
## 24.9.1
|
||||||
|
|
||||||
|
|||||||
@@ -1407,7 +1407,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
|||||||
if (genesisConfigOptionsSupplier.get().getCancunTime().isPresent()
|
if (genesisConfigOptionsSupplier.get().getCancunTime().isPresent()
|
||||||
|| genesisConfigOptionsSupplier.get().getCancunEOFTime().isPresent()
|
|| genesisConfigOptionsSupplier.get().getCancunEOFTime().isPresent()
|
||||||
|| genesisConfigOptionsSupplier.get().getPragueTime().isPresent()
|
|| genesisConfigOptionsSupplier.get().getPragueTime().isPresent()
|
||||||
|| genesisConfigOptionsSupplier.get().getPragueEOFTime().isPresent()) {
|
|| genesisConfigOptionsSupplier.get().getOsakaTime().isPresent()) {
|
||||||
if (kzgTrustedSetupFile != null) {
|
if (kzgTrustedSetupFile != null) {
|
||||||
KZGPointEvalPrecompiledContract.init(kzgTrustedSetupFile);
|
KZGPointEvalPrecompiledContract.init(kzgTrustedSetupFile);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -253,9 +253,18 @@ public class IbftBesuControllerBuilder extends BftBesuControllerBuilder {
|
|||||||
.getValue()
|
.getValue()
|
||||||
.getBlockPeriodSeconds()));
|
.getBlockPeriodSeconds()));
|
||||||
|
|
||||||
if (syncState.isInitialSyncPhaseDone()) {
|
syncState.subscribeSyncStatus(
|
||||||
ibftMiningCoordinator.enable();
|
syncStatus -> {
|
||||||
}
|
if (syncState.syncTarget().isPresent()) {
|
||||||
|
// We're syncing so stop doing other stuff
|
||||||
|
LOG.info("Stopping IBFT mining coordinator while we are syncing");
|
||||||
|
ibftMiningCoordinator.stop();
|
||||||
|
} else {
|
||||||
|
LOG.info("Starting IBFT mining coordinator following sync");
|
||||||
|
ibftMiningCoordinator.enable();
|
||||||
|
ibftMiningCoordinator.start();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
syncState.subscribeCompletionReached(
|
syncState.subscribeCompletionReached(
|
||||||
new BesuEvents.InitialSyncCompletionListener() {
|
new BesuEvents.InitialSyncCompletionListener() {
|
||||||
|
|||||||
@@ -301,9 +301,18 @@ public class QbftBesuControllerBuilder extends BftBesuControllerBuilder {
|
|||||||
.getEmptyBlockPeriodSeconds());
|
.getEmptyBlockPeriodSeconds());
|
||||||
});
|
});
|
||||||
|
|
||||||
if (syncState.isInitialSyncPhaseDone()) {
|
syncState.subscribeSyncStatus(
|
||||||
miningCoordinator.enable();
|
syncStatus -> {
|
||||||
}
|
if (syncState.syncTarget().isPresent()) {
|
||||||
|
// We're syncing so stop doing other stuff
|
||||||
|
LOG.info("Stopping QBFT mining coordinator while we are syncing");
|
||||||
|
miningCoordinator.stop();
|
||||||
|
} else {
|
||||||
|
LOG.info("Starting QBFT mining coordinator following sync");
|
||||||
|
miningCoordinator.enable();
|
||||||
|
miningCoordinator.start();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
syncState.subscribeCompletionReached(
|
syncState.subscribeCompletionReached(
|
||||||
new BesuEvents.InitialSyncCompletionListener() {
|
new BesuEvents.InitialSyncCompletionListener() {
|
||||||
|
|||||||
@@ -271,11 +271,11 @@ public interface GenesisConfigOptions {
|
|||||||
OptionalLong getPragueTime();
|
OptionalLong getPragueTime();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets Prague EOF time.
|
* Gets Osaka time.
|
||||||
*
|
*
|
||||||
* @return the prague time
|
* @return the osaka time
|
||||||
*/
|
*/
|
||||||
OptionalLong getPragueEOFTime();
|
OptionalLong getOsakaTime();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets future eips time.
|
* Gets future eips time.
|
||||||
|
|||||||
@@ -318,8 +318,8 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OptionalLong getPragueEOFTime() {
|
public OptionalLong getOsakaTime() {
|
||||||
return getOptionalLong("pragueeoftime");
|
return getOptionalLong("osakatime");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -496,7 +496,7 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
|
|||||||
getCancunTime().ifPresent(l -> builder.put("cancunTime", l));
|
getCancunTime().ifPresent(l -> builder.put("cancunTime", l));
|
||||||
getCancunEOFTime().ifPresent(l -> builder.put("cancunEOFTime", l));
|
getCancunEOFTime().ifPresent(l -> builder.put("cancunEOFTime", l));
|
||||||
getPragueTime().ifPresent(l -> builder.put("pragueTime", l));
|
getPragueTime().ifPresent(l -> builder.put("pragueTime", l));
|
||||||
getPragueEOFTime().ifPresent(l -> builder.put("pragueEOFTime", l));
|
getOsakaTime().ifPresent(l -> builder.put("osakaTime", l));
|
||||||
getTerminalBlockNumber().ifPresent(l -> builder.put("terminalBlockNumber", l));
|
getTerminalBlockNumber().ifPresent(l -> builder.put("terminalBlockNumber", l));
|
||||||
getTerminalBlockHash().ifPresent(h -> builder.put("terminalBlockHash", h.toHexString()));
|
getTerminalBlockHash().ifPresent(h -> builder.put("terminalBlockHash", h.toHexString()));
|
||||||
getFutureEipsTime().ifPresent(l -> builder.put("futureEipsTime", l));
|
getFutureEipsTime().ifPresent(l -> builder.put("futureEipsTime", l));
|
||||||
@@ -655,7 +655,7 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
|
|||||||
getCancunTime(),
|
getCancunTime(),
|
||||||
getCancunEOFTime(),
|
getCancunEOFTime(),
|
||||||
getPragueTime(),
|
getPragueTime(),
|
||||||
getPragueEOFTime(),
|
getOsakaTime(),
|
||||||
getFutureEipsTime(),
|
getFutureEipsTime(),
|
||||||
getExperimentalEipsTime());
|
getExperimentalEipsTime());
|
||||||
// when adding forks add an entry to ${REPO_ROOT}/config/src/test/resources/all_forks.json
|
// when adding forks add an entry to ${REPO_ROOT}/config/src/test/resources/all_forks.json
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions, Cloneable
|
|||||||
private OptionalLong cancunTime = OptionalLong.empty();
|
private OptionalLong cancunTime = OptionalLong.empty();
|
||||||
private OptionalLong cancunEOFTime = OptionalLong.empty();
|
private OptionalLong cancunEOFTime = OptionalLong.empty();
|
||||||
private OptionalLong pragueTime = OptionalLong.empty();
|
private OptionalLong pragueTime = OptionalLong.empty();
|
||||||
private OptionalLong pragueEOFTime = OptionalLong.empty();
|
private OptionalLong osakaTime = OptionalLong.empty();
|
||||||
private OptionalLong futureEipsTime = OptionalLong.empty();
|
private OptionalLong futureEipsTime = OptionalLong.empty();
|
||||||
private OptionalLong experimentalEipsTime = OptionalLong.empty();
|
private OptionalLong experimentalEipsTime = OptionalLong.empty();
|
||||||
private OptionalLong terminalBlockNumber = OptionalLong.empty();
|
private OptionalLong terminalBlockNumber = OptionalLong.empty();
|
||||||
@@ -265,8 +265,8 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions, Cloneable
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OptionalLong getPragueEOFTime() {
|
public OptionalLong getOsakaTime() {
|
||||||
return pragueEOFTime;
|
return osakaTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -709,14 +709,13 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions, Cloneable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PragueEOF time.
|
* Osaka time.
|
||||||
*
|
*
|
||||||
* @param timestamp the timestamp
|
* @param timestamp the timestamp
|
||||||
* @return the stub genesis config options
|
* @return the stub genesis config options
|
||||||
*/
|
*/
|
||||||
public StubGenesisConfigOptions pragueEOFTime(final long timestamp) {
|
public StubGenesisConfigOptions osakaTime(final long timestamp) {
|
||||||
pragueTime = OptionalLong.of(timestamp);
|
osakaTime = OptionalLong.of(timestamp);
|
||||||
pragueEOFTime = pragueTime;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -207,10 +207,9 @@ class GenesisConfigOptionsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldGetPragueEOFTime() {
|
void shouldGetOsakaTime() {
|
||||||
final GenesisConfigOptions config =
|
final GenesisConfigOptions config = fromConfigOptions(singletonMap("osakaTime", 1670470143));
|
||||||
fromConfigOptions(singletonMap("pragueEOFTime", 1670470143));
|
assertThat(config.getOsakaTime()).hasValue(1670470143);
|
||||||
assertThat(config.getPragueEOFTime()).hasValue(1670470143);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -247,7 +246,7 @@ class GenesisConfigOptionsTest {
|
|||||||
assertThat(config.getCancunTime()).isEmpty();
|
assertThat(config.getCancunTime()).isEmpty();
|
||||||
assertThat(config.getCancunEOFTime()).isEmpty();
|
assertThat(config.getCancunEOFTime()).isEmpty();
|
||||||
assertThat(config.getPragueTime()).isEmpty();
|
assertThat(config.getPragueTime()).isEmpty();
|
||||||
assertThat(config.getPragueEOFTime()).isEmpty();
|
assertThat(config.getOsakaTime()).isEmpty();
|
||||||
assertThat(config.getFutureEipsTime()).isEmpty();
|
assertThat(config.getFutureEipsTime()).isEmpty();
|
||||||
assertThat(config.getExperimentalEipsTime()).isEmpty();
|
assertThat(config.getExperimentalEipsTime()).isEmpty();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,11 @@ public class BftEventQueue {
|
|||||||
started.set(true);
|
started.set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Stop the event queue. No events will be queued for processing until it is started. */
|
||||||
|
public void stop() {
|
||||||
|
started.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isStarted() {
|
private boolean isStarted() {
|
||||||
return started.get();
|
return started.get();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ public class BftExecutors {
|
|||||||
|
|
||||||
/** Start. */
|
/** Start. */
|
||||||
public synchronized void start() {
|
public synchronized void start() {
|
||||||
if (state != State.IDLE) {
|
if (state != State.IDLE && state != State.STOPPED) {
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,8 +44,13 @@ public class BftProcessor implements Runnable {
|
|||||||
this.eventMultiplexer = eventMultiplexer;
|
this.eventMultiplexer = eventMultiplexer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Indicate to the processor that it can be started */
|
||||||
|
public synchronized void start() {
|
||||||
|
shutdown = false;
|
||||||
|
}
|
||||||
|
|
||||||
/** Indicate to the processor that it should gracefully stop at its next opportunity */
|
/** Indicate to the processor that it should gracefully stop at its next opportunity */
|
||||||
public void stop() {
|
public synchronized void stop() {
|
||||||
shutdown = true;
|
shutdown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,6 +72,8 @@ public class BftProcessor implements Runnable {
|
|||||||
while (!shutdown) {
|
while (!shutdown) {
|
||||||
nextEvent().ifPresent(eventMultiplexer::handleBftEvent);
|
nextEvent().ifPresent(eventMultiplexer::handleBftEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
incomingQueue.stop();
|
||||||
} catch (final Throwable t) {
|
} catch (final Throwable t) {
|
||||||
LOG.error("BFT Mining thread has suffered a fatal error, mining has been halted", t);
|
LOG.error("BFT Mining thread has suffered a fatal error, mining has been halted", t);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,7 +93,9 @@ public class BftMiningCoordinator implements MiningCoordinator, BlockAddedObserv
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
if (state.compareAndSet(State.IDLE, State.RUNNING)) {
|
if (state.compareAndSet(State.IDLE, State.RUNNING)
|
||||||
|
|| state.compareAndSet(State.STOPPED, State.RUNNING)) {
|
||||||
|
bftProcessor.start();
|
||||||
bftExecutors.start();
|
bftExecutors.start();
|
||||||
blockAddedObserverId = blockchain.observeBlockAdded(this);
|
blockAddedObserverId = blockchain.observeBlockAdded(this);
|
||||||
eventHandler.start();
|
eventHandler.start();
|
||||||
@@ -110,7 +112,7 @@ public class BftMiningCoordinator implements MiningCoordinator, BlockAddedObserv
|
|||||||
try {
|
try {
|
||||||
bftProcessor.awaitStop();
|
bftProcessor.awaitStop();
|
||||||
} catch (final InterruptedException e) {
|
} catch (final InterruptedException e) {
|
||||||
LOG.debug("Interrupted while waiting for IbftProcessor to stop.", e);
|
LOG.debug("Interrupted while waiting for BftProcessor to stop.", e);
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
bftExecutors.stop();
|
bftExecutors.stop();
|
||||||
@@ -135,12 +137,17 @@ public class BftMiningCoordinator implements MiningCoordinator, BlockAddedObserv
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean disable() {
|
public boolean disable() {
|
||||||
|
if (state.get() == State.PAUSED
|
||||||
|
|| state.compareAndSet(State.IDLE, State.PAUSED)
|
||||||
|
|| state.compareAndSet(State.RUNNING, State.PAUSED)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isMining() {
|
public boolean isMining() {
|
||||||
return true;
|
return state.get() == State.RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -134,6 +134,40 @@ public class BftEventQueueTest {
|
|||||||
assertThat(queue.poll(0, TimeUnit.MICROSECONDS)).isNull();
|
assertThat(queue.poll(0, TimeUnit.MICROSECONDS)).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void supportsStopAndRestart() throws InterruptedException {
|
||||||
|
final BftEventQueue queue = new BftEventQueue(MAX_QUEUE_SIZE);
|
||||||
|
queue.start();
|
||||||
|
|
||||||
|
assertThat(queue.poll(0, TimeUnit.MICROSECONDS)).isNull();
|
||||||
|
final DummyBftEvent dummyMessageEvent = new DummyBftEvent();
|
||||||
|
final DummyRoundExpiryBftEvent dummyRoundTimerEvent = new DummyRoundExpiryBftEvent();
|
||||||
|
final DummyNewChainHeadBftEvent dummyNewChainHeadEvent = new DummyNewChainHeadBftEvent();
|
||||||
|
|
||||||
|
queue.add(dummyMessageEvent);
|
||||||
|
queue.add(dummyRoundTimerEvent);
|
||||||
|
queue.add(dummyNewChainHeadEvent);
|
||||||
|
assertThat(queue.poll(0, TimeUnit.MICROSECONDS)).isNotNull();
|
||||||
|
assertThat(queue.poll(0, TimeUnit.MICROSECONDS)).isNotNull();
|
||||||
|
assertThat(queue.poll(0, TimeUnit.MICROSECONDS)).isNotNull();
|
||||||
|
assertThat(queue.poll(0, TimeUnit.MICROSECONDS)).isNull();
|
||||||
|
|
||||||
|
queue.stop();
|
||||||
|
queue.add(dummyMessageEvent);
|
||||||
|
queue.add(dummyRoundTimerEvent);
|
||||||
|
queue.add(dummyNewChainHeadEvent);
|
||||||
|
assertThat(queue.poll(0, TimeUnit.MICROSECONDS)).isNull();
|
||||||
|
|
||||||
|
queue.start();
|
||||||
|
queue.add(dummyMessageEvent);
|
||||||
|
queue.add(dummyRoundTimerEvent);
|
||||||
|
queue.add(dummyNewChainHeadEvent);
|
||||||
|
assertThat(queue.poll(0, TimeUnit.MICROSECONDS)).isNotNull();
|
||||||
|
assertThat(queue.poll(0, TimeUnit.MICROSECONDS)).isNotNull();
|
||||||
|
assertThat(queue.poll(0, TimeUnit.MICROSECONDS)).isNotNull();
|
||||||
|
assertThat(queue.poll(0, TimeUnit.MICROSECONDS)).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void alwaysAddBlockTimerExpiryEvents() throws InterruptedException {
|
public void alwaysAddBlockTimerExpiryEvents() throws InterruptedException {
|
||||||
final BftEventQueue queue = new BftEventQueue(MAX_QUEUE_SIZE);
|
final BftEventQueue queue = new BftEventQueue(MAX_QUEUE_SIZE);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import static org.mockito.Mockito.lenient;
|
|||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
import static org.mockito.internal.verification.VerificationModeFactory.times;
|
||||||
|
|
||||||
import org.hyperledger.besu.consensus.common.bft.BftEventQueue;
|
import org.hyperledger.besu.consensus.common.bft.BftEventQueue;
|
||||||
import org.hyperledger.besu.consensus.common.bft.BftExecutors;
|
import org.hyperledger.besu.consensus.common.bft.BftExecutors;
|
||||||
@@ -82,6 +83,28 @@ public class BftMiningCoordinatorTest {
|
|||||||
verify(bftProcessor).stop();
|
verify(bftProcessor).stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void restartsMiningAfterStop() {
|
||||||
|
assertThat(bftMiningCoordinator.isMining()).isFalse();
|
||||||
|
bftMiningCoordinator.stop();
|
||||||
|
verify(bftProcessor, never()).stop();
|
||||||
|
|
||||||
|
bftMiningCoordinator.enable();
|
||||||
|
bftMiningCoordinator.start();
|
||||||
|
assertThat(bftMiningCoordinator.isMining()).isTrue();
|
||||||
|
|
||||||
|
bftMiningCoordinator.stop();
|
||||||
|
assertThat(bftMiningCoordinator.isMining()).isFalse();
|
||||||
|
verify(bftProcessor).stop();
|
||||||
|
|
||||||
|
bftMiningCoordinator.start();
|
||||||
|
assertThat(bftMiningCoordinator.isMining()).isTrue();
|
||||||
|
|
||||||
|
// BFT processor should be started once for every time the mining
|
||||||
|
// coordinator is restarted
|
||||||
|
verify(bftProcessor, times(2)).start();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getsMinTransactionGasPrice() {
|
public void getsMinTransactionGasPrice() {
|
||||||
final Wei minGasPrice = Wei.of(10);
|
final Wei minGasPrice = Wei.of(10);
|
||||||
|
|||||||
@@ -81,8 +81,6 @@ public interface HardforkId {
|
|||||||
CANCUN_EOF(false, "Cancun + EOF"),
|
CANCUN_EOF(false, "Cancun + EOF"),
|
||||||
/** Prague fork. */
|
/** Prague fork. */
|
||||||
PRAGUE(false, "Prague"),
|
PRAGUE(false, "Prague"),
|
||||||
/** Prague + EOF fork. */
|
|
||||||
PRAGUE_EOF(false, "Prague + EOF"),
|
|
||||||
/** Osaka fork. */
|
/** Osaka fork. */
|
||||||
OSAKA(false, "Osaka"),
|
OSAKA(false, "Osaka"),
|
||||||
/** Amsterdam fork. */
|
/** Amsterdam fork. */
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;
|
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;
|
||||||
|
|
||||||
import static java.util.stream.Collectors.toUnmodifiableList;
|
|
||||||
import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator.calculateExcessBlobGasForParent;
|
import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator.calculateExcessBlobGasForParent;
|
||||||
|
|
||||||
import org.hyperledger.besu.datatypes.Hash;
|
import org.hyperledger.besu.datatypes.Hash;
|
||||||
@@ -32,6 +31,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSucces
|
|||||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
|
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.FeeHistory;
|
||||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.ImmutableFeeHistory;
|
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.ImmutableFeeHistory;
|
||||||
|
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
|
||||||
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
|
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
|
||||||
import org.hyperledger.besu.ethereum.chain.Blockchain;
|
import org.hyperledger.besu.ethereum.chain.Blockchain;
|
||||||
import org.hyperledger.besu.ethereum.core.Block;
|
import org.hyperledger.besu.ethereum.core.Block;
|
||||||
@@ -57,9 +57,11 @@ import com.github.benmanes.caffeine.cache.Cache;
|
|||||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.collect.Streams;
|
import com.google.common.collect.Streams;
|
||||||
|
import org.apache.tuweni.units.bigints.UInt256s;
|
||||||
|
|
||||||
public class EthFeeHistory implements JsonRpcMethod {
|
public class EthFeeHistory implements JsonRpcMethod {
|
||||||
private final ProtocolSchedule protocolSchedule;
|
private final ProtocolSchedule protocolSchedule;
|
||||||
|
private final BlockchainQueries blockchainQueries;
|
||||||
private final Blockchain blockchain;
|
private final Blockchain blockchain;
|
||||||
private final MiningCoordinator miningCoordinator;
|
private final MiningCoordinator miningCoordinator;
|
||||||
private final ApiConfiguration apiConfiguration;
|
private final ApiConfiguration apiConfiguration;
|
||||||
@@ -70,13 +72,14 @@ public class EthFeeHistory implements JsonRpcMethod {
|
|||||||
|
|
||||||
public EthFeeHistory(
|
public EthFeeHistory(
|
||||||
final ProtocolSchedule protocolSchedule,
|
final ProtocolSchedule protocolSchedule,
|
||||||
final Blockchain blockchain,
|
final BlockchainQueries blockchainQueries,
|
||||||
final MiningCoordinator miningCoordinator,
|
final MiningCoordinator miningCoordinator,
|
||||||
final ApiConfiguration apiConfiguration) {
|
final ApiConfiguration apiConfiguration) {
|
||||||
this.protocolSchedule = protocolSchedule;
|
this.protocolSchedule = protocolSchedule;
|
||||||
this.blockchain = blockchain;
|
this.blockchainQueries = blockchainQueries;
|
||||||
this.miningCoordinator = miningCoordinator;
|
this.miningCoordinator = miningCoordinator;
|
||||||
this.apiConfiguration = apiConfiguration;
|
this.apiConfiguration = apiConfiguration;
|
||||||
|
this.blockchain = blockchainQueries.getBlockchain();
|
||||||
this.cache = Caffeine.newBuilder().maximumSize(MAXIMUM_CACHE_SIZE).build();
|
this.cache = Caffeine.newBuilder().maximumSize(MAXIMUM_CACHE_SIZE).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +139,8 @@ public class EthFeeHistory implements JsonRpcMethod {
|
|||||||
final List<Double> gasUsedRatios = getGasUsedRatios(blockHeaderRange);
|
final List<Double> gasUsedRatios = getGasUsedRatios(blockHeaderRange);
|
||||||
final List<Double> blobGasUsedRatios = getBlobGasUsedRatios(blockHeaderRange);
|
final List<Double> blobGasUsedRatios = getBlobGasUsedRatios(blockHeaderRange);
|
||||||
final Optional<List<List<Wei>>> maybeRewards =
|
final Optional<List<List<Wei>>> maybeRewards =
|
||||||
maybeRewardPercentiles.map(rewards -> getRewards(rewards, blockHeaderRange));
|
maybeRewardPercentiles.map(
|
||||||
|
percentiles -> getRewards(percentiles, blockHeaderRange, nextBaseFee));
|
||||||
return new JsonRpcSuccessResponse(
|
return new JsonRpcSuccessResponse(
|
||||||
requestId,
|
requestId,
|
||||||
createFeeHistoryResult(
|
createFeeHistoryResult(
|
||||||
@@ -203,17 +207,19 @@ public class EthFeeHistory implements JsonRpcMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<List<Wei>> getRewards(
|
private List<List<Wei>> getRewards(
|
||||||
final List<Double> rewardPercentiles, final List<BlockHeader> blockHeaders) {
|
final List<Double> rewardPercentiles,
|
||||||
|
final List<BlockHeader> blockHeaders,
|
||||||
|
final Wei nextBaseFee) {
|
||||||
var sortedPercentiles = rewardPercentiles.stream().sorted().toList();
|
var sortedPercentiles = rewardPercentiles.stream().sorted().toList();
|
||||||
return blockHeaders.stream()
|
return blockHeaders.stream()
|
||||||
.parallel()
|
.parallel()
|
||||||
.map(blockHeader -> calculateBlockHeaderReward(sortedPercentiles, blockHeader))
|
.map(blockHeader -> calculateBlockHeaderReward(sortedPercentiles, blockHeader, nextBaseFee))
|
||||||
.flatMap(Optional::stream)
|
.flatMap(Optional::stream)
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<List<Wei>> calculateBlockHeaderReward(
|
private Optional<List<Wei>> calculateBlockHeaderReward(
|
||||||
final List<Double> sortedPercentiles, final BlockHeader blockHeader) {
|
final List<Double> sortedPercentiles, final BlockHeader blockHeader, final Wei nextBaseFee) {
|
||||||
|
|
||||||
// Create a new key for the reward cache
|
// Create a new key for the reward cache
|
||||||
final RewardCacheKey key = new RewardCacheKey(blockHeader.getBlockHash(), sortedPercentiles);
|
final RewardCacheKey key = new RewardCacheKey(blockHeader.getBlockHash(), sortedPercentiles);
|
||||||
@@ -226,7 +232,7 @@ public class EthFeeHistory implements JsonRpcMethod {
|
|||||||
Optional<Block> block = blockchain.getBlockByHash(blockHeader.getBlockHash());
|
Optional<Block> block = blockchain.getBlockByHash(blockHeader.getBlockHash());
|
||||||
return block.map(
|
return block.map(
|
||||||
b -> {
|
b -> {
|
||||||
List<Wei> rewards = computeRewards(sortedPercentiles, b);
|
List<Wei> rewards = computeRewards(sortedPercentiles, b, nextBaseFee);
|
||||||
// Put the computed rewards in the cache for future use
|
// Put the computed rewards in the cache for future use
|
||||||
cache.put(key, rewards);
|
cache.put(key, rewards);
|
||||||
return rewards;
|
return rewards;
|
||||||
@@ -237,7 +243,8 @@ public class EthFeeHistory implements JsonRpcMethod {
|
|||||||
record TransactionInfo(Transaction transaction, Long gasUsed, Wei effectivePriorityFeePerGas) {}
|
record TransactionInfo(Transaction transaction, Long gasUsed, Wei effectivePriorityFeePerGas) {}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public List<Wei> computeRewards(final List<Double> rewardPercentiles, final Block block) {
|
public List<Wei> computeRewards(
|
||||||
|
final List<Double> rewardPercentiles, final Block block, final Wei nextBaseFee) {
|
||||||
final List<Transaction> transactions = block.getBody().getTransactions();
|
final List<Transaction> transactions = block.getBody().getTransactions();
|
||||||
if (transactions.isEmpty()) {
|
if (transactions.isEmpty()) {
|
||||||
// all 0's for empty block
|
// all 0's for empty block
|
||||||
@@ -253,7 +260,7 @@ public class EthFeeHistory implements JsonRpcMethod {
|
|||||||
// If the priority fee boundary is set, return the bounded rewards. Otherwise, return the real
|
// If the priority fee boundary is set, return the bounded rewards. Otherwise, return the real
|
||||||
// rewards.
|
// rewards.
|
||||||
if (apiConfiguration.isGasAndPriorityFeeLimitingEnabled()) {
|
if (apiConfiguration.isGasAndPriorityFeeLimitingEnabled()) {
|
||||||
return boundRewards(realRewards);
|
return boundRewards(realRewards, nextBaseFee);
|
||||||
} else {
|
} else {
|
||||||
return realRewards;
|
return realRewards;
|
||||||
}
|
}
|
||||||
@@ -292,16 +299,20 @@ public class EthFeeHistory implements JsonRpcMethod {
|
|||||||
* This method returns a list of bounded rewards.
|
* This method returns a list of bounded rewards.
|
||||||
*
|
*
|
||||||
* @param rewards The list of rewards to be bounded.
|
* @param rewards The list of rewards to be bounded.
|
||||||
|
* @param nextBaseFee The base fee of the next block.
|
||||||
* @return The list of bounded rewards.
|
* @return The list of bounded rewards.
|
||||||
*/
|
*/
|
||||||
private List<Wei> boundRewards(final List<Wei> rewards) {
|
private List<Wei> boundRewards(final List<Wei> rewards, final Wei nextBaseFee) {
|
||||||
Wei minPriorityFee = miningCoordinator.getMinPriorityFeePerGas();
|
final Wei lowerBoundGasPrice = blockchainQueries.gasPriceLowerBound();
|
||||||
Wei lowerBound =
|
final Wei lowerBoundPriorityFee = lowerBoundGasPrice.subtract(nextBaseFee);
|
||||||
minPriorityFee
|
final Wei minPriorityFee = miningCoordinator.getMinPriorityFeePerGas();
|
||||||
|
final Wei forcedMinPriorityFee = UInt256s.max(minPriorityFee, lowerBoundPriorityFee);
|
||||||
|
final Wei lowerBound =
|
||||||
|
forcedMinPriorityFee
|
||||||
.multiply(apiConfiguration.getLowerBoundGasAndPriorityFeeCoefficient())
|
.multiply(apiConfiguration.getLowerBoundGasAndPriorityFeeCoefficient())
|
||||||
.divide(100);
|
.divide(100);
|
||||||
Wei upperBound =
|
final Wei upperBound =
|
||||||
minPriorityFee
|
forcedMinPriorityFee
|
||||||
.multiply(apiConfiguration.getUpperBoundGasAndPriorityFeeCoefficient())
|
.multiply(apiConfiguration.getUpperBoundGasAndPriorityFeeCoefficient())
|
||||||
.divide(100);
|
.divide(100);
|
||||||
|
|
||||||
@@ -438,7 +449,7 @@ public class EthFeeHistory implements JsonRpcMethod {
|
|||||||
.oldestBlock(oldestBlock)
|
.oldestBlock(oldestBlock)
|
||||||
.baseFeePerGas(
|
.baseFeePerGas(
|
||||||
Stream.concat(explicitlyRequestedBaseFees.stream(), Stream.of(nextBaseFee))
|
Stream.concat(explicitlyRequestedBaseFees.stream(), Stream.of(nextBaseFee))
|
||||||
.collect(toUnmodifiableList()))
|
.toList())
|
||||||
.baseFeePerBlobGas(requestedBlobBaseFees)
|
.baseFeePerBlobGas(requestedBlobBaseFees)
|
||||||
.gasUsedRatio(gasUsedRatios)
|
.gasUsedRatio(gasUsedRatios)
|
||||||
.blobGasUsedRatio(blobGasUsedRatio)
|
.blobGasUsedRatio(blobGasUsedRatio)
|
||||||
|
|||||||
@@ -95,7 +95,8 @@ public class EthGetBlockReceipts extends AbstractBlockParameterOrBlockHashMethod
|
|||||||
.map(
|
.map(
|
||||||
block ->
|
block ->
|
||||||
block.getTransactions().stream()
|
block.getTransactions().stream()
|
||||||
.map(tx -> txReceipt(tx).get())
|
.map(this::txReceipt)
|
||||||
|
.flatMap(Optional::stream)
|
||||||
.collect(Collectors.toList()))
|
.collect(Collectors.toList()))
|
||||||
.orElse(new ArrayList<>());
|
.orElse(new ArrayList<>());
|
||||||
|
|
||||||
|
|||||||
@@ -132,11 +132,7 @@ public class EthJsonRpcMethods extends ApiGroupJsonRpcMethods {
|
|||||||
blockchainQueries.getWorldStateArchive(),
|
blockchainQueries.getWorldStateArchive(),
|
||||||
protocolSchedule,
|
protocolSchedule,
|
||||||
apiConfiguration.getGasCap())),
|
apiConfiguration.getGasCap())),
|
||||||
new EthFeeHistory(
|
new EthFeeHistory(protocolSchedule, blockchainQueries, miningCoordinator, apiConfiguration),
|
||||||
protocolSchedule,
|
|
||||||
blockchainQueries.getBlockchain(),
|
|
||||||
miningCoordinator,
|
|
||||||
apiConfiguration),
|
|
||||||
new EthGetCode(blockchainQueries),
|
new EthGetCode(blockchainQueries),
|
||||||
new EthGetLogs(blockchainQueries, apiConfiguration.getMaxLogsRange()),
|
new EthGetLogs(blockchainQueries, apiConfiguration.getMaxLogsRange()),
|
||||||
new EthGetProof(blockchainQueries),
|
new EthGetProof(blockchainQueries),
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ 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.FeeHistory;
|
||||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.ImmutableFeeHistory;
|
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.api.jsonrpc.internal.results.ImmutableFeeHistoryResult;
|
||||||
|
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
|
||||||
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
|
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
|
||||||
import org.hyperledger.besu.ethereum.chain.Blockchain;
|
import org.hyperledger.besu.ethereum.chain.Blockchain;
|
||||||
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
|
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
|
||||||
@@ -69,6 +70,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
|
|
||||||
public class EthFeeHistoryTest {
|
public class EthFeeHistoryTest {
|
||||||
final BlockDataGenerator gen = new BlockDataGenerator();
|
final BlockDataGenerator gen = new BlockDataGenerator();
|
||||||
|
private BlockchainQueries blockchainQueries;
|
||||||
private MutableBlockchain blockchain;
|
private MutableBlockchain blockchain;
|
||||||
private EthFeeHistory method;
|
private EthFeeHistory method;
|
||||||
private ProtocolSchedule protocolSchedule;
|
private ProtocolSchedule protocolSchedule;
|
||||||
@@ -82,14 +84,15 @@ public class EthFeeHistoryTest {
|
|||||||
gen.blockSequence(genesisBlock, 10)
|
gen.blockSequence(genesisBlock, 10)
|
||||||
.forEach(block -> blockchain.appendBlock(block, gen.receipts(block)));
|
.forEach(block -> blockchain.appendBlock(block, gen.receipts(block)));
|
||||||
miningCoordinator = mock(MergeCoordinator.class);
|
miningCoordinator = mock(MergeCoordinator.class);
|
||||||
when(miningCoordinator.getMinPriorityFeePerGas()).thenReturn(Wei.ONE);
|
|
||||||
|
blockchainQueries = mockBlockchainQueries(blockchain, Wei.of(7));
|
||||||
|
|
||||||
mockFork();
|
mockFork();
|
||||||
|
|
||||||
method =
|
method =
|
||||||
new EthFeeHistory(
|
new EthFeeHistory(
|
||||||
protocolSchedule,
|
protocolSchedule,
|
||||||
blockchain,
|
blockchainQueries,
|
||||||
miningCoordinator,
|
miningCoordinator,
|
||||||
ImmutableApiConfiguration.builder().build());
|
ImmutableApiConfiguration.builder().build());
|
||||||
}
|
}
|
||||||
@@ -139,11 +142,16 @@ public class EthFeeHistoryTest {
|
|||||||
Block block = mock(Block.class);
|
Block block = mock(Block.class);
|
||||||
Blockchain blockchain = mockBlockchainTransactionsWithPriorityFee(block);
|
Blockchain blockchain = mockBlockchainTransactionsWithPriorityFee(block);
|
||||||
|
|
||||||
|
final var blockchainQueries = mockBlockchainQueries(blockchain, Wei.of(7));
|
||||||
|
|
||||||
EthFeeHistory ethFeeHistory =
|
EthFeeHistory ethFeeHistory =
|
||||||
new EthFeeHistory(
|
new EthFeeHistory(
|
||||||
null, blockchain, miningCoordinator, ImmutableApiConfiguration.builder().build());
|
null,
|
||||||
|
blockchainQueries,
|
||||||
|
miningCoordinator,
|
||||||
|
ImmutableApiConfiguration.builder().build());
|
||||||
|
|
||||||
List<Wei> rewards = ethFeeHistory.computeRewards(rewardPercentiles, block);
|
List<Wei> rewards = ethFeeHistory.computeRewards(rewardPercentiles, block, Wei.of(7));
|
||||||
|
|
||||||
// Define the expected rewards for each percentile
|
// Define the expected rewards for each percentile
|
||||||
// The expected rewards match the fees of the transactions at each percentile in the
|
// The expected rewards match the fees of the transactions at each percentile in the
|
||||||
@@ -179,14 +187,51 @@ public class EthFeeHistoryTest {
|
|||||||
.upperBoundGasAndPriorityFeeCoefficient(500L)
|
.upperBoundGasAndPriorityFeeCoefficient(500L)
|
||||||
.build(); // Max reward = Wei.One * 500L / 100 = 5.0
|
.build(); // Max reward = Wei.One * 500L / 100 = 5.0
|
||||||
|
|
||||||
EthFeeHistory ethFeeHistory =
|
final var blockchainQueries = mockBlockchainQueries(blockchain, Wei.of(7));
|
||||||
new EthFeeHistory(null, blockchain, miningCoordinator, apiConfiguration);
|
when(miningCoordinator.getMinPriorityFeePerGas()).thenReturn(Wei.ONE);
|
||||||
|
|
||||||
List<Wei> rewards = ethFeeHistory.computeRewards(rewardPercentiles, block);
|
EthFeeHistory ethFeeHistory =
|
||||||
|
new EthFeeHistory(null, blockchainQueries, miningCoordinator, apiConfiguration);
|
||||||
|
|
||||||
|
List<Wei> rewards = ethFeeHistory.computeRewards(rewardPercentiles, block, Wei.of(7));
|
||||||
|
|
||||||
// Define the expected bounded rewards for each percentile
|
// Define the expected bounded rewards for each percentile
|
||||||
List<Wei> expectedBoundedRewards = Stream.of(2, 2, 2, 4, 5, 5, 5, 5, 5).map(Wei::of).toList();
|
List<Wei> expectedBoundedRewards = Stream.of(2, 2, 2, 4, 5, 5, 5, 5, 5).map(Wei::of).toList();
|
||||||
assertThat(expectedBoundedRewards).isEqualTo(rewards);
|
assertThat(rewards).isEqualTo(expectedBoundedRewards);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldApplyLowerBoundRewardsCorrectly() {
|
||||||
|
// This test checks that the rewards are correctly bounded by the lower and upper limits,
|
||||||
|
// when the calculated lower bound for the priority fee is greater than the configured one.
|
||||||
|
// Configured minPriorityFeePerGas is 0 wei, minGasPrice is 10 wei and baseFee is 8 wei,
|
||||||
|
// so for a tx to be mined the minPriorityFeePerGas is raised to 2 wei before applying the
|
||||||
|
// coefficients.
|
||||||
|
|
||||||
|
List<Double> rewardPercentiles =
|
||||||
|
Arrays.asList(0.0, 5.0, 10.0, 27.50, 31.0, 59.0, 60.0, 61.0, 100.0);
|
||||||
|
|
||||||
|
Block block = mock(Block.class);
|
||||||
|
Blockchain blockchain = mockBlockchainTransactionsWithPriorityFee(block);
|
||||||
|
|
||||||
|
ApiConfiguration apiConfiguration =
|
||||||
|
ImmutableApiConfiguration.builder()
|
||||||
|
.isGasAndPriorityFeeLimitingEnabled(true)
|
||||||
|
.lowerBoundGasAndPriorityFeeCoefficient(200L) // Min reward = 2 * 200L / 100 = 4.0
|
||||||
|
.upperBoundGasAndPriorityFeeCoefficient(300L)
|
||||||
|
.build(); // Max reward = 2 * 300L / 100 = 6.0
|
||||||
|
|
||||||
|
final var blockchainQueries = mockBlockchainQueries(blockchain, Wei.of(10));
|
||||||
|
when(miningCoordinator.getMinPriorityFeePerGas()).thenReturn(Wei.ZERO);
|
||||||
|
|
||||||
|
EthFeeHistory ethFeeHistory =
|
||||||
|
new EthFeeHistory(null, blockchainQueries, miningCoordinator, apiConfiguration);
|
||||||
|
|
||||||
|
List<Wei> rewards = ethFeeHistory.computeRewards(rewardPercentiles, block, Wei.of(8));
|
||||||
|
|
||||||
|
// Define the expected bounded rewards for each percentile
|
||||||
|
List<Wei> expectedBoundedRewards = Stream.of(4, 4, 4, 4, 5, 6, 6, 6, 6).map(Wei::of).toList();
|
||||||
|
assertThat(rewards).isEqualTo(expectedBoundedRewards);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Blockchain mockBlockchainTransactionsWithPriorityFee(final Block block) {
|
private Blockchain mockBlockchainTransactionsWithPriorityFee(final Block block) {
|
||||||
@@ -399,4 +444,12 @@ public class EthFeeHistoryTest {
|
|||||||
return method.response(
|
return method.response(
|
||||||
new JsonRpcRequestContext(new JsonRpcRequest("2.0", "eth_feeHistory", params)));
|
new JsonRpcRequestContext(new JsonRpcRequest("2.0", "eth_feeHistory", params)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BlockchainQueries mockBlockchainQueries(
|
||||||
|
final Blockchain blockchain, final Wei gasPriceLowerBound) {
|
||||||
|
final var blockchainQueries = mock(BlockchainQueries.class);
|
||||||
|
when(blockchainQueries.getBlockchain()).thenReturn(blockchain);
|
||||||
|
when(blockchainQueries.gasPriceLowerBound()).thenReturn(gasPriceLowerBound);
|
||||||
|
return blockchainQueries;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -312,7 +312,7 @@ public final class GenesisState {
|
|||||||
if (cancunEOFTimestamp.isPresent()) {
|
if (cancunEOFTimestamp.isPresent()) {
|
||||||
return genesis.getTimestamp() >= cancunEOFTimestamp.getAsLong();
|
return genesis.getTimestamp() >= cancunEOFTimestamp.getAsLong();
|
||||||
}
|
}
|
||||||
return isPragueEOFAtGenesis(genesis);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isPragueAtGenesis(final GenesisConfigFile genesis) {
|
private static boolean isPragueAtGenesis(final GenesisConfigFile genesis) {
|
||||||
@@ -320,13 +320,13 @@ public final class GenesisState {
|
|||||||
if (pragueTimestamp.isPresent()) {
|
if (pragueTimestamp.isPresent()) {
|
||||||
return genesis.getTimestamp() >= pragueTimestamp.getAsLong();
|
return genesis.getTimestamp() >= pragueTimestamp.getAsLong();
|
||||||
}
|
}
|
||||||
return isPragueEOFAtGenesis(genesis);
|
return isOsakaAtGenesis(genesis);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isPragueEOFAtGenesis(final GenesisConfigFile genesis) {
|
private static boolean isOsakaAtGenesis(final GenesisConfigFile genesis) {
|
||||||
final OptionalLong pragueEOFTimestamp = genesis.getConfigOptions().getPragueEOFTime();
|
final OptionalLong osakaTimestamp = genesis.getConfigOptions().getOsakaTime();
|
||||||
if (pragueEOFTimestamp.isPresent()) {
|
if (osakaTimestamp.isPresent()) {
|
||||||
return genesis.getTimestamp() >= pragueEOFTimestamp.getAsLong();
|
return genesis.getTimestamp() >= osakaTimestamp.getAsLong();
|
||||||
}
|
}
|
||||||
return isFutureEipsTimeAtGenesis(genesis);
|
return isFutureEipsTimeAtGenesis(genesis);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -224,8 +224,8 @@ public class MainnetProtocolSpecFactory {
|
|||||||
metricsSystem);
|
metricsSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProtocolSpecBuilder pragueEOFDefinition(final GenesisConfigOptions genesisConfigOptions) {
|
public ProtocolSpecBuilder osakaDefinition(final GenesisConfigOptions genesisConfigOptions) {
|
||||||
return MainnetProtocolSpecs.pragueEOFDefinition(
|
return MainnetProtocolSpecs.osakaDefinition(
|
||||||
chainId,
|
chainId,
|
||||||
isRevertReasonEnabled,
|
isRevertReasonEnabled,
|
||||||
genesisConfigOptions,
|
genesisConfigOptions,
|
||||||
|
|||||||
@@ -57,8 +57,8 @@ import org.hyperledger.besu.evm.gascalculator.FrontierGasCalculator;
|
|||||||
import org.hyperledger.besu.evm.gascalculator.HomesteadGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.HomesteadGasCalculator;
|
||||||
import org.hyperledger.besu.evm.gascalculator.IstanbulGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.IstanbulGasCalculator;
|
||||||
import org.hyperledger.besu.evm.gascalculator.LondonGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.LondonGasCalculator;
|
||||||
|
import org.hyperledger.besu.evm.gascalculator.OsakaGasCalculator;
|
||||||
import org.hyperledger.besu.evm.gascalculator.PetersburgGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.PetersburgGasCalculator;
|
||||||
import org.hyperledger.besu.evm.gascalculator.PragueEOFGasCalculator;
|
|
||||||
import org.hyperledger.besu.evm.gascalculator.PragueGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.PragueGasCalculator;
|
||||||
import org.hyperledger.besu.evm.gascalculator.ShanghaiGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.ShanghaiGasCalculator;
|
||||||
import org.hyperledger.besu.evm.gascalculator.SpuriousDragonGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.SpuriousDragonGasCalculator;
|
||||||
@@ -815,7 +815,7 @@ public abstract class MainnetProtocolSpecs {
|
|||||||
.name("Prague");
|
.name("Prague");
|
||||||
}
|
}
|
||||||
|
|
||||||
static ProtocolSpecBuilder pragueEOFDefinition(
|
static ProtocolSpecBuilder osakaDefinition(
|
||||||
final Optional<BigInteger> chainId,
|
final Optional<BigInteger> chainId,
|
||||||
final boolean enableRevertReason,
|
final boolean enableRevertReason,
|
||||||
final GenesisConfigOptions genesisConfigOptions,
|
final GenesisConfigOptions genesisConfigOptions,
|
||||||
@@ -833,7 +833,7 @@ public abstract class MainnetProtocolSpecs {
|
|||||||
miningParameters,
|
miningParameters,
|
||||||
isParallelTxProcessingEnabled,
|
isParallelTxProcessingEnabled,
|
||||||
metricsSystem);
|
metricsSystem);
|
||||||
return addEOF(chainId, evmConfiguration, protocolSpecBuilder).name("PragueEOF");
|
return addEOF(chainId, evmConfiguration, protocolSpecBuilder).name("Osaka");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ProtocolSpecBuilder addEOF(
|
private static ProtocolSpecBuilder addEOF(
|
||||||
@@ -842,12 +842,11 @@ public abstract class MainnetProtocolSpecs {
|
|||||||
final ProtocolSpecBuilder protocolSpecBuilder) {
|
final ProtocolSpecBuilder protocolSpecBuilder) {
|
||||||
return protocolSpecBuilder
|
return protocolSpecBuilder
|
||||||
// EIP-7692 EOF v1 Gas calculator
|
// EIP-7692 EOF v1 Gas calculator
|
||||||
.gasCalculator(PragueEOFGasCalculator::new)
|
.gasCalculator(OsakaGasCalculator::new)
|
||||||
// EIP-7692 EOF v1 EVM and opcodes
|
// EIP-7692 EOF v1 EVM and opcodes
|
||||||
.evmBuilder(
|
.evmBuilder(
|
||||||
(gasCalculator, jdCacheConfig) ->
|
(gasCalculator, jdCacheConfig) ->
|
||||||
MainnetEVMs.pragueEOF(
|
MainnetEVMs.osaka(gasCalculator, chainId.orElse(BigInteger.ZERO), evmConfiguration))
|
||||||
gasCalculator, chainId.orElse(BigInteger.ZERO), evmConfiguration))
|
|
||||||
// EIP-7698 EOF v1 creation transaction
|
// EIP-7698 EOF v1 creation transaction
|
||||||
.contractCreationProcessorBuilder(
|
.contractCreationProcessorBuilder(
|
||||||
evm ->
|
evm ->
|
||||||
@@ -867,7 +866,7 @@ public abstract class MainnetProtocolSpecs {
|
|||||||
final MiningParameters miningParameters,
|
final MiningParameters miningParameters,
|
||||||
final boolean isParallelTxProcessingEnabled,
|
final boolean isParallelTxProcessingEnabled,
|
||||||
final MetricsSystem metricsSystem) {
|
final MetricsSystem metricsSystem) {
|
||||||
return pragueEOFDefinition(
|
return osakaDefinition(
|
||||||
chainId,
|
chainId,
|
||||||
enableRevertReason,
|
enableRevertReason,
|
||||||
genesisConfigOptions,
|
genesisConfigOptions,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ package org.hyperledger.besu.ethereum.mainnet;
|
|||||||
|
|
||||||
import org.hyperledger.besu.config.GenesisConfigOptions;
|
import org.hyperledger.besu.config.GenesisConfigOptions;
|
||||||
import org.hyperledger.besu.datatypes.HardforkId;
|
import org.hyperledger.besu.datatypes.HardforkId;
|
||||||
|
import org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId;
|
||||||
import org.hyperledger.besu.ethereum.chain.BadBlockManager;
|
import org.hyperledger.besu.ethereum.chain.BadBlockManager;
|
||||||
import org.hyperledger.besu.ethereum.core.MiningParameters;
|
import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||||
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
|
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
|
||||||
@@ -281,7 +282,7 @@ public class ProtocolScheduleBuilder {
|
|||||||
lastForkBlock = validateForkOrder("Cancun", config.getCancunTime(), lastForkBlock);
|
lastForkBlock = validateForkOrder("Cancun", config.getCancunTime(), lastForkBlock);
|
||||||
lastForkBlock = validateForkOrder("CancunEOF", config.getCancunEOFTime(), lastForkBlock);
|
lastForkBlock = validateForkOrder("CancunEOF", config.getCancunEOFTime(), lastForkBlock);
|
||||||
lastForkBlock = validateForkOrder("Prague", config.getPragueTime(), lastForkBlock);
|
lastForkBlock = validateForkOrder("Prague", config.getPragueTime(), lastForkBlock);
|
||||||
lastForkBlock = validateForkOrder("PragueEOF", config.getPragueEOFTime(), lastForkBlock);
|
lastForkBlock = validateForkOrder("Osaka", config.getOsakaTime(), lastForkBlock);
|
||||||
lastForkBlock = validateForkOrder("FutureEips", config.getFutureEipsTime(), lastForkBlock);
|
lastForkBlock = validateForkOrder("FutureEips", config.getFutureEipsTime(), lastForkBlock);
|
||||||
lastForkBlock =
|
lastForkBlock =
|
||||||
validateForkOrder("ExperimentalEips", config.getExperimentalEipsTime(), lastForkBlock);
|
validateForkOrder("ExperimentalEips", config.getExperimentalEipsTime(), lastForkBlock);
|
||||||
@@ -443,9 +444,9 @@ public class ProtocolScheduleBuilder {
|
|||||||
config.getPragueTime(),
|
config.getPragueTime(),
|
||||||
specFactory.pragueDefinition(config)),
|
specFactory.pragueDefinition(config)),
|
||||||
timestampMilestone(
|
timestampMilestone(
|
||||||
HardforkId.MainnetHardforkId.PRAGUE_EOF,
|
MainnetHardforkId.OSAKA,
|
||||||
config.getPragueEOFTime(),
|
config.getOsakaTime(),
|
||||||
specFactory.pragueEOFDefinition(config)),
|
specFactory.osakaDefinition(config)),
|
||||||
timestampMilestone(
|
timestampMilestone(
|
||||||
HardforkId.MainnetHardforkId.FUTURE_EIPS,
|
HardforkId.MainnetHardforkId.FUTURE_EIPS,
|
||||||
config.getFutureEipsTime(),
|
config.getFutureEipsTime(),
|
||||||
|
|||||||
@@ -23,8 +23,6 @@ import org.hyperledger.besu.datatypes.KZGProof;
|
|||||||
import org.hyperledger.besu.datatypes.VersionedHash;
|
import org.hyperledger.besu.datatypes.VersionedHash;
|
||||||
import org.hyperledger.besu.evm.precompile.KZGPointEvalPrecompiledContract;
|
import org.hyperledger.besu.evm.precompile.KZGPointEvalPrecompiledContract;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -36,6 +34,8 @@ import org.bouncycastle.crypto.digests.SHA256Digest;
|
|||||||
|
|
||||||
public class BlobTestFixture {
|
public class BlobTestFixture {
|
||||||
|
|
||||||
|
private byte byteValue = 0x00;
|
||||||
|
|
||||||
public BlobTestFixture() {
|
public BlobTestFixture() {
|
||||||
try {
|
try {
|
||||||
// optimistically tear down a potential previous loaded trusted setup
|
// optimistically tear down a potential previous loaded trusted setup
|
||||||
@@ -58,14 +58,8 @@ public class BlobTestFixture {
|
|||||||
;
|
;
|
||||||
|
|
||||||
public BlobTriplet createBlobTriplet() {
|
public BlobTriplet createBlobTriplet() {
|
||||||
byte[] rawMaterial = {};
|
byte[] rawMaterial = new byte[131072];
|
||||||
try (InputStream readme =
|
rawMaterial[0] = byteValue++;
|
||||||
BlobTestFixture.class.getResourceAsStream(
|
|
||||||
"/org/hyperledger/besu/ethereum/core/encoding/BlobDataFixture.bin")) {
|
|
||||||
rawMaterial = readme.readAllBytes();
|
|
||||||
} catch (IOException e) {
|
|
||||||
fail("Failed to read blob file", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
Bytes48 commitment = Bytes48.wrap(CKZG4844JNI.blobToKzgCommitment(rawMaterial));
|
Bytes48 commitment = Bytes48.wrap(CKZG4844JNI.blobToKzgCommitment(rawMaterial));
|
||||||
|
|
||||||
|
|||||||
@@ -179,6 +179,10 @@ public class StorageRangeDataRequest extends SnapDataRequest {
|
|||||||
|
|
||||||
final StackTrie.TaskElement taskElement = stackTrie.getElement(startKeyHash);
|
final StackTrie.TaskElement taskElement = stackTrie.getElement(startKeyHash);
|
||||||
|
|
||||||
|
if (null == taskElement) {
|
||||||
|
return Stream.empty();
|
||||||
|
}
|
||||||
|
|
||||||
findNewBeginElementInRange(storageRoot, taskElement.proofs(), taskElement.keys(), endKeyHash)
|
findNewBeginElementInRange(storageRoot, taskElement.proofs(), taskElement.keys(), endKeyHash)
|
||||||
.ifPresent(
|
.ifPresent(
|
||||||
missingRightElement -> {
|
missingRightElement -> {
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.apache.tuweni.bytes.Bytes;
|
import org.apache.tuweni.bytes.Bytes;
|
||||||
@@ -44,7 +45,7 @@ public abstract class TrieNodeHealingRequest extends SnapDataRequest
|
|||||||
private final Bytes location;
|
private final Bytes location;
|
||||||
protected Bytes data;
|
protected Bytes data;
|
||||||
|
|
||||||
protected boolean requiresPersisting = true;
|
protected AtomicBoolean requiresPersisting = new AtomicBoolean(true);
|
||||||
|
|
||||||
protected TrieNodeHealingRequest(final Hash nodeHash, final Hash rootHash, final Bytes location) {
|
protected TrieNodeHealingRequest(final Hash nodeHash, final Hash rootHash, final Bytes location) {
|
||||||
super(TRIE_NODE, rootHash);
|
super(TRIE_NODE, rootHash);
|
||||||
@@ -65,7 +66,7 @@ public abstract class TrieNodeHealingRequest extends SnapDataRequest
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int saved = 0;
|
int saved = 0;
|
||||||
if (requiresPersisting) {
|
if (requiresPersisting.getAndSet(false)) {
|
||||||
checkNotNull(data, "Must set data before node can be persisted.");
|
checkNotNull(data, "Must set data before node can be persisted.");
|
||||||
saved =
|
saved =
|
||||||
doPersist(
|
doPersist(
|
||||||
@@ -143,7 +144,7 @@ public abstract class TrieNodeHealingRequest extends SnapDataRequest
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRequiresPersisting() {
|
public boolean isRequiresPersisting() {
|
||||||
return requiresPersisting;
|
return requiresPersisting.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bytes32 getNodeHash() {
|
public Bytes32 getNodeHash() {
|
||||||
@@ -173,7 +174,7 @@ public abstract class TrieNodeHealingRequest extends SnapDataRequest
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setRequiresPersisting(final boolean requiresPersisting) {
|
public void setRequiresPersisting(final boolean requiresPersisting) {
|
||||||
this.requiresPersisting = requiresPersisting;
|
this.requiresPersisting.set(requiresPersisting);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean nodeIsHashReferencedDescendant(final Node<Bytes> node) {
|
private boolean nodeIsHashReferencedDescendant(final Node<Bytes> node) {
|
||||||
|
|||||||
@@ -45,11 +45,11 @@ class NewPooledTransactionHashesMessageHandler implements EthMessages.MessageCal
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exec(final EthMessage message) {
|
public void exec(final EthMessage message) {
|
||||||
final Capability capability = message.getPeer().getConnection().capability(EthProtocol.NAME);
|
|
||||||
final NewPooledTransactionHashesMessage transactionsMessage =
|
|
||||||
NewPooledTransactionHashesMessage.readFrom(message.getData(), capability);
|
|
||||||
final Instant startedAt = now();
|
|
||||||
if (isEnabled.get()) {
|
if (isEnabled.get()) {
|
||||||
|
final Capability capability = message.getPeer().getConnection().capability(EthProtocol.NAME);
|
||||||
|
final NewPooledTransactionHashesMessage transactionsMessage =
|
||||||
|
NewPooledTransactionHashesMessage.readFrom(message.getData(), capability);
|
||||||
|
final Instant startedAt = now();
|
||||||
scheduler.scheduleTxWorkerTask(
|
scheduler.scheduleTxWorkerTask(
|
||||||
() ->
|
() ->
|
||||||
transactionsMessageProcessor.processNewPooledTransactionHashesMessage(
|
transactionsMessageProcessor.processNewPooledTransactionHashesMessage(
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ import java.util.HashMap;
|
|||||||
import java.util.IntSummaryStatistics;
|
import java.util.IntSummaryStatistics;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.OptionalLong;
|
import java.util.OptionalLong;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -77,6 +78,8 @@ import java.util.stream.Collectors;
|
|||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.common.collect.ListMultimap;
|
||||||
|
import com.google.common.collect.Multimaps;
|
||||||
import org.apache.tuweni.bytes.Bytes;
|
import org.apache.tuweni.bytes.Bytes;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -107,8 +110,10 @@ public class TransactionPool implements BlockAddedObserver {
|
|||||||
private final SaveRestoreManager saveRestoreManager = new SaveRestoreManager();
|
private final SaveRestoreManager saveRestoreManager = new SaveRestoreManager();
|
||||||
private final Set<Address> localSenders = ConcurrentHashMap.newKeySet();
|
private final Set<Address> localSenders = ConcurrentHashMap.newKeySet();
|
||||||
private final EthScheduler.OrderedProcessor<BlockAddedEvent> blockAddedEventOrderedProcessor;
|
private final EthScheduler.OrderedProcessor<BlockAddedEvent> blockAddedEventOrderedProcessor;
|
||||||
private final Map<VersionedHash, BlobsWithCommitments.BlobQuad> mapOfBlobsInTransactionPool =
|
private final ListMultimap<VersionedHash, BlobsWithCommitments.BlobQuad>
|
||||||
new HashMap<>();
|
mapOfBlobsInTransactionPool =
|
||||||
|
Multimaps.synchronizedListMultimap(
|
||||||
|
Multimaps.newListMultimap(new HashMap<>(), () -> new ArrayList<>(1)));
|
||||||
|
|
||||||
public TransactionPool(
|
public TransactionPool(
|
||||||
final Supplier<PendingTransactions> pendingTransactionsSupplier,
|
final Supplier<PendingTransactions> pendingTransactionsSupplier,
|
||||||
@@ -660,6 +665,7 @@ public class TransactionPool implements BlockAddedObserver {
|
|||||||
}
|
}
|
||||||
final List<BlobsWithCommitments.BlobQuad> blobQuads =
|
final List<BlobsWithCommitments.BlobQuad> blobQuads =
|
||||||
maybeBlobsWithCommitments.get().getBlobQuads();
|
maybeBlobsWithCommitments.get().getBlobQuads();
|
||||||
|
|
||||||
blobQuads.forEach(bq -> mapOfBlobsInTransactionPool.put(bq.versionedHash(), bq));
|
blobQuads.forEach(bq -> mapOfBlobsInTransactionPool.put(bq.versionedHash(), bq));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -672,15 +678,18 @@ public class TransactionPool implements BlockAddedObserver {
|
|||||||
}
|
}
|
||||||
final List<BlobsWithCommitments.BlobQuad> blobQuads =
|
final List<BlobsWithCommitments.BlobQuad> blobQuads =
|
||||||
maybeBlobsWithCommitments.get().getBlobQuads();
|
maybeBlobsWithCommitments.get().getBlobQuads();
|
||||||
blobQuads.forEach(bq -> mapOfBlobsInTransactionPool.remove(bq.versionedHash()));
|
|
||||||
|
blobQuads.forEach(bq -> mapOfBlobsInTransactionPool.remove(bq.versionedHash(), bq));
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlobsWithCommitments.BlobQuad getBlobQuad(final VersionedHash vh) {
|
public BlobsWithCommitments.BlobQuad getBlobQuad(final VersionedHash vh) {
|
||||||
BlobsWithCommitments.BlobQuad blobQuad = mapOfBlobsInTransactionPool.get(vh);
|
try {
|
||||||
if (blobQuad == null) {
|
// returns an empty list if the key is not present, so getFirst() will throw
|
||||||
blobQuad = cacheForBlobsOfTransactionsAddedToABlock.get(vh);
|
return mapOfBlobsInTransactionPool.get(vh).getFirst();
|
||||||
|
} catch (NoSuchElementException e) {
|
||||||
|
// do nothing
|
||||||
}
|
}
|
||||||
return blobQuad;
|
return cacheForBlobsOfTransactionsAddedToABlock.get(vh);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
|
|||||||
@@ -43,9 +43,10 @@ class TransactionsMessageHandler implements EthMessages.MessageCallback {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exec(final EthMessage message) {
|
public void exec(final EthMessage message) {
|
||||||
final TransactionsMessage transactionsMessage = TransactionsMessage.readFrom(message.getData());
|
|
||||||
final Instant startedAt = now();
|
|
||||||
if (isEnabled.get()) {
|
if (isEnabled.get()) {
|
||||||
|
final TransactionsMessage transactionsMessage =
|
||||||
|
TransactionsMessage.readFrom(message.getData());
|
||||||
|
final Instant startedAt = now();
|
||||||
scheduler.scheduleTxWorkerTask(
|
scheduler.scheduleTxWorkerTask(
|
||||||
() ->
|
() ->
|
||||||
transactionsMessageProcessor.processTransactionsMessage(
|
transactionsMessageProcessor.processTransactionsMessage(
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ public class CompleteTaskStepTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldMarkSnapsyncTaskCompleteWhenData() {
|
public void shouldMarkSnapsyncTaskCompleteWhenData() {
|
||||||
final List<Task<SnapDataRequest>> requests = TaskGenerator.createAccountRequest(true);
|
final List<Task<SnapDataRequest>> requests = TaskGenerator.createAccountRequest(true, false);
|
||||||
requests.stream()
|
requests.stream()
|
||||||
.map(StubTask.class::cast)
|
.map(StubTask.class::cast)
|
||||||
.forEach(
|
.forEach(
|
||||||
@@ -132,7 +132,7 @@ public class CompleteTaskStepTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldMarkSnapsyncTaskAsFailedWhenNoData() {
|
public void shouldMarkSnapsyncTaskAsFailedWhenNoData() {
|
||||||
final List<Task<SnapDataRequest>> requests = TaskGenerator.createAccountRequest(false);
|
final List<Task<SnapDataRequest>> requests = TaskGenerator.createAccountRequest(false, false);
|
||||||
requests.stream()
|
requests.stream()
|
||||||
.map(StubTask.class::cast)
|
.map(StubTask.class::cast)
|
||||||
.forEach(
|
.forEach(
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ package org.hyperledger.besu.ethereum.eth.sync.snapsync;
|
|||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.fail;
|
import static org.assertj.core.api.Assertions.fail;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import org.hyperledger.besu.datatypes.Hash;
|
import org.hyperledger.besu.datatypes.Hash;
|
||||||
@@ -25,12 +28,15 @@ import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.AccountRangeDataR
|
|||||||
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.BytecodeRequest;
|
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.BytecodeRequest;
|
||||||
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.SnapDataRequest;
|
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.SnapDataRequest;
|
||||||
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.StorageRangeDataRequest;
|
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.StorageRangeDataRequest;
|
||||||
|
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.heal.AccountTrieNodeHealingRequest;
|
||||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||||
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
|
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
|
||||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||||
|
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
|
||||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
|
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
|
||||||
import org.hyperledger.besu.services.tasks.Task;
|
import org.hyperledger.besu.services.tasks.Task;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.tuweni.bytes.Bytes;
|
import org.apache.tuweni.bytes.Bytes;
|
||||||
@@ -39,9 +45,12 @@ import org.junit.jupiter.api.Test;
|
|||||||
|
|
||||||
public class PersistDataStepTest {
|
public class PersistDataStepTest {
|
||||||
|
|
||||||
|
private final WorldStateKeyValueStorage worldStateKeyValueStorage =
|
||||||
|
spy(
|
||||||
|
new InMemoryKeyValueStorageProvider()
|
||||||
|
.createWorldStateStorage(DataStorageConfiguration.DEFAULT_CONFIG));
|
||||||
private final WorldStateStorageCoordinator worldStateStorageCoordinator =
|
private final WorldStateStorageCoordinator worldStateStorageCoordinator =
|
||||||
new InMemoryKeyValueStorageProvider()
|
new WorldStateStorageCoordinator(worldStateKeyValueStorage);
|
||||||
.createWorldStateStorageCoordinator(DataStorageConfiguration.DEFAULT_CONFIG);
|
|
||||||
|
|
||||||
private final SnapSyncProcessState snapSyncState = mock(SnapSyncProcessState.class);
|
private final SnapSyncProcessState snapSyncState = mock(SnapSyncProcessState.class);
|
||||||
private final SnapWorldDownloadState downloadState = mock(SnapWorldDownloadState.class);
|
private final SnapWorldDownloadState downloadState = mock(SnapWorldDownloadState.class);
|
||||||
@@ -59,7 +68,7 @@ public class PersistDataStepTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldPersistDataWhenPresent() {
|
public void shouldPersistDataWhenPresent() {
|
||||||
final List<Task<SnapDataRequest>> tasks = TaskGenerator.createAccountRequest(true);
|
final List<Task<SnapDataRequest>> tasks = TaskGenerator.createAccountRequest(true, false);
|
||||||
final List<Task<SnapDataRequest>> result = persistDataStep.persist(tasks);
|
final List<Task<SnapDataRequest>> result = persistDataStep.persist(tasks);
|
||||||
|
|
||||||
assertThat(result).isSameAs(tasks);
|
assertThat(result).isSameAs(tasks);
|
||||||
@@ -67,9 +76,36 @@ public class PersistDataStepTest {
|
|||||||
assertDataPersisted(tasks);
|
assertDataPersisted(tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldPersistTrieNodeHealDataOnlyOnce() {
|
||||||
|
|
||||||
|
final Bytes stateTrieNode =
|
||||||
|
Bytes.fromHexString(
|
||||||
|
"0xe2a0310e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf602");
|
||||||
|
final Hash hash = Hash.hash(stateTrieNode);
|
||||||
|
final Bytes location = Bytes.of(0x02);
|
||||||
|
final AccountTrieNodeHealingRequest accountTrieNodeDataRequest =
|
||||||
|
SnapDataRequest.createAccountTrieNodeDataRequest(hash, location, Collections.emptySet());
|
||||||
|
accountTrieNodeDataRequest.setData(stateTrieNode);
|
||||||
|
|
||||||
|
final BonsaiWorldStateKeyValueStorage.Updater updater =
|
||||||
|
(BonsaiWorldStateKeyValueStorage.Updater) spy(worldStateKeyValueStorage.updater());
|
||||||
|
when(worldStateKeyValueStorage.updater())
|
||||||
|
.thenReturn(updater)
|
||||||
|
.thenReturn(mock(BonsaiWorldStateKeyValueStorage.Updater.class));
|
||||||
|
|
||||||
|
List<Task<SnapDataRequest>> result =
|
||||||
|
persistDataStep.persist(List.of(new StubTask(accountTrieNodeDataRequest)));
|
||||||
|
|
||||||
|
persistDataStep.persist(List.of(new StubTask(accountTrieNodeDataRequest)));
|
||||||
|
|
||||||
|
verify(updater, times(1)).putAccountStateTrieNode(location, hash, stateTrieNode);
|
||||||
|
assertDataPersisted(result);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldSkipPersistDataWhenNoData() {
|
public void shouldSkipPersistDataWhenNoData() {
|
||||||
final List<Task<SnapDataRequest>> tasks = TaskGenerator.createAccountRequest(false);
|
final List<Task<SnapDataRequest>> tasks = TaskGenerator.createAccountRequest(false, false);
|
||||||
final List<Task<SnapDataRequest>> result = persistDataStep.persist(tasks);
|
final List<Task<SnapDataRequest>> result = persistDataStep.persist(tasks);
|
||||||
|
|
||||||
assertThat(result).isSameAs(tasks);
|
assertThat(result).isSameAs(tasks);
|
||||||
@@ -80,6 +116,25 @@ public class PersistDataStepTest {
|
|||||||
.isEmpty();
|
.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldHandleNullTaskElementInTrie() {
|
||||||
|
// Create a StorageRangeDataRequest where taskElement might be null or incomplete
|
||||||
|
List<Task<SnapDataRequest>> tasks = TaskGenerator.createAccountRequest(false, true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<Task<SnapDataRequest>> result = persistDataStep.persist(tasks);
|
||||||
|
|
||||||
|
// check for proper handling of null taskElement
|
||||||
|
assertThat(result).isSameAs(tasks);
|
||||||
|
assertThat(result)
|
||||||
|
.isNotNull(); // Make sure the result isn't null even with the bad taskElement
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
fail(
|
||||||
|
"NullPointerException occurred during persist step, taskElement might be null: "
|
||||||
|
+ e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void assertDataPersisted(final List<Task<SnapDataRequest>> tasks) {
|
private void assertDataPersisted(final List<Task<SnapDataRequest>> tasks) {
|
||||||
tasks.forEach(
|
tasks.forEach(
|
||||||
task -> {
|
task -> {
|
||||||
@@ -110,6 +165,14 @@ public class PersistDataStepTest {
|
|||||||
.getStrategy(BonsaiWorldStateKeyValueStorage.class)
|
.getStrategy(BonsaiWorldStateKeyValueStorage.class)
|
||||||
.getCode(Hash.wrap(data.getCodeHash()), Hash.wrap(data.getAccountHash())))
|
.getCode(Hash.wrap(data.getCodeHash()), Hash.wrap(data.getAccountHash())))
|
||||||
.isPresent();
|
.isPresent();
|
||||||
|
} else if (task.getData() instanceof AccountTrieNodeHealingRequest) {
|
||||||
|
final AccountTrieNodeHealingRequest data =
|
||||||
|
(AccountTrieNodeHealingRequest) task.getData();
|
||||||
|
assertThat(
|
||||||
|
worldStateStorageCoordinator
|
||||||
|
.getStrategy(BonsaiWorldStateKeyValueStorage.class)
|
||||||
|
.getTrieNodeUnsafe(data.getLocation()))
|
||||||
|
.isPresent();
|
||||||
} else {
|
} else {
|
||||||
fail("not expected message");
|
fail("not expected message");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,8 @@ import org.apache.tuweni.bytes.Bytes32;
|
|||||||
|
|
||||||
public class TaskGenerator {
|
public class TaskGenerator {
|
||||||
|
|
||||||
public static List<Task<SnapDataRequest>> createAccountRequest(final boolean withData) {
|
public static List<Task<SnapDataRequest>> createAccountRequest(
|
||||||
|
final boolean withData, final boolean withNullTaskElement) {
|
||||||
|
|
||||||
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage =
|
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage =
|
||||||
new BonsaiWorldStateKeyValueStorage(
|
new BonsaiWorldStateKeyValueStorage(
|
||||||
@@ -91,7 +92,8 @@ public class TaskGenerator {
|
|||||||
rootHash,
|
rootHash,
|
||||||
accountHash,
|
accountHash,
|
||||||
stateTrieAccountValue.getStorageRoot(),
|
stateTrieAccountValue.getStorageRoot(),
|
||||||
withData);
|
withData,
|
||||||
|
withNullTaskElement);
|
||||||
final BytecodeRequest bytecodeRequest =
|
final BytecodeRequest bytecodeRequest =
|
||||||
createBytecodeDataRequest(
|
createBytecodeDataRequest(
|
||||||
worldStateKeyValueStorage,
|
worldStateKeyValueStorage,
|
||||||
@@ -112,7 +114,8 @@ public class TaskGenerator {
|
|||||||
final Hash rootHash,
|
final Hash rootHash,
|
||||||
final Hash accountHash,
|
final Hash accountHash,
|
||||||
final Bytes32 storageRoot,
|
final Bytes32 storageRoot,
|
||||||
final boolean withData) {
|
final boolean withData,
|
||||||
|
final boolean withNullTaskElement) {
|
||||||
|
|
||||||
final RangeStorageEntriesCollector collector =
|
final RangeStorageEntriesCollector collector =
|
||||||
RangeStorageEntriesCollector.createCollector(
|
RangeStorageEntriesCollector.createCollector(
|
||||||
@@ -140,6 +143,11 @@ public class TaskGenerator {
|
|||||||
request.setProofValid(true);
|
request.setProofValid(true);
|
||||||
request.addResponse(null, worldStateProofProvider, slots, new ArrayDeque<>());
|
request.addResponse(null, worldStateProofProvider, slots, new ArrayDeque<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (withNullTaskElement) {
|
||||||
|
// setting isValidProof to true to simulate a null task element.
|
||||||
|
request.setProofValid(true);
|
||||||
|
}
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ package org.hyperledger.besu.ethereum.eth.transactions;
|
|||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
import static java.util.Collections.emptyList;
|
import static java.util.Collections.emptyList;
|
||||||
import static java.util.Collections.singletonList;
|
import static java.util.Collections.singletonList;
|
||||||
import static java.util.stream.Collectors.toList;
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.hyperledger.besu.ethereum.mainnet.ValidationResult.valid;
|
import static org.hyperledger.besu.ethereum.mainnet.ValidationResult.valid;
|
||||||
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.EXCEEDS_BLOCK_GAS_LIMIT;
|
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.EXCEEDS_BLOCK_GAS_LIMIT;
|
||||||
@@ -29,275 +28,55 @@ import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason
|
|||||||
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.TRANSACTION_REPLACEMENT_UNDERPRICED;
|
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.TRANSACTION_REPLACEMENT_UNDERPRICED;
|
||||||
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.TX_FEECAP_EXCEEDED;
|
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.TX_FEECAP_EXCEEDED;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.argThat;
|
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.ArgumentMatchers.nullable;
|
|
||||||
import static org.mockito.Mockito.doNothing;
|
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
|
||||||
import static org.mockito.Mockito.spy;
|
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyNoInteractions;
|
import static org.mockito.Mockito.verifyNoInteractions;
|
||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
import static org.mockito.quality.Strictness.LENIENT;
|
import static org.mockito.quality.Strictness.LENIENT;
|
||||||
|
|
||||||
import org.hyperledger.besu.config.GenesisConfigFile;
|
|
||||||
import org.hyperledger.besu.crypto.KeyPair;
|
|
||||||
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
|
|
||||||
import org.hyperledger.besu.datatypes.Address;
|
import org.hyperledger.besu.datatypes.Address;
|
||||||
import org.hyperledger.besu.datatypes.TransactionType;
|
import org.hyperledger.besu.datatypes.TransactionType;
|
||||||
import org.hyperledger.besu.datatypes.Wei;
|
import org.hyperledger.besu.datatypes.Wei;
|
||||||
import org.hyperledger.besu.ethereum.ProtocolContext;
|
|
||||||
import org.hyperledger.besu.ethereum.chain.BadBlockManager;
|
|
||||||
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
|
|
||||||
import org.hyperledger.besu.ethereum.core.BlobTestFixture;
|
|
||||||
import org.hyperledger.besu.ethereum.core.Block;
|
import org.hyperledger.besu.ethereum.core.Block;
|
||||||
import org.hyperledger.besu.ethereum.core.BlockBody;
|
|
||||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||||
import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder;
|
|
||||||
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
|
|
||||||
import org.hyperledger.besu.ethereum.core.Difficulty;
|
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.PrivacyParameters;
|
|
||||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||||
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
|
|
||||||
import org.hyperledger.besu.ethereum.core.TransactionTestFixture;
|
|
||||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
|
||||||
import org.hyperledger.besu.ethereum.eth.manager.EthPeer;
|
import org.hyperledger.besu.ethereum.eth.manager.EthPeer;
|
||||||
import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager;
|
|
||||||
import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil;
|
import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil;
|
||||||
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
|
|
||||||
import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer;
|
import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer;
|
||||||
import org.hyperledger.besu.ethereum.eth.messages.EthPV65;
|
import org.hyperledger.besu.ethereum.eth.messages.EthPV65;
|
||||||
import org.hyperledger.besu.ethereum.eth.transactions.layered.LayeredTransactionPoolBaseFeeTest;
|
|
||||||
import org.hyperledger.besu.ethereum.eth.transactions.sorter.LegacyTransactionPoolBaseFeeTest;
|
|
||||||
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
|
|
||||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
|
||||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder;
|
|
||||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
|
|
||||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters;
|
|
||||||
import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
|
import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
|
||||||
import org.hyperledger.besu.ethereum.mainnet.TransactionValidatorFactory;
|
|
||||||
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
|
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
|
||||||
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
|
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
|
||||||
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
|
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
|
||||||
import org.hyperledger.besu.evm.account.Account;
|
|
||||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
|
||||||
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
|
|
||||||
import org.hyperledger.besu.plugin.services.MetricsSystem;
|
|
||||||
import org.hyperledger.besu.plugin.services.TransactionPoolValidatorService;
|
import org.hyperledger.besu.plugin.services.TransactionPoolValidatorService;
|
||||||
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionPoolValidator;
|
|
||||||
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionPoolValidatorFactory;
|
|
||||||
import org.hyperledger.besu.testutil.DeterministicEthScheduler;
|
|
||||||
import org.hyperledger.besu.util.number.Percentage;
|
import org.hyperledger.besu.util.number.Percentage;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.BiFunction;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.condition.DisabledIf;
|
import org.junit.jupiter.api.condition.DisabledIf;
|
||||||
import org.junit.jupiter.api.condition.EnabledIf;
|
import org.junit.jupiter.api.condition.EnabledIf;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.Arguments;
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
import org.junit.jupiter.params.provider.ValueSource;
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
import org.mockito.Answers;
|
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.Mock;
|
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
import org.mockito.junit.jupiter.MockitoSettings;
|
import org.mockito.junit.jupiter.MockitoSettings;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
@MockitoSettings(strictness = LENIENT)
|
@MockitoSettings(strictness = LENIENT)
|
||||||
public abstract class AbstractTransactionPoolTest {
|
public abstract class AbstractTransactionPoolTest extends AbstractTransactionPoolTestBase {
|
||||||
|
|
||||||
protected static final KeyPair KEY_PAIR1 =
|
|
||||||
SignatureAlgorithmFactory.getInstance().generateKeyPair();
|
|
||||||
private static final KeyPair KEY_PAIR2 =
|
|
||||||
SignatureAlgorithmFactory.getInstance().generateKeyPair();
|
|
||||||
protected static final Wei BASE_FEE_FLOOR = Wei.of(7L);
|
|
||||||
protected static final Wei DEFAULT_MIN_GAS_PRICE = Wei.of(50L);
|
|
||||||
|
|
||||||
protected final EthScheduler ethScheduler = new DeterministicEthScheduler();
|
|
||||||
|
|
||||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
|
||||||
protected TransactionValidatorFactory transactionValidatorFactory;
|
|
||||||
|
|
||||||
@Mock protected PendingTransactionAddedListener listener;
|
|
||||||
|
|
||||||
@Mock protected TransactionsMessageSender transactionsMessageSender;
|
|
||||||
@Mock protected NewPooledTransactionHashesMessageSender newPooledTransactionHashesMessageSender;
|
|
||||||
@Mock protected ProtocolSpec protocolSpec;
|
|
||||||
|
|
||||||
protected ProtocolSchedule protocolSchedule;
|
|
||||||
|
|
||||||
protected final MetricsSystem metricsSystem = new NoOpMetricsSystem();
|
|
||||||
protected MutableBlockchain blockchain;
|
|
||||||
protected TransactionBroadcaster transactionBroadcaster;
|
|
||||||
|
|
||||||
protected PendingTransactions transactions;
|
|
||||||
protected final Transaction transaction0 = createTransaction(0);
|
|
||||||
protected final Transaction transaction1 = createTransaction(1);
|
|
||||||
protected final Transaction transactionBlob = createBlobTransaction(2);
|
|
||||||
|
|
||||||
protected final Transaction transactionOtherSender = createTransaction(1, KEY_PAIR2);
|
|
||||||
private ExecutionContextTestFixture executionContext;
|
|
||||||
protected ProtocolContext protocolContext;
|
|
||||||
protected TransactionPool transactionPool;
|
|
||||||
protected long blockGasLimit;
|
|
||||||
protected EthProtocolManager ethProtocolManager;
|
|
||||||
protected EthContext ethContext;
|
|
||||||
private PeerTransactionTracker peerTransactionTracker;
|
|
||||||
private ArgumentCaptor<Runnable> syncTaskCapture;
|
|
||||||
|
|
||||||
protected abstract PendingTransactions createPendingTransactions(
|
|
||||||
final TransactionPoolConfiguration poolConfig,
|
|
||||||
final BiFunction<PendingTransaction, PendingTransaction, Boolean>
|
|
||||||
transactionReplacementTester);
|
|
||||||
|
|
||||||
protected TransactionTestFixture createBaseTransactionGasPriceMarket(
|
|
||||||
final int transactionNumber) {
|
|
||||||
return new TransactionTestFixture()
|
|
||||||
.nonce(transactionNumber)
|
|
||||||
.gasLimit(blockGasLimit)
|
|
||||||
.type(TransactionType.FRONTIER);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected TransactionTestFixture createBaseTransactionBaseFeeMarket(final int nonce) {
|
|
||||||
return new TransactionTestFixture()
|
|
||||||
.nonce(nonce)
|
|
||||||
.gasLimit(blockGasLimit)
|
|
||||||
.gasPrice(null)
|
|
||||||
.maxFeePerGas(Optional.of(Wei.of(5000L)))
|
|
||||||
.maxPriorityFeePerGas(Optional.of(Wei.of(1000L)))
|
|
||||||
.type(TransactionType.EIP1559);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract ExecutionContextTestFixture createExecutionContextTestFixture();
|
|
||||||
|
|
||||||
protected static ExecutionContextTestFixture createExecutionContextTestFixtureBaseFeeMarket() {
|
|
||||||
final var genesisConfigFile = GenesisConfigFile.fromResource("/txpool-test-genesis.json");
|
|
||||||
final ProtocolSchedule protocolSchedule =
|
|
||||||
new ProtocolScheduleBuilder(
|
|
||||||
genesisConfigFile.getConfigOptions(),
|
|
||||||
BigInteger.valueOf(1),
|
|
||||||
ProtocolSpecAdapters.create(0, Function.identity()),
|
|
||||||
new PrivacyParameters(),
|
|
||||||
false,
|
|
||||||
EvmConfiguration.DEFAULT,
|
|
||||||
MiningParameters.MINING_DISABLED,
|
|
||||||
new BadBlockManager(),
|
|
||||||
false,
|
|
||||||
new NoOpMetricsSystem())
|
|
||||||
.createProtocolSchedule();
|
|
||||||
final ExecutionContextTestFixture executionContextTestFixture =
|
|
||||||
ExecutionContextTestFixture.builder(genesisConfigFile)
|
|
||||||
.protocolSchedule(protocolSchedule)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
final Block block =
|
|
||||||
new Block(
|
|
||||||
new BlockHeaderTestFixture()
|
|
||||||
.gasLimit(
|
|
||||||
executionContextTestFixture
|
|
||||||
.getBlockchain()
|
|
||||||
.getChainHeadBlock()
|
|
||||||
.getHeader()
|
|
||||||
.getGasLimit())
|
|
||||||
.difficulty(Difficulty.ONE)
|
|
||||||
.baseFeePerGas(Wei.of(10L))
|
|
||||||
.parentHash(executionContextTestFixture.getBlockchain().getChainHeadHash())
|
|
||||||
.number(executionContextTestFixture.getBlockchain().getChainHeadBlockNumber() + 1)
|
|
||||||
.buildHeader(),
|
|
||||||
new BlockBody(List.of(), List.of()));
|
|
||||||
executionContextTestFixture.getBlockchain().appendBlock(block, List.of());
|
|
||||||
|
|
||||||
return executionContextTestFixture;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract FeeMarket getFeeMarket();
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
public void setUp() {
|
|
||||||
executionContext = createExecutionContextTestFixture();
|
|
||||||
protocolContext = executionContext.getProtocolContext();
|
|
||||||
blockchain = executionContext.getBlockchain();
|
|
||||||
when(protocolSpec.getTransactionValidatorFactory()).thenReturn(transactionValidatorFactory);
|
|
||||||
when(protocolSpec.getFeeMarket()).thenReturn(getFeeMarket());
|
|
||||||
protocolSchedule = spy(executionContext.getProtocolSchedule());
|
|
||||||
doReturn(protocolSpec).when(protocolSchedule).getByBlockHeader(any());
|
|
||||||
blockGasLimit = blockchain.getChainHeadBlock().getHeader().getGasLimit();
|
|
||||||
ethProtocolManager = EthProtocolManagerTestUtil.create();
|
|
||||||
ethContext = spy(ethProtocolManager.ethContext());
|
|
||||||
|
|
||||||
final EthScheduler ethScheduler = spy(ethContext.getScheduler());
|
|
||||||
syncTaskCapture = ArgumentCaptor.forClass(Runnable.class);
|
|
||||||
doNothing().when(ethScheduler).scheduleSyncWorkerTask(syncTaskCapture.capture());
|
|
||||||
doReturn(ethScheduler).when(ethContext).getScheduler();
|
|
||||||
|
|
||||||
peerTransactionTracker = new PeerTransactionTracker(ethContext.getEthPeers());
|
|
||||||
transactionBroadcaster =
|
|
||||||
spy(
|
|
||||||
new TransactionBroadcaster(
|
|
||||||
ethContext,
|
|
||||||
peerTransactionTracker,
|
|
||||||
transactionsMessageSender,
|
|
||||||
newPooledTransactionHashesMessageSender));
|
|
||||||
|
|
||||||
transactionPool = createTransactionPool();
|
|
||||||
blockchain.observeBlockAdded(transactionPool);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected TransactionPool createTransactionPool() {
|
|
||||||
return createTransactionPool(b -> b.minGasPrice(Wei.of(2)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private TransactionPool createTransactionPool(
|
|
||||||
final Consumer<ImmutableTransactionPoolConfiguration.Builder> configConsumer) {
|
|
||||||
final ImmutableTransactionPoolConfiguration.Builder configBuilder =
|
|
||||||
ImmutableTransactionPoolConfiguration.builder();
|
|
||||||
configConsumer.accept(configBuilder);
|
|
||||||
final TransactionPoolConfiguration poolConfig = configBuilder.build();
|
|
||||||
|
|
||||||
final TransactionPoolReplacementHandler transactionReplacementHandler =
|
|
||||||
new TransactionPoolReplacementHandler(
|
|
||||||
poolConfig.getPriceBump(), poolConfig.getBlobPriceBump());
|
|
||||||
|
|
||||||
final BiFunction<PendingTransaction, PendingTransaction, Boolean> transactionReplacementTester =
|
|
||||||
(t1, t2) ->
|
|
||||||
transactionReplacementHandler.shouldReplace(
|
|
||||||
t1, t2, protocolContext.getBlockchain().getChainHeadHeader());
|
|
||||||
|
|
||||||
transactions = spy(createPendingTransactions(poolConfig, transactionReplacementTester));
|
|
||||||
|
|
||||||
final TransactionPool txPool =
|
|
||||||
new TransactionPool(
|
|
||||||
() -> transactions,
|
|
||||||
protocolSchedule,
|
|
||||||
protocolContext,
|
|
||||||
transactionBroadcaster,
|
|
||||||
ethContext,
|
|
||||||
new TransactionPoolMetrics(metricsSystem),
|
|
||||||
poolConfig,
|
|
||||||
new BlobCache());
|
|
||||||
txPool.setEnabled();
|
|
||||||
return txPool;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@ValueSource(booleans = {true, false})
|
@ValueSource(booleans = {true, false})
|
||||||
@@ -466,21 +245,21 @@ public abstract class AbstractTransactionPoolTest {
|
|||||||
public void shouldReAddBlobTxsWhenReorgHappens() {
|
public void shouldReAddBlobTxsWhenReorgHappens() {
|
||||||
givenTransactionIsValid(transaction0);
|
givenTransactionIsValid(transaction0);
|
||||||
givenTransactionIsValid(transaction1);
|
givenTransactionIsValid(transaction1);
|
||||||
givenTransactionIsValid(transactionBlob);
|
givenTransactionIsValid(transactionWithBlobs);
|
||||||
|
|
||||||
addAndAssertRemoteTransactionsValid(transaction0);
|
addAndAssertRemoteTransactionsValid(transaction0);
|
||||||
addAndAssertRemoteTransactionsValid(transaction1);
|
addAndAssertRemoteTransactionsValid(transaction1);
|
||||||
addAndAssertRemoteTransactionsValid(transactionBlob);
|
addAndAssertRemoteTransactionsValid(transactionWithBlobs);
|
||||||
|
|
||||||
final BlockHeader commonParent = getHeaderForCurrentChainHead();
|
final BlockHeader commonParent = getHeaderForCurrentChainHead();
|
||||||
final Block originalFork1 = appendBlock(Difficulty.of(1000), commonParent, transaction0);
|
final Block originalFork1 = appendBlock(Difficulty.of(1000), commonParent, transaction0);
|
||||||
final Block originalFork2 =
|
final Block originalFork2 =
|
||||||
appendBlock(Difficulty.of(10), originalFork1.getHeader(), transaction1);
|
appendBlock(Difficulty.of(10), originalFork1.getHeader(), transaction1);
|
||||||
final Block originalFork3 =
|
final Block originalFork3 =
|
||||||
appendBlock(Difficulty.of(1), originalFork2.getHeader(), transactionBlob);
|
appendBlock(Difficulty.of(1), originalFork2.getHeader(), transactionWithBlobs);
|
||||||
assertTransactionNotPending(transaction0);
|
assertTransactionNotPending(transaction0);
|
||||||
assertTransactionNotPending(transaction1);
|
assertTransactionNotPending(transaction1);
|
||||||
assertTransactionNotPending(transactionBlob);
|
assertTransactionNotPending(transactionWithBlobs);
|
||||||
|
|
||||||
final Block reorgFork1 = appendBlock(Difficulty.ONE, commonParent);
|
final Block reorgFork1 = appendBlock(Difficulty.ONE, commonParent);
|
||||||
verifyChainHeadIs(originalFork3);
|
verifyChainHeadIs(originalFork3);
|
||||||
@@ -493,14 +272,15 @@ public abstract class AbstractTransactionPoolTest {
|
|||||||
|
|
||||||
assertTransactionPending(transaction0);
|
assertTransactionPending(transaction0);
|
||||||
assertTransactionPending(transaction1);
|
assertTransactionPending(transaction1);
|
||||||
assertTransactionPending(transactionBlob);
|
assertTransactionPending(transactionWithBlobs);
|
||||||
|
|
||||||
Optional<Transaction> maybeBlob = transactions.getTransactionByHash(transactionBlob.getHash());
|
Optional<Transaction> maybeBlob =
|
||||||
|
transactions.getTransactionByHash(transactionWithBlobs.getHash());
|
||||||
assertThat(maybeBlob).isPresent();
|
assertThat(maybeBlob).isPresent();
|
||||||
Transaction restoredBlob = maybeBlob.get();
|
Transaction restoredBlob = maybeBlob.get();
|
||||||
assertThat(restoredBlob).isEqualTo(transactionBlob);
|
assertThat(restoredBlob).isEqualTo(transactionWithBlobs);
|
||||||
assertThat(restoredBlob.getBlobsWithCommitments().get().getBlobQuads())
|
assertThat(restoredBlob.getBlobsWithCommitments().get().getBlobQuads())
|
||||||
.isEqualTo(transactionBlob.getBlobsWithCommitments().get().getBlobQuads());
|
.isEqualTo(transactionWithBlobs.getBlobsWithCommitments().get().getBlobQuads());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@@ -1281,272 +1061,4 @@ public abstract class AbstractTransactionPoolTest {
|
|||||||
.map(PendingTransaction::getTransaction)
|
.map(PendingTransaction::getTransaction)
|
||||||
.containsExactlyInAnyOrder(transaction1, transaction2a, transaction3);
|
.containsExactlyInAnyOrder(transaction1, transaction2a, transaction3);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TransactionPoolValidatorService getTransactionPoolValidatorServiceReturning(
|
|
||||||
final String errorMessage) {
|
|
||||||
return new TransactionPoolValidatorService() {
|
|
||||||
@Override
|
|
||||||
public PluginTransactionPoolValidator createTransactionValidator() {
|
|
||||||
return (transaction, isLocal, hasPriority) -> Optional.ofNullable(errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerPluginTransactionValidatorFactory(
|
|
||||||
final PluginTransactionPoolValidatorFactory pluginTransactionPoolValidatorFactory) {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private static boolean isBaseFeeMarket(final ExtensionContext extensionContext) {
|
|
||||||
final Class<?> cz = extensionContext.getTestClass().get();
|
|
||||||
|
|
||||||
return cz.equals(LegacyTransactionPoolBaseFeeTest.class)
|
|
||||||
|| cz.equals(LayeredTransactionPoolBaseFeeTest.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void assertTransactionNotPending(final Transaction transaction) {
|
|
||||||
assertThat(transactions.getTransactionByHash(transaction.getHash())).isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addAndAssertRemoteTransactionInvalid(final Transaction tx) {
|
|
||||||
transactionPool.addRemoteTransactions(List.of(tx));
|
|
||||||
|
|
||||||
verify(transactionBroadcaster, never()).onTransactionsAdded(singletonList(tx));
|
|
||||||
assertTransactionNotPending(tx);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void assertTransactionPending(final Transaction t) {
|
|
||||||
assertThat(transactions.getTransactionByHash(t.getHash())).contains(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addAndAssertRemoteTransactionsValid(final Transaction... txs) {
|
|
||||||
addAndAssertRemoteTransactionsValid(false, txs);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addAndAssertRemotePriorityTransactionsValid(final Transaction... txs) {
|
|
||||||
addAndAssertRemoteTransactionsValid(true, txs);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addAndAssertRemoteTransactionsValid(
|
|
||||||
final boolean hasPriority, final Transaction... txs) {
|
|
||||||
transactionPool.addRemoteTransactions(List.of(txs));
|
|
||||||
|
|
||||||
verify(transactionBroadcaster)
|
|
||||||
.onTransactionsAdded(
|
|
||||||
argThat(btxs -> btxs.size() == txs.length && btxs.containsAll(List.of(txs))));
|
|
||||||
Arrays.stream(txs).forEach(this::assertTransactionPending);
|
|
||||||
assertThat(transactions.getLocalTransactions()).doesNotContain(txs);
|
|
||||||
if (hasPriority) {
|
|
||||||
assertThat(transactions.getPriorityTransactions()).contains(txs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addAndAssertTransactionViaApiValid(
|
|
||||||
final Transaction tx, final boolean disableLocalPriority) {
|
|
||||||
final ValidationResult<TransactionInvalidReason> result =
|
|
||||||
transactionPool.addTransactionViaApi(tx);
|
|
||||||
|
|
||||||
assertThat(result.isValid()).isTrue();
|
|
||||||
assertTransactionPending(tx);
|
|
||||||
verify(transactionBroadcaster).onTransactionsAdded(singletonList(tx));
|
|
||||||
assertThat(transactions.getLocalTransactions()).contains(tx);
|
|
||||||
if (disableLocalPriority) {
|
|
||||||
assertThat(transactions.getPriorityTransactions()).doesNotContain(tx);
|
|
||||||
} else {
|
|
||||||
assertThat(transactions.getPriorityTransactions()).contains(tx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addAndAssertTransactionViaApiInvalid(
|
|
||||||
final Transaction tx, final TransactionInvalidReason invalidReason) {
|
|
||||||
final ValidationResult<TransactionInvalidReason> result =
|
|
||||||
transactionPool.addTransactionViaApi(tx);
|
|
||||||
|
|
||||||
assertThat(result.isValid()).isFalse();
|
|
||||||
assertThat(result.getInvalidReason()).isEqualTo(invalidReason);
|
|
||||||
assertTransactionNotPending(tx);
|
|
||||||
verify(transactionBroadcaster, never()).onTransactionsAdded(singletonList(tx));
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected void givenTransactionIsValid(final Transaction transaction) {
|
|
||||||
when(transactionValidatorFactory
|
|
||||||
.get()
|
|
||||||
.validate(eq(transaction), any(Optional.class), any(Optional.class), any()))
|
|
||||||
.thenReturn(valid());
|
|
||||||
when(transactionValidatorFactory
|
|
||||||
.get()
|
|
||||||
.validateForSender(
|
|
||||||
eq(transaction), nullable(Account.class), any(TransactionValidationParams.class)))
|
|
||||||
.thenReturn(valid());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract Block appendBlock(
|
|
||||||
final Difficulty difficulty,
|
|
||||||
final BlockHeader parentBlock,
|
|
||||||
final Transaction... transactionsToAdd);
|
|
||||||
|
|
||||||
protected Transaction createTransactionGasPriceMarket(
|
|
||||||
final int transactionNumber, final Wei maxPrice) {
|
|
||||||
return createBaseTransaction(transactionNumber).gasPrice(maxPrice).createTransaction(KEY_PAIR1);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Transaction createTransactionBaseFeeMarket(final int nonce, final Wei maxPrice) {
|
|
||||||
return createBaseTransaction(nonce)
|
|
||||||
.maxFeePerGas(Optional.of(maxPrice))
|
|
||||||
.maxPriorityFeePerGas(Optional.of(maxPrice.divide(5L)))
|
|
||||||
.createTransaction(KEY_PAIR1);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract TransactionTestFixture createBaseTransaction(final int nonce);
|
|
||||||
|
|
||||||
protected Transaction createTransaction(
|
|
||||||
final int transactionNumber, final Optional<BigInteger> maybeChainId) {
|
|
||||||
return createBaseTransaction(transactionNumber)
|
|
||||||
.chainId(maybeChainId)
|
|
||||||
.createTransaction(KEY_PAIR1);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract Transaction createTransaction(final int nonce, final Wei maxPrice);
|
|
||||||
|
|
||||||
protected Transaction createTransaction(final int nonce) {
|
|
||||||
return createTransaction(nonce, Optional.of(BigInteger.ONE));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Transaction createTransaction(final int nonce, final KeyPair keyPair) {
|
|
||||||
return createBaseTransaction(nonce).createTransaction(keyPair);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void verifyChainHeadIs(final Block forkBlock2) {
|
|
||||||
assertThat(blockchain.getChainHeadHash()).isEqualTo(forkBlock2.getHash());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BlockHeader getHeaderForCurrentChainHead() {
|
|
||||||
return blockchain.getBlockHeader(blockchain.getChainHeadHash()).get();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void appendBlock(final Transaction... transactionsToAdd) {
|
|
||||||
appendBlock(Difficulty.ONE, getHeaderForCurrentChainHead(), transactionsToAdd);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void protocolSupportsTxReplayProtection(
|
|
||||||
final long chainId, final boolean isSupportedAtCurrentBlock) {
|
|
||||||
when(protocolSpec.isReplayProtectionSupported()).thenReturn(isSupportedAtCurrentBlock);
|
|
||||||
when(protocolSchedule.getChainId()).thenReturn(Optional.of(BigInteger.valueOf(chainId)));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void protocolDoesNotSupportTxReplayProtection() {
|
|
||||||
when(protocolSchedule.getChainId()).thenReturn(Optional.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Transaction createTransactionWithoutChainId(final int transactionNumber) {
|
|
||||||
return createTransaction(transactionNumber, Optional.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void whenBlockBaseFeeIs(final Wei baseFee) {
|
|
||||||
final BlockHeader header =
|
|
||||||
BlockHeaderBuilder.fromHeader(blockchain.getChainHeadHeader())
|
|
||||||
.baseFee(baseFee)
|
|
||||||
.blockHeaderFunctions(new MainnetBlockHeaderFunctions())
|
|
||||||
.parentHash(blockchain.getChainHeadHash())
|
|
||||||
.buildBlockHeader();
|
|
||||||
blockchain.appendBlock(new Block(header, BlockBody.empty()), emptyList());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Transaction createFrontierTransaction(final int transactionNumber, final Wei gasPrice) {
|
|
||||||
return new TransactionTestFixture()
|
|
||||||
.nonce(transactionNumber)
|
|
||||||
.gasPrice(gasPrice)
|
|
||||||
.gasLimit(blockGasLimit)
|
|
||||||
.type(TransactionType.FRONTIER)
|
|
||||||
.createTransaction(KEY_PAIR1);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Transaction createBlobTransaction(final int nonce) {
|
|
||||||
return new TransactionTestFixture()
|
|
||||||
.nonce(nonce)
|
|
||||||
.gasLimit(blockGasLimit)
|
|
||||||
.gasPrice(null)
|
|
||||||
.maxFeePerGas(Optional.of(Wei.of(5000L)))
|
|
||||||
.maxPriorityFeePerGas(Optional.of(Wei.of(1000L)))
|
|
||||||
.type(TransactionType.BLOB)
|
|
||||||
.blobsWithCommitments(Optional.of(new BlobTestFixture().createBlobsWithCommitments(6)))
|
|
||||||
.createTransaction(KEY_PAIR1);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int addTxAndGetPendingTxsCount(
|
|
||||||
final Wei genesisBaseFee,
|
|
||||||
final Wei minGasPrice,
|
|
||||||
final Wei lastBlockBaseFee,
|
|
||||||
final Wei txMaxFeePerGas,
|
|
||||||
final boolean isLocal,
|
|
||||||
final boolean hasPriority) {
|
|
||||||
when(protocolSpec.getFeeMarket()).thenReturn(FeeMarket.london(0, Optional.of(genesisBaseFee)));
|
|
||||||
whenBlockBaseFeeIs(lastBlockBaseFee);
|
|
||||||
|
|
||||||
final Transaction transaction = createTransaction(0, txMaxFeePerGas);
|
|
||||||
if (hasPriority) {
|
|
||||||
transactionPool =
|
|
||||||
createTransactionPool(
|
|
||||||
b -> b.minGasPrice(minGasPrice).prioritySenders(Set.of(transaction.getSender())));
|
|
||||||
} else {
|
|
||||||
transactionPool =
|
|
||||||
createTransactionPool(b -> b.minGasPrice(minGasPrice).noLocalPriority(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
givenTransactionIsValid(transaction);
|
|
||||||
|
|
||||||
if (isLocal) {
|
|
||||||
transactionPool.addTransactionViaApi(transaction);
|
|
||||||
} else {
|
|
||||||
transactionPool.addRemoteTransactions(List.of(transaction));
|
|
||||||
}
|
|
||||||
|
|
||||||
return transactions.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Block appendBlockGasPriceMarket(
|
|
||||||
final Difficulty difficulty,
|
|
||||||
final BlockHeader parentBlock,
|
|
||||||
final Transaction[] transactionsToAdd) {
|
|
||||||
final List<Transaction> transactionList = asList(transactionsToAdd);
|
|
||||||
final Block block =
|
|
||||||
new Block(
|
|
||||||
new BlockHeaderTestFixture()
|
|
||||||
.difficulty(difficulty)
|
|
||||||
.gasLimit(parentBlock.getGasLimit())
|
|
||||||
.parentHash(parentBlock.getHash())
|
|
||||||
.number(parentBlock.getNumber() + 1)
|
|
||||||
.buildHeader(),
|
|
||||||
new BlockBody(transactionList, emptyList()));
|
|
||||||
final List<TransactionReceipt> transactionReceipts =
|
|
||||||
transactionList.stream()
|
|
||||||
.map(transaction -> new TransactionReceipt(1, 1, emptyList(), Optional.empty()))
|
|
||||||
.collect(toList());
|
|
||||||
blockchain.appendBlock(block, transactionReceipts);
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Block appendBlockBaseFeeMarket(
|
|
||||||
final Difficulty difficulty,
|
|
||||||
final BlockHeader parentBlock,
|
|
||||||
final Transaction[] transactionsToAdd) {
|
|
||||||
final List<Transaction> transactionList = asList(transactionsToAdd);
|
|
||||||
final Block block =
|
|
||||||
new Block(
|
|
||||||
new BlockHeaderTestFixture()
|
|
||||||
.baseFeePerGas(Wei.of(10L))
|
|
||||||
.gasLimit(parentBlock.getGasLimit())
|
|
||||||
.difficulty(difficulty)
|
|
||||||
.parentHash(parentBlock.getHash())
|
|
||||||
.number(parentBlock.getNumber() + 1)
|
|
||||||
.buildHeader(),
|
|
||||||
new BlockBody(transactionList, emptyList()));
|
|
||||||
final List<TransactionReceipt> transactionReceipts =
|
|
||||||
transactionList.stream()
|
|
||||||
.map(transaction -> new TransactionReceipt(1, 1, emptyList(), Optional.empty()))
|
|
||||||
.collect(toList());
|
|
||||||
blockchain.appendBlock(block, transactionReceipts);
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,585 @@
|
|||||||
|
/*
|
||||||
|
* 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.eth.transactions;
|
||||||
|
|
||||||
|
import static java.util.Arrays.asList;
|
||||||
|
import static java.util.Collections.emptyList;
|
||||||
|
import static java.util.Collections.singletonList;
|
||||||
|
import static java.util.stream.Collectors.toList;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.hyperledger.besu.ethereum.mainnet.ValidationResult.valid;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.argThat;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.ArgumentMatchers.nullable;
|
||||||
|
import static org.mockito.Mockito.doNothing;
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
import static org.mockito.quality.Strictness.LENIENT;
|
||||||
|
|
||||||
|
import org.hyperledger.besu.config.GenesisConfigFile;
|
||||||
|
import org.hyperledger.besu.crypto.KeyPair;
|
||||||
|
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
|
||||||
|
import org.hyperledger.besu.datatypes.BlobsWithCommitments;
|
||||||
|
import org.hyperledger.besu.datatypes.TransactionType;
|
||||||
|
import org.hyperledger.besu.datatypes.Wei;
|
||||||
|
import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||||
|
import org.hyperledger.besu.ethereum.chain.BadBlockManager;
|
||||||
|
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
|
||||||
|
import org.hyperledger.besu.ethereum.core.BlobTestFixture;
|
||||||
|
import org.hyperledger.besu.ethereum.core.Block;
|
||||||
|
import org.hyperledger.besu.ethereum.core.BlockBody;
|
||||||
|
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||||
|
import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder;
|
||||||
|
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.PrivacyParameters;
|
||||||
|
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||||
|
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
|
||||||
|
import org.hyperledger.besu.ethereum.core.TransactionTestFixture;
|
||||||
|
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||||
|
import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager;
|
||||||
|
import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil;
|
||||||
|
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
|
||||||
|
import org.hyperledger.besu.ethereum.eth.transactions.layered.LayeredTransactionPoolBaseFeeTest;
|
||||||
|
import org.hyperledger.besu.ethereum.eth.transactions.sorter.LegacyTransactionPoolBaseFeeTest;
|
||||||
|
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
|
||||||
|
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||||
|
import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder;
|
||||||
|
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
|
||||||
|
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters;
|
||||||
|
import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
|
||||||
|
import org.hyperledger.besu.ethereum.mainnet.TransactionValidatorFactory;
|
||||||
|
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
|
||||||
|
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
|
||||||
|
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
|
||||||
|
import org.hyperledger.besu.evm.account.Account;
|
||||||
|
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||||
|
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
|
||||||
|
import org.hyperledger.besu.plugin.services.MetricsSystem;
|
||||||
|
import org.hyperledger.besu.plugin.services.TransactionPoolValidatorService;
|
||||||
|
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionPoolValidator;
|
||||||
|
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionPoolValidatorFactory;
|
||||||
|
import org.hyperledger.besu.testutil.DeterministicEthScheduler;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||||
|
import org.mockito.Answers;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
import org.mockito.junit.jupiter.MockitoSettings;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
@MockitoSettings(strictness = LENIENT)
|
||||||
|
public abstract class AbstractTransactionPoolTestBase {
|
||||||
|
|
||||||
|
protected static final KeyPair KEY_PAIR1 =
|
||||||
|
SignatureAlgorithmFactory.getInstance().generateKeyPair();
|
||||||
|
private static final KeyPair KEY_PAIR2 =
|
||||||
|
SignatureAlgorithmFactory.getInstance().generateKeyPair();
|
||||||
|
protected static final Wei BASE_FEE_FLOOR = Wei.of(7L);
|
||||||
|
protected static final Wei DEFAULT_MIN_GAS_PRICE = Wei.of(50L);
|
||||||
|
|
||||||
|
protected final EthScheduler ethScheduler = new DeterministicEthScheduler();
|
||||||
|
|
||||||
|
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||||
|
protected TransactionValidatorFactory transactionValidatorFactory;
|
||||||
|
|
||||||
|
@Mock protected PendingTransactionAddedListener listener;
|
||||||
|
|
||||||
|
@Mock protected TransactionsMessageSender transactionsMessageSender;
|
||||||
|
@Mock protected NewPooledTransactionHashesMessageSender newPooledTransactionHashesMessageSender;
|
||||||
|
@Mock protected ProtocolSpec protocolSpec;
|
||||||
|
|
||||||
|
protected ProtocolSchedule protocolSchedule;
|
||||||
|
|
||||||
|
protected final MetricsSystem metricsSystem = new NoOpMetricsSystem();
|
||||||
|
protected MutableBlockchain blockchain;
|
||||||
|
protected TransactionBroadcaster transactionBroadcaster;
|
||||||
|
|
||||||
|
protected PendingTransactions transactions;
|
||||||
|
protected final Transaction transaction0 = createTransaction(0);
|
||||||
|
protected final Transaction transaction1 = createTransaction(1);
|
||||||
|
protected final Transaction transactionWithBlobs = createBlobTransaction(2);
|
||||||
|
protected final Transaction transactionWithBlobsReplacement =
|
||||||
|
createReplacementTransactionWithBlobs(2);
|
||||||
|
protected final Transaction transactionWithSameBlobs =
|
||||||
|
createBlobTransactionWithSameBlobs(3, transactionWithBlobs.getBlobsWithCommitments().get());
|
||||||
|
protected final Transaction transactionWithSameBlobsReplacement =
|
||||||
|
createReplacementTransactionWithBlobs(3);
|
||||||
|
|
||||||
|
protected final Transaction transactionOtherSender = createTransaction(1, KEY_PAIR2);
|
||||||
|
private ExecutionContextTestFixture executionContext;
|
||||||
|
protected ProtocolContext protocolContext;
|
||||||
|
protected TransactionPool transactionPool;
|
||||||
|
protected long blockGasLimit;
|
||||||
|
protected EthProtocolManager ethProtocolManager;
|
||||||
|
protected EthContext ethContext;
|
||||||
|
protected ArgumentCaptor<Runnable> syncTaskCapture;
|
||||||
|
protected PeerTransactionTracker peerTransactionTracker;
|
||||||
|
private BlobTestFixture blobTestFixture;
|
||||||
|
|
||||||
|
protected abstract PendingTransactions createPendingTransactions(
|
||||||
|
final TransactionPoolConfiguration poolConfig,
|
||||||
|
final BiFunction<PendingTransaction, PendingTransaction, Boolean>
|
||||||
|
transactionReplacementTester);
|
||||||
|
|
||||||
|
protected TransactionTestFixture createBaseTransactionGasPriceMarket(
|
||||||
|
final int transactionNumber) {
|
||||||
|
return new TransactionTestFixture()
|
||||||
|
.nonce(transactionNumber)
|
||||||
|
.gasLimit(blockGasLimit)
|
||||||
|
.type(TransactionType.FRONTIER);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TransactionTestFixture createBaseTransactionBaseFeeMarket(final int nonce) {
|
||||||
|
return new TransactionTestFixture()
|
||||||
|
.nonce(nonce)
|
||||||
|
.gasLimit(blockGasLimit)
|
||||||
|
.gasPrice(null)
|
||||||
|
.maxFeePerGas(Optional.of(Wei.of(5000L)))
|
||||||
|
.maxPriorityFeePerGas(Optional.of(Wei.of(1000L)))
|
||||||
|
.type(TransactionType.EIP1559);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract ExecutionContextTestFixture createExecutionContextTestFixture();
|
||||||
|
|
||||||
|
protected static ExecutionContextTestFixture createExecutionContextTestFixtureBaseFeeMarket() {
|
||||||
|
final var genesisConfigFile = GenesisConfigFile.fromResource("/txpool-test-genesis.json");
|
||||||
|
final ProtocolSchedule protocolSchedule =
|
||||||
|
new ProtocolScheduleBuilder(
|
||||||
|
genesisConfigFile.getConfigOptions(),
|
||||||
|
BigInteger.valueOf(1),
|
||||||
|
ProtocolSpecAdapters.create(0, Function.identity()),
|
||||||
|
new PrivacyParameters(),
|
||||||
|
false,
|
||||||
|
EvmConfiguration.DEFAULT,
|
||||||
|
MiningParameters.MINING_DISABLED,
|
||||||
|
new BadBlockManager(),
|
||||||
|
false,
|
||||||
|
new NoOpMetricsSystem())
|
||||||
|
.createProtocolSchedule();
|
||||||
|
final ExecutionContextTestFixture executionContextTestFixture =
|
||||||
|
ExecutionContextTestFixture.builder(genesisConfigFile)
|
||||||
|
.protocolSchedule(protocolSchedule)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final Block block =
|
||||||
|
new Block(
|
||||||
|
new BlockHeaderTestFixture()
|
||||||
|
.gasLimit(
|
||||||
|
executionContextTestFixture
|
||||||
|
.getBlockchain()
|
||||||
|
.getChainHeadBlock()
|
||||||
|
.getHeader()
|
||||||
|
.getGasLimit())
|
||||||
|
.difficulty(Difficulty.ONE)
|
||||||
|
.baseFeePerGas(Wei.of(10L))
|
||||||
|
.parentHash(executionContextTestFixture.getBlockchain().getChainHeadHash())
|
||||||
|
.number(executionContextTestFixture.getBlockchain().getChainHeadBlockNumber() + 1)
|
||||||
|
.buildHeader(),
|
||||||
|
new BlockBody(List.of(), List.of()));
|
||||||
|
executionContextTestFixture.getBlockchain().appendBlock(block, List.of());
|
||||||
|
|
||||||
|
return executionContextTestFixture;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract FeeMarket getFeeMarket();
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setUp() {
|
||||||
|
executionContext = createExecutionContextTestFixture();
|
||||||
|
protocolContext = executionContext.getProtocolContext();
|
||||||
|
blockchain = executionContext.getBlockchain();
|
||||||
|
when(protocolSpec.getTransactionValidatorFactory()).thenReturn(transactionValidatorFactory);
|
||||||
|
when(protocolSpec.getFeeMarket()).thenReturn(getFeeMarket());
|
||||||
|
protocolSchedule = spy(executionContext.getProtocolSchedule());
|
||||||
|
doReturn(protocolSpec).when(protocolSchedule).getByBlockHeader(any());
|
||||||
|
blockGasLimit = blockchain.getChainHeadBlock().getHeader().getGasLimit();
|
||||||
|
ethProtocolManager = EthProtocolManagerTestUtil.create();
|
||||||
|
ethContext = spy(ethProtocolManager.ethContext());
|
||||||
|
|
||||||
|
final EthScheduler ethScheduler = spy(ethContext.getScheduler());
|
||||||
|
syncTaskCapture = ArgumentCaptor.forClass(Runnable.class);
|
||||||
|
doNothing().when(ethScheduler).scheduleSyncWorkerTask(syncTaskCapture.capture());
|
||||||
|
doReturn(ethScheduler).when(ethContext).getScheduler();
|
||||||
|
|
||||||
|
peerTransactionTracker = new PeerTransactionTracker(ethContext.getEthPeers());
|
||||||
|
transactionBroadcaster =
|
||||||
|
spy(
|
||||||
|
new TransactionBroadcaster(
|
||||||
|
ethContext,
|
||||||
|
peerTransactionTracker,
|
||||||
|
transactionsMessageSender,
|
||||||
|
newPooledTransactionHashesMessageSender));
|
||||||
|
|
||||||
|
transactionPool = createTransactionPool();
|
||||||
|
blockchain.observeBlockAdded(transactionPool);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TransactionPool createTransactionPool() {
|
||||||
|
return createTransactionPool(b -> b.minGasPrice(Wei.of(2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionPool createTransactionPool(
|
||||||
|
final Consumer<ImmutableTransactionPoolConfiguration.Builder> configConsumer) {
|
||||||
|
final ImmutableTransactionPoolConfiguration.Builder configBuilder =
|
||||||
|
ImmutableTransactionPoolConfiguration.builder();
|
||||||
|
configConsumer.accept(configBuilder);
|
||||||
|
final TransactionPoolConfiguration poolConfig = configBuilder.build();
|
||||||
|
|
||||||
|
final TransactionPoolReplacementHandler transactionReplacementHandler =
|
||||||
|
new TransactionPoolReplacementHandler(
|
||||||
|
poolConfig.getPriceBump(), poolConfig.getBlobPriceBump());
|
||||||
|
|
||||||
|
final BiFunction<PendingTransaction, PendingTransaction, Boolean> transactionReplacementTester =
|
||||||
|
(t1, t2) ->
|
||||||
|
transactionReplacementHandler.shouldReplace(
|
||||||
|
t1, t2, protocolContext.getBlockchain().getChainHeadHeader());
|
||||||
|
|
||||||
|
transactions = spy(createPendingTransactions(poolConfig, transactionReplacementTester));
|
||||||
|
|
||||||
|
final TransactionPool txPool =
|
||||||
|
new TransactionPool(
|
||||||
|
() -> transactions,
|
||||||
|
protocolSchedule,
|
||||||
|
protocolContext,
|
||||||
|
transactionBroadcaster,
|
||||||
|
ethContext,
|
||||||
|
new TransactionPoolMetrics(metricsSystem),
|
||||||
|
poolConfig,
|
||||||
|
new BlobCache());
|
||||||
|
txPool.setEnabled();
|
||||||
|
return txPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TransactionPoolValidatorService getTransactionPoolValidatorServiceReturning(
|
||||||
|
final String errorMessage) {
|
||||||
|
return new TransactionPoolValidatorService() {
|
||||||
|
@Override
|
||||||
|
public PluginTransactionPoolValidator createTransactionValidator() {
|
||||||
|
return (transaction, isLocal, hasPriority) -> Optional.ofNullable(errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerPluginTransactionValidatorFactory(
|
||||||
|
final PluginTransactionPoolValidatorFactory pluginTransactionPoolValidatorFactory) {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private static boolean isBaseFeeMarket(final ExtensionContext extensionContext) {
|
||||||
|
final Class<?> cz = extensionContext.getTestClass().get();
|
||||||
|
|
||||||
|
return cz.equals(LegacyTransactionPoolBaseFeeTest.class)
|
||||||
|
|| cz.equals(LayeredTransactionPoolBaseFeeTest.class)
|
||||||
|
|| cz.equals(BlobV1TransactionPoolTest.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void assertTransactionNotPending(final Transaction transaction) {
|
||||||
|
assertThat(transactions.getTransactionByHash(transaction.getHash())).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addAndAssertRemoteTransactionInvalid(final Transaction tx) {
|
||||||
|
transactionPool.addRemoteTransactions(List.of(tx));
|
||||||
|
|
||||||
|
verify(transactionBroadcaster, never()).onTransactionsAdded(singletonList(tx));
|
||||||
|
assertTransactionNotPending(tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void assertTransactionPending(final Transaction t) {
|
||||||
|
assertThat(transactions.getTransactionByHash(t.getHash())).contains(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addAndAssertRemoteTransactionsValid(final Transaction... txs) {
|
||||||
|
addAndAssertRemoteTransactionsValid(false, txs);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addAndAssertRemotePriorityTransactionsValid(final Transaction... txs) {
|
||||||
|
addAndAssertRemoteTransactionsValid(true, txs);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addAndAssertRemoteTransactionsValid(
|
||||||
|
final boolean hasPriority, final Transaction... txs) {
|
||||||
|
transactionPool.addRemoteTransactions(List.of(txs));
|
||||||
|
|
||||||
|
verify(transactionBroadcaster)
|
||||||
|
.onTransactionsAdded(
|
||||||
|
argThat(btxs -> btxs.size() == txs.length && btxs.containsAll(List.of(txs))));
|
||||||
|
Arrays.stream(txs).forEach(this::assertTransactionPending);
|
||||||
|
assertThat(transactions.getLocalTransactions()).doesNotContain(txs);
|
||||||
|
if (hasPriority) {
|
||||||
|
assertThat(transactions.getPriorityTransactions()).contains(txs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addAndAssertTransactionViaApiValid(
|
||||||
|
final Transaction tx, final boolean disableLocalPriority) {
|
||||||
|
final ValidationResult<TransactionInvalidReason> result =
|
||||||
|
transactionPool.addTransactionViaApi(tx);
|
||||||
|
|
||||||
|
assertThat(result.isValid()).isTrue();
|
||||||
|
assertTransactionPending(tx);
|
||||||
|
verify(transactionBroadcaster).onTransactionsAdded(singletonList(tx));
|
||||||
|
assertThat(transactions.getLocalTransactions()).contains(tx);
|
||||||
|
if (disableLocalPriority) {
|
||||||
|
assertThat(transactions.getPriorityTransactions()).doesNotContain(tx);
|
||||||
|
} else {
|
||||||
|
assertThat(transactions.getPriorityTransactions()).contains(tx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addAndAssertTransactionViaApiInvalid(
|
||||||
|
final Transaction tx, final TransactionInvalidReason invalidReason) {
|
||||||
|
final ValidationResult<TransactionInvalidReason> result =
|
||||||
|
transactionPool.addTransactionViaApi(tx);
|
||||||
|
|
||||||
|
assertThat(result.isValid()).isFalse();
|
||||||
|
assertThat(result.getInvalidReason()).isEqualTo(invalidReason);
|
||||||
|
assertTransactionNotPending(tx);
|
||||||
|
verify(transactionBroadcaster, never()).onTransactionsAdded(singletonList(tx));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected void givenTransactionIsValid(final Transaction transaction) {
|
||||||
|
when(transactionValidatorFactory
|
||||||
|
.get()
|
||||||
|
.validate(eq(transaction), any(Optional.class), any(Optional.class), any()))
|
||||||
|
.thenReturn(valid());
|
||||||
|
when(transactionValidatorFactory
|
||||||
|
.get()
|
||||||
|
.validateForSender(
|
||||||
|
eq(transaction), nullable(Account.class), any(TransactionValidationParams.class)))
|
||||||
|
.thenReturn(valid());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Block appendBlock(
|
||||||
|
final Difficulty difficulty,
|
||||||
|
final BlockHeader parentBlock,
|
||||||
|
final Transaction... transactionsToAdd);
|
||||||
|
|
||||||
|
protected Transaction createTransactionGasPriceMarket(
|
||||||
|
final int transactionNumber, final Wei maxPrice) {
|
||||||
|
return createBaseTransaction(transactionNumber).gasPrice(maxPrice).createTransaction(KEY_PAIR1);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Transaction createTransactionBaseFeeMarket(final int nonce, final Wei maxPrice) {
|
||||||
|
return createBaseTransaction(nonce)
|
||||||
|
.maxFeePerGas(Optional.of(maxPrice))
|
||||||
|
.maxPriorityFeePerGas(Optional.of(maxPrice.divide(5L)))
|
||||||
|
.createTransaction(KEY_PAIR1);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract TransactionTestFixture createBaseTransaction(final int nonce);
|
||||||
|
|
||||||
|
protected Transaction createTransaction(
|
||||||
|
final int transactionNumber, final Optional<BigInteger> maybeChainId) {
|
||||||
|
return createBaseTransaction(transactionNumber)
|
||||||
|
.chainId(maybeChainId)
|
||||||
|
.createTransaction(KEY_PAIR1);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Transaction createTransaction(final int nonce, final Wei maxPrice);
|
||||||
|
|
||||||
|
protected Transaction createTransaction(final int nonce) {
|
||||||
|
return createTransaction(nonce, Optional.of(BigInteger.ONE));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Transaction createTransaction(final int nonce, final KeyPair keyPair) {
|
||||||
|
return createBaseTransaction(nonce).createTransaction(keyPair);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void verifyChainHeadIs(final Block forkBlock2) {
|
||||||
|
assertThat(blockchain.getChainHeadHash()).isEqualTo(forkBlock2.getHash());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BlockHeader getHeaderForCurrentChainHead() {
|
||||||
|
return blockchain.getBlockHeader(blockchain.getChainHeadHash()).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void appendBlock(final Transaction... transactionsToAdd) {
|
||||||
|
appendBlock(Difficulty.ONE, getHeaderForCurrentChainHead(), transactionsToAdd);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void protocolSupportsTxReplayProtection(
|
||||||
|
final long chainId, final boolean isSupportedAtCurrentBlock) {
|
||||||
|
when(protocolSpec.isReplayProtectionSupported()).thenReturn(isSupportedAtCurrentBlock);
|
||||||
|
when(protocolSchedule.getChainId()).thenReturn(Optional.of(BigInteger.valueOf(chainId)));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void protocolDoesNotSupportTxReplayProtection() {
|
||||||
|
when(protocolSchedule.getChainId()).thenReturn(Optional.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Transaction createTransactionWithoutChainId(final int transactionNumber) {
|
||||||
|
return createTransaction(transactionNumber, Optional.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void whenBlockBaseFeeIs(final Wei baseFee) {
|
||||||
|
final BlockHeader header =
|
||||||
|
BlockHeaderBuilder.fromHeader(blockchain.getChainHeadHeader())
|
||||||
|
.baseFee(baseFee)
|
||||||
|
.blockHeaderFunctions(new MainnetBlockHeaderFunctions())
|
||||||
|
.parentHash(blockchain.getChainHeadHash())
|
||||||
|
.buildBlockHeader();
|
||||||
|
blockchain.appendBlock(new Block(header, BlockBody.empty()), emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Transaction createFrontierTransaction(final int transactionNumber, final Wei gasPrice) {
|
||||||
|
return new TransactionTestFixture()
|
||||||
|
.nonce(transactionNumber)
|
||||||
|
.gasPrice(gasPrice)
|
||||||
|
.gasLimit(blockGasLimit)
|
||||||
|
.type(TransactionType.FRONTIER)
|
||||||
|
.createTransaction(KEY_PAIR1);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Transaction createBlobTransaction(final int nonce) {
|
||||||
|
if (blobTestFixture == null) {
|
||||||
|
blobTestFixture = new BlobTestFixture();
|
||||||
|
}
|
||||||
|
return new TransactionTestFixture()
|
||||||
|
.nonce(nonce)
|
||||||
|
.gasLimit(blockGasLimit)
|
||||||
|
.gasPrice(null)
|
||||||
|
.maxFeePerGas(Optional.of(Wei.of(5000L)))
|
||||||
|
.maxPriorityFeePerGas(Optional.of(Wei.of(1000L)))
|
||||||
|
.type(TransactionType.BLOB)
|
||||||
|
.blobsWithCommitments(Optional.of(blobTestFixture.createBlobsWithCommitments(6)))
|
||||||
|
.createTransaction(KEY_PAIR1);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Transaction createBlobTransactionWithSameBlobs(
|
||||||
|
final int nonce, final BlobsWithCommitments blobsWithCommitments) {
|
||||||
|
return new TransactionTestFixture()
|
||||||
|
.nonce(nonce)
|
||||||
|
.gasLimit(blockGasLimit)
|
||||||
|
.gasPrice(null)
|
||||||
|
.maxFeePerGas(Optional.of(Wei.of(5000L)))
|
||||||
|
.maxPriorityFeePerGas(Optional.of(Wei.of(1000L)))
|
||||||
|
.type(TransactionType.BLOB)
|
||||||
|
.blobsWithCommitments(Optional.of(blobsWithCommitments))
|
||||||
|
.createTransaction(KEY_PAIR1);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Transaction createReplacementTransactionWithBlobs(final int nonce) {
|
||||||
|
if (blobTestFixture == null) {
|
||||||
|
blobTestFixture = new BlobTestFixture();
|
||||||
|
}
|
||||||
|
return new TransactionTestFixture()
|
||||||
|
.nonce(nonce)
|
||||||
|
.gasLimit(blockGasLimit)
|
||||||
|
.gasPrice(null)
|
||||||
|
.maxFeePerGas(Optional.of(Wei.of(5000L * 10)))
|
||||||
|
.maxPriorityFeePerGas(Optional.of(Wei.of(1000L * 10)))
|
||||||
|
.maxFeePerBlobGas(Optional.of(Wei.of(5000L)))
|
||||||
|
.type(TransactionType.BLOB)
|
||||||
|
.blobsWithCommitments(Optional.of(blobTestFixture.createBlobsWithCommitments(6)))
|
||||||
|
.createTransaction(KEY_PAIR1);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int addTxAndGetPendingTxsCount(
|
||||||
|
final Wei genesisBaseFee,
|
||||||
|
final Wei minGasPrice,
|
||||||
|
final Wei lastBlockBaseFee,
|
||||||
|
final Wei txMaxFeePerGas,
|
||||||
|
final boolean isLocal,
|
||||||
|
final boolean hasPriority) {
|
||||||
|
when(protocolSpec.getFeeMarket()).thenReturn(FeeMarket.london(0, Optional.of(genesisBaseFee)));
|
||||||
|
whenBlockBaseFeeIs(lastBlockBaseFee);
|
||||||
|
|
||||||
|
final Transaction transaction = createTransaction(0, txMaxFeePerGas);
|
||||||
|
if (hasPriority) {
|
||||||
|
transactionPool =
|
||||||
|
createTransactionPool(
|
||||||
|
b -> b.minGasPrice(minGasPrice).prioritySenders(Set.of(transaction.getSender())));
|
||||||
|
} else {
|
||||||
|
transactionPool =
|
||||||
|
createTransactionPool(b -> b.minGasPrice(minGasPrice).noLocalPriority(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
givenTransactionIsValid(transaction);
|
||||||
|
|
||||||
|
if (isLocal) {
|
||||||
|
transactionPool.addTransactionViaApi(transaction);
|
||||||
|
} else {
|
||||||
|
transactionPool.addRemoteTransactions(List.of(transaction));
|
||||||
|
}
|
||||||
|
|
||||||
|
return transactions.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Block appendBlockGasPriceMarket(
|
||||||
|
final Difficulty difficulty,
|
||||||
|
final BlockHeader parentBlock,
|
||||||
|
final Transaction[] transactionsToAdd) {
|
||||||
|
final List<Transaction> transactionList = asList(transactionsToAdd);
|
||||||
|
final Block block =
|
||||||
|
new Block(
|
||||||
|
new BlockHeaderTestFixture()
|
||||||
|
.difficulty(difficulty)
|
||||||
|
.gasLimit(parentBlock.getGasLimit())
|
||||||
|
.parentHash(parentBlock.getHash())
|
||||||
|
.number(parentBlock.getNumber() + 1)
|
||||||
|
.buildHeader(),
|
||||||
|
new BlockBody(transactionList, emptyList()));
|
||||||
|
final List<TransactionReceipt> transactionReceipts =
|
||||||
|
transactionList.stream()
|
||||||
|
.map(transaction -> new TransactionReceipt(1, 1, emptyList(), Optional.empty()))
|
||||||
|
.collect(toList());
|
||||||
|
blockchain.appendBlock(block, transactionReceipts);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Block appendBlockBaseFeeMarket(
|
||||||
|
final Difficulty difficulty,
|
||||||
|
final BlockHeader parentBlock,
|
||||||
|
final Transaction[] transactionsToAdd) {
|
||||||
|
final List<Transaction> transactionList = asList(transactionsToAdd);
|
||||||
|
final Block block =
|
||||||
|
new Block(
|
||||||
|
new BlockHeaderTestFixture()
|
||||||
|
.baseFeePerGas(Wei.of(10L))
|
||||||
|
.gasLimit(parentBlock.getGasLimit())
|
||||||
|
.difficulty(difficulty)
|
||||||
|
.parentHash(parentBlock.getHash())
|
||||||
|
.number(parentBlock.getNumber() + 1)
|
||||||
|
.buildHeader(),
|
||||||
|
new BlockBody(transactionList, emptyList()));
|
||||||
|
final List<TransactionReceipt> transactionReceipts =
|
||||||
|
transactionList.stream()
|
||||||
|
.map(transaction -> new TransactionReceipt(1, 1, emptyList(), Optional.empty()))
|
||||||
|
.collect(toList());
|
||||||
|
blockchain.appendBlock(block, transactionReceipts);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* 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.eth.transactions;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import org.hyperledger.besu.datatypes.BlobsWithCommitments;
|
||||||
|
import org.hyperledger.besu.datatypes.Wei;
|
||||||
|
import org.hyperledger.besu.ethereum.core.Block;
|
||||||
|
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||||
|
import org.hyperledger.besu.ethereum.core.Difficulty;
|
||||||
|
import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture;
|
||||||
|
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||||
|
import org.hyperledger.besu.ethereum.core.TransactionTestFixture;
|
||||||
|
import org.hyperledger.besu.ethereum.eth.transactions.sorter.BaseFeePendingTransactionsSorter;
|
||||||
|
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
|
||||||
|
import org.hyperledger.besu.testutil.TestClock;
|
||||||
|
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class BlobV1TransactionPoolTest extends AbstractTransactionPoolTestBase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PendingTransactions createPendingTransactions(
|
||||||
|
final TransactionPoolConfiguration poolConfig,
|
||||||
|
final BiFunction<PendingTransaction, PendingTransaction, Boolean>
|
||||||
|
transactionReplacementTester) {
|
||||||
|
|
||||||
|
return new BaseFeePendingTransactionsSorter(
|
||||||
|
poolConfig,
|
||||||
|
TestClock.system(ZoneId.systemDefault()),
|
||||||
|
metricsSystem,
|
||||||
|
protocolContext.getBlockchain()::getChainHeadHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Transaction createTransaction(final int transactionNumber, final Wei maxPrice) {
|
||||||
|
return createTransactionBaseFeeMarket(transactionNumber, maxPrice);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TransactionTestFixture createBaseTransaction(final int transactionNumber) {
|
||||||
|
return createBaseTransactionBaseFeeMarket(transactionNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ExecutionContextTestFixture createExecutionContextTestFixture() {
|
||||||
|
return createExecutionContextTestFixtureBaseFeeMarket();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FeeMarket getFeeMarket() {
|
||||||
|
return FeeMarket.london(0L, Optional.of(BASE_FEE_FLOOR));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Block appendBlock(
|
||||||
|
final Difficulty difficulty,
|
||||||
|
final BlockHeader parentBlock,
|
||||||
|
final Transaction... transactionsToAdd) {
|
||||||
|
return appendBlockBaseFeeMarket(difficulty, parentBlock, transactionsToAdd);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldReturnBlobWhenTransactionAddedToPool() {
|
||||||
|
givenTransactionIsValid(transactionWithBlobs);
|
||||||
|
|
||||||
|
addAndAssertRemoteTransactionsValid(transactionWithBlobs);
|
||||||
|
|
||||||
|
assertTransactionPending(transactionWithBlobs);
|
||||||
|
// assert that the blobs are returned from the tx pool
|
||||||
|
final List<BlobsWithCommitments.BlobQuad> expectedBlobQuads =
|
||||||
|
transactionWithBlobs.getBlobsWithCommitments().get().getBlobQuads();
|
||||||
|
|
||||||
|
expectedBlobQuads.forEach(
|
||||||
|
bq -> assertThat(transactionPool.getBlobQuad(bq.versionedHash())).isEqualTo(bq));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotReturnBlobsWhenAllTxsContainingBlobsHaveBeenReplaced() {
|
||||||
|
givenTransactionIsValid(transactionWithBlobs);
|
||||||
|
givenTransactionIsValid(transactionWithBlobsReplacement);
|
||||||
|
givenTransactionIsValid(transactionWithSameBlobs); // contains same blobs as transactionBlob
|
||||||
|
givenTransactionIsValid(transactionWithSameBlobsReplacement);
|
||||||
|
|
||||||
|
addAndAssertRemoteTransactionsValid(transactionWithBlobs);
|
||||||
|
assertTransactionPending(transactionWithBlobs);
|
||||||
|
|
||||||
|
final List<BlobsWithCommitments.BlobQuad> expectedBlobQuads =
|
||||||
|
transactionWithBlobs.getBlobsWithCommitments().get().getBlobQuads();
|
||||||
|
|
||||||
|
// assert that the blobs are returned from the tx pool
|
||||||
|
expectedBlobQuads.forEach(
|
||||||
|
bq -> assertThat(transactionPool.getBlobQuad(bq.versionedHash())).isEqualTo(bq));
|
||||||
|
|
||||||
|
// add different transaction that contains the same blobs
|
||||||
|
addAndAssertRemoteTransactionsValid(transactionWithSameBlobs);
|
||||||
|
|
||||||
|
assertTransactionPending(transactionWithBlobs);
|
||||||
|
assertTransactionPending(transactionWithSameBlobs);
|
||||||
|
// assert that the blobs are still returned from the tx pool
|
||||||
|
expectedBlobQuads.forEach(
|
||||||
|
bq -> assertThat(transactionPool.getBlobQuad(bq.versionedHash())).isEqualTo(bq));
|
||||||
|
|
||||||
|
// replace the second blob transaction with tx with different blobs
|
||||||
|
addAndAssertRemoteTransactionsValid(transactionWithSameBlobsReplacement);
|
||||||
|
assertTransactionPending(transactionWithSameBlobsReplacement);
|
||||||
|
assertTransactionNotPending(transactionWithSameBlobs);
|
||||||
|
|
||||||
|
// assert that the blob is still returned from the tx pool
|
||||||
|
expectedBlobQuads.forEach(
|
||||||
|
bq -> assertThat(transactionPool.getBlobQuad(bq.versionedHash())).isEqualTo(bq));
|
||||||
|
|
||||||
|
// replace the first blob transaction with tx with different blobs
|
||||||
|
addAndAssertRemoteTransactionsValid(transactionWithBlobsReplacement);
|
||||||
|
assertTransactionPending(transactionWithBlobsReplacement);
|
||||||
|
assertTransactionNotPending(transactionWithBlobs);
|
||||||
|
|
||||||
|
// All txs containing the expected blobs have been replaced,
|
||||||
|
// so the blobs should no longer be returned from the tx pool
|
||||||
|
expectedBlobQuads.forEach(
|
||||||
|
bq -> assertThat(transactionPool.getBlobQuad(bq.versionedHash())).isNull());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -86,7 +86,7 @@ public class CodeValidateSubCommand implements Runnable {
|
|||||||
String fork =
|
String fork =
|
||||||
parentCommand != null && parentCommand.hasFork()
|
parentCommand != null && parentCommand.hasFork()
|
||||||
? parentCommand.getFork()
|
? parentCommand.getFork()
|
||||||
: EvmSpecVersion.PRAGUE.getName();
|
: EvmSpecVersion.OSAKA.getName();
|
||||||
|
|
||||||
evm =
|
evm =
|
||||||
Suppliers.memoize(
|
Suppliers.memoize(
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ public class EOFTestSubCommand implements Runnable {
|
|||||||
}
|
}
|
||||||
ProtocolSpec protocolSpec =
|
ProtocolSpec protocolSpec =
|
||||||
ReferenceTestProtocolSchedules.getInstance()
|
ReferenceTestProtocolSchedules.getInstance()
|
||||||
.geSpecByName(fork == null ? EvmSpecVersion.PRAGUE.getName() : fork);
|
.geSpecByName(fork == null ? EvmSpecVersion.OSAKA.getName() : fork);
|
||||||
evm = protocolSpec.getEvm();
|
evm = protocolSpec.getEvm();
|
||||||
|
|
||||||
final JavaType javaType =
|
final JavaType javaType =
|
||||||
@@ -181,7 +181,7 @@ public class EOFTestSubCommand implements Runnable {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TestResult actualResult;
|
TestResult actualResult;
|
||||||
if (evmVersion.ordinal() < EvmSpecVersion.PRAGUE_EOF.ordinal()) {
|
if (evmVersion.ordinal() < EvmSpecVersion.OSAKA.ordinal()) {
|
||||||
actualResult = failed("EOF_InvalidCode");
|
actualResult = failed("EOF_InvalidCode");
|
||||||
} else {
|
} else {
|
||||||
actualResult = considerCode(code);
|
actualResult = considerCode(code);
|
||||||
|
|||||||
@@ -157,15 +157,16 @@ class MainnetGenesisFileModule extends GenesisFileModule {
|
|||||||
.chainId(chainId))),
|
.chainId(chainId))),
|
||||||
Map.entry(
|
Map.entry(
|
||||||
"prague",
|
"prague",
|
||||||
createSchedule(
|
|
||||||
new StubGenesisConfigOptions().pragueTime(0).baseFeePerGas(0x0a).chainId(chainId))),
|
|
||||||
Map.entry(
|
|
||||||
"pragueeof",
|
|
||||||
createSchedule(
|
createSchedule(
|
||||||
new StubGenesisConfigOptions()
|
new StubGenesisConfigOptions()
|
||||||
.pragueEOFTime(0)
|
.pragueTime(0)
|
||||||
|
.osakaTime(0) // TODO remove this once osaka_devnet_0 launches
|
||||||
.baseFeePerGas(0x0a)
|
.baseFeePerGas(0x0a)
|
||||||
.chainId(chainId))),
|
.chainId(chainId))),
|
||||||
|
Map.entry(
|
||||||
|
"osaka",
|
||||||
|
createSchedule(
|
||||||
|
new StubGenesisConfigOptions().osakaTime(0).baseFeePerGas(0x0a).chainId(chainId))),
|
||||||
Map.entry(
|
Map.entry(
|
||||||
"futureeips",
|
"futureeips",
|
||||||
createSchedule(
|
createSchedule(
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ public class PrettyPrintSubCommand implements Runnable {
|
|||||||
"Pretty printing of legacy EVM is not supported. Patches welcome!");
|
"Pretty printing of legacy EVM is not supported. Patches welcome!");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
String fork = EvmSpecVersion.PRAGUE.getName();
|
String fork = EvmSpecVersion.OSAKA.getName();
|
||||||
if (parentCommand.hasFork()) {
|
if (parentCommand.hasFork()) {
|
||||||
fork = parentCommand.getFork();
|
fork = parentCommand.getFork();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
|||||||
import org.hyperledger.besu.evm.gascalculator.HomesteadGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.HomesteadGasCalculator;
|
||||||
import org.hyperledger.besu.evm.gascalculator.IstanbulGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.IstanbulGasCalculator;
|
||||||
import org.hyperledger.besu.evm.gascalculator.LondonGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.LondonGasCalculator;
|
||||||
|
import org.hyperledger.besu.evm.gascalculator.OsakaGasCalculator;
|
||||||
import org.hyperledger.besu.evm.gascalculator.PetersburgGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.PetersburgGasCalculator;
|
||||||
import org.hyperledger.besu.evm.gascalculator.PragueEOFGasCalculator;
|
|
||||||
import org.hyperledger.besu.evm.gascalculator.PragueGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.PragueGasCalculator;
|
||||||
import org.hyperledger.besu.evm.gascalculator.ShanghaiGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.ShanghaiGasCalculator;
|
||||||
import org.hyperledger.besu.evm.precompile.PrecompiledContract;
|
import org.hyperledger.besu.evm.precompile.PrecompiledContract;
|
||||||
@@ -142,17 +142,11 @@ public abstract class BenchmarkExecutor {
|
|||||||
case LONDON, PARIS, LINEA -> new LondonGasCalculator();
|
case LONDON, PARIS, LINEA -> new LondonGasCalculator();
|
||||||
case SHANGHAI -> new ShanghaiGasCalculator();
|
case SHANGHAI -> new ShanghaiGasCalculator();
|
||||||
case CANCUN -> new CancunGasCalculator();
|
case CANCUN -> new CancunGasCalculator();
|
||||||
|
case CANCUN_EOF -> new OsakaGasCalculator();
|
||||||
case PRAGUE -> new PragueGasCalculator();
|
case PRAGUE -> new PragueGasCalculator();
|
||||||
case CANCUN_EOF,
|
case OSAKA -> new OsakaGasCalculator();
|
||||||
PRAGUE_EOF,
|
case AMSTERDAM, BOGOTA, POLIS, BANGKOK, FUTURE_EIPS, EXPERIMENTAL_EIPS ->
|
||||||
OSAKA,
|
new OsakaGasCalculator();
|
||||||
AMSTERDAM,
|
|
||||||
BOGOTA,
|
|
||||||
POLIS,
|
|
||||||
BANGKOK,
|
|
||||||
FUTURE_EIPS,
|
|
||||||
EXPERIMENTAL_EIPS ->
|
|
||||||
new PragueEOFGasCalculator();
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,13 +4,13 @@
|
|||||||
"stdin"
|
"stdin"
|
||||||
],
|
],
|
||||||
"stdin": {
|
"stdin": {
|
||||||
"tests/prague/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py::test_rjump_zero[fork_PragueEIP7692-blockchain_test]": {
|
"tests/osaka/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py::test_rjump_zero[fork_Osaka-blockchain_test]": {
|
||||||
"network": "Prague",
|
"network": "Osaka",
|
||||||
"genesisBlockHeader": {
|
"genesisBlockHeader": {
|
||||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
"uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
"coinbase": "0x0000000000000000000000000000000000000000",
|
"coinbase": "0x0000000000000000000000000000000000000000",
|
||||||
"stateRoot": "0x34ccf8774a5b8833da9451a3f7f8a0af0147956c058f0831dab07c348d7ac0d9",
|
"stateRoot": "0xbeb30acb62768b375f7e7d36f6ba9240cb692ebd0ee04c9321c756cf4ff1c437",
|
||||||
"transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
"bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
"excessBlobGas": "0x00",
|
"excessBlobGas": "0x00",
|
||||||
"parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
"parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"requestsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"requestsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"hash": "0xc9397e8a1b99cbb2b885852fde56de8fa686091a4f4430163f5237d7aaf33a14"
|
"hash": "0x367310df4a31070aa9a5c92cb61ab8bb2742db0162619ed77594fbec6f0ddbd9"
|
||||||
},
|
},
|
||||||
"pre": {
|
"pre": {
|
||||||
"0x00000000219ab540356cbb839cbe05303d7705fa": {
|
"0x00000000219ab540356cbb839cbe05303d7705fa": {
|
||||||
@@ -75,6 +75,12 @@
|
|||||||
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe146090573615156028575f545f5260205ff35b366038141561012e5760115f54600182026001905f5b5f82111560595781019083028483029004916001019190603e565b90939004341061012e57600154600101600155600354806003026004013381556001015f3581556001016020359055600101600355005b6003546002548082038060101160a4575060105b5f5b81811460dd5780604c02838201600302600401805490600101805490600101549160601b83528260140152906034015260010160a6565b910180921460ed579060025560f8565b90505f6002555f6003555b5f548061049d141561010757505f5b60015460028282011161011c5750505f610122565b01600290035b5f555f600155604c025ff35b5f5ffd",
|
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe146090573615156028575f545f5260205ff35b366038141561012e5760115f54600182026001905f5b5f82111560595781019083028483029004916001019190603e565b90939004341061012e57600154600101600155600354806003026004013381556001015f3581556001016020359055600101600355005b6003546002548082038060101160a4575060105b5f5b81811460dd5780604c02838201600302600401805490600101805490600101549160601b83528260140152906034015260010160a6565b910180921460ed579060025560f8565b90505f6002555f6003555b5f548061049d141561010757505f5b60015460028282011161011c5750505f610122565b01600290035b5f555f600155604c025ff35b5f5ffd",
|
||||||
"storage": {}
|
"storage": {}
|
||||||
},
|
},
|
||||||
|
"0x00b42dbf2194e931e80326d950320f7d9dbeac02": {
|
||||||
|
"nonce": "0x01",
|
||||||
|
"balance": "0x00",
|
||||||
|
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe146098573615156028575f545f5260205ff35b36606014156101445760115f54600182026001905f5b5f82111560595781019083028483029004916001019190603e565b90939004341061014457600154600101600155600354806004026004013381556001015f35815560010160203581556001016040359055600101600355005b6003546002548082038060011160ac575060015b5f5b81811460f15780607402838201600402600401805490600101805490600101805490600101549260601b84529083601401528260340152906054015260010160ae565b9101809214610103579060025561010e565b90505f6002555f6003555b5f548061049d141561011d57505f5b6001546001828201116101325750505f610138565b01600190035b5f555f6001556074025ff35b5f5ffd",
|
||||||
|
"storage": {}
|
||||||
|
},
|
||||||
"0x0aae40965e6800cd9b1f4b05ff21581047e3f91e": {
|
"0x0aae40965e6800cd9b1f4b05ff21581047e3f91e": {
|
||||||
"nonce": "0x01",
|
"nonce": "0x01",
|
||||||
"balance": "0x00",
|
"balance": "0x00",
|
||||||
@@ -161,12 +167,18 @@
|
|||||||
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe146090573615156028575f545f5260205ff35b366038141561012e5760115f54600182026001905f5b5f82111560595781019083028483029004916001019190603e565b90939004341061012e57600154600101600155600354806003026004013381556001015f3581556001016020359055600101600355005b6003546002548082038060101160a4575060105b5f5b81811460dd5780604c02838201600302600401805490600101805490600101549160601b83528260140152906034015260010160a6565b910180921460ed579060025560f8565b90505f6002555f6003555b5f548061049d141561010757505f5b60015460028282011161011c5750505f610122565b01600290035b5f555f600155604c025ff35b5f5ffd",
|
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe146090573615156028575f545f5260205ff35b366038141561012e5760115f54600182026001905f5b5f82111560595781019083028483029004916001019190603e565b90939004341061012e57600154600101600155600354806003026004013381556001015f3581556001016020359055600101600355005b6003546002548082038060101160a4575060105b5f5b81811460dd5780604c02838201600302600401805490600101805490600101549160601b83528260140152906034015260010160a6565b910180921460ed579060025560f8565b90505f6002555f6003555b5f548061049d141561010757505f5b60015460028282011161011c5750505f610122565b01600290035b5f555f600155604c025ff35b5f5ffd",
|
||||||
"storage": {}
|
"storage": {}
|
||||||
},
|
},
|
||||||
|
"0x00b42dbf2194e931e80326d950320f7d9dbeac02": {
|
||||||
|
"nonce": "0x01",
|
||||||
|
"balance": "0x00",
|
||||||
|
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe146098573615156028575f545f5260205ff35b36606014156101445760115f54600182026001905f5b5f82111560595781019083028483029004916001019190603e565b90939004341061014457600154600101600155600354806004026004013381556001015f35815560010160203581556001016040359055600101600355005b6003546002548082038060011160ac575060015b5f5b81811460f15780607402838201600402600401805490600101805490600101805490600101549260601b84529083601401528260340152906054015260010160ae565b9101809214610103579060025561010e565b90505f6002555f6003555b5f548061049d141561011d57505f5b6001546001828201116101325750505f610138565b01600190035b5f555f6001556074025ff35b5f5ffd",
|
||||||
|
"storage": {}
|
||||||
|
},
|
||||||
"0x0aae40965e6800cd9b1f4b05ff21581047e3f91e": {
|
"0x0aae40965e6800cd9b1f4b05ff21581047e3f91e": {
|
||||||
"nonce": "0x01",
|
"nonce": "0x01",
|
||||||
"balance": "0x00",
|
"balance": "0x00",
|
||||||
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe1460575767ffffffffffffffff5f3511605357600143035f3511604b575f35612000014311604b57611fff5f3516545f5260205ff35b5f5f5260205ff35b5f5ffd5b5f35611fff60014303165500",
|
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe1460575767ffffffffffffffff5f3511605357600143035f3511604b575f35612000014311604b57611fff5f3516545f5260205ff35b5f5f5260205ff35b5f5ffd5b5f35611fff60014303165500",
|
||||||
"storage": {
|
"storage": {
|
||||||
"0x00": "0xc9397e8a1b99cbb2b885852fde56de8fa686091a4f4430163f5237d7aaf33a14"
|
"0x00": "0x367310df4a31070aa9a5c92cb61ab8bb2742db0162619ed77594fbec6f0ddbd9"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba": {
|
"0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba": {
|
||||||
@@ -182,14 +194,15 @@
|
|||||||
"storage": {}
|
"storage": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"genesisRLP": "0xf90262f9025ba00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a034ccf8774a5b8833da9451a3f7f8a0af0147956c058f0831dab07c348d7ac0d9a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000808088016345785d8a0000808000a0000000000000000000000000000000000000000000000000000000000000000088000000000000000007a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421c0c0c0c0",
|
"lastblockhash": "0xfb5d1d0e218fa7873bc188f07f3e0a7c78027ff6e6e199c48ba1facd3c3726fd",
|
||||||
|
"genesisRLP": "0xf90262f9025ba00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0beb30acb62768b375f7e7d36f6ba9240cb692ebd0ee04c9321c756cf4ff1c437a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000808088016345785d8a0000808000a0000000000000000000000000000000000000000000000000000000000000000088000000000000000007a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421c0c0c0c0",
|
||||||
"blocks": [
|
"blocks": [
|
||||||
{
|
{
|
||||||
"blockHeader": {
|
"blockHeader": {
|
||||||
"parentHash": "0xc9397e8a1b99cbb2b885852fde56de8fa686091a4f4430163f5237d7aaf33a14",
|
"parentHash": "0x367310df4a31070aa9a5c92cb61ab8bb2742db0162619ed77594fbec6f0ddbd9",
|
||||||
"uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
"uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
"coinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
"coinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
||||||
"stateRoot": "0x1a4885d1f64bac16e5ab17fb13e23fb5d1a0ec2ca4519c81714683f69c8d9a84",
|
"stateRoot": "0x4ab70cbe1abe50d6bb3c8cdb3e9e66111f142cd68ab73870e9ce9e0dd1d6ead2",
|
||||||
"transactionsTrie": "0xec9d10cff79619f2df45db8c66526ef3fbd32d283fdd2dcc9b55c0efe643d8c3",
|
"transactionsTrie": "0xec9d10cff79619f2df45db8c66526ef3fbd32d283fdd2dcc9b55c0efe643d8c3",
|
||||||
"receiptTrie": "0x9593f56abf23bcbb26d27b0c6e46a56415d9103ed6b4d8ac7b4182f9f250cafa",
|
"receiptTrie": "0x9593f56abf23bcbb26d27b0c6e46a56415d9103ed6b4d8ac7b4182f9f250cafa",
|
||||||
"bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
"bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
@@ -207,7 +220,7 @@
|
|||||||
"excessBlobGas": "0x00",
|
"excessBlobGas": "0x00",
|
||||||
"parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
"parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"requestsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"requestsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"hash": "0x879cf54bf493b6585db592b1b24ec30a8a7fbe3b9146d3fb20ca36200f2aca87"
|
"hash": "0xfb5d1d0e218fa7873bc188f07f3e0a7c78027ff6e6e199c48ba1facd3c3726fd"
|
||||||
},
|
},
|
||||||
"transactions": [
|
"transactions": [
|
||||||
{
|
{
|
||||||
@@ -229,22 +242,22 @@
|
|||||||
"withdrawals": [],
|
"withdrawals": [],
|
||||||
"depositRequests": [],
|
"depositRequests": [],
|
||||||
"withdrawalRequests": [],
|
"withdrawalRequests": [],
|
||||||
"rlp": "0xf902c9f9025fa0c9397e8a1b99cbb2b885852fde56de8fa686091a4f4430163f5237d7aaf33a14a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942adc25665018aa1fe0e6bc666dac8fc2697ff9baa01a4885d1f64bac16e5ab17fb13e23fb5d1a0ec2ca4519c81714683f69c8d9a84a0ec9d10cff79619f2df45db8c66526ef3fbd32d283fdd2dcc9b55c0efe643d8c3a09593f56abf23bcbb26d27b0c6e46a56415d9103ed6b4d8ac7b4182f9f250cafab9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800188016345785d8a000082a8648203e800a0000000000000000000000000000000000000000000000000000000000000000088000000000000000007a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421f862f860800a83989680940000000000000000000000000000000000001000808026a0e5d462429669f661291a8dc4c49a092cfd4922b6f3f31c9189a2f4adf5ecd730a001494afaf472fbb80bcb107ffeb918a2b9115f454027840615d6d20d63c69ac0c0c0c0",
|
"consolidationRequests": [],
|
||||||
|
"rlp": "0xf902c9f9025fa0367310df4a31070aa9a5c92cb61ab8bb2742db0162619ed77594fbec6f0ddbd9a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942adc25665018aa1fe0e6bc666dac8fc2697ff9baa04ab70cbe1abe50d6bb3c8cdb3e9e66111f142cd68ab73870e9ce9e0dd1d6ead2a0ec9d10cff79619f2df45db8c66526ef3fbd32d283fdd2dcc9b55c0efe643d8c3a09593f56abf23bcbb26d27b0c6e46a56415d9103ed6b4d8ac7b4182f9f250cafab9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800188016345785d8a000082a8648203e800a0000000000000000000000000000000000000000000000000000000000000000088000000000000000007a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421f862f860800a83989680940000000000000000000000000000000000001000808026a0e5d462429669f661291a8dc4c49a092cfd4922b6f3f31c9189a2f4adf5ecd730a001494afaf472fbb80bcb107ffeb918a2b9115f454027840615d6d20d63c69ac0c0c0c0",
|
||||||
"blocknumber": "1"
|
"blocknumber": "1"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"lastblockhash": "0x879cf54bf493b6585db592b1b24ec30a8a7fbe3b9146d3fb20ca36200f2aca87",
|
|
||||||
"sealEngine": "NoProof",
|
"sealEngine": "NoProof",
|
||||||
"_info": {
|
"_info": {
|
||||||
"hash": "0xbfd1223f9b5b8dbf202178f7c1f18dc089cb24e54c9cb7fc9831907547e937c4",
|
"hash": "0xd0cc15d832c8c0b9cf5bdc0eab79c3b632193a11fde3d5ef32bb07e8c65ba6bd",
|
||||||
"comment": "`execution-spec-tests` generated test",
|
"comment": "`execution-spec-tests` generated test",
|
||||||
"filling-transition-tool": "Hyperledger Besu evm 24.7-develop-8ca7129",
|
"filling-transition-tool": "Hyperledger Besu evm 24.9-develop-0d63955",
|
||||||
"description": "Test function documentation:\nEOF1V4200_0002 (Valid) EOF code containing RJUMP (Zero)",
|
"description": "Test function documentation:\nEOF1V4200_0002 (Valid) EOF code containing RJUMP (Zero)",
|
||||||
"url": "https://github.com/ethereum/execution-spec-tests/blob/891a6111370c89d4ce89bf91589c6d5ff6785158/tests/prague/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py#L63",
|
"url": "https://github.com/ethereum/execution-spec-tests/blob/96efd737b258eeb8efb615e9123d931b6dfda302/tests/osaka/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py#L44",
|
||||||
"reference-spec": "https://github.com/ethereum/EIPs/blob/master/EIPS/eip-4200.md",
|
"reference-spec": "https://github.com/ethereum/EIPs/blob/master/EIPS/eip-4200.md",
|
||||||
"reference-spec-version": "17d4a8d12d2b5e0f2985c866376c16c8c6df7cba"
|
"reference-spec-version": "17d4a8d12d2b5e0f2985c866376c16c8c6df7cba"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"stdout": "Considering tests/prague/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py::test_rjump_zero[fork_PragueEIP7692-blockchain_test]\nBlock 1 (0x879cf54bf493b6585db592b1b24ec30a8a7fbe3b9146d3fb20ca36200f2aca87) Imported\nChain import successful - tests/prague/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py::test_rjump_zero[fork_PragueEIP7692-blockchain_test]\n"
|
"stdout": "Considering tests/osaka/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py::test_rjump_zero[fork_Osaka-blockchain_test]\nBlock 1 (0xfb5d1d0e218fa7873bc188f07f3e0a7c78027ff6e6e199c48ba1facd3c3726fd) Imported\nChain import successful - tests/osaka/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py::test_rjump_zero[fork_Osaka-blockchain_test]\n"
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
},
|
},
|
||||||
"out": "0x",
|
"out": "0x",
|
||||||
"post": {
|
"post": {
|
||||||
"CancunEOF": [
|
"Osaka": [
|
||||||
{
|
{
|
||||||
"hash": "0x1a8642a04dae90535f00f53d3a30284c4db051d508a653db89eb100ba9aecbf3",
|
"hash": "0x1a8642a04dae90535f00f53d3a30284c4db051d508a653db89eb100ba9aecbf3",
|
||||||
"logs": "0xf48b954a6a6f4ce6b28e4950b7027413f4bdc8f459df6003b6e8d7a1567c8940",
|
"logs": "0xf48b954a6a6f4ce6b28e4950b7027413f4bdc8f459df6003b6e8d7a1567c8940",
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
{"pc":5,"section":0,"op":95,"gas":"0x793d71","gasCost":"0x2","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH0"},
|
{"pc":5,"section":0,"op":95,"gas":"0x793d71","gasCost":"0x2","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH0"},
|
||||||
{"pc":6,"section":0,"op":95,"gas":"0x793d6f","gasCost":"0x2","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"PUSH0"},
|
{"pc":6,"section":0,"op":95,"gas":"0x793d6f","gasCost":"0x2","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"PUSH0"},
|
||||||
{"pc":7,"section":0,"op":238,"immediate":"0x00","gas":"0x793d6d","gasCost":"0x0","memSize":0,"stack":["0x0","0x0"],"depth":1,"refund":0,"opName":"RETURNCONTRACT"},
|
{"pc":7,"section":0,"op":238,"immediate":"0x00","gas":"0x793d6d","gasCost":"0x0","memSize":0,"stack":["0x0","0x0"],"depth":1,"refund":0,"opName":"RETURNCONTRACT"},
|
||||||
{"output":"","gasUsed":"0xe433","test":"create-eof","fork":"CancunEOF","d":0,"g":0,"v":0,"postHash":"0x1a8642a04dae90535f00f53d3a30284c4db051d508a653db89eb100ba9aecbf3","postLogsHash":"0xf48b954a6a6f4ce6b28e4950b7027413f4bdc8f459df6003b6e8d7a1567c8940","pass":true},
|
{"output":"","gasUsed":"0xe433","test":"create-eof","fork":"Osaka","d":0,"g":0,"v":0,"postHash":"0x1a8642a04dae90535f00f53d3a30284c4db051d508a653db89eb100ba9aecbf3","postLogsHash":"0xf48b954a6a6f4ce6b28e4950b7027413f4bdc8f459df6003b6e8d7a1567c8940","pass":true},
|
||||||
{"pc":0,"op":239,"gas":"0x794068","gasCost":"0x0","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"INVALID","error":"Bad instruction"},
|
{"pc":0,"op":239,"gas":"0x794068","gasCost":"0x0","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"INVALID","error":"Bad instruction"},
|
||||||
{"output":"","gasUsed":"0x7a1200","test":"create-eof","fork":"Cancun","d":0,"g":0,"v":0,"postHash":"0xaa80d89bc89f58da8de41d3894bd1a241896ff91f7a5964edaefb39e8e3a4a98","postLogsHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","pass":true,"error":"INVALID_OPERATION"}
|
{"output":"","gasUsed":"0x7a1200","test":"create-eof","fork":"Cancun","d":0,"g":0,"v":0,"postHash":"0xaa80d89bc89f58da8de41d3894bd1a241896ff91f7a5964edaefb39e8e3a4a98","postLogsHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","pass":true,"error":"INVALID_OPERATION"}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
},
|
},
|
||||||
"out": "0x",
|
"out": "0x",
|
||||||
"post": {
|
"post": {
|
||||||
"Prague": [
|
"Osaka": [
|
||||||
{
|
{
|
||||||
"hash": "0x1a8642a04dae90535f00f53d3a30284c4db051d508a653db89eb100ba9aecbf3",
|
"hash": "0x1a8642a04dae90535f00f53d3a30284c4db051d508a653db89eb100ba9aecbf3",
|
||||||
"logs": "0xf48b954a6a6f4ce6b28e4950b7027413f4bdc8f459df6003b6e8d7a1567c8940",
|
"logs": "0xf48b954a6a6f4ce6b28e4950b7027413f4bdc8f459df6003b6e8d7a1567c8940",
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"stdout": [
|
"stdout": [
|
||||||
{"output":"","gasUsed":"0xd198","test":"create-eof","fork":"Prague","d":0,"g":0,"v":0,"postHash":"0x2a9c58298ba5d4ec86ca682b9fcc9ff67c3fc44dbd39f85a2f9b74bfe4e5178e","postLogsHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","pass":false,"error":"Invalid EOF Layout: unexpected_header_kind expected 1 actual 17"},
|
{"output":"","gasUsed":"0xd198","test":"create-eof","fork":"Osaka","d":0,"g":0,"v":0,"postHash":"0x2a9c58298ba5d4ec86ca682b9fcc9ff67c3fc44dbd39f85a2f9b74bfe4e5178e","postLogsHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","pass":false,"error":"Invalid EOF Layout: unexpected_header_kind expected 1 actual 17"},
|
||||||
{"pc":0,"op":239,"gas":"0x794068","gasCost":"0x0","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"INVALID","error":"Bad instruction"},
|
{"pc":0,"op":239,"gas":"0x794068","gasCost":"0x0","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"INVALID","error":"Bad instruction"},
|
||||||
{"output":"","gasUsed":"0x7a1200","test":"create-eof","fork":"Cancun","d":0,"g":0,"v":0,"postHash":"0xaa80d89bc89f58da8de41d3894bd1a241896ff91f7a5964edaefb39e8e3a4a98","postLogsHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","pass":true,"error":"INVALID_OPERATION"}
|
{"output":"","gasUsed":"0x7a1200","test":"create-eof","fork":"Cancun","d":0,"g":0,"v":0,"postHash":"0xaa80d89bc89f58da8de41d3894bd1a241896ff91f7a5964edaefb39e8e3a4a98","postLogsHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","pass":true,"error":"INVALID_OPERATION"}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
"--coinbase",
|
"--coinbase",
|
||||||
"4444588443C3A91288C5002483449ABA1054192B",
|
"4444588443C3A91288C5002483449ABA1054192B",
|
||||||
"--fork",
|
"--fork",
|
||||||
"CancunEOF"
|
"Osaka"
|
||||||
],
|
],
|
||||||
"stdin": "",
|
"stdin": "",
|
||||||
"stdout": "EOF Code Invalid : incompatible_container_kind opcode STOP is only valid for runtime.\n"
|
"stdout": "EOF Code Invalid : incompatible_container_kind opcode STOP is only valid for runtime.\n"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
"--coinbase",
|
"--coinbase",
|
||||||
"4444588443C3A91288C5002483449ABA1054192B",
|
"4444588443C3A91288C5002483449ABA1054192B",
|
||||||
"--fork",
|
"--fork",
|
||||||
"CancunEOF"
|
"Osaka"
|
||||||
],
|
],
|
||||||
"stdin": "",
|
"stdin": "",
|
||||||
"stdout": [
|
"stdout": [
|
||||||
@@ -20,6 +20,6 @@
|
|||||||
{"pc":5,"section":0,"op":95,"gas":"0x2540be109","gasCost":"0x2","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH0"},
|
{"pc":5,"section":0,"op":95,"gas":"0x2540be109","gasCost":"0x2","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH0"},
|
||||||
{"pc":6,"section":0,"op":95,"gas":"0x2540be107","gasCost":"0x2","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"PUSH0"},
|
{"pc":6,"section":0,"op":95,"gas":"0x2540be107","gasCost":"0x2","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"PUSH0"},
|
||||||
{"pc":7,"section":0,"op":238,"immediate":"0x00","gas":"0x2540be105","gasCost":"0x0","memSize":0,"stack":["0x0","0x0"],"depth":1,"refund":0,"opName":"RETURNCONTRACT"},
|
{"pc":7,"section":0,"op":238,"immediate":"0x00","gas":"0x2540be105","gasCost":"0x0","memSize":0,"stack":["0x0","0x0"],"depth":1,"refund":0,"opName":"RETURNCONTRACT"},
|
||||||
{"stateRoot":"0x9790b070a5749acec6a7252a867f795df3c2cb5b800fb509ea259a1c0b5d96c1","output":"0x","gasUsed":"0x129b","pass":true,"fork":"CancunEOF"}
|
{"stateRoot":"0x9790b070a5749acec6a7252a867f795df3c2cb5b800fb509ea259a1c0b5d96c1","output":"0x","gasUsed":"0x129b","pass":true,"fork":"Osaka"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -7,17 +7,17 @@
|
|||||||
"--coinbase",
|
"--coinbase",
|
||||||
"4444588443C3A91288C5002483449ABA1054192B",
|
"4444588443C3A91288C5002483449ABA1054192B",
|
||||||
"--fork",
|
"--fork",
|
||||||
"PragueEOF"
|
"Osaka"
|
||||||
],
|
],
|
||||||
"stdin": "",
|
"stdin": "",
|
||||||
"stdout": [
|
"stdout": [
|
||||||
{"pc":0,"section":0,"op":227,"immediate":"0x0002","gas":"0x2540be400","gasCost":"0x5","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"CALLF"},
|
{"pc":0,"section":0,"op":227,"immediate":"0x0002","gas":"0x2540be400","gasCost":"0x5","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"CALLF"},
|
||||||
{"pc":0,"section":2,"op":229,"immediate":"0x0002","gas":"0x2540be3fb","gasCost":"0x5","memSize":0,"stack":[],"depth":1,"functionDepth":1,"refund":0,"opName":"JUMPF"},
|
{"pc":11,"section":2,"op":229,"immediate":"0x0001","gas":"0x2540be3fb","gasCost":"0x5","memSize":0,"stack":[],"depth":1,"functionDepth":1,"refund":0,"opName":"JUMPF"},
|
||||||
{"pc":0,"section":1,"op":228,"gas":"0x2540be3f6","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"functionDepth":1,"refund":0,"opName":"RETF"},
|
{"pc":10,"section":1,"op":228,"gas":"0x2540be3f6","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"functionDepth":1,"refund":0,"opName":"RETF"},
|
||||||
{"pc":3,"section":0,"op":97,"immediate":"0x2015","gas":"0x2540be3f3","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH2"},
|
{"pc":3,"section":0,"op":97,"immediate":"0x2015","gas":"0x2540be3f3","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH2"},
|
||||||
{"pc":6,"section":0,"op":96,"immediate":"0x01","gas":"0x2540be3f0","gasCost":"0x3","memSize":0,"stack":["0x2015"],"depth":1,"refund":0,"opName":"PUSH1"},
|
{"pc":6,"section":0,"op":96,"immediate":"0x01","gas":"0x2540be3f0","gasCost":"0x3","memSize":0,"stack":["0x2015"],"depth":1,"refund":0,"opName":"PUSH1"},
|
||||||
{"pc":8,"section":0,"op":85,"gas":"0x2540be3ed","gasCost":"0x5654","memSize":0,"stack":["0x2015","0x1"],"depth":1,"refund":0,"opName":"SSTORE"},
|
{"pc":8,"section":0,"op":85,"gas":"0x2540be3ed","gasCost":"0x5654","memSize":0,"stack":["0x2015","0x1"],"depth":1,"refund":0,"opName":"SSTORE"},
|
||||||
{"pc":9,"section":0,"op":0,"gas":"0x2540b8d99","gasCost":"0x0","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"STOP"},
|
{"pc":9,"section":0,"op":0,"gas":"0x2540b8d99","gasCost":"0x0","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"STOP"},
|
||||||
{"stateRoot":"0x761f723ceabb467d438fe74abf025c10bf65592b84ec389850038eb572f2b0fa","output":"0x","gasUsed":"0x5667","pass":true,"fork":"PragueEOF"}
|
{"stateRoot":"0x761f723ceabb467d438fe74abf025c10bf65592b84ec389850038eb572f2b0fa","output":"0x","gasUsed":"0x5667","pass":true,"fork":"Osaka"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -7,11 +7,11 @@
|
|||||||
"--coinbase",
|
"--coinbase",
|
||||||
"4444588443C3A91288C5002483449ABA1054192B",
|
"4444588443C3A91288C5002483449ABA1054192B",
|
||||||
"--fork",
|
"--fork",
|
||||||
"PragueEOF"
|
"Osaka"
|
||||||
],
|
],
|
||||||
"stdin": "",
|
"stdin": "",
|
||||||
"stdout": [
|
"stdout": [
|
||||||
{"pc":0,"section":0,"op":0,"gas":"0x2540be400","gasCost":"0x0","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"STOP"},
|
{"pc":0,"section":0,"op":0,"gas":"0x2540be400","gasCost":"0x0","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"STOP"},
|
||||||
{"stateRoot":"0xdae5f2c233bf9fbb7413d06ce744a3345dbf971b5bb5638736c0388f43a61a4b","output":"0x","gasUsed":"0x0","pass":true,"fork":"PragueEOF"}
|
{"stateRoot":"0xdae5f2c233bf9fbb7413d06ce744a3345dbf971b5bb5638736c0388f43a61a4b","output":"0x","gasUsed":"0x0","pass":true,"fork":"Osaka"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
"--coinbase",
|
"--coinbase",
|
||||||
"4444588443C3A91288C5002483449ABA1054192B",
|
"4444588443C3A91288C5002483449ABA1054192B",
|
||||||
"--fork",
|
"--fork",
|
||||||
"CancunEOF"
|
"Osaka"
|
||||||
],
|
],
|
||||||
"stdin": "",
|
"stdin": "",
|
||||||
"stdout": "To evaluate INITCODE mode EOF code use the --create flag\n"
|
"stdout": "To evaluate INITCODE mode EOF code use the --create flag\n"
|
||||||
|
|||||||
@@ -26,16 +26,17 @@ import org.hyperledger.besu.ethereum.p2p.peers.Peer;
|
|||||||
import org.hyperledger.besu.ethereum.p2p.peers.PeerId;
|
import org.hyperledger.besu.ethereum.p2p.peers.PeerId;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ForkJoinPool;
|
import java.util.concurrent.ForkJoinPool;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
import com.google.common.hash.BloomFilter;
|
import com.google.common.hash.BloomFilter;
|
||||||
import org.apache.commons.collections4.queue.CircularFifoQueue;
|
|
||||||
import org.apache.tuweni.bytes.Bytes;
|
import org.apache.tuweni.bytes.Bytes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -54,10 +55,7 @@ public class PeerTable {
|
|||||||
private final Map<Bytes, Integer> distanceCache;
|
private final Map<Bytes, Integer> distanceCache;
|
||||||
private BloomFilter<Bytes> idBloom;
|
private BloomFilter<Bytes> idBloom;
|
||||||
private int evictionCnt = 0;
|
private int evictionCnt = 0;
|
||||||
private final LinkedHashMapWithMaximumSize<String, Integer> ipAddressCheckMap =
|
private final Cache<String, Integer> unresponsiveIPs;
|
||||||
new LinkedHashMapWithMaximumSize<>(DEFAULT_BUCKET_SIZE * N_BUCKETS);
|
|
||||||
private final CircularFifoQueue<String> invalidIPs =
|
|
||||||
new CircularFifoQueue<>(DEFAULT_BUCKET_SIZE * N_BUCKETS);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds a new peer table, where distance is calculated using the provided nodeId as a baseline.
|
* Builds a new peer table, where distance is calculated using the provided nodeId as a baseline.
|
||||||
@@ -72,6 +70,11 @@ public class PeerTable {
|
|||||||
.toArray(Bucket[]::new);
|
.toArray(Bucket[]::new);
|
||||||
this.distanceCache = new ConcurrentHashMap<>();
|
this.distanceCache = new ConcurrentHashMap<>();
|
||||||
this.maxEntriesCnt = N_BUCKETS * DEFAULT_BUCKET_SIZE;
|
this.maxEntriesCnt = N_BUCKETS * DEFAULT_BUCKET_SIZE;
|
||||||
|
this.unresponsiveIPs =
|
||||||
|
CacheBuilder.newBuilder()
|
||||||
|
.maximumSize(maxEntriesCnt)
|
||||||
|
.expireAfterWrite(15L, TimeUnit.MINUTES)
|
||||||
|
.build();
|
||||||
|
|
||||||
// A bloom filter with 4096 expected insertions of 64-byte keys with a 0.1% false positive
|
// A bloom filter with 4096 expected insertions of 64-byte keys with a 0.1% false positive
|
||||||
// probability yields a memory footprint of ~7.5kb.
|
// probability yields a memory footprint of ~7.5kb.
|
||||||
@@ -140,7 +143,6 @@ public class PeerTable {
|
|||||||
if (!res.isPresent()) {
|
if (!res.isPresent()) {
|
||||||
idBloom.put(id);
|
idBloom.put(id);
|
||||||
distanceCache.put(id, distance);
|
distanceCache.put(id, distance);
|
||||||
ipAddressCheckMap.put(getKey(peer.getEndpoint()), peer.getEndpoint().getUdpPort());
|
|
||||||
return AddResult.added();
|
return AddResult.added();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,26 +216,12 @@ public class PeerTable {
|
|||||||
|
|
||||||
public boolean isIpAddressInvalid(final Endpoint endpoint) {
|
public boolean isIpAddressInvalid(final Endpoint endpoint) {
|
||||||
final String key = getKey(endpoint);
|
final String key = getKey(endpoint);
|
||||||
if (invalidIPs.contains(key)) {
|
return unresponsiveIPs.getIfPresent(key) != null;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (ipAddressCheckMap.containsKey(key) && ipAddressCheckMap.get(key) != endpoint.getUdpPort()) {
|
|
||||||
// This peer has multiple discovery services on the same IP address + TCP port.
|
|
||||||
invalidIPs.add(key);
|
|
||||||
for (final Bucket bucket : table) {
|
|
||||||
bucket.getPeers().stream()
|
|
||||||
.filter(p -> p.getEndpoint().getHost().equals(endpoint.getHost()))
|
|
||||||
.forEach(bucket::evict);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void invalidateIP(final Endpoint endpoint) {
|
public void invalidateIP(final Endpoint endpoint) {
|
||||||
final String key = getKey(endpoint);
|
final String key = getKey(endpoint);
|
||||||
invalidIPs.add(key);
|
unresponsiveIPs.put(key, Integer.MAX_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getKey(final Endpoint endpoint) {
|
private static String getKey(final Endpoint endpoint) {
|
||||||
@@ -313,20 +301,6 @@ public class PeerTable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class LinkedHashMapWithMaximumSize<K, V> extends LinkedHashMap<K, V> {
|
|
||||||
private final int maxSize;
|
|
||||||
|
|
||||||
public LinkedHashMapWithMaximumSize(final int maxSize) {
|
|
||||||
super(maxSize, 0.75f, false);
|
|
||||||
this.maxSize = maxSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean removeEldestEntry(final Map.Entry<K, V> eldest) {
|
|
||||||
return size() > maxSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class EvictResult {
|
static class EvictResult {
|
||||||
public enum EvictOutcome {
|
public enum EvictOutcome {
|
||||||
EVICTED,
|
EVICTED,
|
||||||
|
|||||||
@@ -188,15 +188,12 @@ public class PeerTableTest {
|
|||||||
@Test
|
@Test
|
||||||
public void ipAddressIsInvalidReturnsTrue() {
|
public void ipAddressIsInvalidReturnsTrue() {
|
||||||
final Endpoint endpoint1 = new Endpoint("1.1.1.1", 2, Optional.of(Integer.valueOf(1)));
|
final Endpoint endpoint1 = new Endpoint("1.1.1.1", 2, Optional.of(Integer.valueOf(1)));
|
||||||
final Endpoint endpoint2 = new Endpoint("1.1.1.1", 3, Optional.of(Integer.valueOf(1)));
|
|
||||||
final DiscoveryPeer peer1 = DiscoveryPeer.fromIdAndEndpoint(Peer.randomId(), endpoint1);
|
final DiscoveryPeer peer1 = DiscoveryPeer.fromIdAndEndpoint(Peer.randomId(), endpoint1);
|
||||||
final DiscoveryPeer peer2 = DiscoveryPeer.fromIdAndEndpoint(Peer.randomId(), endpoint2);
|
|
||||||
final PeerTable table = new PeerTable(Bytes.random(64));
|
final PeerTable table = new PeerTable(Bytes.random(64));
|
||||||
|
|
||||||
final PeerTable.AddResult addResult1 = table.tryAdd(peer1);
|
table.invalidateIP(endpoint1);
|
||||||
assertThat(addResult1.getOutcome()).isEqualTo(PeerTable.AddResult.added().getOutcome());
|
|
||||||
|
|
||||||
assertThat(table.isIpAddressInvalid(peer2.getEndpoint())).isEqualTo(true);
|
assertThat(table.isIpAddressInvalid(peer1.getEndpoint())).isEqualTo(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -216,16 +213,12 @@ public class PeerTableTest {
|
|||||||
@Test
|
@Test
|
||||||
public void invalidIPAddressNotAdded() {
|
public void invalidIPAddressNotAdded() {
|
||||||
final Endpoint endpoint1 = new Endpoint("1.1.1.1", 2, Optional.of(Integer.valueOf(1)));
|
final Endpoint endpoint1 = new Endpoint("1.1.1.1", 2, Optional.of(Integer.valueOf(1)));
|
||||||
final Endpoint endpoint2 = new Endpoint("1.1.1.1", 3, Optional.of(Integer.valueOf(1)));
|
|
||||||
final DiscoveryPeer peer1 = DiscoveryPeer.fromIdAndEndpoint(Peer.randomId(), endpoint1);
|
final DiscoveryPeer peer1 = DiscoveryPeer.fromIdAndEndpoint(Peer.randomId(), endpoint1);
|
||||||
final DiscoveryPeer peer2 = DiscoveryPeer.fromIdAndEndpoint(Peer.randomId(), endpoint2);
|
|
||||||
final PeerTable table = new PeerTable(Bytes.random(64));
|
final PeerTable table = new PeerTable(Bytes.random(64));
|
||||||
|
|
||||||
|
table.invalidateIP(endpoint1);
|
||||||
final PeerTable.AddResult addResult1 = table.tryAdd(peer1);
|
final PeerTable.AddResult addResult1 = table.tryAdd(peer1);
|
||||||
assertThat(addResult1.getOutcome()).isEqualTo(PeerTable.AddResult.added().getOutcome());
|
assertThat(addResult1.getOutcome()).isEqualTo(PeerTable.AddResult.invalid().getOutcome());
|
||||||
|
|
||||||
final PeerTable.AddResult addResult2 = table.tryAdd(peer2);
|
|
||||||
assertThat(addResult2.getOutcome()).isEqualTo(PeerTable.AddResult.invalid().getOutcome());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -105,8 +105,15 @@ public class ReferenceTestProtocolSchedules {
|
|||||||
Map.entry(
|
Map.entry(
|
||||||
"CancunToPragueAtTime15k",
|
"CancunToPragueAtTime15k",
|
||||||
createSchedule(genesisStub.clone().cancunTime(0).pragueTime(15000))),
|
createSchedule(genesisStub.clone().cancunTime(0).pragueTime(15000))),
|
||||||
Map.entry("Prague", createSchedule(genesisStub.clone().pragueEOFTime(0))),
|
Map.entry(
|
||||||
Map.entry("Osaka", createSchedule(genesisStub.clone().futureEipsTime(0))),
|
"Prague",
|
||||||
|
createSchedule(
|
||||||
|
genesisStub
|
||||||
|
.clone()
|
||||||
|
.pragueTime(0)
|
||||||
|
.osakaTime(0) // TODO remove this once osaka_devnet_0 ships
|
||||||
|
)),
|
||||||
|
Map.entry("Osaka", createSchedule(genesisStub.clone().osakaTime(0))),
|
||||||
Map.entry("Amsterdam", createSchedule(genesisStub.clone().futureEipsTime(0))),
|
Map.entry("Amsterdam", createSchedule(genesisStub.clone().futureEipsTime(0))),
|
||||||
Map.entry("Bogota", createSchedule(genesisStub.clone().futureEipsTime(0))),
|
Map.entry("Bogota", createSchedule(genesisStub.clone().futureEipsTime(0))),
|
||||||
Map.entry("Polis", createSchedule(genesisStub.clone().futureEipsTime(0))),
|
Map.entry("Polis", createSchedule(genesisStub.clone().futureEipsTime(0))),
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
package org.hyperledger.besu.ethereum.eof;
|
package org.hyperledger.besu.ethereum.eof;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.fail;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -33,6 +34,7 @@ import org.hyperledger.besu.ethereum.referencetests.ReferenceTestProtocolSchedul
|
|||||||
import org.hyperledger.besu.evm.Code;
|
import org.hyperledger.besu.evm.Code;
|
||||||
import org.hyperledger.besu.evm.EVM;
|
import org.hyperledger.besu.evm.EVM;
|
||||||
import org.hyperledger.besu.evm.code.CodeInvalid;
|
import org.hyperledger.besu.evm.code.CodeInvalid;
|
||||||
|
import org.hyperledger.besu.evm.code.CodeV1;
|
||||||
import org.hyperledger.besu.evm.code.EOFLayout;
|
import org.hyperledger.besu.evm.code.EOFLayout;
|
||||||
import org.hyperledger.besu.testutil.JsonTestParameters;
|
import org.hyperledger.besu.testutil.JsonTestParameters;
|
||||||
|
|
||||||
@@ -41,7 +43,7 @@ public class EOFReferenceTestTools {
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
final String eips =
|
final String eips =
|
||||||
System.getProperty("test.ethereum.eof.eips", "Prague,Osaka,Amsterdam,Bogota,Polis,Bangkok");
|
System.getProperty("test.ethereum.eof.eips", "Osaka,Amsterdam,Bogota,Polis,Bangkok");
|
||||||
EIPS_TO_RUN = Arrays.asList(eips.split(","));
|
EIPS_TO_RUN = Arrays.asList(eips.split(","));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,6 +81,10 @@ public class EOFReferenceTestTools {
|
|||||||
if (EIPS_TO_RUN.isEmpty()) {
|
if (EIPS_TO_RUN.isEmpty()) {
|
||||||
params.ignoreAll();
|
params.ignoreAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EOF was moved from Prague to Osaka
|
||||||
|
params.ignore("-Prague\\[");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private EOFReferenceTestTools() {
|
private EOFReferenceTestTools() {
|
||||||
@@ -132,28 +138,37 @@ public class EOFReferenceTestTools {
|
|||||||
} else {
|
} else {
|
||||||
parsedCode = evm.getCodeUncached(code);
|
parsedCode = evm.getCodeUncached(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expected.result()) {
|
if (expected.result()) {
|
||||||
assertThat(parsedCode.isValid())
|
assertThat(parsedCode.isValid())
|
||||||
.withFailMessage(
|
.withFailMessage(
|
||||||
() -> "Valid code failed with " + ((CodeInvalid) parsedCode).getInvalidReason())
|
() -> "Valid code failed with " + ((CodeInvalid) parsedCode).getInvalidReason())
|
||||||
.isTrue();
|
.isTrue();
|
||||||
} else {
|
} else if (parsedCode.isValid()) {
|
||||||
assertThat(parsedCode.isValid())
|
if (parsedCode instanceof CodeV1 codeV1
|
||||||
.withFailMessage("Invalid code expected " + expected.exception() + " but was valid")
|
&& expected.exception().contains("EOF_IncompatibleContainerKind")) {
|
||||||
.isFalse();
|
// one last container type check
|
||||||
if (name.contains("eip7692")) {
|
var parsedMode = codeV1.getEofLayout().containerMode().get();
|
||||||
// if the test is from EEST, validate the exception name.
|
String actual = parsedMode == null ? "RUNTIME" : parsedMode.toString();
|
||||||
assertThat(((CodeInvalid) parsedCode).getInvalidReason())
|
String expectedContainerKind = containerKind == null ? "RUNTIME" : containerKind;
|
||||||
.withFailMessage(
|
assertThat(actual)
|
||||||
() ->
|
.withFailMessage("EOF_IncompatibleContainerKind expected")
|
||||||
"Expected exception :%s actual exception: %s"
|
.isNotEqualTo(expectedContainerKind);
|
||||||
.formatted(
|
} else {
|
||||||
expected.exception(),
|
fail("Invalid code expected " + expected.exception() + " but was valid");
|
||||||
(parsedCode.isValid()
|
|
||||||
? null
|
|
||||||
: ((CodeInvalid) parsedCode).getInvalidReason())))
|
|
||||||
.containsIgnoringCase(expected.exception().replace("EOFException.", ""));
|
|
||||||
}
|
}
|
||||||
|
} else if (name.contains("eip7692")) {
|
||||||
|
// if the test is from EEST, validate the exception name.
|
||||||
|
assertThat(((CodeInvalid) parsedCode).getInvalidReason())
|
||||||
|
.withFailMessage(
|
||||||
|
() ->
|
||||||
|
"Expected exception :%s actual exception: %s"
|
||||||
|
.formatted(
|
||||||
|
expected.exception(),
|
||||||
|
(parsedCode.isValid()
|
||||||
|
? null
|
||||||
|
: ((CodeInvalid) parsedCode).getInvalidReason())))
|
||||||
|
.containsIgnoringCase(expected.exception().replace("EOFException.", ""));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assertThat(false)
|
assertThat(false)
|
||||||
|
|||||||
@@ -56,8 +56,6 @@ public enum EvmSpecVersion {
|
|||||||
CANCUN_EOF(MainnetHardforkId.CANCUN_EOF, 0x6000, 0xc000, 1),
|
CANCUN_EOF(MainnetHardforkId.CANCUN_EOF, 0x6000, 0xc000, 1),
|
||||||
/** Prague evm spec version. */
|
/** Prague evm spec version. */
|
||||||
PRAGUE(MainnetHardforkId.PRAGUE, 0x6000, 0xc000, 0),
|
PRAGUE(MainnetHardforkId.PRAGUE, 0x6000, 0xc000, 0),
|
||||||
/** PragueEOF evm spec version. */
|
|
||||||
PRAGUE_EOF(MainnetHardforkId.PRAGUE_EOF, 0x6000, 0xc000, 1),
|
|
||||||
/** Osaka evm spec version. */
|
/** Osaka evm spec version. */
|
||||||
OSAKA(MainnetHardforkId.OSAKA, 0x6000, 0xc000, 1),
|
OSAKA(MainnetHardforkId.OSAKA, 0x6000, 0xc000, 1),
|
||||||
/** Amsterdam evm spec version. */
|
/** Amsterdam evm spec version. */
|
||||||
@@ -186,11 +184,11 @@ public enum EvmSpecVersion {
|
|||||||
* @return the EVM spec version for that fork, or null if no fork matched.
|
* @return the EVM spec version for that fork, or null if no fork matched.
|
||||||
*/
|
*/
|
||||||
public static EvmSpecVersion fromName(final String name) {
|
public static EvmSpecVersion fromName(final String name) {
|
||||||
// TODO remove once PragueEOF settles
|
// TODO remove once CancunEOF tests are removed from EEST
|
||||||
if ("prague".equalsIgnoreCase(name)) {
|
if ("prague".equalsIgnoreCase(name)) {
|
||||||
return EvmSpecVersion.PRAGUE_EOF;
|
return EvmSpecVersion.OSAKA;
|
||||||
}
|
}
|
||||||
// TODO remove once PragueEOF settles
|
// TODO remove once CancunEOF tests are removed from EEST
|
||||||
if ("cancuneof".equalsIgnoreCase(name)) {
|
if ("cancuneof".equalsIgnoreCase(name)) {
|
||||||
return EvmSpecVersion.CANCUN_EOF;
|
return EvmSpecVersion.CANCUN_EOF;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
|||||||
import org.hyperledger.besu.evm.gascalculator.HomesteadGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.HomesteadGasCalculator;
|
||||||
import org.hyperledger.besu.evm.gascalculator.IstanbulGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.IstanbulGasCalculator;
|
||||||
import org.hyperledger.besu.evm.gascalculator.LondonGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.LondonGasCalculator;
|
||||||
|
import org.hyperledger.besu.evm.gascalculator.OsakaGasCalculator;
|
||||||
import org.hyperledger.besu.evm.gascalculator.PetersburgGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.PetersburgGasCalculator;
|
||||||
import org.hyperledger.besu.evm.gascalculator.PragueEOFGasCalculator;
|
|
||||||
import org.hyperledger.besu.evm.gascalculator.PragueGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.PragueGasCalculator;
|
||||||
import org.hyperledger.besu.evm.gascalculator.ShanghaiGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.ShanghaiGasCalculator;
|
||||||
import org.hyperledger.besu.evm.gascalculator.SpuriousDragonGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.SpuriousDragonGasCalculator;
|
||||||
@@ -1089,72 +1089,70 @@ public class MainnetEVMs {
|
|||||||
final GasCalculator gasCalculator,
|
final GasCalculator gasCalculator,
|
||||||
final BigInteger chainID) {
|
final BigInteger chainID) {
|
||||||
registerCancunOperations(registry, gasCalculator, chainID);
|
registerCancunOperations(registry, gasCalculator, chainID);
|
||||||
|
|
||||||
// TODO add EOF operations here once PragueEOF is collapsed into Prague
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PragueEOF evm.
|
* Osaka evm.
|
||||||
*
|
*
|
||||||
* @param evmConfiguration the evm configuration
|
* @param evmConfiguration the evm configuration
|
||||||
* @return the evm
|
* @return the evm
|
||||||
*/
|
*/
|
||||||
public static EVM pragueEOF(final EvmConfiguration evmConfiguration) {
|
public static EVM osaka(final EvmConfiguration evmConfiguration) {
|
||||||
return pragueEOF(DEV_NET_CHAIN_ID, evmConfiguration);
|
return osaka(DEV_NET_CHAIN_ID, evmConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PragueEOF evm.
|
* Osaka evm.
|
||||||
*
|
*
|
||||||
* @param chainId the chain id
|
* @param chainId the chain id
|
||||||
* @param evmConfiguration the evm configuration
|
* @param evmConfiguration the evm configuration
|
||||||
* @return the evm
|
* @return the evm
|
||||||
*/
|
*/
|
||||||
public static EVM pragueEOF(final BigInteger chainId, final EvmConfiguration evmConfiguration) {
|
public static EVM osaka(final BigInteger chainId, final EvmConfiguration evmConfiguration) {
|
||||||
return pragueEOF(new PragueEOFGasCalculator(), chainId, evmConfiguration);
|
return osaka(new OsakaGasCalculator(), chainId, evmConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PragueEOF evm.
|
* Osaka evm.
|
||||||
*
|
*
|
||||||
* @param gasCalculator the gas calculator
|
* @param gasCalculator the gas calculator
|
||||||
* @param chainId the chain id
|
* @param chainId the chain id
|
||||||
* @param evmConfiguration the evm configuration
|
* @param evmConfiguration the evm configuration
|
||||||
* @return the evm
|
* @return the evm
|
||||||
*/
|
*/
|
||||||
public static EVM pragueEOF(
|
public static EVM osaka(
|
||||||
final GasCalculator gasCalculator,
|
final GasCalculator gasCalculator,
|
||||||
final BigInteger chainId,
|
final BigInteger chainId,
|
||||||
final EvmConfiguration evmConfiguration) {
|
final EvmConfiguration evmConfiguration) {
|
||||||
return new EVM(
|
return new EVM(
|
||||||
pragueEOFOperations(gasCalculator, chainId),
|
osakaOperations(gasCalculator, chainId),
|
||||||
gasCalculator,
|
gasCalculator,
|
||||||
evmConfiguration,
|
evmConfiguration,
|
||||||
EvmSpecVersion.PRAGUE_EOF);
|
EvmSpecVersion.OSAKA);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operation registry for PragueEOF's operations.
|
* Operation registry for Osaka's operations.
|
||||||
*
|
*
|
||||||
* @param gasCalculator the gas calculator
|
* @param gasCalculator the gas calculator
|
||||||
* @param chainId the chain id
|
* @param chainId the chain id
|
||||||
* @return the operation registry
|
* @return the operation registry
|
||||||
*/
|
*/
|
||||||
public static OperationRegistry pragueEOFOperations(
|
public static OperationRegistry osakaOperations(
|
||||||
final GasCalculator gasCalculator, final BigInteger chainId) {
|
final GasCalculator gasCalculator, final BigInteger chainId) {
|
||||||
OperationRegistry operationRegistry = new OperationRegistry();
|
OperationRegistry operationRegistry = new OperationRegistry();
|
||||||
registerPragueEOFOperations(operationRegistry, gasCalculator, chainId);
|
registerOsakaOperations(operationRegistry, gasCalculator, chainId);
|
||||||
return operationRegistry;
|
return operationRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register PragueEOF's operations.
|
* Register Osaka's operations.
|
||||||
*
|
*
|
||||||
* @param registry the registry
|
* @param registry the registry
|
||||||
* @param gasCalculator the gas calculator
|
* @param gasCalculator the gas calculator
|
||||||
* @param chainID the chain id
|
* @param chainID the chain id
|
||||||
*/
|
*/
|
||||||
public static void registerPragueEOFOperations(
|
public static void registerOsakaOperations(
|
||||||
final OperationRegistry registry,
|
final OperationRegistry registry,
|
||||||
final GasCalculator gasCalculator,
|
final GasCalculator gasCalculator,
|
||||||
final BigInteger chainID) {
|
final BigInteger chainID) {
|
||||||
@@ -1204,74 +1202,6 @@ public class MainnetEVMs {
|
|||||||
registry.put(new ReturnContractOperation(gasCalculator));
|
registry.put(new ReturnContractOperation(gasCalculator));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Osaka evm.
|
|
||||||
*
|
|
||||||
* @param evmConfiguration the evm configuration
|
|
||||||
* @return the evm
|
|
||||||
*/
|
|
||||||
public static EVM osaka(final EvmConfiguration evmConfiguration) {
|
|
||||||
return osaka(DEV_NET_CHAIN_ID, evmConfiguration);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Osaka evm.
|
|
||||||
*
|
|
||||||
* @param chainId the chain id
|
|
||||||
* @param evmConfiguration the evm configuration
|
|
||||||
* @return the evm
|
|
||||||
*/
|
|
||||||
public static EVM osaka(final BigInteger chainId, final EvmConfiguration evmConfiguration) {
|
|
||||||
return osaka(new PragueGasCalculator(), chainId, evmConfiguration);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Osaka evm.
|
|
||||||
*
|
|
||||||
* @param gasCalculator the gas calculator
|
|
||||||
* @param chainId the chain id
|
|
||||||
* @param evmConfiguration the evm configuration
|
|
||||||
* @return the evm
|
|
||||||
*/
|
|
||||||
public static EVM osaka(
|
|
||||||
final GasCalculator gasCalculator,
|
|
||||||
final BigInteger chainId,
|
|
||||||
final EvmConfiguration evmConfiguration) {
|
|
||||||
return new EVM(
|
|
||||||
osakaOperations(gasCalculator, chainId),
|
|
||||||
gasCalculator,
|
|
||||||
evmConfiguration,
|
|
||||||
EvmSpecVersion.OSAKA);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Operation registry for osaka's operations.
|
|
||||||
*
|
|
||||||
* @param gasCalculator the gas calculator
|
|
||||||
* @param chainId the chain id
|
|
||||||
* @return the operation registry
|
|
||||||
*/
|
|
||||||
public static OperationRegistry osakaOperations(
|
|
||||||
final GasCalculator gasCalculator, final BigInteger chainId) {
|
|
||||||
OperationRegistry operationRegistry = new OperationRegistry();
|
|
||||||
registerOsakaOperations(operationRegistry, gasCalculator, chainId);
|
|
||||||
return operationRegistry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register osaka operations.
|
|
||||||
*
|
|
||||||
* @param registry the registry
|
|
||||||
* @param gasCalculator the gas calculator
|
|
||||||
* @param chainID the chain id
|
|
||||||
*/
|
|
||||||
public static void registerOsakaOperations(
|
|
||||||
final OperationRegistry registry,
|
|
||||||
final GasCalculator gasCalculator,
|
|
||||||
final BigInteger chainID) {
|
|
||||||
registerPragueEOFOperations(registry, gasCalculator, chainID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Amsterdam evm.
|
* Amsterdam evm.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -164,7 +164,6 @@ public class EVMExecutor {
|
|||||||
case CANCUN -> cancun(chainId, evmConfiguration);
|
case CANCUN -> cancun(chainId, evmConfiguration);
|
||||||
case CANCUN_EOF -> cancunEOF(chainId, evmConfiguration);
|
case CANCUN_EOF -> cancunEOF(chainId, evmConfiguration);
|
||||||
case PRAGUE -> prague(chainId, evmConfiguration);
|
case PRAGUE -> prague(chainId, evmConfiguration);
|
||||||
case PRAGUE_EOF -> pragueEOF(chainId, evmConfiguration);
|
|
||||||
case OSAKA -> osaka(chainId, evmConfiguration);
|
case OSAKA -> osaka(chainId, evmConfiguration);
|
||||||
case AMSTERDAM -> amsterdam(chainId, evmConfiguration);
|
case AMSTERDAM -> amsterdam(chainId, evmConfiguration);
|
||||||
case BOGOTA -> bogota(chainId, evmConfiguration);
|
case BOGOTA -> bogota(chainId, evmConfiguration);
|
||||||
@@ -526,21 +525,6 @@ public class EVMExecutor {
|
|||||||
return executor;
|
return executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiate PragueEOF evm executor.
|
|
||||||
*
|
|
||||||
* @param chainId the chain ID
|
|
||||||
* @param evmConfiguration the evm configuration
|
|
||||||
* @return the evm executor
|
|
||||||
*/
|
|
||||||
public static EVMExecutor pragueEOF(
|
|
||||||
final BigInteger chainId, final EvmConfiguration evmConfiguration) {
|
|
||||||
final EVMExecutor executor = new EVMExecutor(MainnetEVMs.pragueEOF(chainId, evmConfiguration));
|
|
||||||
executor.precompileContractRegistry =
|
|
||||||
MainnetPrecompiledContracts.prague(executor.evm.getGasCalculator());
|
|
||||||
return executor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate Osaka evm executor.
|
* Instantiate Osaka evm executor.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -26,13 +26,13 @@ import static org.hyperledger.besu.datatypes.Address.BLS12_MAP_FP2_TO_G2;
|
|||||||
* <LI>TBD
|
* <LI>TBD
|
||||||
* </UL>
|
* </UL>
|
||||||
*/
|
*/
|
||||||
public class PragueEOFGasCalculator extends PragueGasCalculator {
|
public class OsakaGasCalculator extends PragueGasCalculator {
|
||||||
|
|
||||||
static final long MIN_RETAINED_GAS = 5_000;
|
static final long MIN_RETAINED_GAS = 5_000;
|
||||||
static final long MIN_CALLEE_GAS = 2300;
|
static final long MIN_CALLEE_GAS = 2300;
|
||||||
|
|
||||||
/** Instantiates a new Prague Gas Calculator. */
|
/** Instantiates a new Prague Gas Calculator. */
|
||||||
public PragueEOFGasCalculator() {
|
public OsakaGasCalculator() {
|
||||||
this(BLS12_MAP_FP2_TO_G2.toArrayUnsafe()[19]);
|
this(BLS12_MAP_FP2_TO_G2.toArrayUnsafe()[19]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ public class PragueEOFGasCalculator extends PragueGasCalculator {
|
|||||||
*
|
*
|
||||||
* @param maxPrecompile the max precompile
|
* @param maxPrecompile the max precompile
|
||||||
*/
|
*/
|
||||||
protected PragueEOFGasCalculator(final int maxPrecompile) {
|
protected OsakaGasCalculator(final int maxPrecompile) {
|
||||||
super(maxPrecompile);
|
super(maxPrecompile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,15 +109,16 @@ public abstract class AbstractExtCallOperation extends AbstractCallOperation {
|
|||||||
long inputOffset = inputDataOffset(frame);
|
long inputOffset = inputDataOffset(frame);
|
||||||
long inputLength = inputDataLength(frame);
|
long inputLength = inputDataLength(frame);
|
||||||
|
|
||||||
|
GasCalculator gasCalculator = gasCalculator();
|
||||||
if (!zeroValue && isStatic(frame)) {
|
if (!zeroValue && isStatic(frame)) {
|
||||||
return new OperationResult(
|
return new OperationResult(
|
||||||
gasCalculator().callValueTransferGasCost(), ExceptionalHaltReason.ILLEGAL_STATE_CHANGE);
|
gasCalculator.callValueTransferGasCost(), ExceptionalHaltReason.ILLEGAL_STATE_CHANGE);
|
||||||
}
|
}
|
||||||
if (toBytes.size() > Address.SIZE) {
|
if (toBytes.size() > Address.SIZE) {
|
||||||
return new OperationResult(
|
return new OperationResult(
|
||||||
gasCalculator().memoryExpansionGasCost(frame, inputOffset, inputLength)
|
gasCalculator.memoryExpansionGasCost(frame, inputOffset, inputLength)
|
||||||
+ (zeroValue ? 0 : gasCalculator().callValueTransferGasCost())
|
+ (zeroValue ? 0 : gasCalculator.callValueTransferGasCost())
|
||||||
+ gasCalculator().getColdAccountAccessCost(),
|
+ gasCalculator.getColdAccountAccessCost(),
|
||||||
ExceptionalHaltReason.ADDRESS_OUT_OF_RANGE);
|
ExceptionalHaltReason.ADDRESS_OUT_OF_RANGE);
|
||||||
}
|
}
|
||||||
Address to = Words.toAddress(toBytes);
|
Address to = Words.toAddress(toBytes);
|
||||||
@@ -125,7 +126,7 @@ public abstract class AbstractExtCallOperation extends AbstractCallOperation {
|
|||||||
|
|
||||||
if (contract != null) {
|
if (contract != null) {
|
||||||
final DelegatedCodeGasCostHelper.Result result =
|
final DelegatedCodeGasCostHelper.Result result =
|
||||||
deductDelegatedCodeGasCost(frame, gasCalculator(), contract);
|
deductDelegatedCodeGasCost(frame, gasCalculator, contract);
|
||||||
if (result.status() != DelegatedCodeGasCostHelper.Status.SUCCESS) {
|
if (result.status() != DelegatedCodeGasCostHelper.Status.SUCCESS) {
|
||||||
return new Operation.OperationResult(
|
return new Operation.OperationResult(
|
||||||
result.gasCost(), ExceptionalHaltReason.INSUFFICIENT_GAS);
|
result.gasCost(), ExceptionalHaltReason.INSUFFICIENT_GAS);
|
||||||
@@ -134,12 +135,12 @@ public abstract class AbstractExtCallOperation extends AbstractCallOperation {
|
|||||||
|
|
||||||
boolean accountCreation = contract == null && !zeroValue;
|
boolean accountCreation = contract == null && !zeroValue;
|
||||||
long cost =
|
long cost =
|
||||||
gasCalculator().memoryExpansionGasCost(frame, inputOffset, inputLength)
|
gasCalculator.memoryExpansionGasCost(frame, inputOffset, inputLength)
|
||||||
+ (zeroValue ? 0 : gasCalculator().callValueTransferGasCost())
|
+ (zeroValue ? 0 : gasCalculator.callValueTransferGasCost())
|
||||||
+ (frame.warmUpAddress(to)
|
+ (frame.warmUpAddress(to) || gasCalculator.isPrecompile(to)
|
||||||
? gasCalculator().getWarmStorageReadCost()
|
? gasCalculator.getWarmStorageReadCost()
|
||||||
: gasCalculator().getColdAccountAccessCost())
|
: gasCalculator.getColdAccountAccessCost())
|
||||||
+ (accountCreation ? gasCalculator().newAccountGasCost() : 0);
|
+ (accountCreation ? gasCalculator.newAccountGasCost() : 0);
|
||||||
long currentGas = frame.getRemainingGas() - cost;
|
long currentGas = frame.getRemainingGas() - cost;
|
||||||
if (currentGas < 0) {
|
if (currentGas < 0) {
|
||||||
return new OperationResult(cost, ExceptionalHaltReason.INSUFFICIENT_GAS);
|
return new OperationResult(cost, ExceptionalHaltReason.INSUFFICIENT_GAS);
|
||||||
@@ -163,14 +164,14 @@ public abstract class AbstractExtCallOperation extends AbstractCallOperation {
|
|||||||
return softFailure(frame, cost);
|
return softFailure(frame, cost);
|
||||||
}
|
}
|
||||||
|
|
||||||
long retainedGas = Math.max(currentGas / 64, gasCalculator().getMinRetainedGas());
|
long retainedGas = Math.max(currentGas / 64, gasCalculator.getMinRetainedGas());
|
||||||
long childGas = currentGas - retainedGas;
|
long childGas = currentGas - retainedGas;
|
||||||
|
|
||||||
final Account account = frame.getWorldUpdater().get(frame.getRecipientAddress());
|
final Account account = frame.getWorldUpdater().get(frame.getRecipientAddress());
|
||||||
final Wei balance = (zeroValue || account == null) ? Wei.ZERO : account.getBalance();
|
final Wei balance = (zeroValue || account == null) ? Wei.ZERO : account.getBalance();
|
||||||
|
|
||||||
// There myst be a minimum gas for a call to have access to.
|
// There myst be a minimum gas for a call to have access to.
|
||||||
if (childGas < gasCalculator().getMinCalleeGas()) {
|
if (childGas < gasCalculator.getMinCalleeGas()) {
|
||||||
return softFailure(frame, cost);
|
return softFailure(frame, cost);
|
||||||
}
|
}
|
||||||
// transferring value you don't have is not a halting exception, just a failure
|
// transferring value you don't have is not a halting exception, just a failure
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package org.hyperledger.besu.evm.operation;
|
|||||||
import org.hyperledger.besu.evm.Code;
|
import org.hyperledger.besu.evm.Code;
|
||||||
import org.hyperledger.besu.evm.EVM;
|
import org.hyperledger.besu.evm.EVM;
|
||||||
import org.hyperledger.besu.evm.code.CodeSection;
|
import org.hyperledger.besu.evm.code.CodeSection;
|
||||||
|
import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
|
||||||
import org.hyperledger.besu.evm.frame.MessageFrame;
|
import org.hyperledger.besu.evm.frame.MessageFrame;
|
||||||
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
||||||
import org.hyperledger.besu.evm.internal.ReturnStack;
|
import org.hyperledger.besu.evm.internal.ReturnStack;
|
||||||
@@ -30,6 +31,9 @@ public class CallFOperation extends AbstractOperation {
|
|||||||
/** The Call F success. */
|
/** The Call F success. */
|
||||||
static final OperationResult callfSuccess = new OperationResult(5, null);
|
static final OperationResult callfSuccess = new OperationResult(5, null);
|
||||||
|
|
||||||
|
static final OperationResult callfStackOverflow =
|
||||||
|
new OperationResult(5, ExceptionalHaltReason.TOO_MANY_STACK_ITEMS);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new Call F operation.
|
* Instantiates a new Call F operation.
|
||||||
*
|
*
|
||||||
@@ -49,6 +53,11 @@ public class CallFOperation extends AbstractOperation {
|
|||||||
int pc = frame.getPC();
|
int pc = frame.getPC();
|
||||||
int section = code.readBigEndianU16(pc + 1);
|
int section = code.readBigEndianU16(pc + 1);
|
||||||
CodeSection info = code.getCodeSection(section);
|
CodeSection info = code.getCodeSection(section);
|
||||||
|
int operandStackSize = frame.stackSize();
|
||||||
|
if (operandStackSize >= 1024
|
||||||
|
|| operandStackSize > 1024 - info.getMaxStackHeight() + info.getInputs()) {
|
||||||
|
return callfStackOverflow;
|
||||||
|
}
|
||||||
frame.getReturnStack().push(new ReturnStack.ReturnStackItem(frame.getSection(), pc + 2));
|
frame.getReturnStack().push(new ReturnStack.ReturnStackItem(frame.getSection(), pc + 2));
|
||||||
frame.setPC(info.getEntryPoint() - 1); // will be +1ed at end of operations loop
|
frame.setPC(info.getEntryPoint() - 1); // will be +1ed at end of operations loop
|
||||||
frame.setSection(section);
|
frame.setSection(section);
|
||||||
|
|||||||
@@ -127,9 +127,7 @@ public class StandardJsonTracer implements OperationTracer {
|
|||||||
for (int i = messageFrame.stackSize() - 1; i >= 0; i--) {
|
for (int i = messageFrame.stackSize() - 1; i >= 0; i--) {
|
||||||
stack.add("\"" + shortBytes(messageFrame.getStackItem(i)) + "\"");
|
stack.add("\"" + shortBytes(messageFrame.getStackItem(i)) + "\"");
|
||||||
}
|
}
|
||||||
pc =
|
pc = messageFrame.getPC() - messageFrame.getCode().getCodeSection(0).getEntryPoint();
|
||||||
messageFrame.getPC()
|
|
||||||
- messageFrame.getCode().getCodeSection(messageFrame.getSection()).getEntryPoint();
|
|
||||||
section = messageFrame.getSection();
|
section = messageFrame.getSection();
|
||||||
gas = shortNumber(messageFrame.getRemainingGas());
|
gas = shortNumber(messageFrame.getRemainingGas());
|
||||||
memorySize = messageFrame.memoryWordSize() * 32;
|
memorySize = messageFrame.memoryWordSize() * 32;
|
||||||
|
|||||||
@@ -594,26 +594,26 @@ class CodeFactoryTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void validCode(final String str) {
|
private static void validCode(final String str) {
|
||||||
EVM evm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
|
EVM evm = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
Code code = evm.getCodeUncached(bytesFromPrettyPrint(str));
|
Code code = evm.getCodeUncached(bytesFromPrettyPrint(str));
|
||||||
assertThat(code.isValid()).isTrue();
|
assertThat(code.isValid()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void invalidCode(final String str, final String error) {
|
private static void invalidCode(final String str, final String error) {
|
||||||
EVM evm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
|
EVM evm = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
Code code = evm.getCodeUncached(bytesFromPrettyPrint(str));
|
Code code = evm.getCodeUncached(bytesFromPrettyPrint(str));
|
||||||
assertThat(code.isValid()).isFalse();
|
assertThat(code.isValid()).isFalse();
|
||||||
assertThat(((CodeInvalid) code).getInvalidReason()).contains(error);
|
assertThat(((CodeInvalid) code).getInvalidReason()).contains(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void invalidCode(final String str) {
|
private static void invalidCode(final String str) {
|
||||||
EVM evm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
|
EVM evm = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
Code code = evm.getCodeUncached(bytesFromPrettyPrint(str));
|
Code code = evm.getCodeUncached(bytesFromPrettyPrint(str));
|
||||||
assertThat(code.isValid()).isFalse();
|
assertThat(code.isValid()).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void invalidCodeForCreation(final String str) {
|
private static void invalidCodeForCreation(final String str) {
|
||||||
EVM evm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
|
EVM evm = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
Code code = evm.getCodeForCreation(bytesFromPrettyPrint(str));
|
Code code = evm.getCodeForCreation(bytesFromPrettyPrint(str));
|
||||||
assertThat(code.isValid()).isFalse();
|
assertThat(code.isValid()).isFalse();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class CodeV0Test {
|
|||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void startUp() {
|
void startUp() {
|
||||||
evm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
|
evm = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -131,9 +131,13 @@ class EVMExecutorTest {
|
|||||||
assertThat(cancunEOFEVM.getChainId()).contains(defaultChainId);
|
assertThat(cancunEOFEVM.getChainId()).contains(defaultChainId);
|
||||||
|
|
||||||
EVMExecutor pragueEVM =
|
EVMExecutor pragueEVM =
|
||||||
EVMExecutor.pragueEOF(defaultChainId.toBigInteger(), EvmConfiguration.DEFAULT);
|
EVMExecutor.prague(defaultChainId.toBigInteger(), EvmConfiguration.DEFAULT);
|
||||||
assertThat(pragueEVM.getChainId()).contains(defaultChainId);
|
assertThat(pragueEVM.getChainId()).contains(defaultChainId);
|
||||||
|
|
||||||
|
EVMExecutor osakaEVM =
|
||||||
|
EVMExecutor.osaka(defaultChainId.toBigInteger(), EvmConfiguration.DEFAULT);
|
||||||
|
assertThat(osakaEVM.getChainId()).contains(defaultChainId);
|
||||||
|
|
||||||
EVMExecutor futureEipsVM = EVMExecutor.futureEips(EvmConfiguration.DEFAULT);
|
EVMExecutor futureEipsVM = EVMExecutor.futureEips(EvmConfiguration.DEFAULT);
|
||||||
assertThat(futureEipsVM.getChainId()).contains(defaultChainId);
|
assertThat(futureEipsVM.getChainId()).contains(defaultChainId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ import org.hyperledger.besu.datatypes.Address;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
class PragueEOFGasCalculatorTest {
|
class OsakaGasCalculatorTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testPrecompileSize() {
|
void testPrecompileSize() {
|
||||||
PragueEOFGasCalculator subject = new PragueEOFGasCalculator();
|
OsakaGasCalculator subject = new OsakaGasCalculator();
|
||||||
assertThat(subject.isPrecompile(Address.precompiled(0x14))).isFalse();
|
assertThat(subject.isPrecompile(Address.precompiled(0x14))).isFalse();
|
||||||
assertThat(subject.isPrecompile(Address.BLS12_MAP_FP2_TO_G2)).isTrue();
|
assertThat(subject.isPrecompile(Address.BLS12_MAP_FP2_TO_G2)).isTrue();
|
||||||
}
|
}
|
||||||
@@ -32,7 +32,7 @@ class PragueEOFGasCalculatorTest {
|
|||||||
@Test
|
@Test
|
||||||
void testNewConstants() {
|
void testNewConstants() {
|
||||||
CancunGasCalculator cancunGas = new CancunGasCalculator();
|
CancunGasCalculator cancunGas = new CancunGasCalculator();
|
||||||
PragueEOFGasCalculator praugeGasCalculator = new PragueEOFGasCalculator();
|
OsakaGasCalculator praugeGasCalculator = new OsakaGasCalculator();
|
||||||
|
|
||||||
assertThat(praugeGasCalculator.getMinCalleeGas()).isGreaterThan(cancunGas.getMinCalleeGas());
|
assertThat(praugeGasCalculator.getMinCalleeGas()).isGreaterThan(cancunGas.getMinCalleeGas());
|
||||||
assertThat(praugeGasCalculator.getMinRetainedGas())
|
assertThat(praugeGasCalculator.getMinRetainedGas())
|
||||||
@@ -30,7 +30,7 @@ class CodeCacheTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testScale() {
|
void testScale() {
|
||||||
EVM evm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
|
EVM evm = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
final Bytes contractBytes =
|
final Bytes contractBytes =
|
||||||
Bytes.fromHexString("0xDEAD" + op + "BEEF" + op + "B0B0" + op + "C0DE" + op + "FACE");
|
Bytes.fromHexString("0xDEAD" + op + "BEEF" + op + "B0B0" + op + "C0DE" + op + "FACE");
|
||||||
final CodeScale scale = new CodeScale();
|
final CodeScale scale = new CodeScale();
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ public class Create2OperationTest {
|
|||||||
private MessageFrame messageFrame;
|
private MessageFrame messageFrame;
|
||||||
private final WorldUpdater worldUpdater = mock(WorldUpdater.class);
|
private final WorldUpdater worldUpdater = mock(WorldUpdater.class);
|
||||||
private final MutableAccount account = mock(MutableAccount.class);
|
private final MutableAccount account = mock(MutableAccount.class);
|
||||||
private final EVM evm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
|
private final EVM evm = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
private final MutableAccount newAccount = mock(MutableAccount.class);
|
private final MutableAccount newAccount = mock(MutableAccount.class);
|
||||||
|
|
||||||
private final Create2Operation operation =
|
private final Create2Operation operation =
|
||||||
|
|||||||
@@ -219,7 +219,7 @@ class CreateOperationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void eofV1CannotCall() {
|
void eofV1CannotCall() {
|
||||||
final EVM pragueEvm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
|
final EVM pragueEvm = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
final UInt256 memoryOffset = UInt256.fromHexString("0xFF");
|
final UInt256 memoryOffset = UInt256.fromHexString("0xFF");
|
||||||
final UInt256 memoryLength = UInt256.valueOf(SIMPLE_CREATE.size());
|
final UInt256 memoryLength = UInt256.valueOf(SIMPLE_CREATE.size());
|
||||||
final MessageFrame messageFrame =
|
final MessageFrame messageFrame =
|
||||||
@@ -248,7 +248,7 @@ class CreateOperationTest {
|
|||||||
final UInt256 memoryLength,
|
final UInt256 memoryLength,
|
||||||
final UInt256 value,
|
final UInt256 value,
|
||||||
final int depth) {
|
final int depth) {
|
||||||
final EVM evm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
|
final EVM evm = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
final MessageFrame messageFrame =
|
final MessageFrame messageFrame =
|
||||||
MessageFrame.builder()
|
MessageFrame.builder()
|
||||||
.type(MessageFrame.Type.CONTRACT_CREATION)
|
.type(MessageFrame.Type.CONTRACT_CREATION)
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import org.junit.jupiter.params.provider.MethodSource;
|
|||||||
|
|
||||||
class DataCopyOperationTest {
|
class DataCopyOperationTest {
|
||||||
|
|
||||||
static EVM evm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
|
static EVM evm = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
|
|
||||||
static Collection<Object[]> datacopyTestVector() {
|
static Collection<Object[]> datacopyTestVector() {
|
||||||
return Arrays.asList(
|
return Arrays.asList(
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ class EofCreateOperationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void innerContractIsCorrect() {
|
void innerContractIsCorrect() {
|
||||||
final EVM evm = MainnetEVMs.cancunEOF(EvmConfiguration.DEFAULT);
|
final EVM evm = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
Code code = evm.getCodeUncached(INNER_CONTRACT);
|
Code code = evm.getCodeUncached(INNER_CONTRACT);
|
||||||
assertThat(code.isValid()).isTrue();
|
assertThat(code.isValid()).isTrue();
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ class EofCreateOperationTest {
|
|||||||
@Test
|
@Test
|
||||||
void eofCreatePassesInCallData() {
|
void eofCreatePassesInCallData() {
|
||||||
Bytes outerContract = EOF_CREATE_CONTRACT;
|
Bytes outerContract = EOF_CREATE_CONTRACT;
|
||||||
final EVM evm = MainnetEVMs.cancunEOF(EvmConfiguration.DEFAULT);
|
final EVM evm = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
|
|
||||||
Code code = evm.getCodeUncached(outerContract);
|
Code code = evm.getCodeUncached(outerContract);
|
||||||
if (!code.isValid()) {
|
if (!code.isValid()) {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import org.hyperledger.besu.evm.MainnetEVMs;
|
|||||||
import org.hyperledger.besu.evm.account.MutableAccount;
|
import org.hyperledger.besu.evm.account.MutableAccount;
|
||||||
import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
|
import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
|
||||||
import org.hyperledger.besu.evm.frame.MessageFrame;
|
import org.hyperledger.besu.evm.frame.MessageFrame;
|
||||||
import org.hyperledger.besu.evm.gascalculator.PragueEOFGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.OsakaGasCalculator;
|
||||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||||
import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder;
|
import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder;
|
||||||
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
|
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
|
||||||
@@ -44,7 +44,7 @@ public class ExtCallOperationTest {
|
|||||||
|
|
||||||
private final WorldUpdater worldUpdater = mock(WorldUpdater.class);
|
private final WorldUpdater worldUpdater = mock(WorldUpdater.class);
|
||||||
private final MutableAccount account = mock(MutableAccount.class);
|
private final MutableAccount account = mock(MutableAccount.class);
|
||||||
private static final EVM EOF_EVM = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
|
private static final EVM EOF_EVM = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
public static final Code LEGACY_CODE =
|
public static final Code LEGACY_CODE =
|
||||||
EOF_EVM.getCodeUncached(Bytes.of(ExtCallOperation.OPCODE, 1));
|
EOF_EVM.getCodeUncached(Bytes.of(ExtCallOperation.OPCODE, 1));
|
||||||
public static final Code SIMPLE_EOF =
|
public static final Code SIMPLE_EOF =
|
||||||
@@ -115,7 +115,7 @@ public class ExtCallOperationTest {
|
|||||||
final Bytes stackItem,
|
final Bytes stackItem,
|
||||||
final boolean validCode,
|
final boolean validCode,
|
||||||
final boolean warmAddress) {
|
final boolean warmAddress) {
|
||||||
final ExtCallOperation operation = new ExtCallOperation(new PragueEOFGasCalculator());
|
final ExtCallOperation operation = new ExtCallOperation(new OsakaGasCalculator());
|
||||||
|
|
||||||
final var messageFrame =
|
final var messageFrame =
|
||||||
new TestMessageFrameBuilder()
|
new TestMessageFrameBuilder()
|
||||||
@@ -206,7 +206,7 @@ public class ExtCallOperationTest {
|
|||||||
final Wei valueSent,
|
final Wei valueSent,
|
||||||
final Wei valueWeiHave,
|
final Wei valueWeiHave,
|
||||||
final boolean isStatic) {
|
final boolean isStatic) {
|
||||||
final ExtCallOperation operation = new ExtCallOperation(new PragueEOFGasCalculator());
|
final ExtCallOperation operation = new ExtCallOperation(new OsakaGasCalculator());
|
||||||
|
|
||||||
final var messageFrame =
|
final var messageFrame =
|
||||||
new TestMessageFrameBuilder()
|
new TestMessageFrameBuilder()
|
||||||
@@ -242,7 +242,7 @@ public class ExtCallOperationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void overflowTest() {
|
void overflowTest() {
|
||||||
final ExtCallOperation operation = new ExtCallOperation(new PragueEOFGasCalculator());
|
final ExtCallOperation operation = new ExtCallOperation(new OsakaGasCalculator());
|
||||||
|
|
||||||
final var messageFrame =
|
final var messageFrame =
|
||||||
new TestMessageFrameBuilder()
|
new TestMessageFrameBuilder()
|
||||||
@@ -281,7 +281,7 @@ public class ExtCallOperationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void legacyTest() {
|
void legacyTest() {
|
||||||
final ExtCallOperation operation = new ExtCallOperation(new PragueEOFGasCalculator());
|
final ExtCallOperation operation = new ExtCallOperation(new OsakaGasCalculator());
|
||||||
|
|
||||||
final var messageFrame =
|
final var messageFrame =
|
||||||
new TestMessageFrameBuilder()
|
new TestMessageFrameBuilder()
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import org.hyperledger.besu.evm.MainnetEVMs;
|
|||||||
import org.hyperledger.besu.evm.account.MutableAccount;
|
import org.hyperledger.besu.evm.account.MutableAccount;
|
||||||
import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
|
import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
|
||||||
import org.hyperledger.besu.evm.frame.MessageFrame;
|
import org.hyperledger.besu.evm.frame.MessageFrame;
|
||||||
import org.hyperledger.besu.evm.gascalculator.PragueEOFGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.OsakaGasCalculator;
|
||||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||||
import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder;
|
import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder;
|
||||||
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
|
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
|
||||||
@@ -45,7 +45,7 @@ public class ExtDelegateCallOperationTest {
|
|||||||
private final WorldUpdater worldUpdater = mock(WorldUpdater.class);
|
private final WorldUpdater worldUpdater = mock(WorldUpdater.class);
|
||||||
private final MutableAccount account = mock(MutableAccount.class);
|
private final MutableAccount account = mock(MutableAccount.class);
|
||||||
// private final MutableAccount targetAccount = mock(MutableAccount.class);
|
// private final MutableAccount targetAccount = mock(MutableAccount.class);
|
||||||
private static final EVM EOF_EVM = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
|
private static final EVM EOF_EVM = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
public static final Code LEGACY_CODE =
|
public static final Code LEGACY_CODE =
|
||||||
EOF_EVM.getCodeUncached(Bytes.of(ExtDelegateCallOperation.OPCODE, 1));
|
EOF_EVM.getCodeUncached(Bytes.of(ExtDelegateCallOperation.OPCODE, 1));
|
||||||
public static final Code SIMPLE_EOF =
|
public static final Code SIMPLE_EOF =
|
||||||
@@ -119,7 +119,7 @@ public class ExtDelegateCallOperationTest {
|
|||||||
final boolean validCode,
|
final boolean validCode,
|
||||||
final boolean warmAddress) {
|
final boolean warmAddress) {
|
||||||
final ExtDelegateCallOperation operation =
|
final ExtDelegateCallOperation operation =
|
||||||
new ExtDelegateCallOperation(new PragueEOFGasCalculator());
|
new ExtDelegateCallOperation(new OsakaGasCalculator());
|
||||||
|
|
||||||
final var messageFrame =
|
final var messageFrame =
|
||||||
new TestMessageFrameBuilder()
|
new TestMessageFrameBuilder()
|
||||||
@@ -180,7 +180,7 @@ public class ExtDelegateCallOperationTest {
|
|||||||
final ExceptionalHaltReason haltReason,
|
final ExceptionalHaltReason haltReason,
|
||||||
final Bytes stackItem) {
|
final Bytes stackItem) {
|
||||||
final ExtDelegateCallOperation operation =
|
final ExtDelegateCallOperation operation =
|
||||||
new ExtDelegateCallOperation(new PragueEOFGasCalculator());
|
new ExtDelegateCallOperation(new OsakaGasCalculator());
|
||||||
|
|
||||||
final var messageFrame =
|
final var messageFrame =
|
||||||
new TestMessageFrameBuilder()
|
new TestMessageFrameBuilder()
|
||||||
@@ -227,7 +227,7 @@ public class ExtDelegateCallOperationTest {
|
|||||||
@Test
|
@Test
|
||||||
void overflowTest() {
|
void overflowTest() {
|
||||||
final ExtDelegateCallOperation operation =
|
final ExtDelegateCallOperation operation =
|
||||||
new ExtDelegateCallOperation(new PragueEOFGasCalculator());
|
new ExtDelegateCallOperation(new OsakaGasCalculator());
|
||||||
final var messageFrame =
|
final var messageFrame =
|
||||||
new TestMessageFrameBuilder()
|
new TestMessageFrameBuilder()
|
||||||
.initialGas(400000)
|
.initialGas(400000)
|
||||||
@@ -265,7 +265,7 @@ public class ExtDelegateCallOperationTest {
|
|||||||
@Test
|
@Test
|
||||||
void legacyTest() {
|
void legacyTest() {
|
||||||
final ExtDelegateCallOperation operation =
|
final ExtDelegateCallOperation operation =
|
||||||
new ExtDelegateCallOperation(new PragueEOFGasCalculator());
|
new ExtDelegateCallOperation(new OsakaGasCalculator());
|
||||||
|
|
||||||
final var messageFrame =
|
final var messageFrame =
|
||||||
new TestMessageFrameBuilder()
|
new TestMessageFrameBuilder()
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import org.hyperledger.besu.evm.MainnetEVMs;
|
|||||||
import org.hyperledger.besu.evm.account.MutableAccount;
|
import org.hyperledger.besu.evm.account.MutableAccount;
|
||||||
import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
|
import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
|
||||||
import org.hyperledger.besu.evm.frame.MessageFrame;
|
import org.hyperledger.besu.evm.frame.MessageFrame;
|
||||||
import org.hyperledger.besu.evm.gascalculator.PragueEOFGasCalculator;
|
import org.hyperledger.besu.evm.gascalculator.OsakaGasCalculator;
|
||||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||||
import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder;
|
import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder;
|
||||||
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
|
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
|
||||||
@@ -44,7 +44,7 @@ public class ExtStaticCallOperationTest {
|
|||||||
|
|
||||||
private final WorldUpdater worldUpdater = mock(WorldUpdater.class);
|
private final WorldUpdater worldUpdater = mock(WorldUpdater.class);
|
||||||
private final MutableAccount account = mock(MutableAccount.class);
|
private final MutableAccount account = mock(MutableAccount.class);
|
||||||
private static final EVM EOF_EVM = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
|
private static final EVM EOF_EVM = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
public static final Code LEGACY_CODE =
|
public static final Code LEGACY_CODE =
|
||||||
EOF_EVM.getCodeUncached(Bytes.of(ExtStaticCallOperation.OPCODE, 1));
|
EOF_EVM.getCodeUncached(Bytes.of(ExtStaticCallOperation.OPCODE, 1));
|
||||||
public static final Code SIMPLE_EOF =
|
public static final Code SIMPLE_EOF =
|
||||||
@@ -115,8 +115,7 @@ public class ExtStaticCallOperationTest {
|
|||||||
final Bytes stackItem,
|
final Bytes stackItem,
|
||||||
final boolean validCode,
|
final boolean validCode,
|
||||||
final boolean warmAddress) {
|
final boolean warmAddress) {
|
||||||
final ExtStaticCallOperation operation =
|
final ExtStaticCallOperation operation = new ExtStaticCallOperation(new OsakaGasCalculator());
|
||||||
new ExtStaticCallOperation(new PragueEOFGasCalculator());
|
|
||||||
|
|
||||||
final var messageFrame =
|
final var messageFrame =
|
||||||
new TestMessageFrameBuilder()
|
new TestMessageFrameBuilder()
|
||||||
@@ -152,8 +151,7 @@ public class ExtStaticCallOperationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void overflowTest() {
|
void overflowTest() {
|
||||||
final ExtStaticCallOperation operation =
|
final ExtStaticCallOperation operation = new ExtStaticCallOperation(new OsakaGasCalculator());
|
||||||
new ExtStaticCallOperation(new PragueEOFGasCalculator());
|
|
||||||
final var messageFrame =
|
final var messageFrame =
|
||||||
new TestMessageFrameBuilder()
|
new TestMessageFrameBuilder()
|
||||||
.initialGas(400000)
|
.initialGas(400000)
|
||||||
@@ -190,8 +188,7 @@ public class ExtStaticCallOperationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void legacyTest() {
|
void legacyTest() {
|
||||||
final ExtStaticCallOperation operation =
|
final ExtStaticCallOperation operation = new ExtStaticCallOperation(new OsakaGasCalculator());
|
||||||
new ExtStaticCallOperation(new PragueEOFGasCalculator());
|
|
||||||
|
|
||||||
final var messageFrame =
|
final var messageFrame =
|
||||||
new TestMessageFrameBuilder()
|
new TestMessageFrameBuilder()
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class JumpOperationTest {
|
|||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void init() {
|
void init() {
|
||||||
evm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
|
evm = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public class SelfDestructOperationTest {
|
|||||||
@Mock private WorldUpdater worldUpdater;
|
@Mock private WorldUpdater worldUpdater;
|
||||||
@Mock private MutableAccount accountOriginator;
|
@Mock private MutableAccount accountOriginator;
|
||||||
@Mock private MutableAccount accountBeneficiary;
|
@Mock private MutableAccount accountBeneficiary;
|
||||||
private final EVM evm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
|
private final EVM evm = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
|
|
||||||
private final SelfDestructOperation frontierOperation =
|
private final SelfDestructOperation frontierOperation =
|
||||||
new SelfDestructOperation(new ConstantinopleGasCalculator());
|
new SelfDestructOperation(new ConstantinopleGasCalculator());
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
|||||||
class ContractCreationProcessorTest
|
class ContractCreationProcessorTest
|
||||||
extends AbstractMessageProcessorTest<ContractCreationProcessor> {
|
extends AbstractMessageProcessorTest<ContractCreationProcessor> {
|
||||||
|
|
||||||
EVM evm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
|
EVM evm = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
|
|
||||||
private ContractCreationProcessor processor;
|
private ContractCreationProcessor processor;
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class ExtendedOperationTracerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldCallTraceAccountCreationResultIfIsExtendedTracing() {
|
void shouldCallTraceAccountCreationResultIfIsExtendedTracing() {
|
||||||
EVM evm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
|
EVM evm = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
final ContractCreationProcessor contractCreationProcessor =
|
final ContractCreationProcessor contractCreationProcessor =
|
||||||
new ContractCreationProcessor(evm, false, Collections.emptyList(), 0);
|
new ContractCreationProcessor(evm, false, Collections.emptyList(), 0);
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ class ExtendedOperationTracerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldNotCallTraceAccountCreationResultIfIsNotExtendedTracing() {
|
void shouldNotCallTraceAccountCreationResultIfIsNotExtendedTracing() {
|
||||||
EVM evm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
|
EVM evm = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
final ContractCreationProcessor contractCreationProcessor =
|
final ContractCreationProcessor contractCreationProcessor =
|
||||||
new ContractCreationProcessor(evm, false, Collections.emptyList(), 0);
|
new ContractCreationProcessor(evm, false, Collections.emptyList(), 0);
|
||||||
|
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ public class EofContainerSubCommand implements Runnable {
|
|||||||
.constructParametricType(Map.class, String.class, EOFTestCaseSpec.class);
|
.constructParametricType(Map.class, String.class, EOFTestCaseSpec.class);
|
||||||
|
|
||||||
List<FuzzingClient> fuzzingClients = new ArrayList<>();
|
List<FuzzingClient> fuzzingClients = new ArrayList<>();
|
||||||
EVM evm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
|
EVM evm = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
long validContainers;
|
long validContainers;
|
||||||
long totalContainers;
|
long totalContainers;
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class InternalClient implements FuzzingClient {
|
|||||||
|
|
||||||
public InternalClient(final String clientName) {
|
public InternalClient(final String clientName) {
|
||||||
this.name = clientName;
|
this.name = clientName;
|
||||||
this.evm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
|
this.evm = MainnetEVMs.osaka(EvmConfiguration.DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user