Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX:TX block become main block. #310

Merged
merged 3 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/main/java/io/xdag/core/BlockchainImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
14 changes: 14 additions & 0 deletions src/test/java/io/xdag/BlockBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,20 @@ public static Block generateOldTransactionBlock(Config config, KeyPair key, long
b.signOut(key);
return b;
}

public static Block generateOldTransactionBlock(Config config, KeyPair key, long xdagTime, Address from, XAmount amount,Address to,
XAmount amount1, Address to1, XAmount amount2) {
List<Address> refs = Lists.newArrayList();
List<KeyPair> keys = Lists.newArrayList();
refs.add(new Address(from.getAddress(), XDAG_FIELD_IN, amount,false)); // key1
refs.add(new Address(to.getAddress(), XDAG_FIELD_OUTPUT, amount1,true));
refs.add(new Address(to1.getAddress(), XDAG_FIELD_OUTPUT, amount2,true));
keys.add(key);
Block b = new Block(config, xdagTime, refs, null, false, keys, null, 0,XAmount.of(100,XUnit.MILLI_XDAG)); // orphan
b.signOut(key);
return b;
}

public static Block generateNewTransactionBlock(Config config, KeyPair key, long xdagTime, Address from, Address to,
XAmount amount) {
List<Address> refs = Lists.newArrayList();
Expand Down
114 changes: 114 additions & 0 deletions src/test/java/io/xdag/core/BlockchainTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import io.xdag.Wallet;
import io.xdag.config.Config;
import io.xdag.config.DevnetConfig;
import io.xdag.crypto.Hash;
import io.xdag.crypto.Keys;
import io.xdag.crypto.SampleKeys;
import io.xdag.crypto.Sign;
Expand All @@ -42,10 +43,12 @@
import io.xdag.utils.WalletUtils;
import io.xdag.utils.XdagTime;
import lombok.extern.slf4j.Slf4j;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SECPPrivateKey;
import org.bouncycastle.util.encoders.Hex;
import org.hyperledger.besu.crypto.SECPSignature;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
Expand Down Expand Up @@ -686,6 +689,117 @@ 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, poolKey, 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<Address> pending = Lists.newArrayList();
List<Block> extraBlockList = Lists.newLinkedList();

Address from = new Address(addressBlock.getHashLow(), XDAG_FIELD_IN, false);
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 = generateOldTransactionBlock(config, poolKey, xdagTime, from, XAmount.of(100, XUnit.XDAG), to, XAmount.of(30, XUnit.XDAG), to1, 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.getBlockByHash(addressBlock.getHash(), false).getInfo().getAmount();
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);
}

from = new Address(TxBlockTobeMain.getHashLow(), XDAG_FIELD_IN, false);

xdagTime = XdagTime.getEndOfEpoch(XdagTime.msToXdagtimestamp(generateTime));
Block txBlock = generateOldTransactionBlock(config, poolKey, xdagTime - 1, from, to, XAmount.of(1000, 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 and 10 mainblocks

pending.clear();
pending.add(new Address(txBlock.getHashLow(), false));
ref = extraBlockList.get(extraBlockList.size() - 1).getHashLow();
// 4. confirm transaction block with 3 mainblocks
for (int i = 1; i <= 4; 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 TXBalance = blockchain.getBlockByHash(TxBlockTobeMain.getHash(), false).getInfo().getAmount();
assertEquals("24.2", TXBalance.toDecimal(1, XUnit.XDAG).toString());
addressBalance = kernel.getAddressStore().getBalanceByAddress(Keys.toBytesAddress(addrKey));
assertEquals("1029.80", addressBalance.toDecimal(2, XUnit.XDAG).toString());


// 输出签名只有一个
SECPSignature signature = TxBlockTobeMain.getOutsig();
byte[] publicKeyBytes = poolKey.getPublicKey().asEcPoint(Sign.CURVE).getEncoded(true);
Bytes digest = Bytes.wrap(TxBlockTobeMain.getSubRawData(TxBlockTobeMain.getOutsigIndex() - 2), Bytes.wrap(publicKeyBytes));
Bytes32 hash = Hash.hashTwice(Bytes.wrap(digest));
// use hyperledger besu crypto native secp256k1
assertTrue(Sign.SECP256K1.verify(hash, signature, poolKey.getPublicKey()));

}



@Test
public void testNew2NewTxAboutRejected() {
Expand Down
Loading