use of org.aion.base.type.Address in project aion by aionnetwork.
the class AbstractTxPool method updateAccPoolState.
protected void updateAccPoolState() {
// iterate tx by account
List<Address> clearAddr = new ArrayList<>();
for (Entry<Address, AccountState> e : this.accountView.entrySet()) {
AccountState as = e.getValue();
if (as.isDirty()) {
if (as.getMap().isEmpty()) {
this.poolStateView.remove(e.getKey());
clearAddr.add(e.getKey());
} else {
// checking AccountState given by account
List<PoolState> psl = this.poolStateView.get(e.getKey());
if (psl == null) {
psl = new LinkedList<>();
}
List<PoolState> newPoolState = new LinkedList<>();
// Checking new tx has been include into old pools.
BigInteger txNonceStart = as.getFirstNonce();
if (txNonceStart != null) {
if (LOG.isTraceEnabled()) {
LOG.trace("AbstractTxPool.updateAccPoolState fn [{}]", txNonceStart.toString());
}
for (PoolState ps : psl) {
// check the previous txn status in the old PoolState
if (isClean(ps, as) && ps.firstNonce.equals(txNonceStart) && ps.combo == SEQUENTAILTXNCOUNT_MAX) {
ps.resetInFeePool();
newPoolState.add(ps);
if (LOG.isTraceEnabled()) {
LOG.trace("AbstractTxPool.updateAccPoolState add fn [{}]", ps.firstNonce.toString());
}
txNonceStart = txNonceStart.add(BigInteger.valueOf(SEQUENTAILTXNCOUNT_MAX));
} else {
// remove old poolState in the feeMap
Map<ByteArrayWrapper, TxDependList<ByteArrayWrapper>> txDp = this.feeView.get(ps.getFee());
if (txDp != null) {
if (e.getValue().getMap().get(ps.firstNonce) != null) {
txDp.remove(e.getValue().getMap().get(ps.firstNonce).getKey());
}
if (LOG.isTraceEnabled()) {
LOG.trace("AbstractTxPool.updateAccPoolState remove fn [{}]", ps.firstNonce.toString());
}
if (txDp.isEmpty()) {
this.feeView.remove(ps.getFee());
}
}
}
}
}
int cnt = 0;
BigInteger fee = BigInteger.ZERO;
BigInteger totalFee = BigInteger.ZERO;
for (Entry<BigInteger, SimpleEntry<ByteArrayWrapper, BigInteger>> en : as.getMap().entrySet()) {
if (LOG.isTraceEnabled()) {
LOG.trace("AbstractTxPool.updateAccPoolState mapsize[{}] nonce:[{}] cnt[{}] txNonceStart[{}]", as.getMap().size(), en.getKey().toString(), cnt, txNonceStart.toString());
}
if (en.getKey().equals(txNonceStart != null ? txNonceStart.add(BigInteger.valueOf(cnt)) : null)) {
if (en.getValue().getValue().compareTo(fee) > -1) {
fee = en.getValue().getValue();
totalFee = totalFee.add(fee);
if (++cnt == SEQUENTAILTXNCOUNT_MAX) {
if (LOG.isTraceEnabled()) {
LOG.trace("AbstractTxPool.updateAccPoolState case1 - nonce:[{}] totalFee:[{}] cnt:[{}]", txNonceStart, totalFee.toString(), cnt);
}
newPoolState.add(new PoolState(txNonceStart, totalFee.divide(BigInteger.valueOf(cnt)), cnt));
txNonceStart = en.getKey().add(BigInteger.ONE);
totalFee = BigInteger.ZERO;
fee = BigInteger.ZERO;
cnt = 0;
}
} else {
if (LOG.isTraceEnabled()) {
LOG.trace("AbstractTxPool.updateAccPoolState case2 - nonce:[{}] totalFee:[{}] cnt:[{}]", txNonceStart, totalFee.toString(), cnt);
}
newPoolState.add(new PoolState(txNonceStart, totalFee.divide(BigInteger.valueOf(cnt)), cnt));
// next PoolState
txNonceStart = en.getKey();
fee = en.getValue().getValue();
totalFee = fee;
cnt = 1;
}
}
}
if (totalFee.signum() == 1) {
if (LOG.isTraceEnabled()) {
LOG.trace("AbstractTxPool.updateAccPoolState case3 - nonce:[{}] totalFee:[{}] cnt:[{}] bw:[{}]", txNonceStart, totalFee.toString(), cnt, e.getKey().toString());
}
newPoolState.add(new PoolState(txNonceStart, totalFee.divide(BigInteger.valueOf(cnt)), cnt));
}
this.poolStateView.put(e.getKey(), newPoolState);
if (LOG.isTraceEnabled()) {
this.poolStateView.forEach((k, v) -> v.forEach(l -> {
LOG.trace("AbstractTxPool.updateAccPoolState - the first nonce of the poolState list:[{}]", l.firstNonce);
}));
}
as.sorted();
}
}
}
if (!clearAddr.isEmpty()) {
clearAddr.forEach(addr -> {
this.accountView.remove(addr);
this.bestNonce.remove(addr);
});
}
}
use of org.aion.base.type.Address 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.Address 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.Address 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)));
}
}
}
use of org.aion.base.type.Address in project aion by aionnetwork.
the class TxnPoolTest method benchmarkSnapshot3.
@Test
public /* 1M new transactions with 10000 accounts (100 txs per account)in pool snapshot around 10s (cold-call)
gen new txns 55s (spent a lot of time to sign tx)
put txns into pool 2.5s
snapshot txn 5s
*/
void benchmarkSnapshot3() {
Properties config = new Properties();
config.put("txn-timeout", "100");
TxPoolA0<ITransaction> tp = new TxPoolA0<>(config);
List<ITransaction> txnl = new ArrayList<>();
int cnt = 100;
System.out.println("Gen new transactions --");
long start = System.currentTimeMillis();
for (ECKey aKey21 : key2) {
Address acc = Address.wrap(aKey21.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(aKey21);
txn.setNrgConsume(100L);
txnl.add(txn);
}
}
System.out.println("time spent: " + (System.currentTimeMillis() - start) + " ms.");
System.out.println("Adding transactions into pool--");
start = System.currentTimeMillis();
tp.add(txnl);
System.out.println("time spent: " + (System.currentTimeMillis() - start) + " ms.");
assertTrue(tp.size() == cnt * key2.size());
// sort the inserted txs
System.out.println("Snapshoting --");
start = System.currentTimeMillis();
tp.snapshot();
System.out.println("time spent: " + (System.currentTimeMillis() - start) + " ms.");
for (ECKey aKey2 : key2) {
List<BigInteger> nl = tp.getNonceList(Address.wrap(aKey2.getAddress()));
for (int i = 0; i < cnt; i++) {
assertTrue(nl.get(i).equals(BigInteger.valueOf(i)));
}
}
}
Aggregations