[PAN-1062] Specify pending transaction retention period (2 of 2) (#1333)

Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
S. Matthew English 6 years ago committed by GitHub
parent e9be81b342
commit 3d455b38a6
  1. 1
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/ThreadPantheonNodeRunner.java
  2. 22
      consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueBlockCreatorTest.java
  3. 12
      consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueMinerExecutorTest.java
  4. 5
      consensus/ibft/src/integration-test/java/tech/pegasys/pantheon/consensus/ibft/support/TestContextBuilder.java
  5. 4
      consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/IbftBlockCreatorTest.java
  6. 7
      consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/IbftBlockCreatorTest.java
  7. 18
      ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockTransactionSelectorTest.java
  8. 4
      ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/EthHashBlockCreatorTest.java
  9. 6
      ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/EthHashMinerExecutorTest.java
  10. 16
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/transactions/PendingTransactions.java
  11. 8
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/transactions/TransactionPoolFactory.java
  12. 3
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/EthProtocolManagerTest.java
  13. 26
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/PendingTransactionsTest.java
  14. 4
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TestNode.java
  15. 7
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TransactionPoolTest.java
  16. 7
      ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetFilterChangesIntegrationTest.java
  17. 9
      pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java
  18. 10
      pantheon/src/main/java/tech/pegasys/pantheon/controller/PantheonControllerBuilder.java
  19. 1
      pantheon/src/test/java/tech/pegasys/pantheon/PrivacyTest.java
  20. 3
      pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java
  21. 2
      pantheon/src/test/java/tech/pegasys/pantheon/cli/CommandTestAbstract.java
  22. 14
      pantheon/src/test/java/tech/pegasys/pantheon/cli/PantheonCommandTest.java
  23. 2
      pantheon/src/test/java/tech/pegasys/pantheon/util/BlockImporterTest.java
  24. 3
      pantheon/src/test/resources/everything_config.toml
  25. 5
      testutil/src/main/java/tech/pegasys/pantheon/testutil/TestClock.java

@ -76,6 +76,7 @@ public class ThreadPantheonNodeRunner implements PantheonNodeRunner {
.nodePrivateKeyFile(KeyPairUtil.getDefaultKeyFile(node.homeDirectory()))
.metricsSystem(noOpMetricsSystem)
.maxPendingTransactions(PendingTransactions.MAX_PENDING_TRANSACTIONS)
.pendingTransactionRetentionPeriod(PendingTransactions.DEFAULT_TX_RETENTION_HOURS)
.rocksdDbConfiguration(
new RocksDbConfiguration.Builder().databaseDir(tempDir).build())
.ethereumWireProtocolConfiguration(EthereumWireProtocolConfiguration.defaultConfig())

@ -50,14 +50,12 @@ import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.List;
import java.util.concurrent.TimeUnit;
import com.google.common.collect.Lists;
import org.junit.Before;
import org.junit.Test;
public class CliqueBlockCreatorTest {
private static final long TRANSACTION_EVICTION_INTERVAL_MS = TimeUnit.MINUTES.toMillis(1);
private final KeyPair proposerKeyPair = KeyPair.generate();
private final Address proposerAddress = Util.publicKeyToAddress(proposerKeyPair.getPublicKey());
@ -116,7 +114,10 @@ public class CliqueBlockCreatorTest {
coinbase,
parent -> extraData.encode(),
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, 5, TestClock.fixed(), metricsSystem),
PendingTransactions.DEFAULT_TX_RETENTION_HOURS,
5,
TestClock.fixed(),
metricsSystem),
protocolContext,
protocolSchedule,
gasLimit -> gasLimit,
@ -144,7 +145,10 @@ public class CliqueBlockCreatorTest {
coinbase,
parent -> extraData.encode(),
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, 5, TestClock.fixed(), metricsSystem),
PendingTransactions.DEFAULT_TX_RETENTION_HOURS,
5,
TestClock.fixed(),
metricsSystem),
protocolContext,
protocolSchedule,
gasLimit -> gasLimit,
@ -171,7 +175,10 @@ public class CliqueBlockCreatorTest {
coinbase,
parent -> extraData.encode(),
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, 5, TestClock.fixed(), metricsSystem),
PendingTransactions.DEFAULT_TX_RETENTION_HOURS,
5,
TestClock.fixed(),
metricsSystem),
protocolContext,
protocolSchedule,
gasLimit -> gasLimit,
@ -201,7 +208,10 @@ public class CliqueBlockCreatorTest {
coinbase,
parent -> extraData.encode(),
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, 5, TestClock.fixed(), metricsSystem),
PendingTransactions.DEFAULT_TX_RETENTION_HOURS,
5,
TestClock.fixed(),
metricsSystem),
protocolContext,
protocolSchedule,
gasLimit -> gasLimit,

@ -44,7 +44,6 @@ import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import com.google.common.collect.Lists;
import io.vertx.core.json.JsonObject;
@ -55,7 +54,6 @@ public class CliqueMinerExecutorTest {
private static final GenesisConfigOptions GENESIS_CONFIG_OPTIONS =
GenesisConfigFile.fromConfig(new JsonObject()).getConfigOptions();
private static final long TRANSACTION_EVICTION_INTERVAL_MS = TimeUnit.MINUTES.toMillis(1);
private final KeyPair proposerKeyPair = KeyPair.generate();
private Address localAddress;
private final List<Address> validatorList = Lists.newArrayList();
@ -93,7 +91,10 @@ public class CliqueMinerExecutorTest {
Executors.newSingleThreadExecutor(),
CliqueProtocolSchedule.create(GENESIS_CONFIG_OPTIONS, proposerKeyPair),
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, 1, TestClock.fixed(), metricsSystem),
PendingTransactions.DEFAULT_TX_RETENTION_HOURS,
1,
TestClock.fixed(),
metricsSystem),
proposerKeyPair,
new MiningParameters(AddressHelpers.ofValue(1), Wei.ZERO, wrappedVanityData, false),
mock(CliqueBlockScheduler.class),
@ -124,7 +125,10 @@ public class CliqueMinerExecutorTest {
Executors.newSingleThreadExecutor(),
CliqueProtocolSchedule.create(GENESIS_CONFIG_OPTIONS, proposerKeyPair),
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, 1, TestClock.fixed(), metricsSystem),
PendingTransactions.DEFAULT_TX_RETENTION_HOURS,
1,
TestClock.fixed(),
metricsSystem),
proposerKeyPair,
new MiningParameters(AddressHelpers.ofValue(1), Wei.ZERO, wrappedVanityData, false),
mock(CliqueBlockScheduler.class),

@ -80,14 +80,12 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import com.google.common.collect.Iterables;
public class TestContextBuilder {
private static final long TRANSACTION_EVICTION_INTERVAL_MS = TimeUnit.MINUTES.toMillis(1);
private static MetricsSystem metricsSystem = new NoOpMetricsSystem();
private static class ControllerAndState {
@ -286,7 +284,8 @@ public class TestContextBuilder {
blockChain, worldStateArchive, new IbftContext(voteTallyCache, voteProposer));
final PendingTransactions pendingTransactions =
new PendingTransactions(TRANSACTION_EVICTION_INTERVAL_MS, 1, clock, metricsSystem);
new PendingTransactions(
PendingTransactions.DEFAULT_TX_RETENTION_HOURS, 1, clock, metricsSystem);
final IbftBlockCreatorFactory blockCreatorFactory =
new IbftBlockCreatorFactory(

@ -46,13 +46,11 @@ import java.time.Instant;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import com.google.common.collect.Lists;
import org.junit.Test;
public class IbftBlockCreatorTest {
private static final long TRANSACTION_EVICTION_INTERVAL_MS = TimeUnit.MINUTES.toMillis(1);
private final MetricsSystem metricsSystem = new NoOpMetricsSystem();
@Test
@ -85,7 +83,7 @@ public class IbftBlockCreatorTest {
final PendingTransactions pendingTransactions =
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, 1, TestClock.fixed(), metricsSystem);
PendingTransactions.DEFAULT_TX_RETENTION_HOURS, 1, TestClock.fixed(), metricsSystem);
final IbftBlockCreator blockCreator =
new IbftBlockCreator(

@ -46,13 +46,11 @@ import java.time.Instant;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import com.google.common.collect.Lists;
import org.junit.Test;
public class IbftBlockCreatorTest {
private static final long TRANSACTION_EVICTION_INTERVAL_MS = TimeUnit.MINUTES.toMillis(1);
private final MetricsSystem metricsSystem = new NoOpMetricsSystem();
@Test
@ -100,7 +98,10 @@ public class IbftBlockCreatorTest {
initialValidatorList)
.encode(),
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, 1, TestClock.fixed(), metricsSystem),
PendingTransactions.DEFAULT_TX_RETENTION_HOURS,
1,
TestClock.fixed(),
metricsSystem),
protContext,
protocolSchedule,
parentGasLimit -> parentGasLimit,

@ -55,7 +55,6 @@ import tech.pegasys.pantheon.util.uint.UInt256;
import java.math.BigInteger;
import java.time.Instant;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import com.google.common.collect.Lists;
@ -64,7 +63,6 @@ import org.junit.Test;
public class BlockTransactionSelectorTest {
private static final KeyPair keyPair = KeyPair.generate();
private static final long TRANSACTION_EVICTION_INTERVAL_MS = TimeUnit.MINUTES.toMillis(1);
private final MetricsSystem metricsSystem = new NoOpMetricsSystem();
@Test
@ -78,7 +76,7 @@ public class BlockTransactionSelectorTest {
final PendingTransactions pendingTransactions =
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, 5, TestClock.fixed(), metricsSystem);
PendingTransactions.DEFAULT_TX_RETENTION_HOURS, 5, TestClock.fixed(), metricsSystem);
final Supplier<Boolean> isCancelled = () -> false;
@ -118,7 +116,7 @@ public class BlockTransactionSelectorTest {
public void failedTransactionsAreIncludedInTheBlock() {
final PendingTransactions pendingTransactions =
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, 5, TestClock.fixed(), metricsSystem);
PendingTransactions.DEFAULT_TX_RETENTION_HOURS, 5, TestClock.fixed(), metricsSystem);
final Transaction transaction = createTransaction(1);
pendingTransactions.addRemoteTransaction(transaction);
@ -171,7 +169,7 @@ public class BlockTransactionSelectorTest {
public void invalidTransactionsTransactionProcessingAreSkippedButBlockStillFills() {
final PendingTransactions pendingTransactions =
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, 5, TestClock.fixed(), metricsSystem);
PendingTransactions.DEFAULT_TX_RETENTION_HOURS, 5, TestClock.fixed(), metricsSystem);
final List<Transaction> transactionsToInject = Lists.newArrayList();
for (int i = 0; i < 5; i++) {
@ -235,7 +233,7 @@ public class BlockTransactionSelectorTest {
public void subsetOfPendingTransactionsIncludedWhenBlockGasLimitHit() {
final PendingTransactions pendingTransactions =
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, 5, TestClock.fixed(), metricsSystem);
PendingTransactions.DEFAULT_TX_RETENTION_HOURS, 5, TestClock.fixed(), metricsSystem);
final List<Transaction> transactionsToInject = Lists.newArrayList();
// Transactions are reported in reverse order.
@ -302,7 +300,7 @@ public class BlockTransactionSelectorTest {
public void transactionOfferingGasPriceLessThanMinimumIsIdentifiedAndRemovedFromPending() {
final PendingTransactions pendingTransactions =
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, 5, TestClock.fixed(), metricsSystem);
PendingTransactions.DEFAULT_TX_RETENTION_HOURS, 5, TestClock.fixed(), metricsSystem);
final Blockchain blockchain = new TestBlockchain();
@ -348,7 +346,7 @@ public class BlockTransactionSelectorTest {
public void transactionTooLargeForBlockDoesNotPreventMoreBeingAddedIfBlockOccupancyNotReached() {
final PendingTransactions pendingTransactions =
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, 5, TestClock.fixed(), metricsSystem);
PendingTransactions.DEFAULT_TX_RETENTION_HOURS, 5, TestClock.fixed(), metricsSystem);
final Blockchain blockchain = new TestBlockchain();
final DefaultMutableWorldState worldState = inMemoryWorldState();
@ -421,7 +419,7 @@ public class BlockTransactionSelectorTest {
public void transactionSelectionStopsWhenSufficientBlockOccupancyIsReached() {
final PendingTransactions pendingTransactions =
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, 5, TestClock.fixed(), metricsSystem);
PendingTransactions.DEFAULT_TX_RETENTION_HOURS, 5, TestClock.fixed(), metricsSystem);
final Blockchain blockchain = new TestBlockchain();
final DefaultMutableWorldState worldState = inMemoryWorldState();
@ -505,7 +503,7 @@ public class BlockTransactionSelectorTest {
public void shouldDiscardTransactionsThatFailValidation() {
final PendingTransactions pendingTransactions =
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, 5, TestClock.fixed(), metricsSystem);
PendingTransactions.DEFAULT_TX_RETENTION_HOURS, 5, TestClock.fixed(), metricsSystem);
final TransactionProcessor transactionProcessor = mock(TransactionProcessor.class);
final Blockchain blockchain = new TestBlockchain();

@ -30,7 +30,6 @@ import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.io.IOException;
import java.math.BigInteger;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import com.google.common.collect.Lists;
@ -48,7 +47,6 @@ public class EthHashBlockCreatorTest {
private static final BytesValue BLOCK_1_EXTRA_DATA =
BytesValue.fromHexString("0x476574682f76312e302e302f6c696e75782f676f312e342e32");
private static final long TRANSACTION_EVICTION_INTERVAL_MS = TimeUnit.MINUTES.toMillis(1);
private final MetricsSystem metricsSystem = new NoOpMetricsSystem();
private final ExecutionContextTestFixture executionContextTestFixture =
@ -68,7 +66,7 @@ public class EthHashBlockCreatorTest {
final PendingTransactions pendingTransactions =
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, 1, TestClock.fixed(), metricsSystem);
PendingTransactions.DEFAULT_TX_RETENTION_HOURS, 1, TestClock.fixed(), metricsSystem);
final EthHashBlockCreator blockCreator =
new EthHashBlockCreator(

@ -23,12 +23,10 @@ import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.Subscribers;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
public class EthHashMinerExecutorTest {
private static final long TRANSACTION_EVICTION_INTERVAL_MS = TimeUnit.MINUTES.toMillis(1);
private final MetricsSystem metricsSystem = new NoOpMetricsSystem();
@Test
@ -38,7 +36,7 @@ public class EthHashMinerExecutorTest {
final PendingTransactions pendingTransactions =
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, 1, TestClock.fixed(), metricsSystem);
PendingTransactions.DEFAULT_TX_RETENTION_HOURS, 1, TestClock.fixed(), metricsSystem);
final EthHashMinerExecutor executor =
new EthHashMinerExecutor(
@ -60,7 +58,7 @@ public class EthHashMinerExecutorTest {
final PendingTransactions pendingTransactions =
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, 1, TestClock.fixed(), metricsSystem);
PendingTransactions.DEFAULT_TX_RETENTION_HOURS, 1, TestClock.fixed(), metricsSystem);
final EthHashMinerExecutor executor =
new EthHashMinerExecutor(

@ -27,6 +27,7 @@ import tech.pegasys.pantheon.util.Subscribers;
import java.time.Clock;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@ -49,6 +50,10 @@ import java.util.concurrent.atomic.AtomicLong;
*/
public class PendingTransactions {
public static final int MAX_PENDING_TRANSACTIONS = 4096;
public static final int DEFAULT_TX_RETENTION_HOURS = 13;
private final int maxTransactionRetentionHours;
private final Clock clock;
private final Map<Hash, TransactionInfo> pendingTransactions = new HashMap<>();
private final SortedSet<TransactionInfo> prioritizedTransactions =
@ -64,21 +69,18 @@ public class PendingTransactions {
private final Subscribers<PendingTransactionDroppedListener> transactionDroppedListeners =
new Subscribers<>();
private final int maxPendingTransactions;
private final Clock clock;
private final LabelledMetric<Counter> transactionRemovedCounter;
private final Counter localTransactionAddedCounter;
private final Counter remoteTransactionAddedCounter;
private final long transactionEvictionIntervalMs;
private final long maxPendingTransactions;
public PendingTransactions(
final long transactionEvictionIntervalMs,
final int maxTransactionRetentionHours,
final int maxPendingTransactions,
final Clock clock,
final MetricsSystem metricsSystem) {
this.transactionEvictionIntervalMs = transactionEvictionIntervalMs;
this.maxTransactionRetentionHours = maxTransactionRetentionHours;
this.maxPendingTransactions = maxPendingTransactions;
this.clock = clock;
final LabelledMetric<Counter> transactionAddedCounter =
@ -102,7 +104,7 @@ public class PendingTransactions {
public void evictOldTransactions() {
synchronized (pendingTransactions) {
final Instant removeTransactionsBefore =
clock.instant().minusMillis(transactionEvictionIntervalMs);
clock.instant().minus(maxTransactionRetentionHours, ChronoUnit.HOURS);
final List<TransactionInfo> transactionsToRemove =
prioritizedTransactions.stream()
.filter(

@ -20,12 +20,9 @@ import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.metrics.MetricsSystem;
import java.time.Clock;
import java.util.concurrent.TimeUnit;
public class TransactionPoolFactory {
private static final long TRANSACTION_EVICTION_INTERVAL_MS = TimeUnit.HOURS.toMillis(12);
public static TransactionPool createTransactionPool(
final ProtocolSchedule<?> protocolSchedule,
final ProtocolContext<?> protocolContext,
@ -33,11 +30,12 @@ public class TransactionPoolFactory {
final Clock clock,
final int maxPendingTransactions,
final MetricsSystem metricsSystem,
final SyncState syncState) {
final SyncState syncState,
final int maxTransactionRetentionHours) {
final PendingTransactions pendingTransactions =
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, maxPendingTransactions, clock, metricsSystem);
maxTransactionRetentionHours, maxPendingTransactions, clock, metricsSystem);
final PeerTransactionTracker transactionTracker = new PeerTransactionTracker();
final TransactionsMessageSender transactionsMessageSender =

@ -1056,7 +1056,8 @@ public final class EthProtocolManagerTest {
TestClock.fixed(),
PendingTransactions.MAX_PENDING_TRANSACTIONS,
metricsSystem,
mock(SyncState.class));
mock(SyncState.class),
PendingTransactions.DEFAULT_TX_RETENTION_HOURS);
// Send just a transaction message.
final PeerConnection peer = setupPeer(ethManager, (cap, msg, connection) -> {});

@ -29,17 +29,16 @@ import tech.pegasys.pantheon.metrics.MetricsSystem;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.OptionalLong;
import java.util.concurrent.TimeUnit;
import com.google.common.collect.Lists;
import org.junit.Test;
public class PendingTransactionsTest {
private static final long TRANSACTION_EVICTION_INTERVAL_MS = TimeUnit.MINUTES.toMillis(1);
private static final int MAX_TRANSACTIONS = 5;
private static final KeyPair KEYS1 = KeyPair.generate();
private static final KeyPair KEYS2 = KeyPair.generate();
@ -48,7 +47,10 @@ public class PendingTransactionsTest {
private final MetricsSystem metricsSystem = new NoOpMetricsSystem();
private final PendingTransactions transactions =
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, MAX_TRANSACTIONS, TestClock.fixed(), metricsSystem);
PendingTransactions.DEFAULT_TX_RETENTION_HOURS,
MAX_TRANSACTIONS,
TestClock.fixed(),
metricsSystem);
private final Transaction transaction1 = createTransaction(2);
private final Transaction transaction2 = createTransaction(1);
@ -416,43 +418,43 @@ public class PendingTransactionsTest {
@Test
public void shouldEvictMultipleOldTransactions() {
final long transactionEvictionIntervalMs = 1000L;
final int maxTransactionRetentionHours = 1;
final PendingTransactions transactions =
new PendingTransactions(
transactionEvictionIntervalMs, MAX_TRANSACTIONS, clock, metricsSystem);
maxTransactionRetentionHours, MAX_TRANSACTIONS, clock, metricsSystem);
transactions.addRemoteTransaction(transaction1);
assertThat(transactions.size()).isEqualTo(1);
transactions.addRemoteTransaction(transaction2);
assertThat(transactions.size()).isEqualTo(2);
clock.stepMillis(2000);
clock.step(2L, ChronoUnit.HOURS);
transactions.evictOldTransactions();
assertThat(transactions.size()).isEqualTo(0);
}
@Test
public void shouldEvictSingleOldTransaction() {
final long transactionEvictionIntervalMs = 1000L;
final int maxTransactionRetentionHours = 1;
final PendingTransactions transactions =
new PendingTransactions(
transactionEvictionIntervalMs, MAX_TRANSACTIONS, clock, metricsSystem);
maxTransactionRetentionHours, MAX_TRANSACTIONS, clock, metricsSystem);
transactions.addRemoteTransaction(transaction1);
assertThat(transactions.size()).isEqualTo(1);
clock.stepMillis(2000);
clock.step(2L, ChronoUnit.HOURS);
transactions.evictOldTransactions();
assertThat(transactions.size()).isEqualTo(0);
}
@Test
public void shouldEvictExclusivelyOldTransactions() {
final long transactionEvictionIntervalMs = 2L;
final int maxTransactionRetentionHours = 2;
final PendingTransactions transactions =
new PendingTransactions(
transactionEvictionIntervalMs, MAX_TRANSACTIONS, clock, metricsSystem);
maxTransactionRetentionHours, MAX_TRANSACTIONS, clock, metricsSystem);
transactions.addRemoteTransaction(transaction1);
assertThat(transactions.size()).isEqualTo(1);
clock.stepMillis(2001);
clock.step(3L, ChronoUnit.HOURS);
transactions.addRemoteTransaction(transaction2);
assertThat(transactions.size()).isEqualTo(2);
transactions.evictOldTransactions();

@ -152,7 +152,9 @@ public class TestNode implements Closeable {
TestClock.fixed(),
PendingTransactions.MAX_PENDING_TRANSACTIONS,
metricsSystem,
syncState);
syncState,
PendingTransactions.DEFAULT_TX_RETENTION_HOURS);
networkRunner.start();
this.port = network.getLocalEnode().get().getListeningPort();
selfPeer = new DefaultPeer(id(), endpoint());

@ -67,14 +67,12 @@ import tech.pegasys.pantheon.util.uint.UInt256;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Test;
public class TransactionPoolTest {
private static final long TRANSACTION_EVICTION_INTERVAL_MS = TimeUnit.MINUTES.toMillis(1);
private static final int MAX_TRANSACTIONS = 5;
private static final KeyPair KEY_PAIR1 = KeyPair.generate();
@ -94,7 +92,10 @@ public class TransactionPoolTest {
private final PendingTransactions transactions =
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, MAX_TRANSACTIONS, TestClock.fixed(), metricsSystem);
PendingTransactions.DEFAULT_TX_RETENTION_HOURS,
MAX_TRANSACTIONS,
TestClock.fixed(),
metricsSystem);
private final Transaction transaction1 = createTransaction(1);
private final Transaction transaction2 = createTransaction(2);
private final ExecutionContextTestFixture executionContext = ExecutionContextTestFixture.create();

@ -57,7 +57,6 @@ import tech.pegasys.pantheon.util.uint.UInt256;
import java.math.BigInteger;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.assertj.core.util.Lists;
import org.junit.Before;
@ -69,7 +68,6 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class EthGetFilterChangesIntegrationTest {
private static final long TRANSACTION_EVICTION_INTERVAL_MS = TimeUnit.MINUTES.toMillis(1);
@Mock private TransactionBatchAddedListener batchAddedListener;
private MutableBlockchain blockchain;
private final String ETH_METHOD = "eth_getFilterChanges";
@ -79,7 +77,10 @@ public class EthGetFilterChangesIntegrationTest {
private final PendingTransactions transactions =
new PendingTransactions(
TRANSACTION_EVICTION_INTERVAL_MS, MAX_TRANSACTIONS, TestClock.fixed(), metricsSystem);
PendingTransactions.DEFAULT_TX_RETENTION_HOURS,
MAX_TRANSACTIONS,
TestClock.fixed(),
metricsSystem);
private static final int MAX_TRANSACTIONS = 5;
private static final KeyPair keyPair = KeyPair.generate();

@ -483,6 +483,14 @@ public class PantheonCommand implements DefaultCommandValues, Runnable {
arity = "1")
private final Integer txPoolMaxSize = PendingTransactions.MAX_PENDING_TRANSACTIONS;
@Option(
names = {"--tx-pool-retention-hours"},
paramLabel = MANDATORY_INTEGER_FORMAT_HELP,
description =
"Maximum retention period of pending transactions in hours (default: ${DEFAULT-VALUE})",
arity = "1")
private final Integer pendingTxRetentionPeriod = PendingTransactions.DEFAULT_TX_RETENTION_HOURS;
// Inner class so we can get to loggingLevel.
public class PantheonExceptionHandler
extends CommandLine.AbstractHandler<List<Object>, PantheonExceptionHandler>
@ -701,6 +709,7 @@ public class PantheonCommand implements DefaultCommandValues, Runnable {
.miningParameters(
new MiningParameters(coinbase, minTransactionGasPrice, extraData, isMiningEnabled))
.maxPendingTransactions(txPoolMaxSize)
.pendingTransactionRetentionPeriod(pendingTxRetentionPeriod)
.nodePrivateKeyFile(nodePrivateKeyFile())
.metricsSystem(metricsSystem.get())
.privacyParameters(privacyParameters())

@ -72,6 +72,7 @@ public abstract class PantheonControllerBuilder<C> {
protected Path dataDirectory;
protected Clock clock;
protected Integer maxPendingTransactions;
protected Integer pendingTransactionRetentionPeriod;
protected KeyPair nodeKeys;
private StorageProvider storageProvider;
private final List<Runnable> shutdownActions = new ArrayList<>();
@ -151,6 +152,12 @@ public abstract class PantheonControllerBuilder<C> {
return this;
}
public PantheonControllerBuilder<C> pendingTransactionRetentionPeriod(
final int pendingTransactionRetentionPeriod) {
this.pendingTransactionRetentionPeriod = pendingTransactionRetentionPeriod;
return this;
}
public PantheonController<C> build() throws IOException {
checkNotNull(genesisConfig, "Missing genesis config");
checkNotNull(syncConfig, "Missing sync config");
@ -223,7 +230,8 @@ public abstract class PantheonControllerBuilder<C> {
clock,
maxPendingTransactions,
metricsSystem,
syncState);
syncState,
pendingTransactionRetentionPeriod);
final MiningCoordinator miningCoordinator =
createMiningCoordinator(

@ -64,6 +64,7 @@ public class PrivacyTest {
.clock(TestClock.fixed())
.privacyParameters(privacyParameters)
.maxPendingTransactions(PendingTransactions.MAX_PENDING_TRANSACTIONS)
.pendingTransactionRetentionPeriod(PendingTransactions.DEFAULT_TX_RETENTION_HOURS)
.build();
final Address privacyContractAddress = Address.privacyPrecompiled(ADDRESS);

@ -133,6 +133,7 @@ public final class RunnerTest {
.clock(TestClock.fixed())
.maxPendingTransactions(PendingTransactions.MAX_PENDING_TRANSACTIONS)
.storageProvider(createKeyValueStorageProvider(dbAhead))
.pendingTransactionRetentionPeriod(PendingTransactions.DEFAULT_TX_RETENTION_HOURS)
.build()) {
setupState(blockCount, controller.getProtocolSchedule(), controller.getProtocolContext());
}
@ -152,6 +153,7 @@ public final class RunnerTest {
.clock(TestClock.fixed())
.maxPendingTransactions(PendingTransactions.MAX_PENDING_TRANSACTIONS)
.storageProvider(createKeyValueStorageProvider(dbAhead))
.pendingTransactionRetentionPeriod(PendingTransactions.DEFAULT_TX_RETENTION_HOURS)
.build();
final String listenHost = InetAddress.getLoopbackAddress().getHostAddress();
final JsonRpcConfiguration aheadJsonRpcConfiguration = jsonRpcConfiguration();
@ -208,6 +210,7 @@ public final class RunnerTest {
.privacyParameters(PrivacyParameters.DEFAULT)
.clock(TestClock.fixed())
.maxPendingTransactions(PendingTransactions.MAX_PENDING_TRANSACTIONS)
.pendingTransactionRetentionPeriod(PendingTransactions.DEFAULT_TX_RETENTION_HOURS)
.build();
final EnodeURL enode = runnerAhead.getLocalEnode().get();
final EthNetworkConfig behindEthNetworkConfiguration =

@ -116,6 +116,8 @@ public abstract class CommandTestAbstract {
when(mockControllerBuilder.dataDirectory(any())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.miningParameters(any())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.maxPendingTransactions(anyInt())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.pendingTransactionRetentionPeriod(anyInt()))
.thenReturn(mockControllerBuilder);
when(mockControllerBuilder.nodePrivateKeyFile(any())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.metricsSystem(any())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.privacyParameters(any())).thenReturn(mockControllerBuilder);

@ -607,6 +607,8 @@ public class PantheonCommandTest extends CommandTestAbstract {
verify(mockControllerBuilder)
.maxPendingTransactions(eq(PendingTransactions.MAX_PENDING_TRANSACTIONS));
verify(mockControllerBuilder)
.pendingTransactionRetentionPeriod(eq(PendingTransactions.DEFAULT_TX_RETENTION_HOURS));
verify(mockControllerBuilder).build();
verify(mockSyncConfBuilder).syncMode(eq(SyncMode.FULL));
@ -2340,4 +2342,16 @@ public class PantheonCommandTest extends CommandTestAbstract {
assertThat(commandErrorOutput.toString())
.contains(staticNodeURI.toString(), "not in nodes-whitelist");
}
@Test
public void pendingTransactionRetentionPeriod() {
final int pendingTxRetentionHours = 999;
parseCommand("--tx-pool-retention-hours", String.valueOf(pendingTxRetentionHours));
verify(mockControllerBuilder).pendingTransactionRetentionPeriod(intArgumentCaptor.capture());
verify(mockControllerBuilder).pendingTransactionRetentionPeriod(eq(pendingTxRetentionHours));
assertThat(commandOutput.toString()).isEmpty();
assertThat(commandErrorOutput.toString()).isEmpty();
}
}

@ -65,6 +65,7 @@ public final class BlockImporterTest {
.dataDirectory(dataDir)
.clock(TestClock.fixed())
.maxPendingTransactions(PendingTransactions.MAX_PENDING_TRANSACTIONS)
.pendingTransactionRetentionPeriod(PendingTransactions.DEFAULT_TX_RETENTION_HOURS)
.build();
final BlockImporter.ImportResult result =
blockImporter.importBlockchain(source, targetController);
@ -104,6 +105,7 @@ public final class BlockImporterTest {
.dataDirectory(dataDir)
.clock(TestClock.fixed())
.maxPendingTransactions(PendingTransactions.MAX_PENDING_TRANSACTIONS)
.pendingTransactionRetentionPeriod(PendingTransactions.DEFAULT_TX_RETENTION_HOURS)
.build();
final BlockImporter.ImportResult result = blockImporter.importBlockchain(source, controller);

@ -85,4 +85,7 @@ privacy-public-key-file="./pubKey.pub"
privacy-enabled=false
privacy-precompiled-address=9
# Transaction Pool
tx-pool-retention-hours=999
tx-pool-max-size=1234

@ -16,6 +16,7 @@ import java.time.Clock;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.temporal.TemporalUnit;
public class TestClock extends Clock {
public static Clock fixed() {
@ -42,4 +43,8 @@ public class TestClock extends Clock {
public void stepMillis(final long millis) {
now = now.plusMillis(millis);
}
public void step(final long a, final TemporalUnit unit) {
now = now.plus(a, unit);
}
}

Loading…
Cancel
Save