mirror of
https://github.com/vacp2p/status-linea-besu.git
synced 2026-01-06 22:13:59 -05:00
Merge remote-tracking branch 'upstream/main' into zkbesu
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -9,6 +9,7 @@
|
||||
.DS_Store
|
||||
.externalToolBuilders/
|
||||
.gradle/
|
||||
.vscode/
|
||||
.idea/
|
||||
.loadpath
|
||||
.metadata
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
- Implement debug_traceCall [#5885](https://github.com/hyperledger/besu/pull/5885)
|
||||
- Transactions that takes too long to evaluate, during block creation, are dropped from the txpool [#6163](https://github.com/hyperledger/besu/pull/6163)
|
||||
- New option `tx-pool-min-gas-price` to set a lower bound when accepting txs to the pool [#6098](https://github.com/hyperledger/besu/pull/6098)
|
||||
- Allow a transaction selection plugin to specify custom selection results [#6190](https://github.com/hyperledger/besu/pull/6190)
|
||||
|
||||
## 23.10.2
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ dependencies {
|
||||
testImplementation 'com.squareup.okhttp3:okhttp'
|
||||
testImplementation 'commons-io:commons-io'
|
||||
testImplementation 'io.opentelemetry:opentelemetry-api'
|
||||
testImplementation 'junit:junit'
|
||||
testImplementation 'org.mockito:mockito-junit-jupiter'
|
||||
testImplementation 'org.apache.commons:commons-text'
|
||||
testImplementation 'io.tmio:tuweni-bytes'
|
||||
testImplementation 'io.tmio:tuweni-units'
|
||||
|
||||
@@ -41,23 +41,21 @@ import java.nio.file.Path;
|
||||
import java.util.concurrent.CompletionException;
|
||||
|
||||
import org.apache.tuweni.units.bigints.UInt256;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
/** Tests for {@link RlpBlockImporter}. */
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public final class RlpBlockImporterTest {
|
||||
|
||||
@Rule public final TemporaryFolder folder = new TemporaryFolder();
|
||||
@TempDir Path dataDir;
|
||||
|
||||
private final RlpBlockImporter rlpBlockImporter = new RlpBlockImporter();
|
||||
|
||||
@Test
|
||||
public void blockImport() throws IOException {
|
||||
final Path dataDir = folder.newFolder().toPath();
|
||||
final Path source = dataDir.resolve("1000.blocks");
|
||||
BlockTestUtil.write1000Blocks(source);
|
||||
final BesuController targetController =
|
||||
@@ -90,7 +88,6 @@ public final class RlpBlockImporterTest {
|
||||
// set merge flag to false, otherwise this test can fail if a merge test runs first
|
||||
MergeConfigOptions.setMergeEnabled(false);
|
||||
|
||||
final Path dataDir = folder.newFolder().toPath();
|
||||
final Path source = dataDir.resolve("badpow.blocks");
|
||||
BlockTestUtil.writeBadPowBlocks(source);
|
||||
final BesuController targetController =
|
||||
@@ -120,7 +117,6 @@ public final class RlpBlockImporterTest {
|
||||
|
||||
@Test
|
||||
public void blockImportCanSkipPow() throws IOException {
|
||||
final Path dataDir = folder.newFolder().toPath();
|
||||
final Path source = dataDir.resolve("badpow.blocks");
|
||||
BlockTestUtil.writeBadPowBlocks(source);
|
||||
final BesuController targetController =
|
||||
|
||||
@@ -57,6 +57,7 @@ import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -227,11 +228,11 @@ public class BlockTransactionSelector {
|
||||
final PendingTransaction pendingTransaction) {
|
||||
checkCancellation();
|
||||
|
||||
final long evaluationStartedAt = System.currentTimeMillis();
|
||||
final Stopwatch evaluationTimer = Stopwatch.createStarted();
|
||||
|
||||
TransactionSelectionResult selectionResult = evaluatePreProcessing(pendingTransaction);
|
||||
if (!selectionResult.selected()) {
|
||||
return handleTransactionNotSelected(pendingTransaction, selectionResult, evaluationStartedAt);
|
||||
return handleTransactionNotSelected(pendingTransaction, selectionResult, evaluationTimer);
|
||||
}
|
||||
|
||||
final WorldUpdater txWorldStateUpdater = blockWorldStateUpdater.updater();
|
||||
@@ -243,13 +244,10 @@ public class BlockTransactionSelector {
|
||||
|
||||
if (postProcessingSelectionResult.selected()) {
|
||||
return handleTransactionSelected(
|
||||
pendingTransaction, processingResult, txWorldStateUpdater, evaluationStartedAt);
|
||||
pendingTransaction, processingResult, txWorldStateUpdater, evaluationTimer);
|
||||
}
|
||||
return handleTransactionNotSelected(
|
||||
pendingTransaction,
|
||||
postProcessingSelectionResult,
|
||||
txWorldStateUpdater,
|
||||
evaluationStartedAt);
|
||||
pendingTransaction, postProcessingSelectionResult, txWorldStateUpdater, evaluationTimer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -333,14 +331,14 @@ public class BlockTransactionSelector {
|
||||
* @param pendingTransaction The pending transaction.
|
||||
* @param processingResult The result of the transaction processing.
|
||||
* @param txWorldStateUpdater The world state updater.
|
||||
* @param evaluationStartedAt when the evaluation of this tx started
|
||||
* @param evaluationTimer tracks the evaluation elapsed time
|
||||
* @return The result of the transaction selection process.
|
||||
*/
|
||||
private TransactionSelectionResult handleTransactionSelected(
|
||||
final PendingTransaction pendingTransaction,
|
||||
final TransactionProcessingResult processingResult,
|
||||
final WorldUpdater txWorldStateUpdater,
|
||||
final long evaluationStartedAt) {
|
||||
final Stopwatch evaluationTimer) {
|
||||
final Transaction transaction = pendingTransaction.getTransaction();
|
||||
|
||||
final long gasUsedByTransaction =
|
||||
@@ -369,20 +367,19 @@ public class BlockTransactionSelector {
|
||||
}
|
||||
}
|
||||
|
||||
final long evaluationTime = System.currentTimeMillis() - evaluationStartedAt;
|
||||
if (tooLate) {
|
||||
// even if this tx passed all the checks, it is too late to include it in this block,
|
||||
// so we need to treat it as not selected
|
||||
|
||||
// check if this tx took too much to evaluate, and in case remove it from the pool
|
||||
final TransactionSelectionResult timeoutSelectionResult;
|
||||
if (evaluationTime > blockTxsSelectionMaxTime) {
|
||||
if (evaluationTimer.elapsed(TimeUnit.MILLISECONDS) > blockTxsSelectionMaxTime) {
|
||||
LOG.atWarn()
|
||||
.setMessage(
|
||||
"Transaction {} is too late for inclusion, evaluated in {}ms that is over the max limit of {}"
|
||||
"Transaction {} is too late for inclusion, evaluated in {} that is over the max limit of {}ms"
|
||||
+ ", removing it from the pool")
|
||||
.addArgument(transaction::toTraceLog)
|
||||
.addArgument(evaluationTime)
|
||||
.addArgument(evaluationTimer)
|
||||
.addArgument(blockTxsSelectionMaxTime)
|
||||
.log();
|
||||
timeoutSelectionResult = TX_EVALUATION_TOO_LONG;
|
||||
@@ -390,7 +387,7 @@ public class BlockTransactionSelector {
|
||||
LOG.atTrace()
|
||||
.setMessage("Transaction {} is too late for inclusion")
|
||||
.addArgument(transaction::toTraceLog)
|
||||
.addArgument(evaluationTime)
|
||||
.addArgument(evaluationTimer)
|
||||
.log();
|
||||
timeoutSelectionResult = BLOCK_SELECTION_TIMEOUT;
|
||||
}
|
||||
@@ -398,15 +395,15 @@ public class BlockTransactionSelector {
|
||||
// do not rely on the presence of this result, since by the time it is added, the code
|
||||
// reading it could have been already executed by another thread
|
||||
return handleTransactionNotSelected(
|
||||
pendingTransaction, timeoutSelectionResult, txWorldStateUpdater, evaluationStartedAt);
|
||||
pendingTransaction, timeoutSelectionResult, txWorldStateUpdater, evaluationTimer);
|
||||
}
|
||||
|
||||
pluginTransactionSelector.onTransactionSelected(pendingTransaction, processingResult);
|
||||
blockWorldStateUpdater = worldState.updater();
|
||||
LOG.atTrace()
|
||||
.setMessage("Selected {} for block creation, evaluated in {}ms")
|
||||
.setMessage("Selected {} for block creation, evaluated in {}")
|
||||
.addArgument(transaction::toTraceLog)
|
||||
.addArgument(evaluationTime)
|
||||
.addArgument(evaluationTimer)
|
||||
.log();
|
||||
return SELECTED;
|
||||
}
|
||||
@@ -418,22 +415,22 @@ public class BlockTransactionSelector {
|
||||
*
|
||||
* @param pendingTransaction The unselected pending transaction.
|
||||
* @param selectionResult The result of the transaction selection process.
|
||||
* @param evaluationStartedAt when the evaluation of this tx started
|
||||
* @param evaluationTimer tracks the evaluation elapsed time
|
||||
* @return The result of the transaction selection process.
|
||||
*/
|
||||
private TransactionSelectionResult handleTransactionNotSelected(
|
||||
final PendingTransaction pendingTransaction,
|
||||
final TransactionSelectionResult selectionResult,
|
||||
final long evaluationStartedAt) {
|
||||
final Stopwatch evaluationTimer) {
|
||||
|
||||
transactionSelectionResults.updateNotSelected(
|
||||
pendingTransaction.getTransaction(), selectionResult);
|
||||
pluginTransactionSelector.onTransactionNotSelected(pendingTransaction, selectionResult);
|
||||
LOG.atTrace()
|
||||
.setMessage("Not selected {} for block creation with result {}, evaluated in {}ms")
|
||||
.setMessage("Not selected {} for block creation with result {}, evaluated in {}")
|
||||
.addArgument(pendingTransaction::toTraceLog)
|
||||
.addArgument(selectionResult)
|
||||
.addArgument(() -> System.currentTimeMillis() - evaluationStartedAt)
|
||||
.addArgument(evaluationTimer)
|
||||
.log();
|
||||
|
||||
return selectionResult;
|
||||
@@ -443,9 +440,9 @@ public class BlockTransactionSelector {
|
||||
final PendingTransaction pendingTransaction,
|
||||
final TransactionSelectionResult selectionResult,
|
||||
final WorldUpdater txWorldStateUpdater,
|
||||
final long evaluationStartedAt) {
|
||||
final Stopwatch evaluationTimer) {
|
||||
txWorldStateUpdater.revert();
|
||||
return handleTransactionNotSelected(pendingTransaction, selectionResult, evaluationStartedAt);
|
||||
return handleTransactionNotSelected(pendingTransaction, selectionResult, evaluationTimer);
|
||||
}
|
||||
|
||||
private void checkCancellation() {
|
||||
|
||||
@@ -111,7 +111,7 @@ public class TransactionSelectionResults {
|
||||
"Selection stats: Totals[Evaluated={}, Selected={}, NotSelected={}, Discarded={}]; Detailed[{}]",
|
||||
selectedTransactions.size() + notSelectedTxs.size(),
|
||||
selectedTransactions.size(),
|
||||
notSelectedStats.size(),
|
||||
notSelectedTxs.size(),
|
||||
notSelectedStats.entrySet().stream()
|
||||
.filter(e -> e.getKey().discard())
|
||||
.map(Map.Entry::getValue)
|
||||
|
||||
@@ -89,8 +89,9 @@ public class PriceTransactionSelector extends AbstractTransactionSelector {
|
||||
.setMessage(
|
||||
"Current gas price of {} is {} and lower than the configured minimum {}, skipping")
|
||||
.addArgument(pendingTransaction::toTraceLog)
|
||||
.addArgument(transactionGasPriceInBlock)
|
||||
.addArgument(context.miningParameters()::getMinTransactionGasPrice)
|
||||
.addArgument(transactionGasPriceInBlock::toHumanReadableString)
|
||||
.addArgument(
|
||||
context.miningParameters().getMinTransactionGasPrice()::toHumanReadableString)
|
||||
.log();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -587,9 +587,9 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
public TransactionSelectionResult evaluateTransactionPreProcessing(
|
||||
final PendingTransaction pendingTransaction) {
|
||||
if (pendingTransaction.getTransaction().equals(notSelectedTransient))
|
||||
return TransactionSelectionResult.invalidTransient("transient");
|
||||
return PluginTransactionSelectionResult.GENERIC_PLUGIN_INVALID_TRANSIENT;
|
||||
if (pendingTransaction.getTransaction().equals(notSelectedInvalid))
|
||||
return TransactionSelectionResult.invalid("invalid");
|
||||
return PluginTransactionSelectionResult.GENERIC_PLUGIN_INVALID;
|
||||
return SELECTED;
|
||||
}
|
||||
|
||||
@@ -622,8 +622,10 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
assertThat(transactionSelectionResults.getSelectedTransactions()).containsOnly(selected);
|
||||
assertThat(transactionSelectionResults.getNotSelectedTransactions())
|
||||
.containsOnly(
|
||||
entry(notSelectedTransient, TransactionSelectionResult.invalidTransient("transient")),
|
||||
entry(notSelectedInvalid, TransactionSelectionResult.invalid("invalid")));
|
||||
entry(
|
||||
notSelectedTransient,
|
||||
PluginTransactionSelectionResult.GENERIC_PLUGIN_INVALID_TRANSIENT),
|
||||
entry(notSelectedInvalid, PluginTransactionSelectionResult.GENERIC_PLUGIN_INVALID));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -658,7 +660,7 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
processingResult) {
|
||||
// the transaction with max gas +1 should fail
|
||||
if (processingResult.getEstimateGasUsedByTransaction() > maxGasUsedByTransaction) {
|
||||
return TransactionSelectionResult.invalidTransient("Invalid");
|
||||
return PluginTransactionSelectionResult.GENERIC_PLUGIN_INVALID_TRANSIENT;
|
||||
}
|
||||
return SELECTED;
|
||||
}
|
||||
@@ -682,7 +684,8 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
|
||||
assertThat(transactionSelectionResults.getSelectedTransactions()).contains(selected, selected3);
|
||||
assertThat(transactionSelectionResults.getNotSelectedTransactions())
|
||||
.containsOnly(entry(notSelected, TransactionSelectionResult.invalidTransient("Invalid")));
|
||||
.containsOnly(
|
||||
entry(notSelected, PluginTransactionSelectionResult.GENERIC_PLUGIN_INVALID_TRANSIENT));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1193,4 +1196,48 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
private static class PluginTransactionSelectionResult extends TransactionSelectionResult {
|
||||
private enum PluginStatus implements Status {
|
||||
PLUGIN_INVALID(false, true),
|
||||
PLUGIN_INVALID_TRANSIENT(false, false);
|
||||
|
||||
private final boolean stop;
|
||||
private final boolean discard;
|
||||
|
||||
PluginStatus(final boolean stop, final boolean discard) {
|
||||
this.stop = stop;
|
||||
this.discard = discard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
return stop;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean discard() {
|
||||
return discard;
|
||||
}
|
||||
}
|
||||
|
||||
public static final TransactionSelectionResult GENERIC_PLUGIN_INVALID_TRANSIENT =
|
||||
invalidTransient("GENERIC_PLUGIN_INVALID_TRANSIENT");
|
||||
|
||||
public static final TransactionSelectionResult GENERIC_PLUGIN_INVALID =
|
||||
invalid("GENERIC_PLUGIN_INVALID");
|
||||
|
||||
private PluginTransactionSelectionResult(final Status status, final String invalidReason) {
|
||||
super(status, invalidReason);
|
||||
}
|
||||
|
||||
public static TransactionSelectionResult invalidTransient(final String invalidReason) {
|
||||
return new PluginTransactionSelectionResult(
|
||||
PluginStatus.PLUGIN_INVALID_TRANSIENT, invalidReason);
|
||||
}
|
||||
|
||||
public static TransactionSelectionResult invalid(final String invalidReason) {
|
||||
return new PluginTransactionSelectionResult(PluginStatus.PLUGIN_INVALID, invalidReason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ public class EthPeers {
|
||||
disconnectCallbacks.forEach(callback -> callback.onDisconnect(peer));
|
||||
peer.handleDisconnect();
|
||||
abortPendingRequestsAssignedToDisconnectedPeers();
|
||||
LOG.debug("Disconnected EthPeer {}", peer.getShortNodeId());
|
||||
LOG.debug("Disconnected EthPeer {}...", peer.getShortNodeId());
|
||||
LOG.trace("Disconnected EthPeer {}", peer);
|
||||
}
|
||||
}
|
||||
@@ -391,7 +391,7 @@ public class EthPeers {
|
||||
peer -> {
|
||||
LOG.atDebug()
|
||||
.setMessage(
|
||||
"disconnecting peer {}. Waiting for better peers. Current {} of max {}")
|
||||
"disconnecting peer {}... Waiting for better peers. Current {} of max {}")
|
||||
.addArgument(peer::getShortNodeId)
|
||||
.addArgument(this::peerCount)
|
||||
.addArgument(this::getMaxPeers)
|
||||
|
||||
@@ -398,7 +398,7 @@ public class EthProtocolManager implements ProtocolManager, MinedBlockObserver {
|
||||
"Disconnect - {} - {} - {}... - {} peers left\n{}",
|
||||
initiatedByPeer ? "Inbound" : "Outbound",
|
||||
reason,
|
||||
connection.getPeer().getId().slice(0, 16),
|
||||
connection.getPeer().getId().slice(0, 8),
|
||||
ethPeers.peerCount(),
|
||||
ethPeers);
|
||||
}
|
||||
|
||||
@@ -34,10 +34,13 @@ import org.slf4j.LoggerFactory;
|
||||
public class PeerReputation implements Comparable<PeerReputation> {
|
||||
static final long USELESS_RESPONSE_WINDOW_IN_MILLIS =
|
||||
TimeUnit.MILLISECONDS.convert(1, TimeUnit.MINUTES);
|
||||
static final int DEFAULT_MAX_SCORE = 150;
|
||||
static final int DEFAULT_MAX_SCORE = 200;
|
||||
// how much above the initial score you need to be to not get disconnected for timeouts/useless
|
||||
// responses
|
||||
private final int hasBeenUsefulThreshold;
|
||||
static final int DEFAULT_INITIAL_SCORE = 100;
|
||||
private static final Logger LOG = LoggerFactory.getLogger(PeerReputation.class);
|
||||
private static final int TIMEOUT_THRESHOLD = 3;
|
||||
private static final int TIMEOUT_THRESHOLD = 5;
|
||||
private static final int USELESS_RESPONSE_THRESHOLD = 5;
|
||||
|
||||
private final ConcurrentMap<Integer, AtomicInteger> timeoutCountByRequestType =
|
||||
@@ -45,8 +48,7 @@ public class PeerReputation implements Comparable<PeerReputation> {
|
||||
private final Queue<Long> uselessResponseTimes = new ConcurrentLinkedQueue<>();
|
||||
|
||||
private static final int SMALL_ADJUSTMENT = 1;
|
||||
private static final int LARGE_ADJUSTMENT = 10;
|
||||
|
||||
private static final int LARGE_ADJUSTMENT = 5;
|
||||
private int score;
|
||||
|
||||
private final int maxScore;
|
||||
@@ -59,22 +61,37 @@ public class PeerReputation implements Comparable<PeerReputation> {
|
||||
checkArgument(
|
||||
initialScore <= maxScore, "Initial score must be less than or equal to max score");
|
||||
this.maxScore = maxScore;
|
||||
this.hasBeenUsefulThreshold = Math.min(maxScore, initialScore + 10);
|
||||
this.score = initialScore;
|
||||
}
|
||||
|
||||
public Optional<DisconnectReason> recordRequestTimeout(final int requestCode) {
|
||||
final int newTimeoutCount = getOrCreateTimeoutCount(requestCode).incrementAndGet();
|
||||
if (newTimeoutCount >= TIMEOUT_THRESHOLD) {
|
||||
LOG.debug(
|
||||
"Disconnection triggered by {} repeated timeouts for requestCode {}",
|
||||
newTimeoutCount,
|
||||
requestCode);
|
||||
score -= LARGE_ADJUSTMENT;
|
||||
return Optional.of(DisconnectReason.TIMEOUT);
|
||||
// don't trigger disconnect if this peer has a sufficiently high reputation score
|
||||
if (peerHasNotBeenUseful()) {
|
||||
LOG.debug(
|
||||
"Disconnection triggered by {} repeated timeouts for requestCode {}, peer score {}",
|
||||
newTimeoutCount,
|
||||
requestCode,
|
||||
score);
|
||||
return Optional.of(DisconnectReason.TIMEOUT);
|
||||
}
|
||||
|
||||
LOG.trace(
|
||||
"Not triggering disconnect for {} repeated timeouts for requestCode {} because peer has high score {}",
|
||||
newTimeoutCount,
|
||||
requestCode,
|
||||
score);
|
||||
} else {
|
||||
score -= SMALL_ADJUSTMENT;
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private boolean peerHasNotBeenUseful() {
|
||||
return score < hasBeenUsefulThreshold;
|
||||
}
|
||||
|
||||
public void resetTimeoutCount(final int requestCode) {
|
||||
@@ -96,12 +113,19 @@ public class PeerReputation implements Comparable<PeerReputation> {
|
||||
}
|
||||
if (uselessResponseTimes.size() >= USELESS_RESPONSE_THRESHOLD) {
|
||||
score -= LARGE_ADJUSTMENT;
|
||||
LOG.debug("Disconnection triggered by exceeding useless response threshold");
|
||||
return Optional.of(DisconnectReason.USELESS_PEER);
|
||||
// don't trigger disconnect if this peer has a sufficiently high reputation score
|
||||
if (peerHasNotBeenUseful()) {
|
||||
LOG.debug(
|
||||
"Disconnection triggered by exceeding useless response threshold, score {}", score);
|
||||
return Optional.of(DisconnectReason.USELESS_PEER);
|
||||
}
|
||||
LOG.trace(
|
||||
"Not triggering disconnect for exceeding useless response threshold because peer has high score {}",
|
||||
score);
|
||||
} else {
|
||||
score -= SMALL_ADJUSTMENT;
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public void recordUsefulResponse() {
|
||||
|
||||
@@ -36,6 +36,8 @@ public class PeerReputationTest {
|
||||
|
||||
@Test
|
||||
public void shouldOnlyDisconnectWhenTimeoutLimitReached() {
|
||||
assertThat(reputation.recordRequestTimeout(EthPV62.GET_BLOCK_HEADERS)).isEmpty();
|
||||
assertThat(reputation.recordRequestTimeout(EthPV62.GET_BLOCK_HEADERS)).isEmpty();
|
||||
assertThat(reputation.recordRequestTimeout(EthPV62.GET_BLOCK_HEADERS)).isEmpty();
|
||||
assertThat(reputation.recordRequestTimeout(EthPV62.GET_BLOCK_HEADERS)).isEmpty();
|
||||
assertThat(reputation.recordRequestTimeout(EthPV62.GET_BLOCK_HEADERS)).contains(TIMEOUT);
|
||||
@@ -45,6 +47,11 @@ public class PeerReputationTest {
|
||||
public void shouldTrackTimeoutsSeparatelyForDifferentRequestTypes() {
|
||||
assertThat(reputation.recordRequestTimeout(EthPV62.GET_BLOCK_HEADERS)).isEmpty();
|
||||
assertThat(reputation.recordRequestTimeout(EthPV62.GET_BLOCK_HEADERS)).isEmpty();
|
||||
assertThat(reputation.recordRequestTimeout(EthPV62.GET_BLOCK_HEADERS)).isEmpty();
|
||||
assertThat(reputation.recordRequestTimeout(EthPV62.GET_BLOCK_HEADERS)).isEmpty();
|
||||
|
||||
assertThat(reputation.recordRequestTimeout(EthPV62.GET_BLOCK_BODIES)).isEmpty();
|
||||
assertThat(reputation.recordRequestTimeout(EthPV62.GET_BLOCK_BODIES)).isEmpty();
|
||||
assertThat(reputation.recordRequestTimeout(EthPV62.GET_BLOCK_BODIES)).isEmpty();
|
||||
assertThat(reputation.recordRequestTimeout(EthPV62.GET_BLOCK_BODIES)).isEmpty();
|
||||
|
||||
@@ -57,6 +64,8 @@ public class PeerReputationTest {
|
||||
assertThat(reputation.recordRequestTimeout(EthPV62.GET_BLOCK_HEADERS)).isEmpty();
|
||||
assertThat(reputation.recordRequestTimeout(EthPV62.GET_BLOCK_HEADERS)).isEmpty();
|
||||
|
||||
assertThat(reputation.recordRequestTimeout(EthPV62.GET_BLOCK_BODIES)).isEmpty();
|
||||
assertThat(reputation.recordRequestTimeout(EthPV62.GET_BLOCK_BODIES)).isEmpty();
|
||||
assertThat(reputation.recordRequestTimeout(EthPV62.GET_BLOCK_BODIES)).isEmpty();
|
||||
assertThat(reputation.recordRequestTimeout(EthPV62.GET_BLOCK_BODIES)).isEmpty();
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ dependencies {
|
||||
testImplementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts')
|
||||
testImplementation project(':testutil')
|
||||
|
||||
testImplementation 'junit:junit'
|
||||
testImplementation 'org.mockito:mockito-junit-jupiter'
|
||||
testImplementation 'org.assertj:assertj-core'
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter'
|
||||
testImplementation 'org.mockito:mockito-core'
|
||||
|
||||
@@ -33,11 +33,11 @@ import org.hyperledger.besu.nat.upnp.UpnpNatManager;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class NatServiceTest {
|
||||
|
||||
@Test
|
||||
|
||||
@@ -29,12 +29,12 @@ import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class AbstractNatManagerTest {
|
||||
|
||||
@Test
|
||||
|
||||
@@ -30,13 +30,13 @@ import java.util.Optional;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public final class DockerNatManagerTest {
|
||||
|
||||
private final String advertisedHost = "99.45.69.12";
|
||||
@@ -49,7 +49,7 @@ public final class DockerNatManagerTest {
|
||||
|
||||
private DockerNatManager natManager;
|
||||
|
||||
@Before
|
||||
@BeforeEach
|
||||
public void initialize() throws NatInitializationException {
|
||||
hostBasedIpDetector = mock(HostBasedIpDetector.class);
|
||||
when(hostBasedIpDetector.detectAdvertisedIp()).thenReturn(Optional.of(detectedAdvertisedHost));
|
||||
|
||||
@@ -33,13 +33,13 @@ import io.kubernetes.client.openapi.models.V1ObjectMeta;
|
||||
import io.kubernetes.client.openapi.models.V1Service;
|
||||
import io.kubernetes.client.openapi.models.V1ServicePort;
|
||||
import io.kubernetes.client.openapi.models.V1ServiceSpec;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public final class KubernetesClusterIpNatManagerTest {
|
||||
|
||||
private final String detectedAdvertisedHost = "199.45.69.12";
|
||||
@@ -51,7 +51,7 @@ public final class KubernetesClusterIpNatManagerTest {
|
||||
|
||||
private KubernetesNatManager natManager;
|
||||
|
||||
@Before
|
||||
@BeforeEach
|
||||
public void initialize() throws IOException {
|
||||
|
||||
when(v1Service.getSpec())
|
||||
|
||||
@@ -36,13 +36,13 @@ import io.kubernetes.client.openapi.models.V1Service;
|
||||
import io.kubernetes.client.openapi.models.V1ServicePort;
|
||||
import io.kubernetes.client.openapi.models.V1ServiceSpec;
|
||||
import io.kubernetes.client.openapi.models.V1ServiceStatus;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public final class KubernetesLoadManagerNatManagerTest {
|
||||
|
||||
private final String detectedAdvertisedHost = "199.45.69.12";
|
||||
@@ -54,7 +54,7 @@ public final class KubernetesLoadManagerNatManagerTest {
|
||||
|
||||
private KubernetesNatManager natManager;
|
||||
|
||||
@Before
|
||||
@BeforeEach
|
||||
public void initialize() throws IOException {
|
||||
final V1ServiceStatus v1ServiceStatus =
|
||||
new V1ServiceStatus()
|
||||
|
||||
@@ -21,20 +21,20 @@ import static org.mockito.Mockito.when;
|
||||
import io.kubernetes.client.openapi.models.V1ObjectMeta;
|
||||
import io.kubernetes.client.openapi.models.V1Service;
|
||||
import io.kubernetes.client.openapi.models.V1ServiceSpec;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public final class KubernetesUnknownNatManagerTest {
|
||||
|
||||
@Mock private V1Service v1Service;
|
||||
|
||||
private KubernetesNatManager natManager;
|
||||
|
||||
@Before
|
||||
@BeforeEach
|
||||
public void initialize() {
|
||||
|
||||
when(v1Service.getSpec()).thenReturn(new V1ServiceSpec().type("Unknown"));
|
||||
|
||||
@@ -30,8 +30,8 @@ import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.jupnp.UpnpService;
|
||||
import org.jupnp.controlpoint.ControlPoint;
|
||||
import org.jupnp.model.meta.DeviceDetails;
|
||||
@@ -54,7 +54,7 @@ public final class UpnpNatManagerTest {
|
||||
|
||||
private UpnpNatManager upnpManager;
|
||||
|
||||
@Before
|
||||
@BeforeEach
|
||||
public void initialize() {
|
||||
|
||||
mockedRegistry = mock(Registry.class);
|
||||
|
||||
@@ -69,7 +69,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 = 'gKRXd2Ow7wYKSgeGrDMRj0+2LdCzjOhLx8UEno9btGw='
|
||||
knownHash = 'nB1LhUpMWYFQpBdNJ/3Q79c8kLgUgPmEFzlRMlLUl1Y='
|
||||
}
|
||||
check.dependsOn('checkAPIChanges')
|
||||
|
||||
|
||||
@@ -24,7 +24,34 @@ import java.util.Optional;
|
||||
*/
|
||||
public class TransactionSelectionResult {
|
||||
|
||||
private enum Status {
|
||||
/**
|
||||
* Represent the status of a transaction selection result. Plugin can extend this to implement its
|
||||
* own statuses.
|
||||
*/
|
||||
protected interface Status {
|
||||
/**
|
||||
* Should the selection process be stopped?
|
||||
*
|
||||
* @return true if the selection process needs to be stopped
|
||||
*/
|
||||
boolean stop();
|
||||
|
||||
/**
|
||||
* Should the current transaction be removed from the txpool?
|
||||
*
|
||||
* @return yes if the transaction should be removed from the txpool
|
||||
*/
|
||||
boolean discard();
|
||||
|
||||
/**
|
||||
* Name of this status
|
||||
*
|
||||
* @return the name
|
||||
*/
|
||||
String name();
|
||||
}
|
||||
|
||||
private enum BaseStatus implements Status {
|
||||
SELECTED,
|
||||
BLOCK_FULL(true, false),
|
||||
BLOCK_OCCUPANCY_ABOVE_THRESHOLD(true, false),
|
||||
@@ -36,12 +63,12 @@ public class TransactionSelectionResult {
|
||||
private final boolean stop;
|
||||
private final boolean discard;
|
||||
|
||||
Status() {
|
||||
BaseStatus() {
|
||||
this.stop = false;
|
||||
this.discard = false;
|
||||
}
|
||||
|
||||
Status(final boolean stop, final boolean discard) {
|
||||
BaseStatus(final boolean stop, final boolean discard) {
|
||||
this.stop = stop;
|
||||
this.discard = discard;
|
||||
}
|
||||
@@ -50,26 +77,36 @@ public class TransactionSelectionResult {
|
||||
public String toString() {
|
||||
return name() + " (stop=" + stop + ", discard=" + discard + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
return stop;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean discard() {
|
||||
return discard;
|
||||
}
|
||||
}
|
||||
|
||||
/** The transaction has been selected to be included in the new block */
|
||||
public static final TransactionSelectionResult SELECTED =
|
||||
new TransactionSelectionResult(Status.SELECTED);
|
||||
new TransactionSelectionResult(BaseStatus.SELECTED);
|
||||
/** The transaction has not been selected since the block is full. */
|
||||
public static final TransactionSelectionResult BLOCK_FULL =
|
||||
new TransactionSelectionResult(Status.BLOCK_FULL);
|
||||
new TransactionSelectionResult(BaseStatus.BLOCK_FULL);
|
||||
/** There was no more time to add transaction to the block */
|
||||
public static final TransactionSelectionResult BLOCK_SELECTION_TIMEOUT =
|
||||
new TransactionSelectionResult(Status.BLOCK_SELECTION_TIMEOUT);
|
||||
new TransactionSelectionResult(BaseStatus.BLOCK_SELECTION_TIMEOUT);
|
||||
/** Transaction took too much to evaluate */
|
||||
public static final TransactionSelectionResult TX_EVALUATION_TOO_LONG =
|
||||
new TransactionSelectionResult(Status.TX_EVALUATION_TOO_LONG);
|
||||
new TransactionSelectionResult(BaseStatus.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.
|
||||
*/
|
||||
public static final TransactionSelectionResult BLOCK_OCCUPANCY_ABOVE_THRESHOLD =
|
||||
new TransactionSelectionResult(Status.BLOCK_OCCUPANCY_ABOVE_THRESHOLD);
|
||||
new TransactionSelectionResult(BaseStatus.BLOCK_OCCUPANCY_ABOVE_THRESHOLD);
|
||||
/**
|
||||
* The transaction has not been selected since its gas limit is greater than the block remaining
|
||||
* gas, but the selection should continue.
|
||||
@@ -99,11 +136,22 @@ public class TransactionSelectionResult {
|
||||
private final Status status;
|
||||
private final Optional<String> maybeInvalidReason;
|
||||
|
||||
private TransactionSelectionResult(final Status status) {
|
||||
/**
|
||||
* Create a new transaction selection result with the passed status
|
||||
*
|
||||
* @param status the selection result status
|
||||
*/
|
||||
protected TransactionSelectionResult(final Status status) {
|
||||
this(status, null);
|
||||
}
|
||||
|
||||
private TransactionSelectionResult(final Status status, final String invalidReason) {
|
||||
/**
|
||||
* Create a new transaction selection result with the passed status and invalid reason
|
||||
*
|
||||
* @param status the selection result status
|
||||
* @param invalidReason string with a custom invalid reason
|
||||
*/
|
||||
protected TransactionSelectionResult(final Status status, final String invalidReason) {
|
||||
this.status = status;
|
||||
this.maybeInvalidReason = Optional.ofNullable(invalidReason);
|
||||
}
|
||||
@@ -116,7 +164,7 @@ public class TransactionSelectionResult {
|
||||
* @return the selection result
|
||||
*/
|
||||
public static TransactionSelectionResult invalidTransient(final String invalidReason) {
|
||||
return new TransactionSelectionResult(Status.INVALID_TRANSIENT, invalidReason);
|
||||
return new TransactionSelectionResult(BaseStatus.INVALID_TRANSIENT, invalidReason);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,7 +175,7 @@ public class TransactionSelectionResult {
|
||||
* @return the selection result
|
||||
*/
|
||||
public static TransactionSelectionResult invalid(final String invalidReason) {
|
||||
return new TransactionSelectionResult(Status.INVALID, invalidReason);
|
||||
return new TransactionSelectionResult(BaseStatus.INVALID, invalidReason);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,7 +184,7 @@ public class TransactionSelectionResult {
|
||||
* @return true if the selection process should stop, false otherwise
|
||||
*/
|
||||
public boolean stop() {
|
||||
return status.stop;
|
||||
return status.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,7 +194,7 @@ public class TransactionSelectionResult {
|
||||
* otherwise
|
||||
*/
|
||||
public boolean discard() {
|
||||
return status.discard;
|
||||
return status.discard();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,7 +203,7 @@ public class TransactionSelectionResult {
|
||||
* @return true if the candidate transaction is included in the new block, false otherwise
|
||||
*/
|
||||
public boolean selected() {
|
||||
return Status.SELECTED.equals(status);
|
||||
return BaseStatus.SELECTED.equals(status);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user