use of org.aion.base.type.ITransaction in project aion by aionnetwork.
the class AbstractTxPool method sortTxn.
protected void sortTxn() {
Map<Address, Map<BigInteger, SimpleEntry<ByteArrayWrapper, BigInteger>>> accMap = new ConcurrentHashMap<>();
SortedMap<Long, LinkedHashSet<ByteArrayWrapper>> timeMap = Collections.synchronizedSortedMap(new TreeMap<>());
// Map<ITransaction, Long> updatedTx = new HashMap<>();
this.mainMap.entrySet().parallelStream().forEach(e -> {
TXState ts = e.getValue();
if (ts.sorted()) {
return;
}
ITransaction tx = ts.getTx();
// Gen temp timeMap
long timestamp = tx.getTimeStampBI().longValue() / multiplyM;
Map<BigInteger, SimpleEntry<ByteArrayWrapper, BigInteger>> nonceMap;
ITransaction replacedTx = null;
synchronized (accMap) {
if (accMap.get(tx.getFrom()) != null) {
nonceMap = accMap.get(tx.getFrom());
} else {
nonceMap = Collections.synchronizedSortedMap(new TreeMap<>());
}
// considering refactor later
BigInteger nonce = tx.getNonceBI();
BigInteger nrgCharge = BigInteger.valueOf(tx.getNrgPrice()).multiply(BigInteger.valueOf(tx.getNrgConsume()));
if (LOG.isTraceEnabled()) {
LOG.trace("AbstractTxPool.sortTxn Put tx into nonceMap: nonce:[{}] ts:[{}] nrgCharge:[{}]", nonce, ByteUtils.toHexString(e.getKey().getData()), nrgCharge.toString());
}
// considering same nonce tx, only put the latest tx.
// if (nonceMap.get(nonce) != null) {
// try {
// if (this.mainMap.get(nonceMap.get(nonce).getKey()).getTx().getTimeStampBI().compareTo(tx.getTimeStampBI()) < 1) {
// replacedTx = this.mainMap.get(nonceMap.get(nonce).getKey()).getTx();
// updatedTx.put(replacedTx, timestamp);
// nonceMap.put(nonce, new SimpleEntry<>(e.getKey(), nrgCharge));
//
// }
// } catch (Exception ex) {
// LOG.error( "AbsTxPool.sortTxn {} [{}]", ex.toString(), tx.toString());
// }
// } else {
nonceMap.put(nonce, new SimpleEntry<>(e.getKey(), nrgCharge));
if (LOG.isTraceEnabled()) {
LOG.trace("AbstractTxPool.sortTxn Put tx into accMap: acc:[{}] mapsize[{}] ", tx.getFrom().toString(), nonceMap.size());
}
accMap.put(tx.getFrom(), nonceMap);
}
LinkedHashSet<ByteArrayWrapper> lhs;
synchronized (timeMap) {
if (timeMap.get(timestamp) != null) {
lhs = timeMap.get(timestamp);
} else {
lhs = new LinkedHashSet<>();
}
lhs.add(e.getKey());
if (LOG.isTraceEnabled()) {
LOG.trace("AbstractTxPool.sortTxn Put txHash into timeMap: ts:[{}] size:[{}]", timestamp, lhs.size());
}
timeMap.put(timestamp, lhs);
// if (replacedTx != null) {
// long t = new BigInteger(replacedTx.getTimeStamp()).longValue()/multiplyM;
// if (timeMap.get(t) != null) {
// timeMap.get(t).remove(ByteArrayWrapper.wrap(replacedTx.getHash()));
// }
// }
}
ts.setSorted();
});
if (!accMap.isEmpty()) {
timeMap.entrySet().parallelStream().forEach(e -> {
if (this.timeView.get(e.getKey()) == null) {
this.timeView.put(e.getKey(), e.getValue());
} else {
Set<ByteArrayWrapper> lhs = this.getTimeView().get(e.getKey());
lhs.addAll(e.getValue());
this.timeView.put(e.getKey(), (LinkedHashSet<ByteArrayWrapper>) lhs);
}
});
accMap.entrySet().parallelStream().forEach(e -> {
this.accountView.computeIfAbsent(e.getKey(), k -> new AccountState());
this.accountView.get(e.getKey()).updateMap(e.getValue());
});
updateAccPoolState();
updateFeeMap();
}
}
use of org.aion.base.type.ITransaction in project aion by aionnetwork.
the class TxPoolA0 method snapshot.
public synchronized List<TX> snapshot() {
List<TX> rtn = new ArrayList<>();
sortTxn();
removeTimeoutTxn();
int cnt_txSz = 0;
long cnt_nrg = 0;
Set<ByteArrayWrapper> snapshotSet = new HashSet<>();
for (Entry<BigInteger, Map<ByteArrayWrapper, TxDependList<ByteArrayWrapper>>> e : this.getFeeView().entrySet()) {
if (LOG.isTraceEnabled()) {
LOG.trace("snapshot fee[{}]", e.getKey().toString());
}
Map<ByteArrayWrapper, TxDependList<ByteArrayWrapper>> tpl = e.getValue();
for (Entry<ByteArrayWrapper, TxDependList<ByteArrayWrapper>> pair : tpl.entrySet()) {
// Check the small nonce tx must been picked before put the high nonce tx
ByteArrayWrapper dependTx = pair.getValue().getDependTx();
if (dependTx == null || snapshotSet.contains(dependTx)) {
boolean firstTx = true;
for (ByteArrayWrapper bw : pair.getValue().getTxList()) {
ITransaction itx = this.getMainMap().get(bw).getTx();
cnt_txSz += itx.getEncoded().length;
cnt_nrg += itx.getNrgConsume();
if (LOG.isTraceEnabled()) {
LOG.trace("from:[{}] nonce:[{}] txSize: txSize[{}] nrgConsume[{}]", itx.getFrom().toString(), new BigInteger(1, itx.getNonce()).toString(), itx.getEncoded().length, itx.getNrgConsume());
}
if (cnt_txSz < blkSizeLimit && cnt_nrg < blkNrgLimit.get()) {
try {
rtn.add((TX) itx.clone());
if (firstTx) {
snapshotSet.add(bw);
firstTx = false;
}
} catch (Exception ex) {
ex.printStackTrace();
if (LOG.isErrorEnabled()) {
LOG.error("TxPoolA0.snapshot exception[{}], return [{}] TX", ex.toString(), rtn.size());
}
return rtn;
}
} else {
if (LOG.isWarnEnabled()) {
LOG.warn("Reach blockLimit: txSize[{}], nrgConsume[{}], tx#[{}]", cnt_txSz, cnt_nrg, rtn.size());
}
return rtn;
}
}
}
}
}
if (LOG.isInfoEnabled()) {
LOG.info("TxPoolA0.snapshot return [{}] TX, poolSize[{}]", rtn.size(), getMainMap().size());
}
return rtn;
}
use of org.aion.base.type.ITransaction in project aion by aionnetwork.
the class TxnPoolTest method addRepeatedTxn.
@Test
public void addRepeatedTxn() {
Properties config = new Properties();
config.put("txn-timeout", "10");
ITxPool<ITransaction> tp = new TxPoolA0<>(config);
ITransaction txn = new AionTransaction(ByteUtils.fromHexString("0000000000000001"), Address.wrap(key.get(0).getAddress()), Address.wrap(key.get(0).getAddress()), ByteUtils.fromHexString("1"), ByteUtils.fromHexString("1"), 10000L, 1L);
((AionTransaction) txn).sign(key.get(0));
List<ITransaction> txnl = new ArrayList<>();
txnl.add(txn);
txnl.add(txn);
tp.add(txnl);
assertTrue(tp.size() == 1);
}
use of org.aion.base.type.ITransaction in project aion by aionnetwork.
the class TxnPoolTest method feemapTest.
@Test
public void feemapTest() {
Properties config = new Properties();
config.put("txn-timeout", "10");
TxPoolA0<ITransaction> tp = new TxPoolA0<>(config);
List<ITransaction> txnl = new ArrayList<>();
int cnt = 100;
byte[] nonce = new byte[Long.BYTES];
for (int i = 0; i < cnt; i++) {
nonce[Long.BYTES - 1] = 1;
Address addr = Address.wrap(key2.get(i).getAddress());
ITransaction txn = new AionTransaction(nonce, addr, Address.wrap("0000000000000000000000000000000000000000000000000000000000000001"), ByteUtils.fromHexString("1"), ByteUtils.fromHexString("1"), 10000L, 1L);
((AionTransaction) txn).sign(key.get(0));
txn.setNrgConsume(i + 1);
txnl.add(txn);
}
tp.add(txnl);
assertTrue(tp.size() == cnt);
// sort the inserted txs
tp.snapshot();
List<BigInteger> nl = tp.getFeeList();
long val = 100;
for (int i = 0; i < cnt; i++) {
assertTrue(nl.get(i).compareTo(BigInteger.valueOf(val--)) == 0);
}
}
use of org.aion.base.type.ITransaction in project aion by aionnetwork.
the class TxnPoolTest method benchmarkSnapshot.
@Test
public /* 100K new transactions in pool around 1200ms (cold-call)
*/
void benchmarkSnapshot() {
Properties config = new Properties();
config.put("txn-timeout", "100");
TxPoolA0<ITransaction> tp = new TxPoolA0<>(config);
List<ITransaction> txnl = new ArrayList<>();
int cnt = 10000;
for (ECKey aKey1 : key) {
Address acc = Address.wrap(aKey1.getAddress());
for (int i = 0; i < cnt; i++) {
ITransaction txn = new AionTransaction(BigInteger.valueOf(i).toByteArray(), acc, Address.wrap("0000000000000000000000000000000000000000000000000000000000000001"), ByteUtils.fromHexString("1"), ByteUtils.fromHexString("1"), 10000L, 1L);
((AionTransaction) txn).sign(aKey1);
txn.setNrgConsume(100L);
txnl.add(txn);
}
}
tp.add(txnl);
assertTrue(tp.size() == cnt * key.size());
// sort the inserted txs
long start = System.currentTimeMillis();
tp.snapshot();
System.out.println("time spent: " + (System.currentTimeMillis() - start) + " ms.");
for (ECKey aKey : key) {
List<BigInteger> nl = tp.getNonceList(Address.wrap(aKey.getAddress()));
for (int i = 0; i < cnt; i++) {
assertTrue(nl.get(i).equals(BigInteger.valueOf(i)));
}
}
}
Aggregations