From a429fa4d0f0d4626ab16c2f2a7ae9186693b9e36 Mon Sep 17 00:00:00 2001 From: June <2571240520@qq.com> Date: Tue, 23 Apr 2024 19:11:04 +0800 Subject: [PATCH] Fix bug: TX become a main block due to huge difficulty, the fee is charged to itself. --- .../java/io/xdag/core/BlockchainImpl.java | 6 +- .../java/io/xdag/core/BlockchainTest.java | 74 +++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/xdag/core/BlockchainImpl.java b/src/main/java/io/xdag/core/BlockchainImpl.java index a8572642..efff211c 100644 --- a/src/main/java/io/xdag/core/BlockchainImpl.java +++ b/src/main/java/io/xdag/core/BlockchainImpl.java @@ -895,7 +895,11 @@ public void setMain(Block block) { xdagStats.nmain++; // 递归执行主块引用的区块 并获取手续费 - applyBlock(true, block); + XAmount mainBlockFee = applyBlock(true, block); //the mainBlock may have tx, return the fee to itself. + if (!mainBlockFee.equals(XAmount.ZERO)) {// normal mainBlock will not go into this + acceptAmount(block, mainBlockFee); //add the fee + block.getInfo().setFee(mainBlockFee); + } // 主块REF指向自身 // TODO:补充手续费 updateBlockRef(block, new Address(block)); diff --git a/src/test/java/io/xdag/core/BlockchainTest.java b/src/test/java/io/xdag/core/BlockchainTest.java index d4b0c3f3..77d658eb 100644 --- a/src/test/java/io/xdag/core/BlockchainTest.java +++ b/src/test/java/io/xdag/core/BlockchainTest.java @@ -686,6 +686,80 @@ public void testTransaction_WithVariableFee() { } + @Test + public void testIfTxBlockTobeMain() { + 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(); + + 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 TxBlockTobeMain = generateMinerRewardTxBlock(config, poolKey, xdagTime, from, to,to1, XAmount.of(100,XUnit.XDAG),XAmount.of(30,XUnit.XDAG), XAmount.of(70,XUnit.XDAG)); + result = blockchain.tryToConnect(TxBlockTobeMain); + assertTrue(result == IMPORTED_NOT_BEST || result == IMPORTED_BEST); + + blockchain.setMain(TxBlockTobeMain);// set the tx block as mainBlock. + + 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 TxBlockAward =TxBlockTobeMain.getInfo().getAmount(); + + assertEquals("900.00", poolBalance.toDecimal(2, XUnit.XDAG).toString());//1000 - 100 = 900.00 + assertEquals("29.90", addressBalance.toDecimal(2, XUnit.XDAG).toString()); + assertEquals("69.90", addressBalance1.toDecimal(2, XUnit.XDAG).toString()); + + //Tx block get mainBlock reward 1024 , and get itself fee reward 0.2 + assertEquals("1024.2" , TxBlockAward.toDecimal(1, XUnit.XDAG).toString()); + assertEquals("0.2" , TxBlockTobeMain.getFee().toDecimal(1, XUnit.XDAG).toString()); + Bytes32 ref = TxBlockTobeMain.getHashLow(); + // 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); + xdagTime = XdagTime.getEndOfEpoch(time); + Block extraBlock = generateExtraBlock(config, poolKey, xdagTime, pending); + result = blockchain.tryToConnect(extraBlock); + assertSame(result, IMPORTED_BEST); + ref = extraBlock.getHashLow(); + extraBlockList.add(extraBlock); + } + // rollback this TX mainBlock, + blockchain.unSetMain(TxBlockTobeMain); + + + poolBalance = blockchain.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(poolKey)); + addressBalance = kernel.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(addrKey)); + addressBalance1 = kernel.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(addrKey1)); + TxBlockAward =TxBlockTobeMain.getInfo().getAmount(); + //tx will be rollback, reward will set 0 + assertEquals("1000.00", poolBalance.toDecimal(2, XUnit.XDAG).toString()); + assertEquals("0.00", addressBalance.toDecimal(2, XUnit.XDAG).toString()); + assertEquals("0.00", addressBalance1.toDecimal(2, XUnit.XDAG).toString()); + + assertEquals("0.0" , TxBlockAward.toDecimal(1, XUnit.XDAG).toString()); + } + + @Test public void testNew2NewTxAboutRejected() {