From 7444cee6d2d80e7002a8e95a0bc606a8a21467b1 Mon Sep 17 00:00:00 2001 From: AionJayT Date: Tue, 21 May 2019 14:19:06 -0400 Subject: [PATCH] Fixed transaction get empty transansaction when snapshot the transactionpool with the transactions have the same timestamp --- .../org/aion/zero/types/AionTransaction.java | 9 ++ .../src/org/aion/txpool/zero/TxPoolA0.java | 3 +- .../org/aion/txpool/test/TxnPoolTest.java | 107 ++++++++++++++---- 3 files changed, 95 insertions(+), 24 deletions(-) diff --git a/modAion/src/org/aion/zero/types/AionTransaction.java b/modAion/src/org/aion/zero/types/AionTransaction.java index 2b2a154547..29f27a84d0 100644 --- a/modAion/src/org/aion/zero/types/AionTransaction.java +++ b/modAion/src/org/aion/zero/types/AionTransaction.java @@ -2,6 +2,7 @@ import static org.aion.util.bytes.ByteUtil.ZERO_BYTE_ARRAY; +import com.google.common.annotations.VisibleForTesting; import java.math.BigInteger; import java.util.Arrays; import org.aion.mcf.vm.types.DataWordImpl; @@ -343,6 +344,14 @@ public void sign(ECKey key) throws MissingPrivateKeyException { this.rlpEncoded = null; } + + @VisibleForTesting + public void signWithSecTimeStamp(ECKey key) throws MissingPrivateKeyException { + this.timeStamp = ByteUtil.longToBytes(TimeInstant.now().toEpochSec() * 1_000_000L); + this.signature = key.sign(this.getRawHash()); + this.rlpEncoded = null; + } + @Override public String toString() { return toString(Integer.MAX_VALUE); diff --git a/modTxPoolImpl/src/org/aion/txpool/zero/TxPoolA0.java b/modTxPoolImpl/src/org/aion/txpool/zero/TxPoolA0.java index f4ee0061b0..4df45ca462 100644 --- a/modTxPoolImpl/src/org/aion/txpool/zero/TxPoolA0.java +++ b/modTxPoolImpl/src/org/aion/txpool/zero/TxPoolA0.java @@ -464,7 +464,8 @@ public List snapshot() { for (Entry> pair : e.getValue().entrySet()) { BigInteger ts = pair.getValue().getTimeStamp(); - while (timeTxDep.get(ts.add(BigInteger.ONE)) != null) { + // If timestamp has collision, increase 1 for getting a new slot to put the transaction pair. + while (timeTxDep.get(ts) != null) { ts = ts.add(BigInteger.ONE); } timeTxDep.put(ts, pair); diff --git a/modTxPoolImpl/test/org/aion/txpool/test/TxnPoolTest.java b/modTxPoolImpl/test/org/aion/txpool/test/TxnPoolTest.java index aec6a7d886..43b94de33d 100644 --- a/modTxPoolImpl/test/org/aion/txpool/test/TxnPoolTest.java +++ b/modTxPoolImpl/test/org/aion/txpool/test/TxnPoolTest.java @@ -19,8 +19,10 @@ import org.aion.crypto.ECKeyFac; import org.aion.txpool.ITxPool; import org.aion.txpool.zero.TxPoolA0; +import org.aion.types.ByteArrayWrapper; import org.aion.types.Hash256; import org.aion.zero.types.AionTransaction; +import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -479,8 +481,9 @@ public void snapshot9() { TxPoolA0 tp = new TxPoolA0<>(config); List txnl = new ArrayList<>(); + Map txMap = new HashMap<>(); + int cnt = 25; - // Random r = new Random(); for (int i = 0; i < cnt; i++) { byte[] nonce = new byte[Long.BYTES]; nonce[Long.BYTES - 1] = (byte) i; @@ -489,6 +492,7 @@ public void snapshot9() { ((AionTransaction) txn).sign(key.get(0)); txn.setNrgConsume(1); txnl.add(txn); + txMap.put(ByteArrayWrapper.wrap(txn.getTransactionHash()), txn); } tp.add(txnl); assertTrue(tp.size() == cnt); @@ -502,6 +506,7 @@ public void snapshot9() { ((AionTransaction) txn).sign(key.get(1)); txn.setNrgConsume(1); txnl2.add(txn); + txMap.put(ByteArrayWrapper.wrap(txn.getTransactionHash()), txn); } tp.add(txnl2); assertTrue(tp.size() == cnt * 2); @@ -511,21 +516,9 @@ public void snapshot9() { assertTrue(tp.size() == txl.size()); assertTrue(tp.snapshotAll().size() == txl.size()); - int check = 0; for (Transaction tx : txl) { - if (check < 25) { - assertTrue( - Hash256.wrap(txnl.get(check).getTransactionHash()) - .toString() - .equals(Hash256.wrap(tx.getTransactionHash()).toString())); - check++; - } else { - assertTrue( - Hash256.wrap(txnl2.get(check - 25).getTransactionHash()) - .toString() - .equals(Hash256.wrap(tx.getTransactionHash()).toString())); - check++; - } + assertTrue(txMap.containsKey(ByteArrayWrapper.wrap(tx.getTransactionHash()))); + Assert.assertEquals(txMap.get(ByteArrayWrapper.wrap(tx.getTransactionHash())), tx); } } @@ -537,8 +530,8 @@ public void snapshot10() { TxPoolA0 tp = new TxPoolA0<>(config); List txnl = new ArrayList<>(); + Map txMap = new HashMap<>(); int cnt = 16; - // Random r = new Random(); for (int i = 0; i < cnt; i++) { byte[] nonce = new byte[Long.BYTES]; nonce[Long.BYTES - 1] = (byte) i; @@ -547,6 +540,7 @@ public void snapshot10() { ((AionTransaction) txn).sign(key.get(0)); txn.setNrgConsume(1); txnl.add(txn); + txMap.put(ByteArrayWrapper.wrap(txn.getTransactionHash()), txn); } for (int i = 0; i < cnt; i++) { @@ -557,6 +551,7 @@ public void snapshot10() { ((AionTransaction) txn).sign(key.get(1)); txn.setNrgConsume(1); txnl.add(txn); + txMap.put(ByteArrayWrapper.wrap(txn.getTransactionHash()), txn); } for (int i = 16; i < 16 + cnt; i++) { @@ -567,6 +562,7 @@ public void snapshot10() { ((AionTransaction) txn).sign(key.get(0)); txn.setNrgConsume(1); txnl.add(txn); + txMap.put(ByteArrayWrapper.wrap(txn.getTransactionHash()), txn); } for (int i = 16; i < 16 + cnt; i++) { @@ -577,6 +573,7 @@ public void snapshot10() { ((AionTransaction) txn).sign(key.get(1)); txn.setNrgConsume(1); txnl.add(txn); + txMap.put(ByteArrayWrapper.wrap(txn.getTransactionHash()), txn); } tp.add(txnl); @@ -587,13 +584,77 @@ public void snapshot10() { assertTrue(tp.size() == txl.size()); assertTrue(tp.snapshotAll().size() == txl.size()); - int check = 0; for (Transaction tx : txl) { - assertTrue( - Hash256.wrap(txnl.get(check).getTransactionHash()) - .toString() - .equals(Hash256.wrap(tx.getTransactionHash()).toString())); - check++; + assertTrue(txMap.containsKey(ByteArrayWrapper.wrap(tx.getTransactionHash()))); + Assert.assertEquals(txMap.get(ByteArrayWrapper.wrap(tx.getTransactionHash())), tx); + } + } + + @Test + public void snapshotWithSameTransactionTimestamp() { + Properties config = new Properties(); + config.put("tx-timeout", "100"); + + TxPoolA0 tp = new TxPoolA0<>(config); + + List txnl = new ArrayList<>(); + Map txMap = new HashMap<>(); + int cnt = 16; + for (int i = 0; i < cnt; i++) { + byte[] nonce = new byte[Long.BYTES]; + nonce[Long.BYTES - 1] = (byte) i; + Transaction txn = genTransaction(nonce, 0); + + ((AionTransaction) txn).signWithSecTimeStamp(key.get(0)); + txn.setNrgConsume(1); + txnl.add(txn); + txMap.put(ByteArrayWrapper.wrap(txn.getTransactionHash()), txn); + } + + for (int i = 0; i < cnt; i++) { + byte[] nonce = new byte[Long.BYTES]; + nonce[Long.BYTES - 1] = (byte) i; + Transaction txn = genTransaction(nonce, 1); + + ((AionTransaction) txn).signWithSecTimeStamp(key.get(1)); + txn.setNrgConsume(1); + txnl.add(txn); + txMap.put(ByteArrayWrapper.wrap(txn.getTransactionHash()), txn); + } + + for (int i = 16; i < 16 + cnt; i++) { + byte[] nonce = new byte[Long.BYTES]; + nonce[Long.BYTES - 1] = (byte) i; + Transaction txn = genTransaction(nonce, 0); + + ((AionTransaction) txn).signWithSecTimeStamp(key.get(0)); + txn.setNrgConsume(1); + txnl.add(txn); + txMap.put(ByteArrayWrapper.wrap(txn.getTransactionHash()), txn); + } + + for (int i = 16; i < 16 + cnt; i++) { + byte[] nonce = new byte[Long.BYTES]; + nonce[Long.BYTES - 1] = (byte) i; + Transaction txn = genTransaction(nonce, 1); + + ((AionTransaction) txn).signWithSecTimeStamp(key.get(1)); + txn.setNrgConsume(1); + txnl.add(txn); + txMap.put(ByteArrayWrapper.wrap(txn.getTransactionHash()), txn); + } + + tp.add(txnl); + assertTrue(tp.size() == cnt * 4); + + // sort the inserted txs + List txl = tp.snapshot(); + assertTrue(tp.size() == txl.size()); + assertTrue(tp.snapshotAll().size() == txl.size()); + + for (Transaction tx : txl) { + assertTrue(txMap.containsKey(ByteArrayWrapper.wrap(tx.getTransactionHash()))); + Assert.assertEquals(txMap.get(ByteArrayWrapper.wrap(tx.getTransactionHash())), tx); } } @@ -820,7 +881,7 @@ public void feemapTest() { int cnt = 100; byte[] nonce = new byte[Long.BYTES]; for (int i = 0; i < cnt; i++) { - nonce[Long.BYTES - 1] = 1; + nonce[Long.BYTES - 1] = (byte) i; Address addr = Address.wrap(key2.get(i).getAddress()); Transaction txn =