Improve signature verification performance

* Efficient signature verification using tx in txpool
* This feature can enabled with a flag
  --tx-pool-tx-fast-verify-signature-enabled=true
* There was a performance improvement effect of about 30%
* No need to add transaction sender cache space

Signed-off-by: Chulhee Lee <leefehee@naver.com>
pull/7729/head
Chulhee Lee 2 months ago
parent 81f9fc9c33
commit 613363c250
  1. 15
      besu/src/main/java/org/hyperledger/besu/cli/options/TransactionPoolOptions.java
  2. 3
      besu/src/main/java/org/hyperledger/besu/controller/IbftBesuControllerBuilder.java
  3. 3
      besu/src/main/java/org/hyperledger/besu/controller/QbftBesuControllerBuilder.java
  4. 28
      consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRound.java
  5. 9
      consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRoundFactory.java
  6. 28
      consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRound.java
  7. 9
      consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundFactory.java
  8. 28
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java
  9. 27
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java
  10. 8
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java
  11. 6
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolConfiguration.java

@ -61,6 +61,8 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
"--strict-tx-replay-protection-enabled"; "--strict-tx-replay-protection-enabled";
private static final String TX_POOL_PRIORITY_SENDERS = "--tx-pool-priority-senders"; private static final String TX_POOL_PRIORITY_SENDERS = "--tx-pool-priority-senders";
private static final String TX_POOL_MIN_GAS_PRICE = "--tx-pool-min-gas-price"; private static final String TX_POOL_MIN_GAS_PRICE = "--tx-pool-min-gas-price";
private static final String TX_FAST_VERIFY_SIGNATURE_ENABLED =
"--tx-pool-tx-fast-verify-signature-enabled";
private TransactionPoolValidatorService transactionPoolValidatorService; private TransactionPoolValidatorService transactionPoolValidatorService;
@ -277,6 +279,16 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
arity = "1") arity = "1")
private Duration eth65TrxAnnouncedBufferingPeriod = private Duration eth65TrxAnnouncedBufferingPeriod =
TransactionPoolConfiguration.Unstable.ETH65_TRX_ANNOUNCED_BUFFERING_PERIOD; TransactionPoolConfiguration.Unstable.ETH65_TRX_ANNOUNCED_BUFFERING_PERIOD;
@CommandLine.Option(
names = {TX_FAST_VERIFY_SIGNATURE_ENABLED},
paramLabel = "<Boolean>",
hidden = true,
description =
"Efficient signature verification using transaction information in tx pool (default: true)",
arity = "1")
private boolean txFastVerifySignatureEnabled =
TransactionPoolConfiguration.Unstable.DEFAULT_TX_FAST_VERIFY_SIGNATURE_ENABLED;
} }
private TransactionPoolOptions() {} private TransactionPoolOptions() {}
@ -334,6 +346,8 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
config.getUnstable().getTxMessageKeepAliveSeconds(); config.getUnstable().getTxMessageKeepAliveSeconds();
options.unstableOptions.eth65TrxAnnouncedBufferingPeriod = options.unstableOptions.eth65TrxAnnouncedBufferingPeriod =
config.getUnstable().getEth65TrxAnnouncedBufferingPeriod(); config.getUnstable().getEth65TrxAnnouncedBufferingPeriod();
options.unstableOptions.txFastVerifySignatureEnabled =
config.getUnstable().getTxFastVerifySignatureEnabled();
return options; return options;
} }
@ -392,6 +406,7 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
ImmutableTransactionPoolConfiguration.Unstable.builder() ImmutableTransactionPoolConfiguration.Unstable.builder()
.txMessageKeepAliveSeconds(unstableOptions.txMessageKeepAliveSeconds) .txMessageKeepAliveSeconds(unstableOptions.txMessageKeepAliveSeconds)
.eth65TrxAnnouncedBufferingPeriod(unstableOptions.eth65TrxAnnouncedBufferingPeriod) .eth65TrxAnnouncedBufferingPeriod(unstableOptions.eth65TrxAnnouncedBufferingPeriod)
.txFastVerifySignatureEnabled(unstableOptions.txFastVerifySignatureEnabled)
.build()) .build())
.build(); .build();
} }

@ -222,7 +222,8 @@ public class IbftBesuControllerBuilder extends BftBesuControllerBuilder {
minedBlockObservers, minedBlockObservers,
messageValidatorFactory, messageValidatorFactory,
messageFactory, messageFactory,
bftExtraDataCodec().get()), bftExtraDataCodec().get(),
transactionPool),
messageValidatorFactory, messageValidatorFactory,
messageFactory), messageFactory),
gossiper, gossiper,

@ -262,7 +262,8 @@ public class QbftBesuControllerBuilder extends BftBesuControllerBuilder {
minedBlockObservers, minedBlockObservers,
messageValidatorFactory, messageValidatorFactory,
messageFactory, messageFactory,
bftExtraDataCodec().get()), bftExtraDataCodec().get(),
transactionPool),
messageValidatorFactory, messageValidatorFactory,
messageFactory, messageFactory,
new ValidatorModeTransitionLogger(qbftForksSchedule)), new ValidatorModeTransitionLogger(qbftForksSchedule)),

@ -38,12 +38,16 @@ import org.hyperledger.besu.ethereum.chain.MinedBlockObserver;
import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockImporter; import org.hyperledger.besu.ethereum.core.BlockImporter;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.eth.transactions.sorter.AbstractPendingTransactionsSorter;
import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.BlockImportResult;
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException; import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException;
import org.hyperledger.besu.util.Subscribers; import org.hyperledger.besu.util.Subscribers;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -54,6 +58,8 @@ public class IbftRound {
private static final Logger LOG = LoggerFactory.getLogger(IbftRound.class); private static final Logger LOG = LoggerFactory.getLogger(IbftRound.class);
private final TransactionPool transactionPool;
private final Subscribers<MinedBlockObserver> observers; private final Subscribers<MinedBlockObserver> observers;
private final RoundState roundState; private final RoundState roundState;
private final BlockCreator blockCreator; private final BlockCreator blockCreator;
@ -94,7 +100,8 @@ public class IbftRound {
final IbftMessageTransmitter transmitter, final IbftMessageTransmitter transmitter,
final RoundTimer roundTimer, final RoundTimer roundTimer,
final BftExtraDataCodec bftExtraDataCodec, final BftExtraDataCodec bftExtraDataCodec,
final BlockHeader parentHeader) { final BlockHeader parentHeader,
final TransactionPool transactionPool) {
this.roundState = roundState; this.roundState = roundState;
this.blockCreator = blockCreator; this.blockCreator = blockCreator;
this.protocolContext = protocolContext; this.protocolContext = protocolContext;
@ -105,6 +112,7 @@ public class IbftRound {
this.transmitter = transmitter; this.transmitter = transmitter;
this.bftExtraDataCodec = bftExtraDataCodec; this.bftExtraDataCodec = bftExtraDataCodec;
this.parentHeader = parentHeader; this.parentHeader = parentHeader;
this.transactionPool = transactionPool;
roundTimer.startTimer(getRoundIdentifier()); roundTimer.startTimer(getRoundIdentifier());
} }
@ -188,6 +196,24 @@ public class IbftRound {
LOG.debug("Received a proposal message. round={}", roundState.getRoundIdentifier()); LOG.debug("Received a proposal message. round={}", roundState.getRoundIdentifier());
final Block block = msg.getBlock(); final Block block = msg.getBlock();
if (transactionPool.getConfigTxFastVerifySignatureEnabled()) {
final AbstractPendingTransactionsSorter pendingTransactions;
pendingTransactions =
(AbstractPendingTransactionsSorter) (transactionPool.getPendingTransactionsObject());
final List<Transaction> blockTransactions = block.getBody().getTransactions();
for (final Transaction blockTransaction : blockTransactions) {
final Transaction pendingTransaction =
pendingTransactions.getTransactionByHash(blockTransaction.getHash()).orElse(null);
if (pendingTransaction != null) {
blockTransaction.setSender(pendingTransaction.getSender());
}
}
}
if (updateStateWithProposedBlock(msg)) { if (updateStateWithProposedBlock(msg)) {
LOG.debug("Sending prepare message. round={}", roundState.getRoundIdentifier()); LOG.debug("Sending prepare message. round={}", roundState.getRoundIdentifier());
try { try {

@ -26,6 +26,7 @@ import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.blockcreation.BlockCreator; import org.hyperledger.besu.ethereum.blockcreation.BlockCreator;
import org.hyperledger.besu.ethereum.chain.MinedBlockObserver; import org.hyperledger.besu.ethereum.chain.MinedBlockObserver;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.util.Subscribers; import org.hyperledger.besu.util.Subscribers;
/** The Ibft round factory. */ /** The Ibft round factory. */
@ -39,6 +40,7 @@ public class IbftRoundFactory {
private final MessageValidatorFactory messageValidatorFactory; private final MessageValidatorFactory messageValidatorFactory;
private final MessageFactory messageFactory; private final MessageFactory messageFactory;
private final BftExtraDataCodec bftExtraDataCodec; private final BftExtraDataCodec bftExtraDataCodec;
private final TransactionPool transactionPool;
/** /**
* Instantiates a new Ibft round factory. * Instantiates a new Ibft round factory.
@ -58,7 +60,8 @@ public class IbftRoundFactory {
final Subscribers<MinedBlockObserver> minedBlockObservers, final Subscribers<MinedBlockObserver> minedBlockObservers,
final MessageValidatorFactory messageValidatorFactory, final MessageValidatorFactory messageValidatorFactory,
final MessageFactory messageFactory, final MessageFactory messageFactory,
final BftExtraDataCodec bftExtraDataCodec) { final BftExtraDataCodec bftExtraDataCodec,
final TransactionPool transactionPool) {
this.finalState = finalState; this.finalState = finalState;
this.blockCreatorFactory = finalState.getBlockCreatorFactory(); this.blockCreatorFactory = finalState.getBlockCreatorFactory();
this.protocolContext = protocolContext; this.protocolContext = protocolContext;
@ -67,6 +70,7 @@ public class IbftRoundFactory {
this.messageValidatorFactory = messageValidatorFactory; this.messageValidatorFactory = messageValidatorFactory;
this.messageFactory = messageFactory; this.messageFactory = messageFactory;
this.bftExtraDataCodec = bftExtraDataCodec; this.bftExtraDataCodec = bftExtraDataCodec;
this.transactionPool = transactionPool;
} }
/** /**
@ -116,6 +120,7 @@ public class IbftRoundFactory {
messageTransmitter, messageTransmitter,
finalState.getRoundTimer(), finalState.getRoundTimer(),
bftExtraDataCodec, bftExtraDataCodec,
parentHeader); parentHeader,
transactionPool);
} }
} }

@ -42,6 +42,9 @@ import org.hyperledger.besu.ethereum.chain.MinedBlockObserver;
import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockImporter; import org.hyperledger.besu.ethereum.core.BlockImporter;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.eth.transactions.sorter.AbstractPendingTransactionsSorter;
import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.BlockImportResult;
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
@ -59,6 +62,8 @@ public class QbftRound {
private static final Logger LOG = LoggerFactory.getLogger(QbftRound.class); private static final Logger LOG = LoggerFactory.getLogger(QbftRound.class);
private final TransactionPool transactionPool;
private final Subscribers<MinedBlockObserver> observers; private final Subscribers<MinedBlockObserver> observers;
/** The Round state. */ /** The Round state. */
@ -108,7 +113,8 @@ public class QbftRound {
final QbftMessageTransmitter transmitter, final QbftMessageTransmitter transmitter,
final RoundTimer roundTimer, final RoundTimer roundTimer,
final BftExtraDataCodec bftExtraDataCodec, final BftExtraDataCodec bftExtraDataCodec,
final BlockHeader parentHeader) { final BlockHeader parentHeader,
final TransactionPool transactionPool) {
this.roundState = roundState; this.roundState = roundState;
this.blockCreator = blockCreator; this.blockCreator = blockCreator;
this.protocolContext = protocolContext; this.protocolContext = protocolContext;
@ -119,6 +125,7 @@ public class QbftRound {
this.transmitter = transmitter; this.transmitter = transmitter;
this.bftExtraDataCodec = bftExtraDataCodec; this.bftExtraDataCodec = bftExtraDataCodec;
this.parentHeader = parentHeader; this.parentHeader = parentHeader;
this.transactionPool = transactionPool;
roundTimer.startTimer(getRoundIdentifier()); roundTimer.startTimer(getRoundIdentifier());
} }
@ -217,6 +224,25 @@ public class QbftRound {
roundState.getRoundIdentifier(), roundState.getRoundIdentifier(),
msg.getAuthor()); msg.getAuthor());
final Block block = msg.getSignedPayload().getPayload().getProposedBlock(); final Block block = msg.getSignedPayload().getPayload().getProposedBlock();
if (transactionPool.getConfigTxFastVerifySignatureEnabled()) {
final AbstractPendingTransactionsSorter pendingTransactions;
pendingTransactions =
(AbstractPendingTransactionsSorter) (transactionPool.getPendingTransactionsObject());
final List<Transaction> blockTransactions = block.getBody().getTransactions();
for (final Transaction blockTransaction : blockTransactions) {
final Transaction pendingTransaction =
pendingTransactions.getTransactionByHash(blockTransaction.getHash()).orElse(null);
if (pendingTransaction != null) {
blockTransaction.setSender(pendingTransaction.getSender());
}
}
}
if (updateStateWithProposedBlock(msg)) { if (updateStateWithProposedBlock(msg)) {
sendPrepare(block); sendPrepare(block);
} }

@ -26,6 +26,7 @@ import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.blockcreation.BlockCreator; import org.hyperledger.besu.ethereum.blockcreation.BlockCreator;
import org.hyperledger.besu.ethereum.chain.MinedBlockObserver; import org.hyperledger.besu.ethereum.chain.MinedBlockObserver;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.util.Subscribers; import org.hyperledger.besu.util.Subscribers;
/** The Qbft round factory. */ /** The Qbft round factory. */
@ -39,6 +40,7 @@ public class QbftRoundFactory {
private final MessageValidatorFactory messageValidatorFactory; private final MessageValidatorFactory messageValidatorFactory;
private final MessageFactory messageFactory; private final MessageFactory messageFactory;
private final BftExtraDataCodec bftExtraDataCodec; private final BftExtraDataCodec bftExtraDataCodec;
private final TransactionPool transactionPool;
/** /**
* Instantiates a new Qbft round factory. * Instantiates a new Qbft round factory.
@ -58,7 +60,8 @@ public class QbftRoundFactory {
final Subscribers<MinedBlockObserver> minedBlockObservers, final Subscribers<MinedBlockObserver> minedBlockObservers,
final MessageValidatorFactory messageValidatorFactory, final MessageValidatorFactory messageValidatorFactory,
final MessageFactory messageFactory, final MessageFactory messageFactory,
final BftExtraDataCodec bftExtraDataCodec) { final BftExtraDataCodec bftExtraDataCodec,
final TransactionPool transactionPool) {
this.finalState = finalState; this.finalState = finalState;
this.blockCreatorFactory = finalState.getBlockCreatorFactory(); this.blockCreatorFactory = finalState.getBlockCreatorFactory();
this.protocolContext = protocolContext; this.protocolContext = protocolContext;
@ -67,6 +70,7 @@ public class QbftRoundFactory {
this.messageValidatorFactory = messageValidatorFactory; this.messageValidatorFactory = messageValidatorFactory;
this.messageFactory = messageFactory; this.messageFactory = messageFactory;
this.bftExtraDataCodec = bftExtraDataCodec; this.bftExtraDataCodec = bftExtraDataCodec;
this.transactionPool = transactionPool;
} }
/** /**
@ -116,6 +120,7 @@ public class QbftRoundFactory {
messageTransmitter, messageTransmitter,
finalState.getRoundTimer(), finalState.getRoundTimer(),
bftExtraDataCodec, bftExtraDataCodec,
parentHeader); parentHeader,
transactionPool);
} }
} }

@ -53,8 +53,6 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.primitives.Longs; import com.google.common.primitives.Longs;
import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.bytes.Bytes32;
@ -79,9 +77,6 @@ public class Transaction
public static final BigInteger TWO = BigInteger.valueOf(2); public static final BigInteger TWO = BigInteger.valueOf(2);
private static final Cache<Hash, Address> senderCache =
CacheBuilder.newBuilder().recordStats().maximumSize(100_000L).build();
private final long nonce; private final long nonce;
private final Optional<Wei> gasPrice; private final Optional<Wei> gasPrice;
@ -427,23 +422,20 @@ public class Transaction
@Override @Override
public Address getSender() { public Address getSender() {
if (sender == null) { if (sender == null) {
Optional<Address> cachedSender = Optional.ofNullable(senderCache.getIfPresent(getHash())); final SECPPublicKey publicKey =
sender = cachedSender.orElseGet(this::computeSender); signatureAlgorithm
.recoverPublicKeyFromSignature(getOrComputeSenderRecoveryHash(), signature)
.orElseThrow(
() ->
new IllegalStateException(
"Cannot recover public key from signature for " + this));
sender = Address.extract(Hash.hash(publicKey.getEncodedBytes()));
} }
return sender; return sender;
} }
private Address computeSender() { public void setSender(final Address sender) {
final SECPPublicKey publicKey = this.sender = sender;
signatureAlgorithm
.recoverPublicKeyFromSignature(getOrComputeSenderRecoveryHash(), signature)
.orElseThrow(
() ->
new IllegalStateException(
"Cannot recover public key from signature for " + this));
final Address calculatedSender = Address.extract(Hash.hash(publicKey.getEncodedBytes()));
senderCache.put(this.hash, calculatedSender);
return calculatedSender;
} }
/** /**

@ -290,18 +290,21 @@ public class MainnetTransactionProcessor {
try { try {
final var transactionValidator = transactionValidatorFactory.get(); final var transactionValidator = transactionValidatorFactory.get();
LOG.trace("Starting execution of {}", transaction); LOG.trace("Starting execution of {}", transaction);
ValidationResult<TransactionInvalidReason> validationResult = ValidationResult<TransactionInvalidReason> validationResult;
transactionValidator.validate( if (transaction.getSender() == null) {
transaction, validationResult =
blockHeader.getBaseFee(), transactionValidator.validate(
Optional.ofNullable(blobGasPrice), transaction,
transactionValidationParams); blockHeader.getBaseFee(),
// Make sure the transaction is intrinsically valid before trying to Optional.ofNullable(blobGasPrice),
// compare against a sender account (because the transaction may not transactionValidationParams);
// be signed correctly to extract the sender). // Make sure the transaction is intrinsically valid before trying to
if (!validationResult.isValid()) { // compare against a sender account (because the transaction may not
LOG.debug("Invalid transaction: {}", validationResult.getErrorMessage()); // be signed correctly to extract the sender).
return TransactionProcessingResult.invalid(validationResult); if (!validationResult.isValid()) {
LOG.warn("Invalid transaction: {}", validationResult.getErrorMessage());
return TransactionProcessingResult.invalid(validationResult);
}
} }
final Address senderAddress = transaction.getSender(); final Address senderAddress = transaction.getSender();

@ -577,6 +577,10 @@ public class TransactionPool implements BlockAddedObserver {
return pendingTransactions.logStats(); return pendingTransactions.logStats();
} }
public PendingTransactions getPendingTransactionsObject() {
return pendingTransactions;
}
@VisibleForTesting @VisibleForTesting
Class<? extends PendingTransactions> pendingTransactionsImplementation() { Class<? extends PendingTransactions> pendingTransactionsImplementation() {
return pendingTransactions.getClass(); return pendingTransactions.getClass();
@ -687,6 +691,10 @@ public class TransactionPool implements BlockAddedObserver {
return isPoolEnabled.get(); return isPoolEnabled.get();
} }
public boolean getConfigTxFastVerifySignatureEnabled() {
return this.configuration.getUnstable().getTxFastVerifySignatureEnabled();
}
public int getBlobCacheSize() { public int getBlobCacheSize() {
return (int) cacheForBlobsOfTransactionsAddedToABlock.size(); return (int) cacheForBlobsOfTransactionsAddedToABlock.size();
} }

@ -40,6 +40,7 @@ public interface TransactionPoolConfiguration {
interface Unstable { interface Unstable {
Duration ETH65_TRX_ANNOUNCED_BUFFERING_PERIOD = Duration.ofMillis(500); Duration ETH65_TRX_ANNOUNCED_BUFFERING_PERIOD = Duration.ofMillis(500);
int DEFAULT_TX_MSG_KEEP_ALIVE = 60; int DEFAULT_TX_MSG_KEEP_ALIVE = 60;
boolean DEFAULT_TX_FAST_VERIFY_SIGNATURE_ENABLED = true;
TransactionPoolConfiguration.Unstable DEFAULT = TransactionPoolConfiguration.Unstable DEFAULT =
ImmutableTransactionPoolConfiguration.Unstable.builder().build(); ImmutableTransactionPoolConfiguration.Unstable.builder().build();
@ -53,6 +54,11 @@ public interface TransactionPoolConfiguration {
default int getTxMessageKeepAliveSeconds() { default int getTxMessageKeepAliveSeconds() {
return DEFAULT_TX_MSG_KEEP_ALIVE; return DEFAULT_TX_MSG_KEEP_ALIVE;
} }
@Value.Default
default boolean getTxFastVerifySignatureEnabled() {
return DEFAULT_TX_FAST_VERIFY_SIGNATURE_ENABLED;
}
} }
enum Implementation { enum Implementation {

Loading…
Cancel
Save