Merge remote-tracking branch 'upstream/main' into zkbesu

This commit is contained in:
Fabio Di Fabio
2023-11-21 12:39:08 +01:00
22 changed files with 235 additions and 111 deletions

1
.gitignore vendored
View File

@@ -9,6 +9,7 @@
.DS_Store
.externalToolBuilders/
.gradle/
.vscode/
.idea/
.loadpath
.metadata

View File

@@ -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

View File

@@ -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'

View File

@@ -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 =

View File

@@ -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() {

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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);
}
}
}

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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() {

View File

@@ -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();

View File

@@ -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'

View File

@@ -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

View File

@@ -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

View File

@@ -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));

View File

@@ -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())

View File

@@ -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()

View File

@@ -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"));

View File

@@ -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);

View File

@@ -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')

View File

@@ -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);
}
/**