From cf376852ef9e3a9b33eeb9c77bcd085ae66ef4dc Mon Sep 17 00:00:00 2001
From: June <2571240520@qq.com>
Date: Tue, 16 Apr 2024 22:43:49 +0800
Subject: [PATCH 1/2] add some transaction test unit.
---
src/test/java/io/xdag/BlockBuilder.java | 12 +
.../java/io/xdag/core/BlockchainTest.java | 324 +++++++++++++++++-
2 files changed, 332 insertions(+), 4 deletions(-)
diff --git a/src/test/java/io/xdag/BlockBuilder.java b/src/test/java/io/xdag/BlockBuilder.java
index ed0b118f..30ffcf7d 100644
--- a/src/test/java/io/xdag/BlockBuilder.java
+++ b/src/test/java/io/xdag/BlockBuilder.java
@@ -100,6 +100,18 @@ public static Block generateNewTransactionBlock(Config config, KeyPair key, long
return b;
}
+ public static Block generateNewTransactionBlock(Config config, KeyPair key, long xdagTime, Address from, Address to,
+ XAmount amount, XAmount VariableFee) {
+ List
refs = Lists.newArrayList();
+ List keys = Lists.newArrayList();
+ refs.add(new Address(from.getAddress(), XDAG_FIELD_INPUT, amount,true)); // key1
+ refs.add(new Address(to.getAddress(), XDAG_FIELD_OUTPUT, amount,true));
+ keys.add(key);
+ Block b = new Block(config, xdagTime, refs, null, false, keys, null, 0, VariableFee); // orphan
+ b.signOut(key);
+ return b;
+ }
+
public static Block generateWalletTransactionBlock(Config config, KeyPair key, long xdagTime, Address from, Address to,
XAmount amount) {
List refs = Lists.newArrayList();
diff --git a/src/test/java/io/xdag/core/BlockchainTest.java b/src/test/java/io/xdag/core/BlockchainTest.java
index cc83e805..d4b0c3f3 100644
--- a/src/test/java/io/xdag/core/BlockchainTest.java
+++ b/src/test/java/io/xdag/core/BlockchainTest.java
@@ -56,7 +56,9 @@
import java.io.IOException;
import java.math.BigInteger;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import static io.xdag.BlockBuilder.*;
import static io.xdag.core.ImportResult.*;
@@ -267,7 +269,8 @@ public void testNew2NewTransactionBlock() {
assertChainStatus(12, 10, 1, 1, blockchain);
pending.clear();
- pending.add(new Address(txBlock.getHashLow(),false));
+ Address txAddress = new Address(txBlock.getHashLow(), false);
+ pending.add(txAddress);
ref = extraBlockList.get(extraBlockList.size() - 1).getHashLow();
// 4. confirm transaction block with 16 mainblocks
for (int i = 1; i <= 16; i++) {
@@ -299,9 +302,9 @@ public void testNew2NewTransactionBlock() {
XAmount RollBackPoolBalance = blockchain.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(poolKey));
XAmount RollBackAddressBalance = kernel.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(addrKey));
XAmount RollBackMainBlockLinkTxBalance = blockchain.getBlockByHash(extraBlockList.get(10).getHash(), false).getInfo().getAmount();
- assertEquals("1000.00", RollBackPoolBalance.toDecimal(2, XUnit.XDAG).toString());//1000 - 100*3 = 700.00
- assertEquals("0.00", RollBackAddressBalance.toDecimal(2, XUnit.XDAG).toString());//100 - 0.1 = 99.90
- assertEquals("0.0" , RollBackMainBlockLinkTxBalance.toDecimal(1, XUnit.XDAG).toString());//A mainBlock link a TX get 1024 + 0.1 reward.
+ assertEquals("1000.00", RollBackPoolBalance.toDecimal(2, XUnit.XDAG).toString());//rollback 900 + 100 = 1000
+ assertEquals("0.00", RollBackAddressBalance.toDecimal(2, XUnit.XDAG).toString());//rollback 99.9 -99.9 = 0
+ assertEquals("0.0" , RollBackMainBlockLinkTxBalance.toDecimal(1, XUnit.XDAG).toString());//A mainBlock reward back 1024 - 1024 = 0.
//TODO:test wallet create txBlock with fee = 0,
@@ -371,6 +374,319 @@ public void testNew2NewTransactionBlock() {
}
+ @Test
+ public void DuplicateLink_Rollback(){
+ KeyPair addrKey = KeyPair.create(secretary_1, Sign.CURVE, Sign.CURVE_NAME);
+ KeyPair addrKey1 = KeyPair.create(secretary_2, Sign.CURVE, Sign.CURVE_NAME);
+ KeyPair poolKey = KeyPair.create(SampleKeys.SRIVATE_KEY, Sign.CURVE, Sign.CURVE_NAME);
+// Date date = fastDateFormat.parse("2020-09-20 23:45:00");
+ long generateTime = 1600616700000L;
+ // 1. first block
+ Block addressBlock = generateAddressBlock(config, addrKey, generateTime);
+ MockBlockchain blockchain = new MockBlockchain(kernel);
+ blockchain.getAddressStore().updateBalance(Keys.toBytesAddress(poolKey), XAmount.of(1000, XUnit.XDAG));
+ ImportResult result = blockchain.tryToConnect(addressBlock);
+ // import address block, result must be IMPORTED_BEST
+ assertSame(result, IMPORTED_BEST);
+ List pending = Lists.newArrayList();
+ List extraBlockList = Lists.newLinkedList();
+ Bytes32 ref = addressBlock.getHashLow(); //这个是链的创世区块
+ // 2. create 10 mainblocks
+ for (int i = 1; i <= 10; i++) {
+ generateTime += 64000L;
+ pending.clear();
+ pending.add(new Address(ref, XDAG_FIELD_OUT,false));//ref 为创世区块
+ pending.add(new Address(keyPair2Hash(wallet.getDefKey()),
+ XdagField.FieldType.XDAG_FIELD_COINBASE,
+ true));
+ long time = XdagTime.msToXdagtimestamp(generateTime);
+ long xdagTime = XdagTime.getEndOfEpoch(time);
+ Block extraBlock = generateExtraBlock(config, poolKey, xdagTime, pending);
+ result = blockchain.tryToConnect(extraBlock);
+ assertSame(result, IMPORTED_BEST);
+ assertChainStatus(i + 1, i - 1, 1, i < 2 ? 1 : 0, blockchain);
+ ref = extraBlock.getHashLow(); //更新ref为当前区块
+ extraBlockList.add(extraBlock);
+ }
+
+ //构造一笔交易,用于被两个块连续链接
+ Address from = new Address(BytesUtils.arrayToByte32(Keys.toBytesAddress(poolKey)), XDAG_FIELD_INPUT,true);
+ Address to = new Address(BytesUtils.arrayToByte32(Keys.toBytesAddress(addrKey)), XDAG_FIELD_OUTPUT,true);
+ long xdagTime = XdagTime.getEndOfEpoch(XdagTime.msToXdagtimestamp(generateTime));
+ Block txBlock = generateNewTransactionBlock(config, poolKey, xdagTime - 1, from, to, XAmount.of(100, XUnit.XDAG));
+
+
+ // 4. local check
+ assertTrue(blockchain.canUseInput(txBlock));
+ assertTrue(blockchain.checkMineAndAdd(txBlock));
+ // 5. remote check
+ assertTrue(blockchain.canUseInput(new Block(txBlock.getXdagBlock())));
+ assertTrue(blockchain.checkMineAndAdd(txBlock));
+ result = blockchain.tryToConnect(txBlock);
+ Block c = blockchain.getBlockByHash(txBlock.getHashLow(),true);
+ // import transaction block, result may be IMPORTED_NOT_BEST or IMPORTED_BEST
+ assertTrue(result == IMPORTED_NOT_BEST || result == IMPORTED_BEST);
+ // there is 12 blocks : 10 mainBlocks, 1 txBlock
+ assertChainStatus(12, 10, 1, 1, blockchain);
+
+
+ pending.clear();
+ Address TxblockAddress = new Address(txBlock.getHashLow(),false);
+ pending.add(TxblockAddress);
+ ref = extraBlockList.get(extraBlockList.size() - 1).getHashLow();
+ //高度 11 主块链接交易块,第一次
+ generateTime += 64000L;
+ pending.add(new Address(ref, XDAG_FIELD_OUT,false));
+ pending.add(new Address(keyPair2Hash(wallet.getDefKey()),
+ XdagField.FieldType.XDAG_FIELD_COINBASE,
+ true));
+ long time = XdagTime.msToXdagtimestamp(generateTime);
+ xdagTime = XdagTime.getEndOfEpoch(time);
+ Block extraBlock = generateExtraBlock(config, poolKey, xdagTime, pending);
+ blockchain.tryToConnect(extraBlock);
+ extraBlockList.add(extraBlock);
+ pending.clear();
+
+
+ List links = extraBlockList.get(10).getLinks();
+ Set linkset = new HashSet<>();
+ for (Address link : links){ //将主块的链接块都放进Hashset里面,用于确认链接了交易块
+ linkset.add(WalletUtils.toBase58(link.getAddress().slice(8, 20).toArray()));
+ }
+ //确认高度 11 主块链接了 交易块
+ assertTrue(linkset.contains(WalletUtils.toBase58(TxblockAddress.getAddress().slice(8, 20).toArray())));
+
+ //为高度12的去看构造一笔属于它的交易:
+ from = new Address(BytesUtils.arrayToByte32(Keys.toBytesAddress(poolKey)), XDAG_FIELD_INPUT,true);
+ Address to1 = new Address(BytesUtils.arrayToByte32(Keys.toBytesAddress(addrKey1)), XDAG_FIELD_OUTPUT,true);
+ Block txBlock1 = generateNewTransactionBlock(config, poolKey, xdagTime - 2, from, to1, XAmount.of(10, XUnit.XDAG));
+ assertTrue(blockchain.canUseInput(txBlock1));
+ assertTrue(blockchain.checkMineAndAdd(txBlock1));
+ // 5. remote check
+ assertTrue(blockchain.canUseInput(new Block(txBlock1.getXdagBlock())));
+ assertTrue(blockchain.checkMineAndAdd(txBlock1));
+ result = blockchain.tryToConnect(txBlock1);
+ // import transaction block, result may be IMPORTED_NOT_BEST or IMPORTED_BEST
+ assertTrue(result == IMPORTED_NOT_BEST || result == IMPORTED_BEST);
+
+ //高度 12 主块再次链接交易块,第二次
+ pending.add(TxblockAddress);
+ pending.add(new Address(txBlock1.getHashLow(),false));
+ ref = extraBlockList.get(extraBlockList.size() - 1).getHashLow();
+ for (int i = 1; i <= 16; i++) {
+ generateTime += 64000L;
+ pending.add(new Address(ref, XDAG_FIELD_OUT,false));
+ pending.add(new Address(keyPair2Hash(wallet.getDefKey()),
+ XdagField.FieldType.XDAG_FIELD_COINBASE,
+ true));
+ time = XdagTime.msToXdagtimestamp(generateTime);
+ xdagTime = XdagTime.getEndOfEpoch(time);
+ extraBlock = generateExtraBlock(config, poolKey, xdagTime, pending);
+ blockchain.tryToConnect(extraBlock);
+ ref = extraBlock.getHashLow();
+ extraBlockList.add(extraBlock);
+ pending.clear();
+ }
+ links = extraBlockList.get(11).getLinks();
+ linkset = new HashSet<>();
+ for (Address link : links){ //将主块的链接块都放进Hashset里面,用于确认链接了两个交易块
+ linkset.add(WalletUtils.toBase58(link.getAddress().slice(8, 20).toArray()));
+ }
+ //确认高度 12 主块链接了 两个交易块
+ assertTrue(linkset.contains(WalletUtils.toBase58(TxblockAddress.getAddress().slice(8, 20).toArray())));
+ assertTrue(linkset.contains(WalletUtils.toBase58(new Address(txBlock1.getHashLow(),false).getAddress().slice(8, 20).toArray())));
+ //16个块确认后,目前高度 11+16 = 27
+
+ //测试重复链接是否影响手续费收取
+ XAmount poolBalance = blockchain.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(poolKey));
+ XAmount addressBalance = kernel.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(addrKey));
+ XAmount addressBalance1 = kernel.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(addrKey1));
+ XAmount mainBlockLinkTxBalance = blockchain.getBlockByHash(extraBlockList.get(10).getHash(), false).getInfo().getAmount();
+
+ assertEquals("890.00", poolBalance.toDecimal(2, XUnit.XDAG).toString());//1000 - 100 - 10 = 890.00
+ assertEquals("99.90", addressBalance.toDecimal(2, XUnit.XDAG).toString());//100 - 0.1 = 99.90
+ assertEquals("9.90", addressBalance1.toDecimal(2, XUnit.XDAG).toString());//10 - 0.1 = 9.90
+ assertEquals("1024.1" , mainBlockLinkTxBalance.toDecimal(1, XUnit.XDAG).toString());//A mainBlock link a TX get 1024 + 0.1 reward.
+ XAmount mainBlockFee = kernel.getBlockStore().getBlockInfoByHash(extraBlockList.get(10).getHashLow()).getFee();
+ assertEquals("0.1",mainBlockFee.toDecimal(1, XUnit.XDAG).toString());
+
+ //重复连接的第12个主块,只有属于自己交易的手续费
+ XAmount mainBlock_doubleLink_Balance = blockchain.getBlockByHash(extraBlockList.get(11).getHash(), false).getInfo().getAmount();
+ assertEquals("1024.1" , mainBlock_doubleLink_Balance.toDecimal(1, XUnit.XDAG).toString());//double link will not get fee
+ XAmount mainBlock_doubleLink_Fee = kernel.getBlockStore().getBlockInfoByHash(extraBlockList.get(11).getHashLow()).getFee();
+ assertEquals("0.1",mainBlock_doubleLink_Fee.toDecimal(1, XUnit.XDAG).toString());
+
+ //TODO:回滚重复链接的第12个主块,
+ blockchain.unSetMain(extraBlockList.get(11));
+ poolBalance = blockchain.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(poolKey));
+ addressBalance = kernel.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(addrKey));
+ assertEquals("900.00", poolBalance.toDecimal(2, XUnit.XDAG).toString());//890 + 10 = 900, 只回滚自己的交易,不回滚别的主块的交易
+ assertEquals("99.90", addressBalance.toDecimal(2, XUnit.XDAG).toString());//99.90 -99.90 = 0 只回滚自己的交易,不回滚别的主块的交易
+ }
+
+ @Test
+ public void testTransaction_WithVariableFee() {
+ KeyPair addrKey = KeyPair.create(secretary_1, Sign.CURVE, Sign.CURVE_NAME);
+ KeyPair addrKey1 = KeyPair.create(secretary_2, Sign.CURVE, Sign.CURVE_NAME);
+ KeyPair poolKey = KeyPair.create(SampleKeys.SRIVATE_KEY, Sign.CURVE, Sign.CURVE_NAME);
+// Date date = fastDateFormat.parse("2020-09-20 23:45:00");
+ long generateTime = 1600616700000L;
+ // 1. first block
+ Block addressBlock = generateAddressBlock(config, addrKey, generateTime);
+ MockBlockchain blockchain = new MockBlockchain(kernel);
+ blockchain.getAddressStore().updateBalance(Keys.toBytesAddress(poolKey), XAmount.of(1000, XUnit.XDAG));
+ ImportResult result = blockchain.tryToConnect(addressBlock);
+ // import address block, result must be IMPORTED_BEST
+ assertSame(result, IMPORTED_BEST);
+ List pending = Lists.newArrayList();
+ List extraBlockList = Lists.newLinkedList();
+ Bytes32 ref = addressBlock.getHashLow();
+ // 2. create 10 mainblocks
+ for (int i = 1; i <= 10; i++) {
+ generateTime += 64000L;
+ pending.clear();
+ pending.add(new Address(ref, XDAG_FIELD_OUT,false));
+ pending.add(new Address(keyPair2Hash(wallet.getDefKey()),
+ XdagField.FieldType.XDAG_FIELD_COINBASE,
+ true));
+ long time = XdagTime.msToXdagtimestamp(generateTime);
+ long xdagTime = XdagTime.getEndOfEpoch(time);
+ Block extraBlock = generateExtraBlock(config, poolKey, xdagTime, pending);
+ result = blockchain.tryToConnect(extraBlock);
+ assertSame(result, IMPORTED_BEST);
+ assertChainStatus(i + 1, i - 1, 1, i < 2 ? 1 : 0, blockchain);
+ ref = extraBlock.getHashLow();
+ extraBlockList.add(extraBlock);
+ }
+
+ // 测试各种交易模式,手续费是可变的:make one transaction(100 XDAG) block(from No.1 mainblock to address block)
+ Address from = new Address(BytesUtils.arrayToByte32(Keys.toBytesAddress(poolKey)), XDAG_FIELD_INPUT,true);
+ Address to = new Address(BytesUtils.arrayToByte32(Keys.toBytesAddress(addrKey)), XDAG_FIELD_OUTPUT,true);
+ Address to1 = new Address(BytesUtils.arrayToByte32(Keys.toBytesAddress(addrKey1)), XDAG_FIELD_OUTPUT,true);
+ long xdagTime = XdagTime.getEndOfEpoch(XdagTime.msToXdagtimestamp(generateTime));
+ Block txBlock = generateNewTransactionBlock(config, poolKey, xdagTime - 1, from, to, XAmount.of(100, XUnit.XDAG), XAmount.of(10, XUnit.XDAG) ); //收10 Xdag 手续费
+
+ // 4. local check
+ assertTrue(blockchain.canUseInput(txBlock));
+ assertTrue(blockchain.checkMineAndAdd(txBlock));
+ // 5. remote check
+ assertTrue(blockchain.canUseInput(new Block(txBlock.getXdagBlock())));
+ assertTrue(blockchain.checkMineAndAdd(txBlock));
+
+ result = blockchain.tryToConnect(txBlock);
+ Block c = blockchain.getBlockByHash(txBlock.getHashLow(),true);
+ // import transaction block, result may be IMPORTED_NOT_BEST or IMPORTED_BEST
+ assertTrue(result == IMPORTED_NOT_BEST || result == IMPORTED_BEST);
+ // there is 12 blocks and 10 mainblocks
+ assertChainStatus(12, 10, 1, 1, blockchain);
+
+ pending.clear();
+ Address txAddress = new Address(txBlock.getHashLow(), false);
+ pending.add(txAddress);
+ ref = extraBlockList.get(extraBlockList.size() - 1).getHashLow();
+ // 4. confirm transaction block with 16 mainblocks
+ for (int i = 1; i <= 16; i++) {
+ generateTime += 64000L;
+ pending.add(new Address(ref, XDAG_FIELD_OUT,false));
+ pending.add(new Address(keyPair2Hash(wallet.getDefKey()),
+ XdagField.FieldType.XDAG_FIELD_COINBASE,
+ true));
+ long time = XdagTime.msToXdagtimestamp(generateTime);
+ xdagTime = XdagTime.getEndOfEpoch(time);
+ Block extraBlock = generateExtraBlock(config, poolKey, xdagTime, pending);
+ blockchain.tryToConnect(extraBlock);
+ ref = extraBlock.getHashLow();
+ extraBlockList.add(extraBlock);
+ pending.clear();
+ }
+
+ XAmount poolBalance = blockchain.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(poolKey));
+ XAmount addressBalance = kernel.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(addrKey));
+ XAmount mainBlockLinkTxBalance = blockchain.getBlockByHash(extraBlockList.get(10).getHash(), false).getInfo().getAmount();
+ assertEquals("900.00", poolBalance.toDecimal(2, XUnit.XDAG).toString());//1000 - 100 = 900.00
+ assertEquals("90.00", addressBalance.toDecimal(2, XUnit.XDAG).toString());//100 - 10 = 90.00
+ assertEquals("1034.0" , mainBlockLinkTxBalance.toDecimal(1, XUnit.XDAG).toString());//A mainBlock link a TX get 1024 + 10 reward.
+ XAmount mainBlockFee = kernel.getBlockStore().getBlockInfoByHash(extraBlockList.get(10).getHashLow()).getFee();
+ assertEquals("10.0",mainBlockFee.toDecimal(1, XUnit.XDAG).toString());
+
+// blockchain.unSetMain(extraBlockList.get(10));//test rollback
+//
+// XAmount RollBackPoolBalance = blockchain.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(poolKey));
+// XAmount RollBackAddressBalance = kernel.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(addrKey));
+// XAmount RollBackMainBlockLinkTxBalance = blockchain.getBlockByHash(extraBlockList.get(10).getHash(), false).getInfo().getAmount();
+// assertEquals("1000.00", RollBackPoolBalance.toDecimal(2, XUnit.XDAG).toString());//rollback 900 + 100 = 1000
+// assertEquals("0.00", RollBackAddressBalance.toDecimal(2, XUnit.XDAG).toString());//rollback 99.9 -99.9 = 0
+// assertEquals("0.0" , RollBackMainBlockLinkTxBalance.toDecimal(1, XUnit.XDAG).toString());//A mainBlock reward back 1024 - 1024 = 0.
+//
+//
+// //TODO:test wallet create txBlock with fee = 0,
+// List txList = Lists.newLinkedList();
+// for (int i = 1; i <= 10; i++) {
+// Block txBlock_0;
+// if (i == 1){//TODO:test give miners reward with a TX block :one input several output
+// txBlock_0 = generateMinerRewardTxBlock(config, poolKey, xdagTime - i, from, to,to1, XAmount.of(20,XUnit.XDAG),XAmount.of(10,XUnit.XDAG), XAmount.of(10,XUnit.XDAG));
+// }else {
+// txBlock_0 = generateWalletTransactionBlock(config, poolKey, xdagTime - i, from, to, XAmount.of(1,XUnit.XDAG));}
+//
+// assertEquals(XAmount.ZERO, txBlock_0.getFee());//fee is zero.
+// // 4. local check
+// assertTrue(blockchain.canUseInput(txBlock_0));
+// assertTrue(blockchain.checkMineAndAdd(txBlock_0));
+// // 5. remote check
+// assertTrue(blockchain.canUseInput(new Block(txBlock_0.getXdagBlock())));
+// assertTrue(blockchain.checkMineAndAdd(txBlock_0));
+//
+// result = blockchain.tryToConnect(txBlock_0);
+// // import transaction block, result may be IMPORTED_NOT_BEST or IMPORTED_BEST
+// assertTrue(result == IMPORTED_NOT_BEST || result == IMPORTED_BEST);
+// txList.add(txBlock_0);
+// }
+// pending.clear();
+// for (Block tx : txList) {
+// pending.add(new Address(tx.getHashLow(), false));
+// }
+// ref = extraBlockList.get(extraBlockList.size() - 1).getHashLow();
+// // 4. confirm transaction block with 16 mainblocks
+// for (int i = 1; i <= 16; i++) {
+// generateTime += 64000L;
+// pending.add(new Address(ref, XDAG_FIELD_OUT,false));
+// pending.add(new Address(keyPair2Hash(wallet.getDefKey()),
+// XdagField.FieldType.XDAG_FIELD_COINBASE,
+// true));
+// long time = XdagTime.msToXdagtimestamp(generateTime);
+// xdagTime = XdagTime.getEndOfEpoch(time);
+// Block extraBlock = generateExtraBlock(config, poolKey, xdagTime, pending);
+// blockchain.tryToConnect(extraBlock);
+// ref = extraBlock.getHashLow();
+// extraBlockList.add(extraBlock);
+// pending.clear();
+// }
+// XAmount poolBalance_0 = blockchain.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(poolKey));
+// XAmount addressBalance_0 = kernel.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(addrKey));
+// XAmount addressBalance_1 = kernel.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(addrKey1));
+// XAmount mainBlockLinkTxBalance_0 = blockchain.getBlockByHash(extraBlockList.get(26).getHash(), false).getInfo().getAmount();
+// assertEquals("971.00", poolBalance_0.toDecimal(2, XUnit.XDAG).toString());//1000 - 20 - 1*9 = 971.00
+// assertEquals("18.00", addressBalance_0.toDecimal(2, XUnit.XDAG).toString());//0 + (10-0.1) + (1 - 0.1) * 9 = 18 (ps:0.1 is fee)
+// assertEquals("9.90", addressBalance_1.toDecimal(2, XUnit.XDAG).toString());//0 + 10 - 0.1 = 9.90
+// assertEquals("1025.1" , mainBlockLinkTxBalance_0.toDecimal(1, XUnit.XDAG).toString());//A mainBlock link a TX get 1024 + 0.1*11 reward.
+// XAmount mainBlockFee_1 = kernel.getBlockStore().getBlockInfoByHash(extraBlockList.get(26).getHashLow()).getFee();
+// assertEquals("1.1",mainBlockFee_1.toDecimal(1, XUnit.XDAG).toString());
+//
+// //TODO:test rollback
+// blockchain.unSetMain(extraBlockList.get(26));
+//
+// XAmount RollBackPoolBalance_1 = blockchain.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(poolKey));
+// XAmount RollBackAddressBalance_0 = kernel.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(addrKey));
+// XAmount RollBackAddressBalance_1 = kernel.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(addrKey1));
+// XAmount RollBackMainBlockLinkTxBalance_1 = blockchain.getBlockByHash(extraBlockList.get(26).getHash(), false).getInfo().getAmount();
+// assertEquals("1000.00", RollBackPoolBalance_1.toDecimal(2, XUnit.XDAG).toString());//1000
+// assertEquals("0.00", RollBackAddressBalance_0.toDecimal(2, XUnit.XDAG).toString());//rollback is zero
+// assertEquals("0.00", RollBackAddressBalance_1.toDecimal(2, XUnit.XDAG).toString());
+// assertEquals("0.0" , RollBackMainBlockLinkTxBalance_1.toDecimal(1, XUnit.XDAG).toString());// rollback is zero
+
+ }
+
+
@Test
public void testNew2NewTxAboutRejected() {
KeyPair addrKey = KeyPair.create(secretary_1, Sign.CURVE, Sign.CURVE_NAME);
From 4ae0f8eeea6a270b2be30ebb9f797a89939fed85 Mon Sep 17 00:00:00 2001
From: June <2571240520@qq.com>
Date: Sat, 20 Apr 2024 15:32:57 +0800
Subject: [PATCH 2/2] Optimized some sync bugs and improved synchronization
speed; Now a full used single sync thread will consume 3 Mbps.
---
.../java/io/xdag/config/AbstractConfig.java | 2 +-
.../java/io/xdag/config/spec/NodeSpec.java | 2 +-
.../java/io/xdag/core/BlockchainImpl.java | 1 +
src/main/java/io/xdag/net/XdagP2pHandler.java | 8 ++---
.../io/xdag/net/message/MessageQueue.java | 29 +++++++++----------
5 files changed, 20 insertions(+), 22 deletions(-)
diff --git a/src/main/java/io/xdag/config/AbstractConfig.java b/src/main/java/io/xdag/config/AbstractConfig.java
index 8582e8e4..5e636b8f 100644
--- a/src/main/java/io/xdag/config/AbstractConfig.java
+++ b/src/main/java/io/xdag/config/AbstractConfig.java
@@ -80,7 +80,7 @@ public class AbstractConfig implements Config, AdminSpec, NodeSpec, WalletSpec,
protected int netMaxOutboundConnections = 128;
protected int netMaxInboundConnections = 512;
protected int netMaxInboundConnectionsPerIp = 5;
- protected int netMaxMessageQueueSize = 4096;
+// protected int netMaxMessageQueueSize = 4096;
protected int netMaxFrameBodySize = 128 * 1024;
protected int netMaxPacketSize = 16 * 1024 * 1024;
protected int netRelayRedundancy = 8;
diff --git a/src/main/java/io/xdag/config/spec/NodeSpec.java b/src/main/java/io/xdag/config/spec/NodeSpec.java
index d0a28c17..7b95843b 100644
--- a/src/main/java/io/xdag/config/spec/NodeSpec.java
+++ b/src/main/java/io/xdag/config/spec/NodeSpec.java
@@ -44,7 +44,7 @@ public interface NodeSpec {
int getWaitEpoch();
- int getNetMaxMessageQueueSize();
+// int getNetMaxMessageQueueSize();
int getNetHandshakeExpiry();
diff --git a/src/main/java/io/xdag/core/BlockchainImpl.java b/src/main/java/io/xdag/core/BlockchainImpl.java
index 8be5a81d..a8572642 100644
--- a/src/main/java/io/xdag/core/BlockchainImpl.java
+++ b/src/main/java/io/xdag/core/BlockchainImpl.java
@@ -866,6 +866,7 @@ public XAmount unApplyBlock(Block block) {
for (Address link : links) {
if (!link.isAddress) {
Block ref = getBlockByHash(link.getAddress(), false);
+ //even mainBlock duplicate link the TX_block which other mainBlock is handled, we could check the TX ref if this mainBlock.
if (ref.getInfo().getRef() != null
&& equalBytes(ref.getInfo().getRef(), block.getHashLow().toArray())
&& ((ref.getInfo().flags & BI_MAIN_REF) != 0)) {
diff --git a/src/main/java/io/xdag/net/XdagP2pHandler.java b/src/main/java/io/xdag/net/XdagP2pHandler.java
index a8af0a18..07a9398d 100644
--- a/src/main/java/io/xdag/net/XdagP2pHandler.java
+++ b/src/main/java/io/xdag/net/XdagP2pHandler.java
@@ -338,10 +338,10 @@ private ReasonCode checkPeer(Peer peer, boolean newHandShake) {
// }
// validator can't share IP address
- if (channelMgr.isActiveIP(channel.getRemoteIp()) // already connected
- && nodeSpec.getNetwork() == Network.MAINNET) { // on main net
- return ReasonCode.VALIDATOR_IP_LIMITED;
- }
+// if (channelMgr.isActiveIP(channel.getRemoteIp()) // already connected
+// && nodeSpec.getNetwork() == Network.MAINNET) { // on main net
+// return ReasonCode.VALIDATOR_IP_LIMITED;
+// }
return null;
}
diff --git a/src/main/java/io/xdag/net/message/MessageQueue.java b/src/main/java/io/xdag/net/message/MessageQueue.java
index 0e647fbf..ceee7e84 100644
--- a/src/main/java/io/xdag/net/message/MessageQueue.java
+++ b/src/main/java/io/xdag/net/message/MessageQueue.java
@@ -30,11 +30,7 @@
import io.netty.channel.ChannelHandlerContext;
import io.xdag.config.Config;
import java.util.Queue;
-import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import io.xdag.net.message.p2p.DisconnectMessage;
@@ -50,8 +46,8 @@ public class MessageQueue {
.daemon(true)
.build());
private final Config config;
-
- private final Queue queue = new ConcurrentLinkedQueue<>();
+ //'8192' is a value obtained from testing experience, not a standard value.Looking forward to optimization.
+ private final BlockingQueue queue = new LinkedBlockingQueue<>(8192);
private final Queue prioritized = new ConcurrentLinkedQueue<>();
private ChannelHandlerContext ctx;
private ScheduledFuture> timerTask;
@@ -95,18 +91,18 @@ public void disconnect(ReasonCode code) {
}
}
- public boolean sendMessage(Message msg) {
- if (size() >= config.getNodeSpec().getNetMaxMessageQueueSize()) {
- disconnect(ReasonCode.MESSAGE_QUEUE_FULL);
- return false;
- }
-
+ public void sendMessage(Message msg) {
+ //when full message queue, whitelist don't need to disconnect.
if (config.getNodeSpec().getNetPrioritizedMessages().contains(msg.getCode())) {
prioritized.add(msg);
} else {
- queue.add(msg);
+ try {
+ //update to BlockingQueue, capacity 8192
+ queue.put(msg);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
}
- return true;
}
public int size() {
@@ -114,7 +110,8 @@ public int size() {
}
private void nudgeQueue() {
- int n = Math.min(5, size());
+ //Increase bandwidth consumption of a full used single sync thread to 3 Mbps.
+ int n = Math.min(8, size());
if (n == 0) {
return;
}