From 4b840547cff8caf4303b7adbc359331a92f69a5e Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Tue, 23 Jul 2024 12:00:48 +1000 Subject: [PATCH 01/14] TrieLogPruner preload with 30 second timeout Signed-off-by: Simon Dudley --- .../common/trielog/TrieLogPruner.java | 70 ++++++++++++++++--- 1 file changed, 59 insertions(+), 11 deletions(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java index cea5c1a327d..8674add1fd4 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java @@ -25,7 +25,14 @@ import org.hyperledger.besu.plugin.services.trielogs.TrieLogEvent; import java.util.Comparator; +import java.util.List; import java.util.Optional; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; import java.util.stream.Stream; @@ -40,6 +47,7 @@ public class TrieLogPruner implements TrieLogEvent.TrieLogObserver { private static final Logger LOG = LoggerFactory.getLogger(TrieLogPruner.class); + private static final int PRELOAD_TIMEOUT_IN_SECONDS = 30; private final int pruningLimit; private final int loadingLimit; @@ -83,25 +91,56 @@ public TrieLogPruner( BesuMetricCategory.PRUNER, "trie_log_pruned_orphan", "trie log pruned orphan"); } - public int initialize() { - return preloadQueue(); + public void initialize() { + preloadQueueWithTimeout(); } - private int preloadQueue() { + private void preloadQueueWithTimeout() { LOG.atInfo() - .setMessage("Loading first {} trie logs from database...") + .setMessage("Attempting to load first {} trie logs from database...") .addArgument(loadingLimit) .log(); - try (final Stream trieLogKeys = rootWorldStateStorage.streamTrieLogKeys(loadingLimit)) { - final AtomicLong count = new AtomicLong(); + + final AtomicBoolean timeoutOccurred = new AtomicBoolean(false); + final Runnable timeoutTask = + () -> { + timeoutOccurred.set(true); + LOG.atWarn() + .setMessage("Timeout occurred while loading {} trie logs from database") + .addArgument(loadingLimit) + .log(); + }; + + try (final Stream trieLogKeysStream = + rootWorldStateStorage.streamTrieLogKeys(loadingLimit); + final ScheduledExecutorService preloadExecutor = Executors.newScheduledThreadPool(1)) { + + final List trieLogKeys = trieLogKeysStream.toList(); + + LOG.atInfo().log( + "Loaded {} trie logs from database, determining if any can be pruned...", + trieLogKeys.size()); + LOG.atInfo() + .setMessage( + "Trie log loading will timeout after {} seconds. If this is timing out, consider using `besu storage trie-log prune` subcommand, see https://besu.hyperledger.org/public-networks/how-to/bonsai-limit-trie-logs") + .addArgument(PRELOAD_TIMEOUT_IN_SECONDS) + .log(); + final ScheduledFuture timeoutFuture = + preloadExecutor.schedule(timeoutTask, PRELOAD_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS); + + final AtomicLong addToPruneQueueCount = new AtomicLong(); final AtomicLong orphansPruned = new AtomicLong(); trieLogKeys.forEach( blockHashAsBytes -> { + if (timeoutOccurred.get()) { + throw new RuntimeException( + new TimeoutException("Timeout occurred while preloading trie log prune queue")); + } final Hash blockHash = Hash.wrap(Bytes32.wrap(blockHashAsBytes)); final Optional header = blockchain.getBlockHeader(blockHash); if (header.isPresent()) { addToPruneQueue(header.get().getNumber(), blockHash); - count.getAndIncrement(); + addToPruneQueueCount.getAndIncrement(); } else { // prune orphaned blocks (sometimes created during block production) rootWorldStateStorage.pruneTrieLog(blockHash); @@ -109,12 +148,21 @@ private int preloadQueue() { prunedOrphanCounter.inc(); } }); + + timeoutFuture.cancel(true); LOG.atDebug().log("Pruned {} orphaned trie logs from database...", orphansPruned.intValue()); - LOG.atInfo().log("Loaded {} trie logs from database", count); - return pruneFromQueue() + orphansPruned.intValue(); + LOG.atInfo().log( + "Added {} trie logs to prune queue. Commencing pruning of eligible trie logs...", + addToPruneQueueCount.intValue()); + int prunedCount = pruneFromQueue(); + LOG.atInfo().log("Pruned {} trie logs.", prunedCount); } catch (Exception e) { - LOG.error("Error loading trie logs from database, nothing pruned", e); - return 0; + if (e.getCause() != null && e.getCause() instanceof TimeoutException) { + int prunedCount = pruneFromQueue(); + LOG.atInfo().log("Operation timed out, but still pruned {} trie logs.", prunedCount); + } else { + LOG.error("Error loading trie logs from database, nothing pruned", e); + } } } From 3f91cda50525140cf6f0e7ed0aa11df03065db2c Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Tue, 23 Jul 2024 12:33:49 +1000 Subject: [PATCH 02/14] Schedule timeout task before key streaming begins Signed-off-by: Simon Dudley --- .../common/trielog/TrieLogPruner.java | 96 ++++++++++--------- 1 file changed, 51 insertions(+), 45 deletions(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java index 8674add1fd4..8ff1ff77b8e 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java @@ -96,10 +96,6 @@ public void initialize() { } private void preloadQueueWithTimeout() { - LOG.atInfo() - .setMessage("Attempting to load first {} trie logs from database...") - .addArgument(loadingLimit) - .log(); final AtomicBoolean timeoutOccurred = new AtomicBoolean(false); final Runnable timeoutTask = @@ -111,57 +107,67 @@ private void preloadQueueWithTimeout() { .log(); }; - try (final Stream trieLogKeysStream = - rootWorldStateStorage.streamTrieLogKeys(loadingLimit); - final ScheduledExecutorService preloadExecutor = Executors.newScheduledThreadPool(1)) { + LOG.atInfo() + .setMessage("Attempting to load first {} trie logs from database...") + .addArgument(loadingLimit) + .log(); - final List trieLogKeys = trieLogKeysStream.toList(); + try (final ScheduledExecutorService preloadExecutor = Executors.newScheduledThreadPool(1)) { - LOG.atInfo().log( - "Loaded {} trie logs from database, determining if any can be pruned...", - trieLogKeys.size()); + final ScheduledFuture timeoutFuture = + preloadExecutor.schedule(timeoutTask, PRELOAD_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS); LOG.atInfo() .setMessage( "Trie log loading will timeout after {} seconds. If this is timing out, consider using `besu storage trie-log prune` subcommand, see https://besu.hyperledger.org/public-networks/how-to/bonsai-limit-trie-logs") .addArgument(PRELOAD_TIMEOUT_IN_SECONDS) .log(); - final ScheduledFuture timeoutFuture = - preloadExecutor.schedule(timeoutTask, PRELOAD_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS); - final AtomicLong addToPruneQueueCount = new AtomicLong(); - final AtomicLong orphansPruned = new AtomicLong(); - trieLogKeys.forEach( - blockHashAsBytes -> { - if (timeoutOccurred.get()) { - throw new RuntimeException( - new TimeoutException("Timeout occurred while preloading trie log prune queue")); - } - final Hash blockHash = Hash.wrap(Bytes32.wrap(blockHashAsBytes)); - final Optional header = blockchain.getBlockHeader(blockHash); - if (header.isPresent()) { - addToPruneQueue(header.get().getNumber(), blockHash); - addToPruneQueueCount.getAndIncrement(); - } else { - // prune orphaned blocks (sometimes created during block production) - rootWorldStateStorage.pruneTrieLog(blockHash); - orphansPruned.getAndIncrement(); - prunedOrphanCounter.inc(); - } - }); + try (final Stream trieLogKeysStream = + rootWorldStateStorage.streamTrieLogKeys(loadingLimit)) { + + final List trieLogKeys = trieLogKeysStream.toList(); + + LOG.atInfo() + .setMessage("Loaded {} trie logs from database, determining if any can be pruned...") + .addArgument(trieLogKeys.size()) + .log(); + + final AtomicLong addToPruneQueueCount = new AtomicLong(); + final AtomicLong orphansPruned = new AtomicLong(); + trieLogKeys.forEach( + blockHashAsBytes -> { + if (timeoutOccurred.get()) { + throw new RuntimeException( + new TimeoutException("Timeout occurred while preloading trie log prune queue")); + } + final Hash blockHash = Hash.wrap(Bytes32.wrap(blockHashAsBytes)); + final Optional header = blockchain.getBlockHeader(blockHash); + if (header.isPresent()) { + addToPruneQueue(header.get().getNumber(), blockHash); + addToPruneQueueCount.getAndIncrement(); + } else { + // prune orphaned blocks (sometimes created during block production) + rootWorldStateStorage.pruneTrieLog(blockHash); + orphansPruned.getAndIncrement(); + prunedOrphanCounter.inc(); + } + }); - timeoutFuture.cancel(true); - LOG.atDebug().log("Pruned {} orphaned trie logs from database...", orphansPruned.intValue()); - LOG.atInfo().log( - "Added {} trie logs to prune queue. Commencing pruning of eligible trie logs...", - addToPruneQueueCount.intValue()); - int prunedCount = pruneFromQueue(); - LOG.atInfo().log("Pruned {} trie logs.", prunedCount); - } catch (Exception e) { - if (e.getCause() != null && e.getCause() instanceof TimeoutException) { + timeoutFuture.cancel(true); + LOG.atDebug().log( + "Pruned {} orphaned trie logs from database...", orphansPruned.intValue()); + LOG.atInfo().log( + "Added {} trie logs to prune queue. Commencing pruning of eligible trie logs...", + addToPruneQueueCount.intValue()); int prunedCount = pruneFromQueue(); - LOG.atInfo().log("Operation timed out, but still pruned {} trie logs.", prunedCount); - } else { - LOG.error("Error loading trie logs from database, nothing pruned", e); + LOG.atInfo().log("Pruned {} trie logs.", prunedCount); + } catch (Exception e) { + if (e.getCause() != null && e.getCause() instanceof TimeoutException) { + int prunedCount = pruneFromQueue(); + LOG.atInfo().log("Operation timed out, but still pruned {} trie logs.", prunedCount); + } else { + LOG.error("Error loading trie logs from database, nothing pruned", e); + } } } } From 5ba166db6916dd8ce4a1c2a5ec80c45b214ca2dc Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Tue, 23 Jul 2024 14:01:26 +1000 Subject: [PATCH 03/14] Maintain stream instead of terminating with toList Signed-off-by: Simon Dudley --- .../common/trielog/TrieLogPruner.java | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java index 8ff1ff77b8e..ebcbf550b08 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java @@ -25,7 +25,6 @@ import org.hyperledger.besu.plugin.services.trielogs.TrieLogEvent; import java.util.Comparator; -import java.util.List; import java.util.Optional; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -97,16 +96,6 @@ public void initialize() { private void preloadQueueWithTimeout() { - final AtomicBoolean timeoutOccurred = new AtomicBoolean(false); - final Runnable timeoutTask = - () -> { - timeoutOccurred.set(true); - LOG.atWarn() - .setMessage("Timeout occurred while loading {} trie logs from database") - .addArgument(loadingLimit) - .log(); - }; - LOG.atInfo() .setMessage("Attempting to load first {} trie logs from database...") .addArgument(loadingLimit) @@ -114,6 +103,17 @@ private void preloadQueueWithTimeout() { try (final ScheduledExecutorService preloadExecutor = Executors.newScheduledThreadPool(1)) { + final AtomicBoolean timeoutOccurred = new AtomicBoolean(false); + final Runnable timeoutTask = + () -> { + timeoutOccurred.set(true); + LOG.atWarn() + .setMessage( + "Timeout occurred while loading and processing {} trie logs from database") + .addArgument(loadingLimit) + .log(); + }; + final ScheduledFuture timeoutFuture = preloadExecutor.schedule(timeoutTask, PRELOAD_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS); LOG.atInfo() @@ -122,14 +122,11 @@ private void preloadQueueWithTimeout() { .addArgument(PRELOAD_TIMEOUT_IN_SECONDS) .log(); - try (final Stream trieLogKeysStream = + try (final Stream trieLogKeys = rootWorldStateStorage.streamTrieLogKeys(loadingLimit)) { - final List trieLogKeys = trieLogKeysStream.toList(); - LOG.atInfo() - .setMessage("Loaded {} trie logs from database, determining if any can be pruned...") - .addArgument(trieLogKeys.size()) + .setMessage("Loaded trie logs from database, determining if any can be pruned...") .log(); final AtomicLong addToPruneQueueCount = new AtomicLong(); From b94c6c28387339e644a34fa490846ad45fa17804 Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Tue, 23 Jul 2024 14:18:12 +1000 Subject: [PATCH 04/14] Refactor Signed-off-by: Simon Dudley --- .../common/trielog/TrieLogPruner.java | 84 ++++++++++--------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java index ebcbf550b08..88d32be475c 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java @@ -118,53 +118,57 @@ private void preloadQueueWithTimeout() { preloadExecutor.schedule(timeoutTask, PRELOAD_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS); LOG.atInfo() .setMessage( - "Trie log loading will timeout after {} seconds. If this is timing out, consider using `besu storage trie-log prune` subcommand, see https://besu.hyperledger.org/public-networks/how-to/bonsai-limit-trie-logs") + "Trie log pruning will timeout after {} seconds. If this is timing out, consider using `besu storage trie-log prune` subcommand, see https://besu.hyperledger.org/public-networks/how-to/bonsai-limit-trie-logs") .addArgument(PRELOAD_TIMEOUT_IN_SECONDS) .log(); - try (final Stream trieLogKeys = - rootWorldStateStorage.streamTrieLogKeys(loadingLimit)) { + preloadQueue(timeoutOccurred, timeoutFuture); + } + } + + private void preloadQueue( + final AtomicBoolean timeoutOccurred, final ScheduledFuture timeoutFuture) { + + try (final Stream trieLogKeys = rootWorldStateStorage.streamTrieLogKeys(loadingLimit)) { - LOG.atInfo() - .setMessage("Loaded trie logs from database, determining if any can be pruned...") - .log(); + LOG.atInfo() + .setMessage("Loaded trie logs from database, determining if any can be pruned...") + .log(); - final AtomicLong addToPruneQueueCount = new AtomicLong(); - final AtomicLong orphansPruned = new AtomicLong(); - trieLogKeys.forEach( - blockHashAsBytes -> { - if (timeoutOccurred.get()) { - throw new RuntimeException( - new TimeoutException("Timeout occurred while preloading trie log prune queue")); - } - final Hash blockHash = Hash.wrap(Bytes32.wrap(blockHashAsBytes)); - final Optional header = blockchain.getBlockHeader(blockHash); - if (header.isPresent()) { - addToPruneQueue(header.get().getNumber(), blockHash); - addToPruneQueueCount.getAndIncrement(); - } else { - // prune orphaned blocks (sometimes created during block production) - rootWorldStateStorage.pruneTrieLog(blockHash); - orphansPruned.getAndIncrement(); - prunedOrphanCounter.inc(); - } - }); + final AtomicLong addToPruneQueueCount = new AtomicLong(); + final AtomicLong orphansPruned = new AtomicLong(); + trieLogKeys.forEach( + blockHashAsBytes -> { + if (timeoutOccurred.get()) { + throw new RuntimeException( + new TimeoutException("Timeout occurred while preloading trie log prune queue")); + } + final Hash blockHash = Hash.wrap(Bytes32.wrap(blockHashAsBytes)); + final Optional header = blockchain.getBlockHeader(blockHash); + if (header.isPresent()) { + addToPruneQueue(header.get().getNumber(), blockHash); + addToPruneQueueCount.getAndIncrement(); + } else { + // prune orphaned blocks (sometimes created during block production) + rootWorldStateStorage.pruneTrieLog(blockHash); + orphansPruned.getAndIncrement(); + prunedOrphanCounter.inc(); + } + }); - timeoutFuture.cancel(true); - LOG.atDebug().log( - "Pruned {} orphaned trie logs from database...", orphansPruned.intValue()); - LOG.atInfo().log( - "Added {} trie logs to prune queue. Commencing pruning of eligible trie logs...", - addToPruneQueueCount.intValue()); + timeoutFuture.cancel(true); + LOG.atDebug().log("Pruned {} orphaned trie logs from database...", orphansPruned.intValue()); + LOG.atInfo().log( + "Added {} trie logs to prune queue. Commencing pruning of eligible trie logs...", + addToPruneQueueCount.intValue()); + int prunedCount = pruneFromQueue(); + LOG.atInfo().log("Pruned {} trie logs.", prunedCount); + } catch (Exception e) { + if (e.getCause() != null && e.getCause() instanceof TimeoutException) { int prunedCount = pruneFromQueue(); - LOG.atInfo().log("Pruned {} trie logs.", prunedCount); - } catch (Exception e) { - if (e.getCause() != null && e.getCause() instanceof TimeoutException) { - int prunedCount = pruneFromQueue(); - LOG.atInfo().log("Operation timed out, but still pruned {} trie logs.", prunedCount); - } else { - LOG.error("Error loading trie logs from database, nothing pruned", e); - } + LOG.atInfo().log("Operation timed out, but still pruned {} trie logs.", prunedCount); + } else { + LOG.error("Error loading trie logs from database, nothing pruned", e); } } } From 06c5beecfc53c44ee970a09d7117cd290f69376d Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Tue, 23 Jul 2024 15:01:09 +1000 Subject: [PATCH 05/14] Reduce pruning window from 30_000 to 5_000 Signed-off-by: Simon Dudley --- .../besu/ethereum/worldstate/DataStorageConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/DataStorageConfiguration.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/DataStorageConfiguration.java index 615b5bad6eb..8d767f442aa 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/DataStorageConfiguration.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/DataStorageConfiguration.java @@ -25,7 +25,7 @@ public interface DataStorageConfiguration { long DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD = 512; boolean DEFAULT_BONSAI_LIMIT_TRIE_LOGS_ENABLED = true; long MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT = DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD; - int DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE = 30_000; + int DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE = 5_000; boolean DEFAULT_RECEIPT_COMPACTION_ENABLED = false; DataStorageConfiguration DEFAULT_CONFIG = From b24eb1a1bb4a162bf1ff1cba3b1ece4d4d75b56b Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Tue, 23 Jul 2024 16:02:55 +1000 Subject: [PATCH 06/14] remove redundant log Signed-off-by: Simon Dudley --- .../ethereum/trie/diffbased/common/trielog/TrieLogPruner.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java index 88d32be475c..98bc4246ebe 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java @@ -131,10 +131,6 @@ private void preloadQueue( try (final Stream trieLogKeys = rootWorldStateStorage.streamTrieLogKeys(loadingLimit)) { - LOG.atInfo() - .setMessage("Loaded trie logs from database, determining if any can be pruned...") - .log(); - final AtomicLong addToPruneQueueCount = new AtomicLong(); final AtomicLong orphansPruned = new AtomicLong(); trieLogKeys.forEach( From e57c811e472b7f9fc4d229ac5c9fd30983c9de52 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Wed, 24 Jul 2024 08:36:38 -0600 Subject: [PATCH 07/14] Add EXTCODE* unit Tests (#7374) Add unit tests to the EXTCODE* series operations. Also, put all EVM operations tests in the proper package. Signed-off-by: Danno Ferrin --- .../org/hyperledger/besu/evm/MainnetEVMs.java | 11 +- .../evm/operation/ExtCodeCopyOperation.java | 18 +- .../evm/operation/ExtCodeHashOperation.java | 18 +- .../evm/operation/ExtCodeSizeOperation.java | 18 +- .../BaseFeeOperationTest.java | 4 +- .../BlobHashOperationTest.java | 4 +- .../BlockHashOperationTest.java | 3 +- .../CallFOperationTest.java | 4 +- .../ChainIdOperationTest.java | 3 +- ...stantinopleSStoreOperationGasCostTest.java | 2 +- .../Create2OperationTest.java | 3 +- .../CreateOperationTest.java | 3 +- .../DataCopyOperationTest.java | 4 +- .../EofCreateOperationTest.java | 2 +- .../ExtCallOperationTest.java | 4 +- .../operation/ExtCodeCopyOperationTest.java | 245 ++++++++++++++++++ .../ExtCodeHashOperationTest.java | 54 +++- .../operation/ExtCodeSizeOperationTest.java | 183 +++++++++++++ .../ExtDelegateCallOperationTest.java | 4 +- .../ExtStaticCallOperationTest.java | 4 +- .../JumpFOperationTest.java | 4 +- .../JumpOperationTest.java | 3 +- .../LondonSStoreOperationGasCostTest.java | 2 +- .../MCopyOperationTest.java | 4 +- .../PrevRanDaoOperationTest.java | 4 +- .../Push0OperationTest.java | 4 +- .../RelativeJumpOperationTest.java | 6 +- .../RetFOperationTest.java | 4 +- .../RevertOperationTest.java | 3 +- .../SStoreOperationTest.java | 3 +- .../SarOperationTest.java | 3 +- .../SelfDestructOperationTest.java | 4 +- .../ShlOperationTest.java | 3 +- .../ShrOperationTest.java | 3 +- .../TStoreOperationTest.java | 4 +- 35 files changed, 565 insertions(+), 80 deletions(-) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/BaseFeeOperationTest.java (95%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/BlobHashOperationTest.java (96%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/BlockHashOperationTest.java (97%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/CallFOperationTest.java (93%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/ChainIdOperationTest.java (96%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/ConstantinopleSStoreOperationGasCostTest.java (98%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/Create2OperationTest.java (99%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/CreateOperationTest.java (99%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/DataCopyOperationTest.java (97%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/EofCreateOperationTest.java (99%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/ExtCallOperationTest.java (98%) create mode 100644 evm/src/test/java/org/hyperledger/besu/evm/operation/ExtCodeCopyOperationTest.java rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/ExtCodeHashOperationTest.java (70%) create mode 100644 evm/src/test/java/org/hyperledger/besu/evm/operation/ExtCodeSizeOperationTest.java rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/ExtDelegateCallOperationTest.java (98%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/ExtStaticCallOperationTest.java (97%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/JumpFOperationTest.java (93%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/JumpOperationTest.java (98%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/LondonSStoreOperationGasCostTest.java (98%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/MCopyOperationTest.java (96%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/PrevRanDaoOperationTest.java (94%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/Push0OperationTest.java (94%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/RelativeJumpOperationTest.java (96%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/RetFOperationTest.java (93%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/RevertOperationTest.java (95%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/SStoreOperationTest.java (97%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/SarOperationTest.java (98%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/SelfDestructOperationTest.java (97%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/ShlOperationTest.java (98%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/ShrOperationTest.java (98%) rename evm/src/test/java/org/hyperledger/besu/evm/{operations => operation}/TStoreOperationTest.java (99%) diff --git a/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java b/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java index 2d9be8d3129..06ef2da2536 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java @@ -240,8 +240,8 @@ public static void registerFrontierOperations( registry.put(new CodeSizeOperation(gasCalculator)); registry.put(new CodeCopyOperation(gasCalculator)); registry.put(new GasPriceOperation(gasCalculator)); - registry.put(new ExtCodeCopyOperation(gasCalculator)); - registry.put(new ExtCodeSizeOperation(gasCalculator)); + registry.put(new ExtCodeCopyOperation(gasCalculator, false)); + registry.put(new ExtCodeSizeOperation(gasCalculator, false)); registry.put(new BlockHashOperation(gasCalculator)); registry.put(new CoinbaseOperation(gasCalculator)); registry.put(new TimestampOperation(gasCalculator)); @@ -478,7 +478,7 @@ public static void registerConstantinopleOperations( registry.put(new SarOperation(gasCalculator)); registry.put(new ShlOperation(gasCalculator)); registry.put(new ShrOperation(gasCalculator)); - registry.put(new ExtCodeHashOperation(gasCalculator)); + registry.put(new ExtCodeHashOperation(gasCalculator, false)); } /** @@ -1114,6 +1114,11 @@ private static void registerEOFOperations( registry.put(new SwapNOperation(gasCalculator)); registry.put(new ExchangeOperation(gasCalculator)); + // EIP-3540 EOF Aware EXTCODE* operations + registry.put(new ExtCodeCopyOperation(gasCalculator, true)); + registry.put(new ExtCodeHashOperation(gasCalculator, true)); + registry.put(new ExtCodeSizeOperation(gasCalculator, true)); + // EIP-4200 relative jump registry.put(new RelativeJumpOperation(gasCalculator)); registry.put(new RelativeJumpIfOperation(gasCalculator)); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeCopyOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeCopyOperation.java index 37a92ffc6ef..2f1c1391826 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeCopyOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeCopyOperation.java @@ -34,13 +34,26 @@ public class ExtCodeCopyOperation extends AbstractOperation { /** This is the "code" legacy contracts see when copying code from an EOF contract. */ public static final Bytes EOF_REPLACEMENT_CODE = Bytes.fromHexString("0xef00"); + private final boolean enableEIP3540; + /** * Instantiates a new Ext code copy operation. * * @param gasCalculator the gas calculator */ public ExtCodeCopyOperation(final GasCalculator gasCalculator) { + this(gasCalculator, false); + } + + /** + * Instantiates a new Ext code copy operation. + * + * @param gasCalculator the gas calculator + * @param enableEIP3540 enable EIP-3540 semantics (don't copy EOF) + */ + public ExtCodeCopyOperation(final GasCalculator gasCalculator, final boolean enableEIP3540) { super(0x3C, "EXTCODECOPY", 4, 0, gasCalculator); + this.enableEIP3540 = enableEIP3540; } /** @@ -82,7 +95,10 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { final Account account = frame.getWorldUpdater().get(address); final Bytes code = account != null ? account.getCode() : Bytes.EMPTY; - if (code.size() >= 2 && code.get(0) == EOFLayout.EOF_PREFIX_BYTE && code.get(1) == 0) { + if (enableEIP3540 + && code.size() >= 2 + && code.get(0) == EOFLayout.EOF_PREFIX_BYTE + && code.get(1) == 0) { frame.writeMemory(memOffset, sourceOffset, numBytes, EOF_REPLACEMENT_CODE); } else { frame.writeMemory(memOffset, sourceOffset, numBytes, code); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeHashOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeHashOperation.java index 953ddfb04d2..c08331b0065 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeHashOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeHashOperation.java @@ -34,13 +34,26 @@ public class ExtCodeHashOperation extends AbstractOperation { // // 0x9dbf3648db8210552e9c4f75c6a1c3057c0ca432043bd648be15fe7be05646f5 static final Hash EOF_REPLACEMENT_HASH = Hash.hash(ExtCodeCopyOperation.EOF_REPLACEMENT_CODE); + private final boolean enableEIP3540; + /** * Instantiates a new Ext code hash operation. * * @param gasCalculator the gas calculator */ public ExtCodeHashOperation(final GasCalculator gasCalculator) { + this(gasCalculator, false); + } + + /** + * Instantiates a new Ext code copy operation. + * + * @param gasCalculator the gas calculator + * @param enableEIP3540 enable EIP-3540 semantics (don't copy EOF) + */ + public ExtCodeHashOperation(final GasCalculator gasCalculator, final boolean enableEIP3540) { super(0x3F, "EXTCODEHASH", 1, 1, gasCalculator); + this.enableEIP3540 = enableEIP3540; } /** @@ -71,7 +84,10 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { frame.pushStackItem(Bytes.EMPTY); } else { final Bytes code = account.getCode(); - if (code.size() >= 2 && code.get(0) == EOFLayout.EOF_PREFIX_BYTE && code.get(1) == 0) { + if (enableEIP3540 + && code.size() >= 2 + && code.get(0) == EOFLayout.EOF_PREFIX_BYTE + && code.get(1) == 0) { frame.pushStackItem(EOF_REPLACEMENT_HASH); } else { frame.pushStackItem(account.getCodeHash()); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeSizeOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeSizeOperation.java index 95e5acc6ff1..1779175f152 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeSizeOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeSizeOperation.java @@ -32,13 +32,26 @@ public class ExtCodeSizeOperation extends AbstractOperation { static final Bytes EOF_SIZE = Bytes.of(2); + private final boolean enableEIP3540; + /** * Instantiates a new Ext code size operation. * * @param gasCalculator the gas calculator */ public ExtCodeSizeOperation(final GasCalculator gasCalculator) { + this(gasCalculator, false); + } + + /** + * Instantiates a new Ext code size operation. + * + * @param gasCalculator the gas calculator + * @param enableEIP3540 enable EIP-3540 semantics (EOF is size 2) + */ + public ExtCodeSizeOperation(final GasCalculator gasCalculator, final boolean enableEIP3540) { super(0x3B, "EXTCODESIZE", 1, 1, gasCalculator); + this.enableEIP3540 = enableEIP3540; } /** @@ -70,7 +83,10 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { codeSize = Bytes.EMPTY; } else { final Bytes code = account.getCode(); - if (code.size() >= 2 && code.get(0) == EOFLayout.EOF_PREFIX_BYTE && code.get(1) == 0) { + if (enableEIP3540 + && code.size() >= 2 + && code.get(0) == EOFLayout.EOF_PREFIX_BYTE + && code.get(1) == 0) { codeSize = EOF_SIZE; } else { codeSize = Words.intBytes(code.size()); diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/BaseFeeOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/BaseFeeOperationTest.java similarity index 95% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/BaseFeeOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/BaseFeeOperationTest.java index ac816137af3..13f04849887 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/BaseFeeOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/BaseFeeOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -26,8 +26,6 @@ import org.hyperledger.besu.evm.gascalculator.BerlinGasCalculator; import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.internal.Words; -import org.hyperledger.besu.evm.operation.BaseFeeOperation; -import org.hyperledger.besu.evm.operation.Operation; import org.hyperledger.besu.evm.operation.Operation.OperationResult; import java.util.Optional; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/BlobHashOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/BlobHashOperationTest.java similarity index 96% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/BlobHashOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/BlobHashOperationTest.java index cebffeb9105..9692c27625d 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/BlobHashOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/BlobHashOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -25,8 +25,6 @@ import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator; import org.hyperledger.besu.evm.gascalculator.LondonGasCalculator; -import org.hyperledger.besu.evm.operation.BlobHashOperation; -import org.hyperledger.besu.evm.operation.Operation; import java.util.ArrayList; import java.util.Arrays; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/BlockHashOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/BlockHashOperationTest.java similarity index 97% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/BlockHashOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/BlockHashOperationTest.java index d19e94e0a62..3ce7e3c207a 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/BlockHashOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/BlockHashOperationTest.java @@ -12,14 +12,13 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.FrontierGasCalculator; -import org.hyperledger.besu.evm.operation.BlockHashOperation; import org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; import org.hyperledger.besu.evm.testutils.FakeBlockValues; import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/CallFOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/CallFOperationTest.java similarity index 93% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/CallFOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/CallFOperationTest.java index fe662893e1e..9d7fa85d416 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/CallFOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/CallFOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.evm.testutils.OperationsTestUtils.mockCode; @@ -24,8 +24,6 @@ import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.internal.ReturnStack; -import org.hyperledger.besu.evm.operation.CallFOperation; -import org.hyperledger.besu.evm.operation.Operation; import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder; import org.apache.tuweni.bytes.Bytes; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/ChainIdOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/ChainIdOperationTest.java similarity index 96% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/ChainIdOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/ChainIdOperationTest.java index 969039266d8..acae6249c4d 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/ChainIdOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/ChainIdOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -20,7 +20,6 @@ import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.ConstantinopleGasCalculator; -import org.hyperledger.besu.evm.operation.ChainIdOperation; import org.hyperledger.besu.evm.operation.Operation.OperationResult; import java.util.List; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/ConstantinopleSStoreOperationGasCostTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/ConstantinopleSStoreOperationGasCostTest.java similarity index 98% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/ConstantinopleSStoreOperationGasCostTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/ConstantinopleSStoreOperationGasCostTest.java index 3cea9300e11..b8a254bbe40 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/ConstantinopleSStoreOperationGasCostTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/ConstantinopleSStoreOperationGasCostTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/Create2OperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/Create2OperationTest.java similarity index 99% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/Create2OperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/Create2OperationTest.java index 73a4abd34ab..51e2863a69b 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/Create2OperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/Create2OperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.evm.MainnetEVMs.DEV_NET_CHAIN_ID; @@ -35,7 +35,6 @@ import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.Words; import org.hyperledger.besu.evm.log.Log; -import org.hyperledger.besu.evm.operation.Create2Operation; import org.hyperledger.besu.evm.operation.Operation.OperationResult; import org.hyperledger.besu.evm.processor.ContractCreationProcessor; import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/CreateOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/CreateOperationTest.java similarity index 99% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/CreateOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/CreateOperationTest.java index 4fa5a0fdd74..c10d8f3d6c8 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/CreateOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/CreateOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.evm.MainnetEVMs.DEV_NET_CHAIN_ID; @@ -34,7 +34,6 @@ import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.Words; import org.hyperledger.besu.evm.log.Log; -import org.hyperledger.besu.evm.operation.CreateOperation; import org.hyperledger.besu.evm.processor.ContractCreationProcessor; import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder; import org.hyperledger.besu.evm.tracing.OperationTracer; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/DataCopyOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/DataCopyOperationTest.java similarity index 97% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/DataCopyOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/DataCopyOperationTest.java index 83d7f09e5a9..af5922aa074 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/DataCopyOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/DataCopyOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assumptions.assumeThat; @@ -24,8 +24,6 @@ import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.PragueGasCalculator; import org.hyperledger.besu.evm.internal.EvmConfiguration; -import org.hyperledger.besu.evm.operation.DataCopyOperation; -import org.hyperledger.besu.evm.operation.Operation; import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder; import java.util.Arrays; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/EofCreateOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/EofCreateOperationTest.java similarity index 99% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/EofCreateOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/EofCreateOperationTest.java index 86a0f8cce10..d5d1212dfba 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/EofCreateOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/EofCreateOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/ExtCallOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/ExtCallOperationTest.java similarity index 98% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/ExtCallOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/ExtCallOperationTest.java index 946dd0b52eb..c43893a5435 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/ExtCallOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/ExtCallOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -29,8 +29,6 @@ import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.PragueEOFGasCalculator; import org.hyperledger.besu.evm.internal.EvmConfiguration; -import org.hyperledger.besu.evm.operation.AbstractExtCallOperation; -import org.hyperledger.besu.evm.operation.ExtCallOperation; import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder; import org.hyperledger.besu.evm.worldstate.WorldUpdater; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operation/ExtCodeCopyOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/ExtCodeCopyOperationTest.java new file mode 100644 index 00000000000..b45824a92b4 --- /dev/null +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/ExtCodeCopyOperationTest.java @@ -0,0 +1,245 @@ +/* + * 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.evm.operation; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.evm.EVM; +import org.hyperledger.besu.evm.account.MutableAccount; +import org.hyperledger.besu.evm.frame.MessageFrame; +import org.hyperledger.besu.evm.gascalculator.PragueGasCalculator; +import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder; +import org.hyperledger.besu.evm.toy.ToyWorld; +import org.hyperledger.besu.evm.worldstate.WorldUpdater; + +import java.util.Arrays; +import java.util.Collection; + +import org.apache.tuweni.bytes.Bytes; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class ExtCodeCopyOperationTest { + + private static final Address REQUESTED_ADDRESS = Address.fromHexString("0x22222222"); + + private final ToyWorld toyWorld = new ToyWorld(); + private final WorldUpdater worldStateUpdater = toyWorld.updater(); + + @Mock EVM evm; + + static Collection extCodeCopyTestVector() { + return Arrays.asList( + new Object[][] { + { + "Copy after, no overlap", + Bytes.fromHexString("0123456789abcdef000000000000000000000000000000000000000000000000"), + 32, + 0, + 8, + Bytes.fromHexString( + "00000000000000000000000000000000000000000000000000000000000000000123456789abcdef"), + false, + 2609L + }, + { + "copy from uninitialized memory", + Bytes.EMPTY, + 0, + 24, + 16, + Bytes.fromHexString( + "0x000000000000000000000000000000000000000000000000000000000000000000"), + false, + 2606L + }, + { + "copy from initialized + uninitialized memory", + Bytes.fromHexString( + "0x0000000000000000000000000000000000000000000000000123456789abcdef"), + 64, + 24, + 16, + Bytes.fromHexString( + "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000123456789abcdef000000000000000000000000000000000000000000000000"), + false, + 2612L + }, + { + "overlapping src < dst", + Bytes.fromHexString( + "0x0123456789abcdef000000000000000000000000000000000000000000000000"), + 4, + 0, + 8, + Bytes.fromHexString( + "0x000000000123456789abcdef0000000000000000000000000000000000000000"), + false, + 2606L + }, + { + "overlapping src > dst", + Bytes.fromHexString( + "0x00112233445566778899aabbccddeeff00000000000000000000000000000000"), + 0, + 4, + 8, + Bytes.fromHexString( + "0x445566778899aabb000000000000000000000000000000000000000000000000"), + false, + 2606L + }, + { + "overlapping src == dst", + Bytes.fromHexString( + "0x00112233445566778899aabbccddeeff00000000000000000000000000000000"), + 4, + 4, + 8, + Bytes.fromHexString( + "0x00000000445566778899aabb0000000000000000000000000000000000000000"), + false, + 2606L + }, + { + "EOF-reserved pre-eof", + Bytes.fromHexString("0xEF009f918bf09f9fa9"), + 0, + 0, + 9, + Bytes.fromHexString("0xEF009f918bf09f9fa9"), + false, + 2606L + }, + { + "EOF-reserved post-epf", + Bytes.fromHexString("0xEF009f918bf09f9fa9"), + 0, + 0, + 9, + Bytes.fromHexString("0xEF000000000000000000"), + true, + 2606L + }, + { + "EF-reserved pre-epf", + Bytes.fromHexString("0xEFF09f918bf09f9fa9"), + 0, + 0, + 9, + Bytes.fromHexString("0xEFF09f918bf09f9fa9"), + false, + 2606L + }, + { + "EOF-reserved post-eof", + Bytes.fromHexString("0xEFF09f918bf09f9fa9"), + 0, + 0, + 9, + Bytes.fromHexString("0xEFF09f918bf09f9fa9"), + true, + 2606L + } + }); + } + + @SuppressWarnings("unused") + @ParameterizedTest(name = "{0}") + @MethodSource("extCodeCopyTestVector") + void testExtCodeCopy( + final String name, + final Bytes code, + final long dst, + final long src, + final long len, + final Bytes expected, + final boolean eof, + final long gasCost) { + final MutableAccount account = worldStateUpdater.getOrCreate(REQUESTED_ADDRESS); + account.setCode(code); + + ExtCodeCopyOperation subject = new ExtCodeCopyOperation(new PragueGasCalculator(), eof); + MessageFrame frame = + new TestMessageFrameBuilder() + .worldUpdater(worldStateUpdater) + .pushStackItem(Bytes.ofUnsignedLong(len)) + .pushStackItem(Bytes.ofUnsignedLong(src)) + .pushStackItem(Bytes.ofUnsignedLong(dst)) + .pushStackItem(REQUESTED_ADDRESS) + .build(); + + Operation.OperationResult result = subject.execute(frame, evm); + + assertThat(frame.readMemory(0, expected.size())).isEqualTo(expected); + assertThat(frame.memoryWordSize()).isEqualTo((expected.size() + 31) / 32); + assertThat(result.getGasCost()).isEqualTo(gasCost); + } + + @Test + void testExtCodeCopyCold() { + final MutableAccount account = worldStateUpdater.getOrCreate(REQUESTED_ADDRESS); + Bytes code = Bytes.fromHexString("0xEFF09f918bf09f9fa9"); + account.setCode(code); + + ExtCodeCopyOperation subject = new ExtCodeCopyOperation(new PragueGasCalculator(), false); + MessageFrame frame = + new TestMessageFrameBuilder() + .worldUpdater(worldStateUpdater) + .pushStackItem(Bytes.ofUnsignedLong(9)) + .pushStackItem(Bytes.ofUnsignedLong(0)) + .pushStackItem(Bytes.ofUnsignedLong(0)) + .pushStackItem(REQUESTED_ADDRESS) + .build(); + frame.warmUpAddress(REQUESTED_ADDRESS); + + Operation.OperationResult result = subject.execute(frame, evm); + + assertThat(frame.readMemory(0, 9)).isEqualTo(code); + assertThat(frame.memoryWordSize()).isEqualTo(1); + assertThat(result.getGasCost()).isEqualTo(106); + } + + @Test + void testExtCodeEOFDirtyMemory() { + final MutableAccount account = worldStateUpdater.getOrCreate(REQUESTED_ADDRESS); + Bytes code = Bytes.fromHexString("0xEF009f918bf09f9fa9"); + account.setCode(code); + + ExtCodeCopyOperation subject = new ExtCodeCopyOperation(new PragueGasCalculator(), true); + MessageFrame frame = + new TestMessageFrameBuilder() + .worldUpdater(worldStateUpdater) + .pushStackItem(Bytes.ofUnsignedLong(9)) + .pushStackItem(Bytes.ofUnsignedLong(0)) + .pushStackItem(Bytes.ofUnsignedLong(0)) + .pushStackItem(REQUESTED_ADDRESS) + .build(); + frame.writeMemory(0, 15, Bytes.fromHexString("0x112233445566778899aabbccddeeff")); + + Operation.OperationResult result = subject.execute(frame, evm); + + assertThat(frame.readMemory(0, 16)) + .isEqualTo(Bytes.fromHexString("0xEF0000000000000000aabbccddeeff00")); + assertThat(frame.memoryWordSize()).isEqualTo(1); + assertThat(result.getGasCost()).isEqualTo(2603); + } +} diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/ExtCodeHashOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/ExtCodeHashOperationTest.java similarity index 70% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/ExtCodeHashOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/ExtCodeHashOperationTest.java index a7ca5eefe67..97461cdbcdb 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/ExtCodeHashOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/ExtCodeHashOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; @@ -24,8 +24,8 @@ import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.ConstantinopleGasCalculator; import org.hyperledger.besu.evm.gascalculator.IstanbulGasCalculator; +import org.hyperledger.besu.evm.gascalculator.PragueGasCalculator; import org.hyperledger.besu.evm.internal.Words; -import org.hyperledger.besu.evm.operation.ExtCodeHashOperation; import org.hyperledger.besu.evm.operation.Operation.OperationResult; import org.hyperledger.besu.evm.testutils.FakeBlockValues; import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder; @@ -44,9 +44,11 @@ class ExtCodeHashOperationTest { private final WorldUpdater worldStateUpdater = toyWorld.updater(); private final ExtCodeHashOperation operation = - new ExtCodeHashOperation(new ConstantinopleGasCalculator()); + new ExtCodeHashOperation(new ConstantinopleGasCalculator(), false); private final ExtCodeHashOperation operationIstanbul = - new ExtCodeHashOperation(new IstanbulGasCalculator()); + new ExtCodeHashOperation(new IstanbulGasCalculator(), false); + private final ExtCodeHashOperation operationEOF = + new ExtCodeHashOperation(new PragueGasCalculator(), true); @Test void shouldCharge400Gas() { @@ -113,6 +115,50 @@ void shouldZeroOutLeftMostBitsToGetAddress() { assertThat(frame.getStackItem(0)).isEqualTo(Hash.hash(code)); } + @Test + void shouldGetNonEOFHash() { + final Bytes code = Bytes.fromHexString("0xEFF09f918bf09f9fa9"); + final MutableAccount account = worldStateUpdater.getOrCreate(REQUESTED_ADDRESS); + account.setCode(code); + final UInt256 value = + UInt256.fromBytes(Words.fromAddress(REQUESTED_ADDRESS)) + .add(UInt256.valueOf(2).pow(UInt256.valueOf(160))); + + final MessageFrame frame = createMessageFrame(value); + operation.execute(frame, null); + assertThat(frame.getStackItem(0)).isEqualTo(Hash.hash(code)); + + final MessageFrame frameIstanbul = createMessageFrame(value); + operationIstanbul.execute(frameIstanbul, null); + assertThat(frameIstanbul.getStackItem(0)).isEqualTo(Hash.hash(code)); + + final MessageFrame frameEOF = createMessageFrame(value); + operationEOF.execute(frameEOF, null); + assertThat(frameEOF.getStackItem(0)).isEqualTo(Hash.hash(code)); + } + + @Test + void shouldGetEOFHash() { + final Bytes code = Bytes.fromHexString("0xEF009f918bf09f9fa9"); + final MutableAccount account = worldStateUpdater.getOrCreate(REQUESTED_ADDRESS); + account.setCode(code); + final UInt256 value = + UInt256.fromBytes(Words.fromAddress(REQUESTED_ADDRESS)) + .add(UInt256.valueOf(2).pow(UInt256.valueOf(160))); + + final MessageFrame frame = createMessageFrame(value); + operation.execute(frame, null); + assertThat(frame.getStackItem(0)).isEqualTo(Hash.hash(code)); + + final MessageFrame frameIstanbul = createMessageFrame(value); + operationIstanbul.execute(frameIstanbul, null); + assertThat(frameIstanbul.getStackItem(0)).isEqualTo(Hash.hash(code)); + + final MessageFrame frameEOF = createMessageFrame(value); + operationEOF.execute(frameEOF, null); + assertThat(frameEOF.getStackItem(0)).isEqualTo(Hash.hash(Bytes.fromHexString("0xef00"))); + } + private Bytes executeOperation(final Address requestedAddress) { final MessageFrame frame = createMessageFrame(requestedAddress); operation.execute(frame, null); diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operation/ExtCodeSizeOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/ExtCodeSizeOperationTest.java new file mode 100644 index 00000000000..8c324692234 --- /dev/null +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/ExtCodeSizeOperationTest.java @@ -0,0 +1,183 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.evm.operation; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.evm.account.MutableAccount; +import org.hyperledger.besu.evm.frame.BlockValues; +import org.hyperledger.besu.evm.frame.MessageFrame; +import org.hyperledger.besu.evm.gascalculator.ConstantinopleGasCalculator; +import org.hyperledger.besu.evm.gascalculator.IstanbulGasCalculator; +import org.hyperledger.besu.evm.gascalculator.PragueGasCalculator; +import org.hyperledger.besu.evm.internal.Words; +import org.hyperledger.besu.evm.operation.Operation.OperationResult; +import org.hyperledger.besu.evm.testutils.FakeBlockValues; +import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder; +import org.hyperledger.besu.evm.toy.ToyWorld; +import org.hyperledger.besu.evm.worldstate.WorldUpdater; + +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.units.bigints.UInt256; +import org.junit.jupiter.api.Test; + +class ExtCodeSizeOperationTest { + + private static final Address REQUESTED_ADDRESS = Address.fromHexString("0x22222222"); + + private final ToyWorld toyWorld = new ToyWorld(); + private final WorldUpdater worldStateUpdater = toyWorld.updater(); + + private final ExtCodeSizeOperation operation = + new ExtCodeSizeOperation(new ConstantinopleGasCalculator(), false); + private final ExtCodeSizeOperation operationIstanbul = + new ExtCodeSizeOperation(new IstanbulGasCalculator(), false); + private final ExtCodeSizeOperation operationEOF = + new ExtCodeSizeOperation(new PragueGasCalculator(), true); + + @Test + void shouldCharge700Gas() { + final OperationResult result = operation.execute(createMessageFrame(REQUESTED_ADDRESS), null); + assertThat(result.getGasCost()).isEqualTo(700L); + } + + @Test + void istanbulShouldCharge700Gas() { + final OperationResult result = + operationIstanbul.execute(createMessageFrame(REQUESTED_ADDRESS), null); + assertThat(result.getGasCost()).isEqualTo(700L); + } + + @Test + void shouldReturnZeroWhenAccountDoesNotExist() { + final Bytes result = executeOperation(REQUESTED_ADDRESS); + assertThat(result.trimLeadingZeros()).isEqualTo(Bytes.EMPTY); + } + + @Test + void shouldReturnSizeOfEmptyDataWhenAccountExistsButDoesNotHaveCode() { + worldStateUpdater.getOrCreate(REQUESTED_ADDRESS).setBalance(Wei.of(1)); + assertThat(executeOperation(REQUESTED_ADDRESS).toInt()).isZero(); + } + + @Test + void shouldReturnZeroWhenAccountExistsButIsEmpty() { + worldStateUpdater.getOrCreate(REQUESTED_ADDRESS); + assertThat(executeOperation(REQUESTED_ADDRESS).trimLeadingZeros()).isEqualTo(Bytes.EMPTY); + } + + @Test + void shouldReturnZeroWhenPrecompiledContractHasNoBalance() { + assertThat(executeOperation(Address.ECREC).trimLeadingZeros()).isEqualTo(Bytes.EMPTY); + } + + @Test + void shouldReturnEmptyCodeSizeWhenPrecompileHasBalance() { + // Sending money to a precompile causes it to exist in the world state archive. + worldStateUpdater.getOrCreate(Address.ECREC).setBalance(Wei.of(10)); + assertThat(executeOperation(Address.ECREC).toInt()).isZero(); + } + + @Test + void shouldGetSizeOfAccountCodeWhenCodeIsPresent() { + final Bytes code = Bytes.fromHexString("0xabcdef"); + final MutableAccount account = worldStateUpdater.getOrCreate(REQUESTED_ADDRESS); + account.setCode(code); + assertThat(executeOperation(REQUESTED_ADDRESS).toInt()).isEqualTo(3); + } + + @Test + void shouldZeroOutLeftMostBitsToGetAddress() { + // If EXTCODESIZE of A is X, then EXTCODESIZE of A + 2**160 is X. + final Bytes code = Bytes.fromHexString("0xabcdef"); + final MutableAccount account = worldStateUpdater.getOrCreate(REQUESTED_ADDRESS); + account.setCode(code); + final UInt256 value = + UInt256.fromBytes(Words.fromAddress(REQUESTED_ADDRESS)) + .add(UInt256.valueOf(2).pow(UInt256.valueOf(160))); + final MessageFrame frame = createMessageFrame(value); + operation.execute(frame, null); + assertThat(frame.getStackItem(0).toInt()).isEqualTo(3); + } + + @Test + void shouldGetNonEOFSize() { + final Bytes code = Bytes.fromHexString("0xEFF09f918bf09f9fa9"); + final MutableAccount account = worldStateUpdater.getOrCreate(REQUESTED_ADDRESS); + account.setCode(code); + final UInt256 value = + UInt256.fromBytes(Words.fromAddress(REQUESTED_ADDRESS)) + .add(UInt256.valueOf(2).pow(UInt256.valueOf(160))); + + final MessageFrame frame = createMessageFrame(value); + operation.execute(frame, null); + assertThat(frame.getStackItem(0).toInt()).isEqualTo(9); + + final MessageFrame frameIstanbul = createMessageFrame(value); + operationIstanbul.execute(frameIstanbul, null); + assertThat(frame.getStackItem(0).toInt()).isEqualTo(9); + + final MessageFrame frameEOF = createMessageFrame(value); + operationEOF.execute(frameEOF, null); + assertThat(frame.getStackItem(0).toInt()).isEqualTo(9); + } + + @Test + void shouldGetEOFSize() { + final Bytes code = Bytes.fromHexString("0xEF009f918bf09f9fa9"); + final MutableAccount account = worldStateUpdater.getOrCreate(REQUESTED_ADDRESS); + account.setCode(code); + final UInt256 value = + UInt256.fromBytes(Words.fromAddress(REQUESTED_ADDRESS)) + .add(UInt256.valueOf(2).pow(UInt256.valueOf(160))); + + final MessageFrame frame = createMessageFrame(value); + operation.execute(frame, null); + assertThat(frame.getStackItem(0).toInt()).isEqualTo(9); + + final MessageFrame frameIstanbul = createMessageFrame(value); + operationIstanbul.execute(frameIstanbul, null); + + assertThat(frameIstanbul.getStackItem(0).toInt()).isEqualTo(9); + final MessageFrame frameEOF = createMessageFrame(value); + operationEOF.execute(frameEOF, null); + assertThat(frameEOF.getStackItem(0).toInt()).isEqualTo(2); + } + + private Bytes executeOperation(final Address requestedAddress) { + final MessageFrame frame = createMessageFrame(requestedAddress); + operation.execute(frame, null); + return frame.getStackItem(0); + } + + private MessageFrame createMessageFrame(final Address requestedAddress) { + final UInt256 stackItem = Words.fromAddress(requestedAddress); + return createMessageFrame(stackItem); + } + + private MessageFrame createMessageFrame(final UInt256 stackItem) { + final BlockValues blockValues = new FakeBlockValues(1337); + final MessageFrame frame = + new TestMessageFrameBuilder() + .worldUpdater(worldStateUpdater) + .blockValues(blockValues) + .build(); + + frame.pushStackItem(stackItem); + return frame; + } +} diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/ExtDelegateCallOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/ExtDelegateCallOperationTest.java similarity index 98% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/ExtDelegateCallOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/ExtDelegateCallOperationTest.java index d83e9f3ddc5..e1881892d53 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/ExtDelegateCallOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/ExtDelegateCallOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -29,8 +29,6 @@ import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.PragueEOFGasCalculator; import org.hyperledger.besu.evm.internal.EvmConfiguration; -import org.hyperledger.besu.evm.operation.AbstractExtCallOperation; -import org.hyperledger.besu.evm.operation.ExtDelegateCallOperation; import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder; import org.hyperledger.besu.evm.worldstate.WorldUpdater; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/ExtStaticCallOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/ExtStaticCallOperationTest.java similarity index 97% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/ExtStaticCallOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/ExtStaticCallOperationTest.java index 76f267ec538..90f2d300887 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/ExtStaticCallOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/ExtStaticCallOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -29,8 +29,6 @@ import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.PragueEOFGasCalculator; import org.hyperledger.besu.evm.internal.EvmConfiguration; -import org.hyperledger.besu.evm.operation.AbstractExtCallOperation; -import org.hyperledger.besu.evm.operation.ExtStaticCallOperation; import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder; import org.hyperledger.besu.evm.worldstate.WorldUpdater; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/JumpFOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/JumpFOperationTest.java similarity index 93% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/JumpFOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/JumpFOperationTest.java index 52a7211050c..4611faa0f87 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/JumpFOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/JumpFOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.evm.testutils.OperationsTestUtils.mockCode; @@ -23,8 +23,6 @@ import org.hyperledger.besu.evm.code.CodeSection; import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.GasCalculator; -import org.hyperledger.besu.evm.operation.JumpFOperation; -import org.hyperledger.besu.evm.operation.Operation; import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder; import org.apache.tuweni.bytes.Bytes; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/JumpOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/JumpOperationTest.java similarity index 98% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/JumpOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/JumpOperationTest.java index 3c466422ed3..7b9fab338e0 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/JumpOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/JumpOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; @@ -24,7 +24,6 @@ import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.IstanbulGasCalculator; import org.hyperledger.besu.evm.internal.EvmConfiguration; -import org.hyperledger.besu.evm.operation.JumpOperation; import org.hyperledger.besu.evm.operation.Operation.OperationResult; import org.hyperledger.besu.evm.testutils.FakeBlockValues; import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/LondonSStoreOperationGasCostTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/LondonSStoreOperationGasCostTest.java similarity index 98% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/LondonSStoreOperationGasCostTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/LondonSStoreOperationGasCostTest.java index f2cf9506837..b4865df5d23 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/LondonSStoreOperationGasCostTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/LondonSStoreOperationGasCostTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/MCopyOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/MCopyOperationTest.java similarity index 96% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/MCopyOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/MCopyOperationTest.java index 29753129209..6bf5a8afd21 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/MCopyOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/MCopyOperationTest.java @@ -12,15 +12,13 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import org.hyperledger.besu.evm.EVM; import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator; -import org.hyperledger.besu.evm.operation.MCopyOperation; -import org.hyperledger.besu.evm.operation.Operation; import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder; import java.util.Arrays; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/PrevRanDaoOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/PrevRanDaoOperationTest.java similarity index 94% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/PrevRanDaoOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/PrevRanDaoOperationTest.java index 25a2682e87d..28340920a07 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/PrevRanDaoOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/PrevRanDaoOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -23,8 +23,6 @@ import org.hyperledger.besu.evm.frame.BlockValues; import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.LondonGasCalculator; -import org.hyperledger.besu.evm.operation.Operation; -import org.hyperledger.besu.evm.operation.PrevRanDaoOperation; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/Push0OperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/Push0OperationTest.java similarity index 94% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/Push0OperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/Push0OperationTest.java index 3309fccce81..d7440b07961 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/Push0OperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/Push0OperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -24,9 +24,7 @@ import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.BerlinGasCalculator; import org.hyperledger.besu.evm.gascalculator.GasCalculator; -import org.hyperledger.besu.evm.operation.Operation; import org.hyperledger.besu.evm.operation.Operation.OperationResult; -import org.hyperledger.besu.evm.operation.Push0Operation; import org.hyperledger.besu.evm.testutils.FakeBlockValues; import java.util.Optional; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/RelativeJumpOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/RelativeJumpOperationTest.java similarity index 96% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/RelativeJumpOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/RelativeJumpOperationTest.java index 31042257759..7ca5eb04caa 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/RelativeJumpOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/RelativeJumpOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.evm.testutils.OperationsTestUtils.mockCode; @@ -23,10 +23,6 @@ import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.internal.Words; -import org.hyperledger.besu.evm.operation.Operation; -import org.hyperledger.besu.evm.operation.RelativeJumpIfOperation; -import org.hyperledger.besu.evm.operation.RelativeJumpOperation; -import org.hyperledger.besu.evm.operation.RelativeJumpVectorOperation; import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder; import org.apache.tuweni.bytes.Bytes; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/RetFOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/RetFOperationTest.java similarity index 93% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/RetFOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/RetFOperationTest.java index 672628140cf..f2a0947086b 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/RetFOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/RetFOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.evm.testutils.OperationsTestUtils.mockCode; @@ -24,8 +24,6 @@ import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.internal.ReturnStack; -import org.hyperledger.besu.evm.operation.Operation; -import org.hyperledger.besu.evm.operation.RetFOperation; import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder; import org.apache.tuweni.bytes.Bytes; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/RevertOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/RevertOperationTest.java similarity index 95% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/RevertOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/RevertOperationTest.java index 9ffc422d609..d5094494a3c 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/RevertOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/RevertOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.anyLong; @@ -20,7 +20,6 @@ import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.ConstantinopleGasCalculator; -import org.hyperledger.besu.evm.operation.RevertOperation; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.units.bigints.UInt256; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/SStoreOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/SStoreOperationTest.java similarity index 97% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/SStoreOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/SStoreOperationTest.java index 3993d9f81e7..6f3c7fd21f6 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/SStoreOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/SStoreOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.evm.frame.ExceptionalHaltReason.INSUFFICIENT_GAS; @@ -25,7 +25,6 @@ import org.hyperledger.besu.evm.gascalculator.ConstantinopleGasCalculator; import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.operation.Operation.OperationResult; -import org.hyperledger.besu.evm.operation.SStoreOperation; import org.hyperledger.besu.evm.testutils.FakeBlockValues; import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder; import org.hyperledger.besu.evm.toy.ToyWorld; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/SarOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/SarOperationTest.java similarity index 98% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/SarOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/SarOperationTest.java index 86182e47e39..c7d7cad00dc 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/SarOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/SarOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -22,7 +22,6 @@ import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.gascalculator.SpuriousDragonGasCalculator; -import org.hyperledger.besu.evm.operation.SarOperation; import java.util.List; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/SelfDestructOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/SelfDestructOperationTest.java similarity index 97% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/SelfDestructOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/SelfDestructOperationTest.java index 7842174e90d..d3a3db754b0 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/SelfDestructOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/SelfDestructOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.atLeast; @@ -31,8 +31,6 @@ import org.hyperledger.besu.evm.gascalculator.ConstantinopleGasCalculator; import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.Words; -import org.hyperledger.besu.evm.operation.Operation; -import org.hyperledger.besu.evm.operation.SelfDestructOperation; import org.hyperledger.besu.evm.worldstate.WorldUpdater; import org.apache.tuweni.bytes.Bytes; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/ShlOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/ShlOperationTest.java similarity index 98% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/ShlOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/ShlOperationTest.java index b567cb6302f..a4d0b8f3104 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/ShlOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/ShlOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -22,7 +22,6 @@ import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.gascalculator.SpuriousDragonGasCalculator; -import org.hyperledger.besu.evm.operation.ShlOperation; import java.util.Arrays; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/ShrOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/ShrOperationTest.java similarity index 98% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/ShrOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/ShrOperationTest.java index 659c50d35ce..5acc7466a2e 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/ShrOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/ShrOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -22,7 +22,6 @@ import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.gascalculator.SpuriousDragonGasCalculator; -import org.hyperledger.besu.evm.operation.ShrOperation; import java.util.Arrays; diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/TStoreOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/TStoreOperationTest.java similarity index 99% rename from evm/src/test/java/org/hyperledger/besu/evm/operations/TStoreOperationTest.java rename to evm/src/test/java/org/hyperledger/besu/evm/operation/TStoreOperationTest.java index c73a4544f9f..c7c3470825a 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/TStoreOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/TStoreOperationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.evm.operations; +package org.hyperledger.besu.evm.operation; import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.evm.frame.ExceptionalHaltReason.INSUFFICIENT_GAS; @@ -26,8 +26,6 @@ import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.operation.Operation.OperationResult; -import org.hyperledger.besu.evm.operation.TLoadOperation; -import org.hyperledger.besu.evm.operation.TStoreOperation; import org.hyperledger.besu.evm.testutils.ByteCodeBuilder; import org.hyperledger.besu.evm.testutils.FakeBlockValues; import org.hyperledger.besu.evm.testutils.TestCodeExecutor; From 30dfa66c1ebd01c53966f4274af626b2168e1ee2 Mon Sep 17 00:00:00 2001 From: Fabio Di Fabio Date: Thu, 25 Jul 2024 23:53:53 +0200 Subject: [PATCH 08/14] Penalize invalid transient pending transactions in the layered transaction pool (#7359) * Introduce score for pending transactions Signed-off-by: Fabio Di Fabio * Introduce score for pending transactions Signed-off-by: Fabio Di Fabio * Update package javadoc Signed-off-by: Fabio Di Fabio --------- Signed-off-by: Fabio Di Fabio --- .../txselection/BlockTransactionSelector.java | 21 +++- .../ProcessingResultTransactionSelector.java | 3 +- .../AbstractBlockTransactionSelectorTest.java | 37 +++--- .../eth/transactions/PendingTransaction.java | 48 +++++--- .../transactions/TransactionPoolMetrics.java | 20 ++++ .../AbstractPrioritizedTransactions.java | 65 +++++++++++ .../layered/AbstractTransactionsLayer.java | 12 ++ .../BaseFeePrioritizedTransactions.java | 30 +++-- .../eth/transactions/layered/EndLayer.java | 3 + .../GasPricePrioritizedTransactions.java | 29 +++-- .../layered/LayeredPendingTransactions.java | 99 ++++++++++------ .../layered/ReadyTransactions.java | 34 ++++-- .../layered/SparseTransactions.java | 5 + .../layered/TransactionsLayer.java | 13 +++ .../transactions/layered/package-info.java | 27 +++-- .../eth/transactions/layered/LayersTest.java | 106 +++++++++++++++++- plugin-api/build.gradle | 2 +- .../data/TransactionSelectionResult.java | 49 ++++++-- 18 files changed, 480 insertions(+), 123 deletions(-) diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java index c106b7aff16..ed028767d6a 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java @@ -15,6 +15,7 @@ package org.hyperledger.besu.ethereum.blockcreation.txselection; import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.BLOCK_SELECTION_TIMEOUT; +import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.INVALID_TX_EVALUATION_TOO_LONG; import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.SELECTED; import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.TX_EVALUATION_TOO_LONG; @@ -419,11 +420,14 @@ private TransactionSelectionResult handleTransactionNotSelected( final var pendingTransaction = evaluationContext.getPendingTransaction(); - // check if this tx took too much to evaluate, and in case remove it from the pool + // check if this tx took too much to evaluate, and in case it was invalid remove it from the + // pool, otherwise penalize it. final TransactionSelectionResult actualResult = isTimeout.get() - ? transactionTookTooLong(evaluationContext) - ? TX_EVALUATION_TOO_LONG + ? transactionTookTooLong(evaluationContext, selectionResult) + ? selectionResult.discard() + ? INVALID_TX_EVALUATION_TOO_LONG + : TX_EVALUATION_TOO_LONG : BLOCK_SELECTION_TIMEOUT : selectionResult; @@ -441,16 +445,21 @@ private TransactionSelectionResult handleTransactionNotSelected( return actualResult; } - private boolean transactionTookTooLong(final TransactionEvaluationContext evaluationContext) { + private boolean transactionTookTooLong( + final TransactionEvaluationContext evaluationContext, + final TransactionSelectionResult selectionResult) { final var evaluationTimer = evaluationContext.getEvaluationTimer(); if (evaluationTimer.elapsed(TimeUnit.MILLISECONDS) > blockTxsSelectionMaxTime) { LOG.atWarn() .setMessage( - "Transaction {} is too late for inclusion, evaluated in {} that is over the max limit of {}ms" - + ", removing it from the pool") + "Transaction {} is too late for inclusion, with result {}, evaluated in {} that is over the max limit of {}ms" + + ", {}") .addArgument(evaluationContext.getPendingTransaction()::getHash) + .addArgument(selectionResult) .addArgument(evaluationTimer) .addArgument(blockTxsSelectionMaxTime) + .addArgument( + selectionResult.discard() ? "removing it from the pool" : "penalizing it in the pool") .log(); return true; } diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/ProcessingResultTransactionSelector.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/ProcessingResultTransactionSelector.java index 85d97bdf460..9eed2bff09e 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/ProcessingResultTransactionSelector.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/ProcessingResultTransactionSelector.java @@ -110,7 +110,8 @@ private TransactionSelectionResult transactionSelectionResultForInvalidResult( * @return True if the invalid reason is transient, false otherwise. */ private boolean isTransientValidationError(final TransactionInvalidReason invalidReason) { - return invalidReason.equals(TransactionInvalidReason.GAS_PRICE_BELOW_CURRENT_BASE_FEE) + return invalidReason.equals(TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE) + || invalidReason.equals(TransactionInvalidReason.GAS_PRICE_BELOW_CURRENT_BASE_FEE) || invalidReason.equals(TransactionInvalidReason.NONCE_TOO_HIGH); } } diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java index c6ee454241a..adcc3ee1e27 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java @@ -18,8 +18,9 @@ import static org.assertj.core.api.Assertions.entry; import static org.awaitility.Awaitility.await; import static org.hyperledger.besu.ethereum.core.MiningParameters.DEFAULT_NON_POA_BLOCK_TXS_SELECTION_MAX_TIME; -import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE; +import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.NONCE_TOO_LOW; import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.BLOCK_SELECTION_TIMEOUT; +import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.INVALID_TX_EVALUATION_TOO_LONG; import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.PRIORITY_FEE_PER_GAS_BELOW_CURRENT_MIN; import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.SELECTED; import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.TX_EVALUATION_TOO_LONG; @@ -296,7 +297,7 @@ public void invalidTransactionsAreSkippedButBlockStillFills() { final Transaction tx = createTransaction(i, Wei.of(7), 100_000); transactionsToInject.add(tx); if (i == 1) { - ensureTransactionIsInvalid(tx, TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE); + ensureTransactionIsInvalid(tx, TransactionInvalidReason.NONCE_TOO_LOW); } else { ensureTransactionIsValid(tx); } @@ -311,8 +312,7 @@ public void invalidTransactionsAreSkippedButBlockStillFills() { .containsOnly( entry( invalidTx, - TransactionSelectionResult.invalid( - TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE.name()))); + TransactionSelectionResult.invalid(TransactionInvalidReason.NONCE_TOO_LOW.name()))); assertThat(results.getSelectedTransactions().size()).isEqualTo(4); assertThat(results.getSelectedTransactions().contains(invalidTx)).isFalse(); assertThat(results.getReceipts().size()).isEqualTo(4); @@ -568,8 +568,7 @@ public void shouldDiscardTransactionsThatFailValidation() { ensureTransactionIsValid(validTransaction, 21_000, 0); final Transaction invalidTransaction = createTransaction(3, Wei.of(10), 21_000); - ensureTransactionIsInvalid( - invalidTransaction, TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE); + ensureTransactionIsInvalid(invalidTransaction, TransactionInvalidReason.NONCE_TOO_LOW); transactionPool.addRemoteTransactions(List.of(validTransaction, invalidTransaction)); @@ -582,8 +581,7 @@ public void shouldDiscardTransactionsThatFailValidation() { .containsOnly( entry( invalidTransaction, - TransactionSelectionResult.invalid( - TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE.name()))); + TransactionSelectionResult.invalid(TransactionInvalidReason.NONCE_TOO_LOW.name()))); } @Test @@ -948,7 +946,7 @@ public void subsetOfPendingTransactionsIncludedWhenTxSelectionMaxTimeIsOver( @ParameterizedTest @MethodSource("subsetOfPendingTransactionsIncludedWhenTxSelectionMaxTimeIsOver") - public void pendingTransactionsThatTakesTooLongToEvaluateIsDroppedFromThePool( + public void pendingTransactionsThatTakesTooLongToEvaluateIsPenalized( final boolean isPoa, final boolean preProcessingTooLate, final boolean processingTooLate, @@ -961,7 +959,7 @@ public void pendingTransactionsThatTakesTooLongToEvaluateIsDroppedFromThePool( postProcessingTooLate, 900, TX_EVALUATION_TOO_LONG, - true); + false); } private void internalBlockSelectionTimeoutSimulation( @@ -1085,7 +1083,7 @@ public void subsetOfInvalidPendingTransactionsIncludedWhenTxSelectionMaxTimeIsOv 500, BLOCK_SELECTION_TIMEOUT, false, - UPFRONT_COST_EXCEEDS_BALANCE); + NONCE_TOO_LOW); } @ParameterizedTest @@ -1102,9 +1100,9 @@ public void invalidPendingTransactionsThatTakesTooLongToEvaluateIsDroppedFromThe processingTooLate, postProcessingTooLate, 900, - TX_EVALUATION_TOO_LONG, + INVALID_TX_EVALUATION_TOO_LONG, true, - UPFRONT_COST_EXCEEDS_BALANCE); + NONCE_TOO_LOW); } private void internalBlockSelectionTimeoutSimulationInvalidTxs( @@ -1423,15 +1421,17 @@ protected MiningParameters createMiningParameters( private static class PluginTransactionSelectionResult extends TransactionSelectionResult { private enum PluginStatus implements Status { - PLUGIN_INVALID(false, true), - PLUGIN_INVALID_TRANSIENT(false, false); + PLUGIN_INVALID(false, true, false), + PLUGIN_INVALID_TRANSIENT(false, false, true); private final boolean stop; private final boolean discard; + private final boolean penalize; - PluginStatus(final boolean stop, final boolean discard) { + PluginStatus(final boolean stop, final boolean discard, final boolean penalize) { this.stop = stop; this.discard = discard; + this.penalize = penalize; } @Override @@ -1443,6 +1443,11 @@ public boolean stop() { public boolean discard() { return discard; } + + @Override + public boolean penalize() { + return penalize; + } } public static final TransactionSelectionResult GENERIC_PLUGIN_INVALID_TRANSIENT = diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransaction.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransaction.java index 6ce8f47a7aa..bd98bee5adc 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransaction.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransaction.java @@ -50,18 +50,20 @@ public abstract class PendingTransaction private final Transaction transaction; private final long addedAt; private final long sequence; // Allows prioritization based on order transactions are added + private volatile byte score; private int memorySize = NOT_INITIALIZED; private PendingTransaction( - final Transaction transaction, final long addedAt, final long sequence) { + final Transaction transaction, final long addedAt, final long sequence, final byte score) { this.transaction = transaction; this.addedAt = addedAt; this.sequence = sequence; + this.score = score; } private PendingTransaction(final Transaction transaction, final long addedAt) { - this(transaction, addedAt, TRANSACTIONS_ADDED.getAndIncrement()); + this(transaction, addedAt, TRANSACTIONS_ADDED.getAndIncrement(), Byte.MAX_VALUE); } public static PendingTransaction newPendingTransaction( @@ -123,6 +125,20 @@ public int memorySize() { return memorySize; } + public byte getScore() { + return score; + } + + public void decrementScore() { + // use temp var to avoid non-atomic update of volatile var + final byte newScore = (byte) (score - 1); + + // check to avoid underflow + if (newScore < score) { + score = newScore; + } + } + public abstract PendingTransaction detachedCopy(); private int computeMemorySize() { @@ -255,6 +271,8 @@ public String toString() { + isReceivedFromLocalSource() + ", hasPriority=" + hasPriority() + + ", score=" + + score + '}'; } @@ -267,6 +285,8 @@ public String toTraceLog() { + isReceivedFromLocalSource() + ", hasPriority=" + hasPriority() + + ", score=" + + score + ", " + transaction.toTraceLog() + "}"; @@ -282,13 +302,13 @@ public Local(final Transaction transaction) { this(transaction, System.currentTimeMillis()); } - private Local(final long sequence, final Transaction transaction) { - super(transaction, System.currentTimeMillis(), sequence); + private Local(final long sequence, final byte score, final Transaction transaction) { + super(transaction, System.currentTimeMillis(), sequence, score); } @Override public PendingTransaction detachedCopy() { - return new Local(getSequence(), getTransaction().detachedCopy()); + return new Local(getSequence(), getScore(), getTransaction().detachedCopy()); } @Override @@ -310,13 +330,13 @@ public Priority(final Transaction transaction, final long addedAt) { super(transaction, addedAt); } - public Priority(final long sequence, final Transaction transaction) { - super(sequence, transaction); + public Priority(final long sequence, final byte score, final Transaction transaction) { + super(sequence, score, transaction); } @Override public PendingTransaction detachedCopy() { - return new Priority(getSequence(), getTransaction().detachedCopy()); + return new Priority(getSequence(), getScore(), getTransaction().detachedCopy()); } @Override @@ -336,13 +356,13 @@ public Remote(final Transaction transaction) { this(transaction, System.currentTimeMillis()); } - private Remote(final long sequence, final Transaction transaction) { - super(transaction, System.currentTimeMillis(), sequence); + private Remote(final long sequence, final byte score, final Transaction transaction) { + super(transaction, System.currentTimeMillis(), sequence, score); } @Override public PendingTransaction detachedCopy() { - return new Remote(getSequence(), getTransaction().detachedCopy()); + return new Remote(getSequence(), getScore(), getTransaction().detachedCopy()); } @Override @@ -364,13 +384,13 @@ public Priority(final Transaction transaction, final long addedAt) { super(transaction, addedAt); } - public Priority(final long sequence, final Transaction transaction) { - super(sequence, transaction); + public Priority(final long sequence, final byte score, final Transaction transaction) { + super(sequence, score, transaction); } @Override public PendingTransaction detachedCopy() { - return new Priority(getSequence(), getTransaction().detachedCopy()); + return new Priority(getSequence(), getScore(), getTransaction().detachedCopy()); } @Override diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolMetrics.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolMetrics.java index 812e7de9f4e..90e9628e5c4 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolMetrics.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolMetrics.java @@ -37,12 +37,14 @@ public class TransactionPoolMetrics { public static final String ADDED_COUNTER_NAME = "added_total"; public static final String REMOVED_COUNTER_NAME = "removed_total"; public static final String REJECTED_COUNTER_NAME = "rejected_total"; + public static final String PENALIZED_COUNTER_NAME = "penalized_total"; public static final String EXPIRED_MESSAGES_COUNTER_NAME = "messages_expired_total"; private static final int SKIPPED_MESSAGES_LOGGING_THRESHOLD = 1000; private final MetricsSystem metricsSystem; private final LabelledMetric addedCounter; private final LabelledMetric removedCounter; private final LabelledMetric rejectedCounter; + private final LabelledMetric penalizedCounter; private final LabelledGauge spaceUsed; private final LabelledGauge transactionCount; private final LabelledGauge transactionCountByType; @@ -88,6 +90,15 @@ public TransactionPoolMetrics(final MetricsSystem metricsSystem) { "reason", "layer"); + penalizedCounter = + metricsSystem.createLabelledCounter( + BesuMetricCategory.TRANSACTION_POOL, + PENALIZED_COUNTER_NAME, + "Count of penalized transactions in the transaction pool", + "source", + "priority", + "layer"); + spaceUsed = metricsSystem.createLabelledGauge( BesuMetricCategory.TRANSACTION_POOL, @@ -246,6 +257,15 @@ public void incrementRejected( .inc(); } + public void incrementPenalized(final PendingTransaction pendingTransaction, final String layer) { + penalizedCounter + .labels( + location(pendingTransaction.isReceivedFromLocalSource()), + priority(pendingTransaction.hasPriority()), + layer) + .inc(); + } + public void incrementExpiredMessages(final String message) { expiredMessagesCounter.labels(message).inc(); } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractPrioritizedTransactions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractPrioritizedTransactions.java index 7a65b3febca..470e7f5b7b7 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractPrioritizedTransactions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractPrioritizedTransactions.java @@ -24,13 +24,17 @@ import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolMetrics; +import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.NavigableMap; +import java.util.TreeMap; import java.util.TreeSet; import java.util.function.BiFunction; import java.util.function.Predicate; +import java.util.stream.Collectors; /** * Holds the current set of executable pending transactions, that are candidate for inclusion on @@ -137,6 +141,13 @@ protected void internalRemove( orderByFee.remove(removedTx); } + @Override + protected void internalPenalize(final PendingTransaction penalizedTx) { + orderByFee.remove(penalizedTx); + penalizedTx.decrementScore(); + orderByFee.add(penalizedTx); + } + @Override public List promote( final Predicate promotionFilter, @@ -188,6 +199,60 @@ public List getBySender() { .toList(); } + /** + * Returns pending txs by sender and ordered by score desc. In case a sender has pending txs with + * different scores, then in nonce sequence, every time there is a score decrease, his pending txs + * will be put in a new entry with that score. For example if a sender has 3 pending txs (where + * the first number is the nonce and the score is between parenthesis): 0(127), 1(126), 2(127), + * then for he there will be 2 entries: + * + *
    + *
  • 0(127) + *
  • 1(126), 2(127) + *
+ * + * @return pending txs by sender and ordered by score desc + */ + public NavigableMap> getByScore() { + final var sendersToAdd = new HashSet<>(txsBySender.keySet()); + return orderByFee.descendingSet().stream() + .map(PendingTransaction::getSender) + .filter(sendersToAdd::remove) + .flatMap(sender -> splitByScore(sender, txsBySender.get(sender)).entrySet().stream()) + .collect( + Collectors.toMap( + Map.Entry::getKey, + Map.Entry::getValue, + (a, b) -> { + a.addAll(b); + return a; + }, + TreeMap::new)) + .descendingMap(); + } + + private Map> splitByScore( + final Address sender, final NavigableMap txsBySender) { + final var splitByScore = new HashMap>(); + byte currScore = txsBySender.firstEntry().getValue().getScore(); + var currSplit = new ArrayList(); + for (final var entry : txsBySender.entrySet()) { + if (entry.getValue().getScore() < currScore) { + // score decreased, we need to save current split and start a new one + splitByScore + .computeIfAbsent(currScore, k -> new ArrayList<>()) + .add(new SenderPendingTransactions(sender, currSplit)); + currSplit = new ArrayList<>(); + currScore = entry.getValue().getScore(); + } + currSplit.add(entry.getValue()); + } + splitByScore + .computeIfAbsent(currScore, k -> new ArrayList<>()) + .add(new SenderPendingTransactions(sender, currSplit)); + return splitByScore; + } + @Override protected long cacheFreeSpace() { return Integer.MAX_VALUE; diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractTransactionsLayer.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractTransactionsLayer.java index 5997fe6c189..b4f6e927c0d 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractTransactionsLayer.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractTransactionsLayer.java @@ -463,6 +463,18 @@ final void promoteTransactions() { } } + @Override + public void penalize(final PendingTransaction penalizedTransaction) { + if (pendingTransactions.containsKey(penalizedTransaction.getHash())) { + internalPenalize(penalizedTransaction); + metrics.incrementPenalized(penalizedTransaction, name()); + } else { + nextLayer.penalize(penalizedTransaction); + } + } + + protected abstract void internalPenalize(final PendingTransaction pendingTransaction); + /** * How many txs of a specified type can be promoted? This make sense when a max number of txs of a * type can be included in a single block (ex. blob txs), to avoid filling the layer with more txs diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseFeePrioritizedTransactions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseFeePrioritizedTransactions.java index 8140cd5d7a2..b3dec34b772 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseFeePrioritizedTransactions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseFeePrioritizedTransactions.java @@ -19,7 +19,6 @@ import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.MiningParameters; -import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction; @@ -66,7 +65,8 @@ public BaseFeePrioritizedTransactions( @Override protected int compareByFee(final PendingTransaction pt1, final PendingTransaction pt2) { - return Comparator.comparing(PendingTransaction::hasPriority) + return Comparator.comparing(PendingTransaction::getScore) + .thenComparing(PendingTransaction::hasPriority) .thenComparing( (PendingTransaction pendingTransaction) -> pendingTransaction.getTransaction().getEffectivePriorityFeePerGas(nextBlockBaseFee)) @@ -195,8 +195,8 @@ protected String internalLogStats() { return "Basefee Prioritized: Empty"; } - final Transaction highest = orderByFee.last().getTransaction(); - final Transaction lowest = orderByFee.first().getTransaction(); + final PendingTransaction highest = orderByFee.last(); + final PendingTransaction lowest = orderByFee.first(); return "Basefee Prioritized: " + "count: " @@ -205,16 +205,26 @@ protected String internalLogStats() { + spaceUsed + ", unique senders: " + txsBySender.size() - + ", highest priority tx: [max fee: " - + highest.getMaxGasPrice().toHumanReadableString() + + ", highest priority tx: [score: " + + highest.getScore() + + ", max fee: " + + highest.getTransaction().getMaxGasPrice().toHumanReadableString() + ", curr prio fee: " - + highest.getEffectivePriorityFeePerGas(nextBlockBaseFee).toHumanReadableString() + + highest + .getTransaction() + .getEffectivePriorityFeePerGas(nextBlockBaseFee) + .toHumanReadableString() + ", hash: " + highest.getHash() - + "], lowest priority tx: [max fee: " - + lowest.getMaxGasPrice().toHumanReadableString() + + "], lowest priority tx: [score: " + + lowest.getScore() + + ", max fee: " + + lowest.getTransaction().getMaxGasPrice().toHumanReadableString() + ", curr prio fee: " - + lowest.getEffectivePriorityFeePerGas(nextBlockBaseFee).toHumanReadableString() + + lowest + .getTransaction() + .getEffectivePriorityFeePerGas(nextBlockBaseFee) + .toHumanReadableString() + ", hash: " + lowest.getHash() + "], next block base fee: " diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/EndLayer.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/EndLayer.java index 0f5d9a6d15d..f383f178c2c 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/EndLayer.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/EndLayer.java @@ -85,6 +85,9 @@ public TransactionAddedResult add(final PendingTransaction pendingTransaction, f @Override public void remove(final PendingTransaction pendingTransaction, final RemovalReason reason) {} + @Override + public void penalize(final PendingTransaction penalizedTx) {} + @Override public void blockAdded( final FeeMarket feeMarket, diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/GasPricePrioritizedTransactions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/GasPricePrioritizedTransactions.java index 97bd3a88ee4..504a453fa88 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/GasPricePrioritizedTransactions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/GasPricePrioritizedTransactions.java @@ -56,7 +56,8 @@ public GasPricePrioritizedTransactions( @Override protected int compareByFee(final PendingTransaction pt1, final PendingTransaction pt2) { - return comparing(PendingTransaction::hasPriority) + return comparing(PendingTransaction::getScore) + .thenComparing(PendingTransaction::hasPriority) .thenComparing(PendingTransaction::getGasPrice) .thenComparing(PendingTransaction::getSequence) .compare(pt1, pt2); @@ -78,21 +79,33 @@ protected boolean promotionFilter(final PendingTransaction pendingTransaction) { } @Override - public String internalLogStats() { + protected String internalLogStats() { if (orderByFee.isEmpty()) { return "GasPrice Prioritized: Empty"; } + final PendingTransaction highest = orderByFee.last(); + final PendingTransaction lowest = orderByFee.first(); + return "GasPrice Prioritized: " + "count: " + pendingTransactions.size() - + " space used: " + + ", space used: " + spaceUsed - + " unique senders: " + + ", unique senders: " + txsBySender.size() - + ", highest fee tx: " - + orderByFee.last().getTransaction().getGasPrice().get().toHumanReadableString() - + ", lowest fee tx: " - + orderByFee.first().getTransaction().getGasPrice().get().toHumanReadableString(); + + ", highest priority tx: [score: " + + highest.getScore() + + ", gas price: " + + highest.getTransaction().getGasPrice().get().toHumanReadableString() + + ", hash: " + + highest.getHash() + + "], lowest priority tx: [score: " + + lowest.getScore() + + ", gas price: " + + lowest.getTransaction().getGasPrice().get().toHumanReadableString() + + ", hash: " + + lowest.getHash() + + "]"; } } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactions.java index 9444885ebe4..5297f080215 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactions.java @@ -42,10 +42,12 @@ import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.OptionalLong; +import java.util.Set; import java.util.stream.Collector; import java.util.stream.Collectors; @@ -314,55 +316,80 @@ public synchronized List getPriorityTransactions() { @Override public void selectTransactions(final PendingTransactions.TransactionSelector selector) { final List invalidTransactions = new ArrayList<>(); + final List penalizedTransactions = new ArrayList<>(); + final Set
skipSenders = new HashSet<>(); - final List candidateTxsBySender; + final Map> candidateTxsByScore; synchronized (this) { // since selecting transactions for block creation is a potential long operation // we want to avoid to keep the lock for all the process, but we just lock to get // the candidate transactions - candidateTxsBySender = prioritizedTransactions.getBySender(); + candidateTxsByScore = prioritizedTransactions.getByScore(); } selection: - for (final var senderTxs : candidateTxsBySender) { - LOG.trace("highPrioSenderTxs {}", senderTxs); - - for (final var candidatePendingTx : senderTxs.pendingTransactions()) { - final var selectionResult = selector.evaluateTransaction(candidatePendingTx); - - LOG.atTrace() - .setMessage("Selection result {} for transaction {}") - .addArgument(selectionResult) - .addArgument(candidatePendingTx::toTraceLog) - .log(); - - if (selectionResult.discard()) { - invalidTransactions.add(candidatePendingTx); - logDiscardedTransaction(candidatePendingTx, selectionResult); - } - - if (selectionResult.stop()) { - LOG.trace("Stopping selection"); - break selection; - } - - if (!selectionResult.selected()) { - // avoid processing other txs from this sender if this one is skipped - // since the following will not be selected due to the nonce gap - LOG.trace("Skipping remaining txs for sender {}", candidatePendingTx.getSender()); - break; + for (final var entry : candidateTxsByScore.entrySet()) { + LOG.trace("Evaluating txs with score {}", entry.getKey()); + + for (final var senderTxs : entry.getValue()) { + LOG.trace("Evaluating sender txs {}", senderTxs); + + if (!skipSenders.contains(senderTxs.sender())) { + + for (final var candidatePendingTx : senderTxs.pendingTransactions()) { + final var selectionResult = selector.evaluateTransaction(candidatePendingTx); + + LOG.atTrace() + .setMessage("Selection result {} for transaction {}") + .addArgument(selectionResult) + .addArgument(candidatePendingTx::toTraceLog) + .log(); + + if (selectionResult.discard()) { + invalidTransactions.add(candidatePendingTx); + logDiscardedTransaction(candidatePendingTx, selectionResult); + } + + if (selectionResult.penalize()) { + penalizedTransactions.add(candidatePendingTx); + LOG.atTrace() + .setMessage("Transaction {} penalized") + .addArgument(candidatePendingTx::toTraceLog) + .log(); + } + + if (selectionResult.stop()) { + LOG.trace("Stopping selection"); + break selection; + } + + if (!selectionResult.selected()) { + // avoid processing other txs from this sender if this one is skipped + // since the following will not be selected due to the nonce gap + LOG.trace("Skipping remaining txs for sender {}", candidatePendingTx.getSender()); + skipSenders.add(candidatePendingTx.getSender()); + break; + } + } } } } ethScheduler.scheduleTxWorkerTask( - () -> - invalidTransactions.forEach( - invalidTx -> { - synchronized (this) { - prioritizedTransactions.remove(invalidTx, INVALIDATED); - } - })); + () -> { + invalidTransactions.forEach( + invalidTx -> { + synchronized (this) { + prioritizedTransactions.remove(invalidTx, INVALIDATED); + } + }); + penalizedTransactions.forEach( + penalizedTx -> { + synchronized (this) { + prioritizedTransactions.internalPenalize(penalizedTx); + } + }); + }); } @Override diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/ReadyTransactions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/ReadyTransactions.java index 1f9fc0ab8d6..0f52e1c5c3e 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/ReadyTransactions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/ReadyTransactions.java @@ -18,7 +18,6 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction; @@ -43,7 +42,8 @@ public class ReadyTransactions extends AbstractSequentialTransactionsLayer { private final NavigableSet orderByMaxFee = new TreeSet<>( - Comparator.comparing(PendingTransaction::hasPriority) + Comparator.comparing(PendingTransaction::getScore) + .thenComparing(PendingTransaction::hasPriority) .thenComparing((PendingTransaction pt) -> pt.getTransaction().getMaxGasPrice()) .thenComparing(PendingTransaction::getSequence)); @@ -116,6 +116,20 @@ protected void internalRemove( } } + @Override + protected void internalPenalize(final PendingTransaction penalizedTx) { + final var senderTxs = txsBySender.get(penalizedTx.getSender()); + if (senderTxs.firstKey() == penalizedTx.getNonce()) { + // since we only sort the first tx of sender, we only need to re-sort in this case + orderByMaxFee.remove(penalizedTx); + penalizedTx.decrementScore(); + orderByMaxFee.add(penalizedTx); + } else { + // otherwise we just decrement the score + penalizedTx.decrementScore(); + } + } + @Override protected void internalReplaced(final PendingTransaction replacedTx) { orderByMaxFee.remove(replacedTx); @@ -213,8 +227,8 @@ public String internalLogStats() { return "Ready: Empty"; } - final Transaction top = orderByMaxFee.last().getTransaction(); - final Transaction last = orderByMaxFee.first().getTransaction(); + final PendingTransaction top = orderByMaxFee.last(); + final PendingTransaction last = orderByMaxFee.first(); return "Ready: " + "count=" @@ -223,12 +237,16 @@ public String internalLogStats() { + spaceUsed + ", unique senders: " + txsBySender.size() - + ", top by max fee[max fee:" - + top.getMaxGasPrice().toHumanReadableString() + + ", top by score and max gas price[score: " + + top.getScore() + + ", max gas price:" + + top.getTransaction().getMaxGasPrice().toHumanReadableString() + ", hash: " + top.getHash() - + "], last by max fee [max fee: " - + last.getMaxGasPrice().toHumanReadableString() + + "], last by score and max gas price [score: " + + last.getScore() + + ", max fee: " + + last.getTransaction().getMaxGasPrice().toHumanReadableString() + ", hash: " + last.getHash() + "]"; diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/SparseTransactions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/SparseTransactions.java index 52f598ba71a..aef318e6df9 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/SparseTransactions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/SparseTransactions.java @@ -303,6 +303,11 @@ protected void internalRemove( } } + @Override + protected void internalPenalize(final PendingTransaction penalizedTx) { + // intentionally no-op + } + private void deleteGap(final Address sender) { orderByGap.get(gapBySender.remove(sender)).remove(sender); } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/TransactionsLayer.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/TransactionsLayer.java index d3c22aeef10..531add0af7b 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/TransactionsLayer.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/TransactionsLayer.java @@ -45,6 +45,19 @@ public interface TransactionsLayer { void remove(PendingTransaction pendingTransaction, RemovalReason reason); + /** + * Penalize a pending transaction. Penalization could be applied to notify the txpool that this + * pending tx has some temporary issues that prevent it from being included in a block, and so it + * should be de-prioritized in some ways, so it will be re-evaluated only after non penalized + * pending txs. For example: if during the evaluation for block inclusion, the pending tx is + * excluded because the sender has not enough balance to send it, this could be a transient issue + * since later the sender could receive some funds, but in any case we penalize the pending tx, so + * it is pushed down in the order of prioritized pending txs. + * + * @param penalizedTransaction the tx to penalize + */ + void penalize(PendingTransaction penalizedTransaction); + void blockAdded( FeeMarket feeMarket, BlockHeader blockHeader, diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/package-info.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/package-info.java index fbc9da9fe57..ff274ce4ea4 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/package-info.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/package-info.java @@ -22,7 +22,8 @@ * transactions that could be selected for a future block proposal, and at the same time, without * penalizing legitimate unordered transactions, that are only temporary non-executable. * - *

It is disabled by default, to enable use the option {@code Xlayered-tx-pool=true} + *

It is enabled by default on public networks, to switch to another implementation use the + * option {@code tx-pool} * *

The main idea is to organize the txpool in an arbitrary number of layers, where each layer has * specific rules and constraints that determine if a transaction belong or not to that layer and @@ -38,6 +39,14 @@ * transactions are removed since confirmed in a block, transactions from the next layer are * promoted until there is space. * + *

Some layers could make use of the score of a pending transactions, to push back in the rank + * those pending transactions that have been penalized. + * + *

Layers are not thread safe, since they are not meant to be accessed directly, and all the + * synchronization is managed at the level of {@link + * org.hyperledger.besu.ethereum.eth.transactions.layered.LayeredPendingTransactions + * LayeredPendingTransactions} class. + * *

The current implementation is based on 3 layers, plus the last one that just drop every * transaction when the previous layers are full. The 3 layers are, in order: * @@ -48,20 +57,20 @@ * * *

Prioritized: This is where candidate transactions are selected for creating a new block. - * Transactions ordered by the effective priority fee, and it is limited by size, 2000 by default, - * to reduce the overhead of the sorting and because that number is enough to fill any block, at the - * current gas limit. Does not allow nonce gaps, and the first transaction for each sender must be - * the next one for that sender. Eviction is done removing the transaction with the higher nonce for - * the sender of the less valuable transaction, to avoid creating nonce gaps, evicted transactions - * go into the next layer Ready. + * Transactions ordered by score and then effective priority fee, and it is limited by size, 2000 by + * default, to reduce the overhead of the sorting and because that number is enough to fill any + * block, at the current gas limit. Does not allow nonce gaps, and the first transaction for each + * sender must be the next one for that sender. Eviction is done removing the transaction with the + * higher nonce for the sender of the less score and less effective priority fee transaction, to + * avoid creating nonce gaps, evicted transactions go into the next layer Ready. * *

Ready: Similar to the Prioritized, it does not allow nonce gaps, and the first transaction for * each sender must be the next one for that sender, but it is limited by space instead of count, * thus allowing many more transactions, think about this layer like a buffer for the Prioritized. * Since it is meant to keep ten to hundreds of thousand of transactions, it does not have a full * ordering, like the previous, but only the first transaction for each sender is ordered using a - * stable value that is the max fee per gas. Eviction is the same as the Prioritized, and evicted - * transaction go into the next layer Sparse. + * stable value that is score and then max fee per gas. Eviction is the same as the Prioritized, and + * evicted transaction go into the next layer Sparse. * *

Sparse: This is the first layer where nonce gaps are allowed and where the first transaction * for a sender could not be the next expected one for that sender. The main purpose of this layer diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayersTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayersTest.java index c5c2bdcf976..84ac759a798 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayersTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayersTest.java @@ -159,6 +159,12 @@ void maxPrioritizedByType(final Scenario scenario) { assertScenario(scenario, BLOB_TX_POOL_CONFIG); } + @ParameterizedTest + @MethodSource("providerPenalized") + void penalized(final Scenario scenario) { + assertScenario(scenario); + } + private void assertScenario(final Scenario scenario) { assertScenario(scenario, DEFAULT_TX_POOL_CONFIG); } @@ -1256,6 +1262,79 @@ static Stream providerMaxPrioritizedByType() { .expectedSparseForSenders())); } + static Stream providerPenalized() { + return Stream.of( + Arguments.of( + new Scenario("single sender, single tx") + .addForSender(S1, 0) + .expectedPrioritizedForSender(S1, 0) + .penalizeForSender(S1, 0) + .expectedPrioritizedForSender(S1, 0)), + Arguments.of( + new Scenario("single sender penalize last") + .addForSender(S1, 0, 1) + .expectedPrioritizedForSender(S1, 0, 1) + .penalizeForSender(S1, 1) + .expectedPrioritizedForSender(S1, 0, 1)), + Arguments.of( + new Scenario("single sender penalize first") + .addForSender(S1, 0, 1) + .expectedPrioritizedForSender(S1, 0, 1) + .penalizeForSender(S1, 0, 1) + // even if 0 has less score it is always the first for the sender + // since otherwise there is a nonce gap + .expectedPrioritizedForSender(S1, 0, 1)), + Arguments.of( + new Scenario("multiple senders, penalize top") + .addForSenders(S1, 0, S2, 0) + // remember S2 pays more fees + .expectedPrioritizedForSenders(S2, 0, S1, 0) + .penalizeForSender(S2, 0) + .expectedPrioritizedForSenders(S1, 0, S2, 0)), + Arguments.of( + new Scenario("multiple senders, penalize bottom") + .addForSenders(S1, 0, S2, 0) + .expectedPrioritizedForSenders(S2, 0, S1, 0) + .penalizeForSender(S1, 0) + .expectedPrioritizedForSenders(S2, 0, S1, 0)), + Arguments.of( + new Scenario("multiple senders, penalize middle") + .addForSenders(S1, 0, S2, 0, S3, 0) + .expectedPrioritizedForSenders(S3, 0, S2, 0, S1, 0) + .penalizeForSender(S2, 0) + .expectedPrioritizedForSenders(S3, 0, S1, 0, S2, 0)), + Arguments.of( + new Scenario("single sender, promote from ready") + .addForSender(S1, 0, 1, 2, 3, 4, 5) + .expectedPrioritizedForSender(S1, 0, 1, 2) + .expectedReadyForSender(S1, 3, 4, 5) + .penalizeForSender(S1, 3) + .confirmedForSenders(S1, 0) + // even if penalized 3 is promoted to avoid nonce gap + .expectedPrioritizedForSender(S1, 1, 2, 3) + .expectedReadyForSender(S1, 4, 5)), + Arguments.of( + new Scenario("multiple senders, overflow to ready") + .addForSenders(S1, 0, S2, 0, S3, 0) + .expectedPrioritizedForSenders(S3, 0, S2, 0, S1, 0) + .expectedReadyForSenders() + .penalizeForSender(S3, 0) + .addForSender(S1, 1) + .expectedPrioritizedForSenders(S2, 0, S1, 0, S1, 1) + // S3(0) is demoted to ready even if it is paying more fees, + // since has a lower score + .expectedReadyForSender(S3, 0)), + Arguments.of( + new Scenario("multiple senders, overflow to sparse") + .addForSenders(S1, 0, S2, 0, S3, 0, S1, 1, S2, 1, S3, 1) + .expectedPrioritizedForSenders(S3, 0, S3, 1, S2, 0) + .expectedReadyForSenders(S2, 1, S1, 0, S1, 1) + .penalizeForSender(S2, 1) + .addForSender(S2, 2) + .expectedReadyForSenders(S1, 0, S1, 1, S2, 1) + .expectedSparseForSender(S2, 2))); + } + private static BlockHeader mockBlockHeader() { final BlockHeader blockHeader = mock(BlockHeader.class); when(blockHeader.getBaseFee()).thenReturn(Optional.of(BASE_FEE)); @@ -1511,10 +1590,12 @@ public Scenario expectedDroppedForSenders() { private void assertExpectedPrioritized( final AbstractPrioritizedTransactions prioLayer, final List expected) { - assertThat(prioLayer.getBySender()) - .describedAs("Prioritized") - .flatExtracting(SenderPendingTransactions::pendingTransactions) - .containsExactlyElementsOf(expected); + final var flatOrder = + prioLayer.getByScore().values().stream() + .flatMap(List::stream) + .flatMap(spt -> spt.pendingTransactions().stream()) + .toList(); + assertThat(flatOrder).describedAs("Prioritized").containsExactlyElementsOf(expected); } private void assertExpectedReady( @@ -1582,6 +1663,23 @@ public Scenario removeForSender(final Sender sender, final long... nonce) { return this; } + public Scenario penalizeForSender(final Sender sender, final long... nonce) { + Arrays.stream(nonce) + .forEach( + n -> { + actions.add( + (pending, prio, ready, sparse, dropped) -> { + final var senderTxs = prio.getAllFor(sender.address); + Arrays.stream(nonce) + .mapToObj( + n2 -> senderTxs.stream().filter(pt -> pt.getNonce() == n2).findAny()) + .map(Optional::get) + .forEach(prio::penalize); + }); + }); + return this; + } + public Scenario expectedSelectedTransactions(final Object... args) { List expectedSelected = new ArrayList<>(); for (int i = 0; i < args.length; i = i + 2) { diff --git a/plugin-api/build.gradle b/plugin-api/build.gradle index 58c241509ee..81e66a06a04 100644 --- a/plugin-api/build.gradle +++ b/plugin-api/build.gradle @@ -70,7 +70,7 @@ Calculated : ${currentHash} tasks.register('checkAPIChanges', FileStateChecker) { description = "Checks that the API for the Plugin-API project does not change without deliberate thought" files = sourceSets.main.allJava.files - knownHash = 'F07ix5Mkvycb2W2luprKmcMyrWcSLB4Xtou5Id10DW0=' + knownHash = '6L5dNJ975Ka/X7g4lTdpkBvPQrJgJu+vAf/m1dFCneU=' } check.dependsOn('checkAPIChanges') diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/TransactionSelectionResult.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/TransactionSelectionResult.java index b59fb269670..66b1c1f2d65 100644 --- a/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/TransactionSelectionResult.java +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/TransactionSelectionResult.java @@ -42,6 +42,13 @@ protected interface Status { */ boolean discard(); + /** + * Should the score of this transaction be decremented? + * + * @return yes if the score of this transaction needs to be decremented + */ + boolean penalize(); + /** * Name of this status * @@ -52,30 +59,34 @@ protected interface Status { private enum BaseStatus implements Status { SELECTED, - BLOCK_FULL(true, false), - BLOBS_FULL(false, false), - BLOCK_OCCUPANCY_ABOVE_THRESHOLD(true, false), - BLOCK_SELECTION_TIMEOUT(true, false), - TX_EVALUATION_TOO_LONG(true, true), - INVALID_TRANSIENT(false, false), - INVALID(false, true); + BLOCK_FULL(true, false, false), + BLOBS_FULL(false, false, false), + BLOCK_OCCUPANCY_ABOVE_THRESHOLD(true, false, false), + BLOCK_SELECTION_TIMEOUT(true, false, false), + TX_EVALUATION_TOO_LONG(true, false, true), + INVALID_TX_EVALUATION_TOO_LONG(true, true, true), + INVALID_TRANSIENT(false, false, true), + INVALID(false, true, false); private final boolean stop; private final boolean discard; + private final boolean penalize; BaseStatus() { this.stop = false; this.discard = false; + this.penalize = false; } - BaseStatus(final boolean stop, final boolean discard) { + BaseStatus(final boolean stop, final boolean discard, final boolean penalize) { this.stop = stop; this.discard = discard; + this.penalize = penalize; } @Override public String toString() { - return name() + " (stop=" + stop + ", discard=" + discard + ")"; + return name() + " (stop=" + stop + ", discard=" + discard + ", penalize=" + penalize + ")"; } @Override @@ -87,6 +98,11 @@ public boolean stop() { public boolean discard() { return discard; } + + @Override + public boolean penalize() { + return penalize; + } } /** The transaction has been selected to be included in the new block */ @@ -105,10 +121,14 @@ public boolean discard() { public static final TransactionSelectionResult BLOCK_SELECTION_TIMEOUT = new TransactionSelectionResult(BaseStatus.BLOCK_SELECTION_TIMEOUT); - /** Transaction took too much to evaluate */ + /** Transaction took too much to evaluate, but it was not invalid */ public static final TransactionSelectionResult TX_EVALUATION_TOO_LONG = new TransactionSelectionResult(BaseStatus.TX_EVALUATION_TOO_LONG); + /** Transaction took too much to evaluate, and it was invalid */ + public static final TransactionSelectionResult INVALID_TX_EVALUATION_TOO_LONG = + new TransactionSelectionResult(BaseStatus.INVALID_TX_EVALUATION_TOO_LONG); + /** * The transaction has not been selected since too large and the occupancy of the block is enough * to stop the selection. @@ -215,6 +235,15 @@ public boolean discard() { return status.discard(); } + /** + * Should the score of this transaction be decremented? + * + * @return yes if the score of this transaction needs to be decremented + */ + public boolean penalize() { + return status.penalize(); + } + /** * Is the candidate transaction selected for block inclusion? * From cf358c0e7ae222428029f6ae93c09a56c1529d5f Mon Sep 17 00:00:00 2001 From: Gaurav Ahuja Date: Fri, 26 Jul 2024 03:50:05 +0530 Subject: [PATCH 09/14] Update GeneralStateTestCaseEipSpec for use in linea-arithmetization (#7377) * Update GeneralStateTestCaseEipSpec for use in linea-arithmetization Signed-off-by: Gaurav Ahuja * formatting Signed-off-by: Sally MacFarlane --------- Signed-off-by: Gaurav Ahuja Signed-off-by: Sally MacFarlane Co-authored-by: Sally MacFarlane --- .../besu/evmtool/StateTestSubCommand.java | 2 +- .../GeneralStateTestCaseEipSpec.java | 15 ++++++++++----- .../referencetests/GeneralStateTestCaseSpec.java | 5 +++-- .../vm/GeneralStateReferenceTestTools.java | 2 +- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java index 064a093e840..40f36f18f1c 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java @@ -232,7 +232,7 @@ private void traceTestSpecs(final String test, final List transactionSupplier; + private final List> transactionSuppliers; private final ReferenceTestWorldState initialWorldState; @@ -51,7 +52,7 @@ public class GeneralStateTestCaseEipSpec { GeneralStateTestCaseEipSpec( final String fork, - final Supplier transactionSupplier, + final List> transactionSuppliers, final ReferenceTestWorldState initialWorldState, final Hash expectedRootHash, final Hash expectedLogsHash, @@ -61,7 +62,7 @@ public class GeneralStateTestCaseEipSpec { final int valueIndex, final String expectException) { this.fork = fork; - this.transactionSupplier = transactionSupplier; + this.transactionSuppliers = transactionSuppliers; this.initialWorldState = initialWorldState; this.expectedRootHash = expectedRootHash; this.expectedLogsHash = expectedLogsHash; @@ -88,9 +89,13 @@ public Hash getExpectedLogsHash() { return expectedLogsHash; } - public Transaction getTransaction() { + public int getTransactionsCount() { + return transactionSuppliers.size(); + } + + public Transaction getTransaction(final int txIndex) { try { - return transactionSupplier.get(); + return transactionSuppliers.get(txIndex).get(); } catch (RuntimeException re) { // some tests specify invalid transactions. We throw exceptions in // GeneralStateTests but they are encoded in BlockchainTests, so we diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/GeneralStateTestCaseSpec.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/GeneralStateTestCaseSpec.java index affc6e46010..394cb9a2695 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/GeneralStateTestCaseSpec.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/GeneralStateTestCaseSpec.java @@ -72,11 +72,12 @@ private Map> generate( .stateRoot(p.rootHash) .blockHeaderFunctions(MAINNET_FUNCTIONS) .buildBlockHeader(); - final Supplier txSupplier = () -> versionedTransaction.get(p.indexes); + final List> txSupplierList = + List.of(() -> versionedTransaction.get(p.indexes)); specs.add( new GeneralStateTestCaseEipSpec( eip, - txSupplier, + txSupplierList, initialWorldState, p.rootHash, p.logsHash, diff --git a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/GeneralStateReferenceTestTools.java b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/GeneralStateReferenceTestTools.java index f948a5b24e3..18d574adc15 100644 --- a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/GeneralStateReferenceTestTools.java +++ b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/GeneralStateReferenceTestTools.java @@ -120,7 +120,7 @@ public static Collection generateTestParametersForConfig(final String[ public static void executeTest(final GeneralStateTestCaseEipSpec spec) { final BlockHeader blockHeader = spec.getBlockHeader(); final ReferenceTestWorldState initialWorldState = spec.getInitialWorldState(); - final Transaction transaction = spec.getTransaction(); + final Transaction transaction = spec.getTransaction(0); ProtocolSpec protocolSpec = protocolSpec(spec.getFork()); BlockchainReferenceTestTools.verifyJournaledEVMAccountCompatability(initialWorldState, protocolSpec); From c182ba113ac35632ac0983c79c6a1ba011fb231e Mon Sep 17 00:00:00 2001 From: garyschulte Date: Thu, 25 Jul 2024 15:41:45 -0700 Subject: [PATCH 10/14] bump execution-spec-tests, account for new name for main stable artifact (#7380) Signed-off-by: garyschulte --- ethereum/referencetests/build.gradle | 2 +- gradle/verification-metadata.xml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ethereum/referencetests/build.gradle b/ethereum/referencetests/build.gradle index 3c073136acd..426c1084db6 100644 --- a/ethereum/referencetests/build.gradle +++ b/ethereum/referencetests/build.gradle @@ -204,7 +204,7 @@ dependencies { referenceTestImplementation project(path: ':testutil') referenceTestImplementation project(path: ':util') // the following will be resolved via custom ivy repository declared in root build.gradle - referenceTestImplementation 'ethereum:execution-spec-tests:2.1.1:fixtures@tar.gz' + referenceTestImplementation 'ethereum:execution-spec-tests:3.0.0:fixtures_stable@tar.gz' referenceTestImplementation 'com.fasterxml.jackson.core:jackson-databind' referenceTestImplementation 'com.google.guava:guava' referenceTestImplementation 'io.tmio:tuweni-bytes' diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 7cdf7ce0803..950e0ee8661 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1385,9 +1385,9 @@ - - - + + + From 4a670a1dbe1da35f31fce75d1e760f195a5b1059 Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Fri, 26 Jul 2024 09:16:49 +1000 Subject: [PATCH 11/14] Disable bonsai-limit-trie-logs-enabled if sync-mode=FULL (#7357) There is still a startup error when bonsai-limit-trie-logs-enabled is explicitly set to true --------- Signed-off-by: Simon Dudley --- CHANGELOG.md | 3 +- .../org/hyperledger/besu/cli/BesuCommand.java | 29 ++++++++++++++++++- .../options/stable/DataStorageOptions.java | 16 ++-------- .../hyperledger/besu/cli/BesuCommandTest.java | 26 +++++++++++++++-- .../stable/DataStorageOptionsTest.java | 8 ----- 5 files changed, 57 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b999bca71e..c5754da1c96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,12 +23,13 @@ - Added EIP-7702 [#7237](https://github.com/hyperledger/besu/pull/7237) - Implement gnark-crypto for eip-196 [#7262](https://github.com/hyperledger/besu/pull/7262) - Add trie log pruner metrics [#7352](https://github.com/hyperledger/besu/pull/7352) +- Force bonsai-limit-trie-logs-enabled=false when sync-mode=FULL instead of startup error [#7357](https://github.com/hyperledger/besu/pull/7357) - `--Xbonsai-parallel-tx-processing-enabled` option enables executing transactions in parallel during block processing for Bonsai nodes - - Add option `--poa-discovery-retry-bootnodes` for PoA networks to always use bootnodes during peer refresh, not just on first start [#7314](https://github.com/hyperledger/besu/pull/7314) ### Bug fixes - Fix `eth_call` deserialization to correctly ignore unknown fields in the transaction object. [#7323](https://github.com/hyperledger/besu/pull/7323) +- Prevent Besu from starting up with sync-mode=FULL and bonsai-limit-trie-logs-enabled=true for private networks [#7357](https://github.com/hyperledger/besu/pull/7357) - Avoid executing pruner preload during trie log subcommands [#7366](https://github.com/hyperledger/besu/pull/7366) ## 24.7.0 diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index 1eaab20bd27..d300fbea457 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -139,6 +139,7 @@ import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProviderBuilder; import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; +import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration; import org.hyperledger.besu.evm.precompile.AbstractAltBnPrecompiledContract; import org.hyperledger.besu.evm.precompile.BigIntegerModularExponentiationPrecompiledContract; import org.hyperledger.besu.evm.precompile.KZGPointEvalPrecompiledContract; @@ -1587,7 +1588,7 @@ private void validateTransactionPoolOptions() { } private void validateDataStorageOptions() { - dataStorageOptions.validate(commandLine, syncMode); + dataStorageOptions.validate(commandLine); } private void validateRequiredOptions() { @@ -2255,6 +2256,32 @@ public DataStorageConfiguration getDataStorageConfiguration() { if (dataStorageConfiguration == null) { dataStorageConfiguration = dataStorageOptions.toDomainObject(); } + + if (SyncMode.FULL.equals(getDefaultSyncModeIfNotSet()) + && DataStorageFormat.BONSAI.equals(dataStorageConfiguration.getDataStorageFormat()) + && dataStorageConfiguration.getBonsaiLimitTrieLogsEnabled()) { + + if (CommandLineUtils.isOptionSet( + commandLine, DataStorageOptions.BONSAI_LIMIT_TRIE_LOGS_ENABLED)) { + throw new ParameterException( + commandLine, + String.format( + "Cannot enable %s with --sync-mode=%s and --data-storage-format=%s. You must set %s or use a different sync-mode", + DataStorageOptions.BONSAI_LIMIT_TRIE_LOGS_ENABLED, + SyncMode.FULL, + DataStorageFormat.BONSAI, + DataStorageOptions.BONSAI_LIMIT_TRIE_LOGS_ENABLED + "=false")); + } + + dataStorageConfiguration = + ImmutableDataStorageConfiguration.copyOf(dataStorageConfiguration) + .withBonsaiLimitTrieLogsEnabled(false); + logger.warn( + "Forcing {}, since it cannot be enabled with --sync-mode={} and --data-storage-format={}.", + DataStorageOptions.BONSAI_LIMIT_TRIE_LOGS_ENABLED + "=false", + SyncMode.FULL, + DataStorageFormat.BONSAI); + } return dataStorageConfiguration; } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/DataStorageOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/DataStorageOptions.java index fc92a7e5dd9..a0403c39420 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/DataStorageOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/DataStorageOptions.java @@ -24,7 +24,6 @@ import org.hyperledger.besu.cli.options.CLIOptions; import org.hyperledger.besu.cli.util.CommandLineUtils; -import org.hyperledger.besu.ethereum.eth.sync.SyncMode; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration; import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; @@ -63,7 +62,8 @@ public class DataStorageOptions implements CLIOptions arity = "1") private Long bonsaiMaxLayersToLoad = DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD; - private static final String BONSAI_LIMIT_TRIE_LOGS_ENABLED = "--bonsai-limit-trie-logs-enabled"; + /** The bonsai limit trie logs enabled option name */ + public static final String BONSAI_LIMIT_TRIE_LOGS_ENABLED = "--bonsai-limit-trie-logs-enabled"; /** The bonsai trie logs pruning window size. */ public static final String BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE = @@ -147,20 +147,10 @@ public static DataStorageOptions create() { * Validates the data storage options * * @param commandLine the full commandLine to check all the options specified by the user - * @param syncMode the sync mode */ - public void validate(final CommandLine commandLine, final SyncMode syncMode) { + public void validate(final CommandLine commandLine) { if (DataStorageFormat.BONSAI == dataStorageFormat) { if (bonsaiLimitTrieLogsEnabled) { - if (SyncMode.FULL == syncMode) { - throw new CommandLine.ParameterException( - commandLine, - String.format( - "Cannot enable %s with sync-mode %s. You must set %s or use a different sync-mode", - BONSAI_LIMIT_TRIE_LOGS_ENABLED, - SyncMode.FULL, - BONSAI_LIMIT_TRIE_LOGS_ENABLED + "=false")); - } if (bonsaiMaxLayersToLoad < MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT) { throw new CommandLine.ParameterException( commandLine, diff --git a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java index c892ffe7fe6..d0c42f67188 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java @@ -65,6 +65,7 @@ import org.hyperledger.besu.metrics.StandardMetricCategory; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.plugin.data.EnodeURL; +import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; import org.hyperledger.besu.util.number.Fraction; import org.hyperledger.besu.util.number.Percentage; import org.hyperledger.besu.util.number.PositiveNumber; @@ -1303,13 +1304,34 @@ public void bonsaiLimitTrieLogsEnabledByDefault() { } @Test - public void parsesInvalidDefaultBonsaiLimitTrieLogsWhenFullSyncEnabled() { + public void bonsaiLimitTrieLogsDisabledWhenFullSyncEnabled() { parseCommand("--sync-mode=FULL"); + verify(mockControllerBuilder) + .dataStorageConfiguration(dataStorageConfigurationArgumentCaptor.capture()); + + final DataStorageConfiguration dataStorageConfiguration = + dataStorageConfigurationArgumentCaptor.getValue(); + assertThat(dataStorageConfiguration.getDataStorageFormat()).isEqualTo(BONSAI); + assertThat(dataStorageConfiguration.getBonsaiLimitTrieLogsEnabled()).isFalse(); + verify(mockLogger) + .warn( + "Forcing {}, since it cannot be enabled with --sync-mode={} and --data-storage-format={}.", + "--bonsai-limit-trie-logs-enabled=false", + SyncMode.FULL, + DataStorageFormat.BONSAI); + assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); + } + + @Test + public void parsesInvalidWhenFullSyncAndBonsaiLimitTrieLogsExplicitlyTrue() { + parseCommand("--sync-mode=FULL", "--bonsai-limit-trie-logs-enabled=true"); + Mockito.verifyNoInteractions(mockRunnerBuilder); assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)) - .contains("Cannot enable --bonsai-limit-trie-logs-enabled with sync-mode FULL"); + .contains( + "Cannot enable --bonsai-limit-trie-logs-enabled with --sync-mode=FULL and --data-storage-format=BONSAI. You must set --bonsai-limit-trie-logs-enabled=false or use a different sync-mode"); } @Test diff --git a/besu/src/test/java/org/hyperledger/besu/cli/options/stable/DataStorageOptionsTest.java b/besu/src/test/java/org/hyperledger/besu/cli/options/stable/DataStorageOptionsTest.java index 5ab2757f888..2086381825f 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/options/stable/DataStorageOptionsTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/options/stable/DataStorageOptionsTest.java @@ -55,14 +55,6 @@ public void bonsaiTrieLogsEnabled_explicitlySetToFalse() { "--bonsai-limit-trie-logs-enabled=false"); } - @Test - public void bonsaiTrieLogPruningWindowSizeShouldBePositive2() { - internalTestFailure( - "Cannot enable --bonsai-limit-trie-logs-enabled with sync-mode FULL. You must set --bonsai-limit-trie-logs-enabled=false or use a different sync-mode", - "--sync-mode", - "FULL"); - } - @Test public void bonsaiTrieLogPruningWindowSizeShouldBePositive() { internalTestFailure( From a1efd211572b36f345eea985390a0a888d20806e Mon Sep 17 00:00:00 2001 From: Matt Whitehead Date: Fri, 26 Jul 2024 01:10:23 +0100 Subject: [PATCH 12/14] Do not maintain connections to bootnodes (#7358) * Do not maintain connections to bootnodes Signed-off-by: Matthew Whitehead * Update changelog entry Signed-off-by: Matthew Whitehead --------- Signed-off-by: Matthew Whitehead Co-authored-by: Stefan Pingel <16143240+pinges@users.noreply.github.com> --- CHANGELOG.md | 1 + .../java/org/hyperledger/besu/RunnerBuilder.java | 15 +-------------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5754da1c96..813cf6804b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ ### Breaking Changes - Remove deprecated sync modes (X_SNAP and X_CHECKPOINT). Use SNAP and CHECKPOINT instead [#7309](https://github.com/hyperledger/besu/pull/7309) - Remove PKI-backed QBFT (deprecated in 24.5.1) Other forms of QBFT remain unchanged. [#7293](https://github.com/hyperledger/besu/pull/7293) +- Do not maintain connections to PoA bootnodes [#7358](https://github.com/hyperledger/besu/pull/7358). See [#7314](https://github.com/hyperledger/besu/pull/7314) for recommended alternative behaviour. ### Additions and Improvements - `--Xsnapsync-bft-enabled` option enables experimental support for snap sync with IBFT/QBFT permissioned Bonsai-DB chains [#7140](https://github.com/hyperledger/besu/pull/7140) diff --git a/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java b/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java index dfd09165b7d..d0c434fc819 100644 --- a/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java @@ -807,20 +807,7 @@ public Runner build() { LOG.debug("added ethash observer: {}", stratumServer.get()); } - final Stream maintainedPeers; - if (besuController.getGenesisConfigOptions().isPoa()) { - // In a permissioned chain Besu should maintain connections to both static nodes and - // bootnodes, which includes retries periodically - maintainedPeers = - sanitizePeers( - network, - Stream.concat(staticNodes.stream(), bootnodes.stream()).collect(Collectors.toList())); - LOG.debug("Added bootnodes to the maintained peer list"); - } else { - // In a public chain only maintain connections to static nodes - maintainedPeers = sanitizePeers(network, staticNodes); - } - maintainedPeers + sanitizePeers(network, staticNodes) .map(DefaultPeer::fromEnodeURL) .forEach(peerNetwork::addMaintainedConnectionPeer); From 8a5b6319fd880caa1c31896ea000fad13d18c17d Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Fri, 26 Jul 2024 11:48:57 +1000 Subject: [PATCH 13/14] changelog Signed-off-by: Simon Dudley --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 813cf6804b8..da6ae993789 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ ### Bug fixes - Fix `eth_call` deserialization to correctly ignore unknown fields in the transaction object. [#7323](https://github.com/hyperledger/besu/pull/7323) - Prevent Besu from starting up with sync-mode=FULL and bonsai-limit-trie-logs-enabled=true for private networks [#7357](https://github.com/hyperledger/besu/pull/7357) +- Add 30 second timeout to trie log pruner preload [#7365](https://github.com/hyperledger/besu/pull/7365) - Avoid executing pruner preload during trie log subcommands [#7366](https://github.com/hyperledger/besu/pull/7366) ## 24.7.0 From 95c41041edb81be4065fd4bfc24d6798ddf4658e Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Fri, 26 Jul 2024 11:50:49 +1000 Subject: [PATCH 14/14] changelog again Signed-off-by: Simon Dudley --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index da6ae993789..4d3f9eb4012 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ - Add trie log pruner metrics [#7352](https://github.com/hyperledger/besu/pull/7352) - Force bonsai-limit-trie-logs-enabled=false when sync-mode=FULL instead of startup error [#7357](https://github.com/hyperledger/besu/pull/7357) - `--Xbonsai-parallel-tx-processing-enabled` option enables executing transactions in parallel during block processing for Bonsai nodes +- Reduce default trie log pruning window size from 30,000 to 5,000 [#7365](https://github.com/hyperledger/besu/pull/7365) - Add option `--poa-discovery-retry-bootnodes` for PoA networks to always use bootnodes during peer refresh, not just on first start [#7314](https://github.com/hyperledger/besu/pull/7314) ### Bug fixes