use of org.aion.base.PooledTransaction in project aion by aionnetwork.
the class AionPendingStateImpl method addPendingTransactions.
/**
* Tries to add the given transactions to the PendingState
*
* @param transactions, the list of AionTransactions to be added
* @return a list of TxResponses of the same size as the input param transactions The entries in
* the returned list of responses correspond one-to-one with the input txs
*/
private List<TxResponse> addPendingTransactions(List<AionTransaction> transactions) {
List<AionTransaction> newPending = new ArrayList<>();
List<AionTransaction> newLargeNonceTx = new ArrayList<>();
List<TxResponse> txResponses = new ArrayList<>();
int fetchLimit = calculateTxFetchNumberLimit();
for (AionTransaction tx : transactions) {
TxResponse response;
if (pendingTxCache.isInCache(tx.getSenderAddress(), tx.getNonceBI())) {
response = TxResponse.ALREADY_CACHED;
} else {
BigInteger bestPendingStateNonce = bestPendingStateNonce(tx.getSenderAddress());
int cmp = tx.getNonceBI().compareTo(bestPendingStateNonce);
boolean isFutureNonce = (cmp > 0);
boolean isBestPendingNonce = (cmp == 0);
boolean isSealed = (tx.getNonceBI().compareTo(bestRepoNonce(tx.getSenderAddress())) < 0);
if (isFutureNonce) {
response = processTxToCachePool(tx, false, newLargeNonceTx);
} else if (isBestPendingNonce) {
if (txPool.isFull()) {
response = processTxToCachePool(tx, true, newLargeNonceTx);
} else {
response = processTxToTxPool(tx, fetchLimit, newPending);
}
} else if (isSealed) {
response = TxResponse.ALREADY_SEALED;
} else {
// This case happens when this tx was received before, but never sealed,
// typically because of low energy
TxResponse implResponse = addPendingTransactionInner(tx);
if (implResponse.equals(TxResponse.REPAID)) {
newPending.add(tx);
response = TxResponse.REPAID;
addPendingTxToBackupDatabase(tx);
PooledTransaction ptx = txPool.getDroppedPoolTx();
if (ptx != null) {
fireDroppedTx(ptx.tx, TxResponse.REPAYTX_LOWPRICE.getMessage());
}
} else {
response = implResponse;
}
}
}
txResponses.add(response);
LOGGER_TX.debug("add tx [{}], result:[{}]", tx, response.getMessage());
}
LOGGER_TX.info("Wire transaction list added: total: {}, newPending: {}, cached: {}, txPool size: {}", transactions.size(), newPending, newLargeNonceTx.size(), txPool.size());
executeCallback(newPending, newLargeNonceTx);
return txResponses;
}
use of org.aion.base.PooledTransaction in project aion by aionnetwork.
the class AionPendingStateImpl method clearOutdated.
private void clearOutdated(final long blockNumber) {
List<PooledTransaction> clearedTxFromTxPool = txPool.clearOutDateTransaction();
for (PooledTransaction pTx : clearedTxFromTxPool) {
removeBackupDBPendingTx(pTx.tx.getTransactionHash());
fireTxUpdate(createDroppedReceipt(pTx.tx, "Tx was not included into last " + txPool.transactionTimeout + " seconds"), PendingTransactionState.DROPPED, currentBestBlock.get());
}
List<AionTransaction> clearedTxFromCache = pendingTxCache.pollRemovedTransactionForPoolBackup();
for (AionTransaction tx : clearedTxFromCache) {
removeBackupDBCachedTx(tx.getTransactionHash());
fireTxUpdate(createDroppedReceipt(tx, "Tx was not included into last " + PendingTxCacheV1.CACHE_TIMEOUT + " seconds"), PendingTransactionState.DROPPED, currentBestBlock.get());
}
LOGGER_TX.info("clearOutdated block#[{}] tx#[{}]", blockNumber, clearedTxFromTxPool.size() + clearedTxFromCache.size());
}
use of org.aion.base.PooledTransaction in project aion by aionnetwork.
the class TxPoolV1 method remove.
/**
* @implNote remove transactions into the pool.
* @param tx pool transactions
* @return the transactions has been removed from the pool.
*/
public List<PooledTransaction> remove(List<PooledTransaction> tx) {
Objects.requireNonNull(tx);
lock.lock();
try {
List<PooledTransaction> removedTx = new ArrayList<>();
for (PooledTransaction pTx : tx) {
ByteArrayWrapper txHash = ByteArrayWrapper.wrap(pTx.tx.getTransactionHash());
PooledTransaction removedPoolTx = poolRemove(txHash);
if (removedPoolTx != null) {
removedTx.add(removedPoolTx);
}
}
return removedTx;
} finally {
lock.unlock();
}
}
use of org.aion.base.PooledTransaction in project aion by aionnetwork.
the class TxPoolV1 method add.
/**
* @implNote add transactions into the pool. If the transaction has the same account nonce and
* the new transaction has higher energy price. The pool will remove the old transaction and
* update to the new one.
* @param list pool transactions
* @return the transactions has been added into the pool.
*/
public List<PooledTransaction> add(List<PooledTransaction> list) {
Objects.requireNonNull(list);
if (list.isEmpty()) {
return Collections.emptyList();
}
lock.lock();
try {
List<PooledTransaction> addedTransactions = new ArrayList<>();
for (PooledTransaction poolTx : list) {
if (poolTransactions.size() == maxPoolSize) {
LOG_TXPOOL.warn("txPool is full. No transaction has been added!");
return addedTransactions;
}
ByteArrayWrapper repayOldTx = checkRepayTransaction(poolTx.tx);
ByteArrayWrapper poolTxHash = ByteArrayWrapper.wrap(poolTx.tx.getTransactionHash());
if (repayOldTx != null) {
if (repayOldTx.equals(poolTxHash)) {
LOG_TXPOOL.debug("skip adding the tx [{}] because it's not a valid repay transaction.", poolTx.tx);
continue;
} else {
LOG_TXPOOL.debug("repay tx found! Remove original tx");
droppedPoolTx = poolRemove(repayOldTx);
}
}
poolAdd(poolTxHash, poolTx);
addedTransactions.add(poolTx);
}
return addedTransactions;
} finally {
lock.unlock();
}
}
use of org.aion.base.PooledTransaction in project aion by aionnetwork.
the class TxnPoolV1BenchmarkTest method benchmarkSnapshot2.
@Test
public void benchmarkSnapshot2() {
Properties config = new Properties();
config.put(TXPOOL_PROPERTY.PROP_TX_TIMEOUT, "100");
config.put(TXPOOL_PROPERTY.PROP_POOL_SIZE_MAX, "10100");
TxPoolV1 tp = new TxPoolV1(config);
List<PooledTransaction> txnl = new ArrayList<>();
int cnt = 1000;
for (ECKey aKey2 : key) {
for (int i = 0; i < cnt; i++) {
AionTransaction txn = AionTransaction.create(aKey2, BigInteger.valueOf(i).toByteArray(), AddressUtils.wrapAddress("0000000000000000000000000000000000000000000000000000000000000001"), ByteUtils.fromHexString("1"), ByteUtils.fromHexString("1"), Constant.MIN_ENERGY_CONSUME, 1L, TransactionTypes.DEFAULT, null);
PooledTransaction pooledTx = new PooledTransaction(txn, Constant.MIN_ENERGY_CONSUME);
txnl.add(pooledTx);
}
}
tp.add(txnl);
Assert.assertEquals(tp.size(), cnt * key.size());
// sort the inserted txs
long start = System.currentTimeMillis();
tp.snapshot();
System.out.println("time spent: " + (System.currentTimeMillis() - start) + " ms.");
int cnt2 = 10;
txnl.clear();
for (ECKey aKey1 : key) {
for (int i = 0; i < cnt2; i++) {
AionTransaction txn = AionTransaction.create(aKey1, BigInteger.valueOf(cnt + i).toByteArray(), AddressUtils.wrapAddress("0000000000000000000000000000000000000000000000000000000000000001"), ByteUtils.fromHexString("1"), ByteUtils.fromHexString("1"), Constant.MIN_ENERGY_CONSUME, 1L, TransactionTypes.DEFAULT, null);
PooledTransaction pooledTx = new PooledTransaction(txn, Constant.MIN_ENERGY_CONSUME);
txnl.add(pooledTx);
}
}
tp.add(txnl);
Assert.assertEquals(tp.size(), (cnt + cnt2) * key.size());
start = System.currentTimeMillis();
tp.snapshot();
System.out.println("2nd time spent: " + (System.currentTimeMillis() - start) + " ms.");
for (ECKey aKey : key) {
List<BigInteger> nl = tp.getNonceList(new AionAddress(aKey.getAddress()));
for (int i = 0; i < cnt + cnt2; i++) {
Assert.assertEquals(nl.get(i), BigInteger.valueOf(i));
}
}
}
Aggregations