use of org.aion.base.PooledTransaction in project aion by aionnetwork.
the class TxPoolV1 method snapshotAll.
/**
* @implNote snapshot all transactions in the pool by account nonce order.
* @return a list of the AionTransaction in the current transaction pool.
* @exception IllegalStateException if cannot find the transaction hash in the mainMap.
*/
public List<AionTransaction> snapshotAll() {
lock.lock();
try {
List<AionTransaction> allPoolTransactions = new ArrayList<>();
for (SortedMap<BigInteger, ByteArrayWrapper> txHashes : accountView.values()) {
for (ByteArrayWrapper hash : txHashes.values()) {
PooledTransaction pTx = poolTransactions.get(hash);
if (pTx == null) {
throw new IllegalStateException("The pool data has broken, cannot find the txHash:" + hash);
}
allPoolTransactions.add(pTx.tx);
}
}
LOG_TXPOOL.info("snapshotAll: tx#[{}]", allPoolTransactions.size());
return allPoolTransactions;
} finally {
lock.unlock();
}
}
use of org.aion.base.PooledTransaction in project aion by aionnetwork.
the class TxPoolV1 method pickTransaction.
private Triple<List<AionTransaction>, Long, Long> pickTransaction(Map<AionAddress, BigInteger> accountPickingInfo, Set<ByteArrayWrapper> pickedTxHash, long cumulatedTxEncodedSize, long cumulatedTxEnergy) {
List<AionTransaction> pickedTx = new ArrayList<>();
long pickedTxEncodedSize = 0;
long pickedEnergyConsumed = 0;
for (Set<ByteArrayWrapper> s : feeView.values()) {
for (ByteArrayWrapper hash : s) {
if (!pickedTxHash.contains(hash)) {
PooledTransaction pendingTx = poolTransactions.get(hash);
AionAddress sender = pendingTx.tx.getSenderAddress();
BigInteger currentAccountPickingNonce = accountPickingInfo.getOrDefault(sender, getAccountFirstPickingNonce(sender));
if (currentAccountPickingNonce.equals(pendingTx.tx.getNonceBI())) {
long txEncodedSize = pendingTx.tx.getEncoded().length;
long txEnergyConsumed = Math.max(pendingTx.energyConsumed, (Constant.MIN_ENERGY_CONSUME / 2));
if ((cumulatedTxEncodedSize + pickedTxEncodedSize + txEncodedSize) <= Constant.MAX_BLK_SIZE && (cumulatedTxEnergy + pickedEnergyConsumed + txEncodedSize) <= blockEnergyLimit) {
LOG_TXPOOL.trace("Transaction picked: [{}]", pendingTx.tx);
pickedTx.add(pendingTx.tx);
pickedTxHash.add(hash);
currentAccountPickingNonce = currentAccountPickingNonce.add(BigInteger.ONE);
accountPickingInfo.put(sender, currentAccountPickingNonce);
pickedTxEncodedSize += txEncodedSize;
pickedEnergyConsumed += txEnergyConsumed;
} else {
return Triple.of(pickedTx, pickedTxEncodedSize, pickedEnergyConsumed);
}
}
}
}
}
return Triple.of(pickedTx, pickedTxEncodedSize, pickedEnergyConsumed);
}
use of org.aion.base.PooledTransaction in project aion by aionnetwork.
the class TxPoolV1 method removeTxsWithNonceLessThan.
/**
* @implNote remove transactions relate with the account and the expecting nonce. If the transactions in the pool
* match the account and less than the expecting nonce. The transactions will be removed.
* @param accountsWithNonce the map stored accounts with related expecting nonces.
* @return the pool transactions has been removed from the pool.
*/
public List<PooledTransaction> removeTxsWithNonceLessThan(Map<AionAddress, BigInteger> accountsWithNonce) {
Objects.requireNonNull(accountsWithNonce);
Objects.requireNonNull(accountsWithNonce.entrySet());
if (accountsWithNonce.isEmpty()) {
return Collections.emptyList();
}
lock.lock();
try {
List<PooledTransaction> removedTransaction = new ArrayList<>();
List<ByteArrayWrapper> removeTxHash = new ArrayList<>();
for (Map.Entry<AionAddress, BigInteger> account : accountsWithNonce.entrySet()) {
if (accountView.containsKey(account.getKey())) {
SortedMap<BigInteger, ByteArrayWrapper> accountInfo = accountView.get(account.getKey());
removeTxHash.addAll(accountInfo.headMap(account.getValue()).values());
}
}
for (ByteArrayWrapper hash : removeTxHash) {
PooledTransaction pTx = poolRemove(hash);
if (pTx != null) {
removedTransaction.add(pTx);
}
}
return removedTransaction;
} finally {
lock.unlock();
}
}
use of org.aion.base.PooledTransaction in project aion by aionnetwork.
the class TxPoolV1 method poolRemove.
private PooledTransaction poolRemove(ByteArrayWrapper txHash) {
PooledTransaction removedTx = poolTransactions.remove(txHash);
if (removedTx == null) {
LOG_TXPOOL.debug("Did not find the transaction hash:{} in the pool", txHash);
return null;
}
LOG_TXPOOL.debug("Removing tx[{}]", removedTx.tx);
long time = TimeUnit.MICROSECONDS.toSeconds(removedTx.tx.getTimeStampBI().longValue()) + transactionTimeout;
Set<ByteArrayWrapper> timeSet = timeView.get(time);
timeSet.remove(txHash);
if (timeSet.isEmpty()) {
timeView.remove(time);
}
Set<ByteArrayWrapper> feeSet = feeView.get(removedTx.tx.getEnergyPrice());
feeSet.remove(txHash);
if (feeSet.isEmpty()) {
feeView.remove(removedTx.tx.getEnergyPrice());
}
SortedMap<BigInteger, ByteArrayWrapper> accountInfo = accountView.get(removedTx.tx.getSenderAddress());
accountInfo.remove(removedTx.tx.getNonceBI());
if (accountInfo.isEmpty()) {
accountView.remove(removedTx.tx.getSenderAddress());
}
LOG_TXPOOL.debug("Removed tx[{}]", removedTx.tx);
return removedTx;
}
use of org.aion.base.PooledTransaction in project aion by aionnetwork.
the class TxnPoolV1BenchmarkTest method benchmarkSnapshot4.
@Test
public /* 100K new transactions in pool around 350ms (cold-call)
*/
void benchmarkSnapshot4() {
Properties config = new Properties();
config.put(TXPOOL_PROPERTY.PROP_TX_TIMEOUT, "100");
config.put(TXPOOL_PROPERTY.PROP_POOL_SIZE_MAX, "10000");
TxPoolV1 tp = new TxPoolV1(config);
List<PooledTransaction> txnl = new ArrayList<>();
List<PooledTransaction> txnlrm = new ArrayList<>();
int cnt = 1000;
int rmCnt = 10;
System.out.println("gen new transactions...");
long start = System.currentTimeMillis();
for (int i = 0; i < cnt; i++) {
AionTransaction txn = AionTransaction.create(key.get(0), 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);
if (i < rmCnt) {
txnlrm.add(pooledTx);
}
}
System.out.println("time spent: " + (System.currentTimeMillis() - start) + " ms.");
System.out.println("Inserting txns...");
start = System.currentTimeMillis();
tp.add(txnl);
System.out.println("time spent: " + (System.currentTimeMillis() - start) + " ms.");
Assert.assertEquals(tp.size(), cnt);
// sort the inserted txs
System.out.println("Snapshoting...");
start = System.currentTimeMillis();
tp.snapshot();
System.out.println("time spent: " + (System.currentTimeMillis() - start) + " ms.");
System.out.println("Removing the first 10 txns...");
start = System.currentTimeMillis();
List rm = tp.remove(txnlrm);
System.out.println("time spent: " + (System.currentTimeMillis() - start) + " ms.");
Assert.assertEquals(rm.size(), rmCnt);
Assert.assertEquals(tp.size(), cnt - rmCnt);
System.out.println("Re-Snapshot after some txns was been removed...");
start = System.currentTimeMillis();
tp.snapshot();
System.out.println("time spent: " + (System.currentTimeMillis() - start) + " ms.");
List<BigInteger> nl = tp.getNonceList(new AionAddress(key.get(0).getAddress()));
for (int i = 0; i < nl.size(); i++) {
Assert.assertEquals(nl.get(i), BigInteger.valueOf(i).add(BigInteger.valueOf(rmCnt)));
}
}
Aggregations