diff --git a/src/main/java/io/xdag/Kernel.java b/src/main/java/io/xdag/Kernel.java
index 1cc86379..35aa5b0f 100644
--- a/src/main/java/io/xdag/Kernel.java
+++ b/src/main/java/io/xdag/Kernel.java
@@ -45,6 +45,7 @@
import io.xdag.net.message.MessageQueue;
import io.xdag.net.NetDB;
import io.xdag.net.node.NodeManager;
+import io.xdag.net.websocket.WebSocketServer;
import io.xdag.rpc.Web3;
import io.xdag.rpc.Web3Impl;
import io.xdag.rpc.cors.CorsConfiguration;
@@ -94,6 +95,7 @@ public class Kernel {
protected byte[] firstAccount;
protected Block firstBlock;
+ protected WebSocketServer webSocketServer;
protected XdagState xdagState;
protected AtomicInteger channelsAccount = new AtomicInteger(0);
@@ -206,7 +208,7 @@ public synchronized void testStart() throws Exception {
// 如果是第一次启动,则新建一个创世块
if (xdagStats.getOurLastBlockHash() == null) {
firstAccount = Keys.toBytesAddress(wallet.getDefKey().getPublicKey());
- firstBlock = new Block(config, XdagTime.getCurrentTimestamp(), null, null, false, null, null, -1);
+ firstBlock = new Block(config, XdagTime.getCurrentTimestamp(), null, null, false, null, null, -1, XAmount.ZERO);
firstBlock.signOut(wallet.getDefKey());
xdagStats.setOurLastBlockHash(firstBlock.getHashLow().toArray());
if (xdagStats.getGlobalMiner() == null) {
@@ -279,6 +281,10 @@ public synchronized void testStart() throws Exception {
syncMgr.start();
log.info("SyncManager start...");
+ // ====================================
+ // set up pool websocket channel
+ // ====================================
+ getWsServer().start();
// ====================================
// pow
// ====================================
@@ -338,6 +344,13 @@ private JsonRpcWeb3ServerHandler getJsonRpcWeb3ServerHandler() {
return jsonRpcWeb3ServerHandler;
}
+ private WebSocketServer getWsServer(){
+ if (webSocketServer == null) {
+ webSocketServer = new WebSocketServer(config.getPoolIP(), config.getPoolTag(), config.getWebsocketServerPort());
+ }
+ return webSocketServer;
+ }
+
private Web3WebSocketServer getWeb3WebSocketServer() throws UnknownHostException {
if (web3WebSocketServer == null) {
JsonRpcSerializer jsonRpcSerializer = getJsonRpcSerializer();
diff --git a/src/main/java/io/xdag/Wallet.java b/src/main/java/io/xdag/Wallet.java
index d9603e04..c32bb552 100644
--- a/src/main/java/io/xdag/Wallet.java
+++ b/src/main/java/io/xdag/Wallet.java
@@ -31,11 +31,8 @@
import com.google.common.collect.Lists;
import io.xdag.config.Config;
-import io.xdag.core.Address;
-import io.xdag.core.Block;
-import io.xdag.core.BlockWrapper;
+import io.xdag.core.*;
import io.xdag.utils.SimpleEncoder;
-import io.xdag.core.XAmount;
import io.xdag.crypto.Aes;
import io.xdag.crypto.Bip32ECKeyPair;
import io.xdag.crypto.Keys;
@@ -605,7 +602,7 @@ private Block createNewBlock(Map
pairs, List to,
long sendTime = XdagTime.getCurrentTimestamp();
- return new Block(getConfig(), sendTime, all, null, false, keys, remark, defKeyIndex);
+ return new Block(getConfig(), sendTime, all, null, false, keys, remark, defKeyIndex, XAmount.of(100, XUnit.MILLI_XDAG));
}
diff --git a/src/main/java/io/xdag/cli/Commands.java b/src/main/java/io/xdag/cli/Commands.java
index a4b6e64a..a16d01f8 100644
--- a/src/main/java/io/xdag/cli/Commands.java
+++ b/src/main/java/io/xdag/cli/Commands.java
@@ -30,6 +30,7 @@
import io.xdag.Kernel;
import io.xdag.core.*;
import io.xdag.net.Channel;
+import io.xdag.net.websocket.ChannelSupervise;
import io.xdag.utils.BasicUtils;
import io.xdag.utils.BytesUtils;
import io.xdag.utils.XdagTime;
@@ -306,7 +307,7 @@ private List createTransactionBlock(Map ourKeys,
private BlockWrapper createTransaction(Bytes32 to, XAmount amount, Map keys, String remark) {
List tos = Lists.newArrayList(new Address(to, XDAG_FIELD_OUTPUT, amount, true));
- Block block = kernel.getBlockchain().createNewBlock(new HashMap<>(keys), tos, false, remark);
+ Block block = kernel.getBlockchain().createNewBlock(new HashMap<>(keys), tos, false, remark, XAmount.of(100,XUnit.MILLI_XDAG));
if (block == null) {
return null;
@@ -462,6 +463,11 @@ public String printBlockInfo(Block block, boolean raw) {
if (getStateByFlags(block.getInfo().getFlags()).equals(MAIN.getDesc()) && block.getInfo().getHeight() > kernel.getConfig().getSnapshotSpec().getSnapshotHeight()) {
tx.append(String.format(" earn: %s %s %s%n", hash2Address(block.getHashLow()),
kernel.getBlockchain().getReward(block.getInfo().getHeight()).toDecimal(9, XUnit.XDAG).toPlainString(),
+ FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss.SSS")
+ .format(XdagTime.xdagTimestampToMs(block.getTimestamp()))))
+ .append(String.format("fee earn: %s %s %s%n", hash2Address(block.getHashLow()),
+ block.getInfo().getAmount().equals(XAmount.ZERO) ? XAmount.ZERO.toString() :
+ block.getInfo().getAmount().subtract(kernel.getBlockchain().getReward(block.getInfo().getHeight())).toDecimal(9, XUnit.XDAG).toPlainString(),
FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss.SSS")
.format(XdagTime.xdagTimestampToMs(block.getTimestamp()))));
}
@@ -502,7 +508,9 @@ public String printBlockInfo(Block block, boolean raw) {
hash2Address(block.getHash()), block.getInfo().getAmount().toDecimal(9, XUnit.XDAG).toPlainString(),
// fee目前为0
block.getInfo().getRef() == null ? "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" : hash2Address(Bytes32.wrap(block.getInfo().getRef())),
- XAmount.ZERO.toDecimal(9, XUnit.XDAG).toPlainString()
+ block.getInfo().getRef() == null ? XAmount.ZERO.toDecimal(9, XUnit.XDAG).toPlainString() :
+ (block.getFee().equals(XAmount.ZERO) ? XAmount.of(100,XUnit.MILLI_XDAG).multiply(block.getOutputs().size()).toDecimal(9,XUnit.XDAG).toPlainString() :
+ block.getFee().multiply(block.getOutputs().size()).toDecimal(9,XUnit.XDAG).toPlainString())
)
+ "\n"
+ (inputs == null ? "" : inputs.toString()) + (outputs == null ? "" : outputs.toString())
@@ -567,6 +575,10 @@ public String listConnect() {
return stringBuilder.toString();
}
+ public String pool(){
+ return ChannelSupervise.showChannel();
+ }
+
public String keygen()
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException {
kernel.getXdagState().tempSet(XdagState.KEYS);
diff --git a/src/main/java/io/xdag/cli/Shell.java b/src/main/java/io/xdag/cli/Shell.java
index 6f93ebfa..31e7a75b 100644
--- a/src/main/java/io/xdag/cli/Shell.java
+++ b/src/main/java/io/xdag/cli/Shell.java
@@ -78,7 +78,7 @@ public Shell() {
commandExecute.put("stats", new CommandMethods(this::processStats, this::defaultCompleter));
commandExecute.put("xfer", new CommandMethods(this::processXfer, this::defaultCompleter));
commandExecute.put("xfertonew", new CommandMethods(this::processXferToNew, this::defaultCompleter));
-// commandExecute.put("miners", new CommandMethods(this::processMiners, this::defaultCompleter));
+ commandExecute.put("pool", new CommandMethods(this::processPool, this::defaultCompleter));
// commandExecute.put("run", new CommandMethods(this::processRun, this::defaultCompleter));
commandExecute.put("keygen", new CommandMethods(this::processKeygen, this::defaultCompleter));
commandExecute.put("net", new CommandMethods(this::processNet, this::defaultCompleter));
@@ -396,6 +396,23 @@ private void processXfer(CommandInput input) {
}
}
+ private void processPool(CommandInput input){
+ final String[] usage = {
+ "pool - for pool, print list of recent connected pool",
+ "Usage: pool ",
+ " -? --help Show help",
+ };
+ try {
+ Options opt = parseOptions(usage, input.args());
+ if (opt.isSet("help")) {
+ throw new Options.HelpException(opt.usage());
+ }
+ println(commands.pool());
+ } catch (Exception e) {
+ saveException(e);
+ }
+ }
+
private void processKeygen(CommandInput input) {
final String[] usage = {
"keygen - generate new private/public key pair and set it by default",
diff --git a/src/main/java/io/xdag/config/AbstractConfig.java b/src/main/java/io/xdag/config/AbstractConfig.java
index 4baa0ac3..14608189 100644
--- a/src/main/java/io/xdag/config/AbstractConfig.java
+++ b/src/main/java/io/xdag/config/AbstractConfig.java
@@ -67,6 +67,13 @@ public class AbstractConfig implements Config, AdminSpec, NodeSpec, WalletSpec,
protected int telnetPort = 7001;
protected String telnetPassword;
+ // =========================
+ // Pool websocket spec
+ // =========================
+ protected String poolIp;
+ protected int WebsocketServerPort;
+ protected String poolTag;
+
protected int maxShareCountPerChannel = 20;
protected int awardEpoch = 0xf;
protected int waitEpoch = 20;
@@ -245,6 +252,10 @@ public void getSetting() {
telnetPort = config.hasPath("admin.telnet.port")?config.getInt("admin.telnet.port"):6001;
telnetPassword = config.getString("admin.telnet.password");
+ poolIp = config.hasPath("pool.ip")?config.getString("pool.ip"):"127.0.0.1";
+ WebsocketServerPort = config.hasPath("pool.ws.port")?config.getInt("pool.ws.port"):7001;
+ poolTag = config.hasPath("pool.tag")?config.getString("pool.tag"):"xdagj";
+
nodeIp = config.hasPath("node.ip")?config.getString("node.ip"):"127.0.0.1";
nodePort = config.hasPath("node.port")?config.getInt("node.port"):8001;
nodeTag = config.hasPath("node.tag")?config.getString("node.tag"):"xdagj";
@@ -373,6 +384,13 @@ public List getRpcModules() {
return modules;
}
+ @Override
+ public String getPoolIP(){return poolIp;}
+ @Override
+ public int getWebsocketServerPort() {return WebsocketServerPort;}
+ @Override
+ public String getPoolTag(){return poolTag;}
+
@Override
public boolean isRPCEnabled() {
return rpcEnabled;
diff --git a/src/main/java/io/xdag/config/Config.java b/src/main/java/io/xdag/config/Config.java
index de9a9ea9..b318cef0 100644
--- a/src/main/java/io/xdag/config/Config.java
+++ b/src/main/java/io/xdag/config/Config.java
@@ -95,4 +95,12 @@ public interface Config {
boolean getEnableGenerateBlock();
long getTxPageSizeLimit();
+
+ //websocket
+ String getPoolIP();
+
+ int getWebsocketServerPort();
+
+ String getPoolTag();
+
}
diff --git a/src/main/java/io/xdag/config/Constants.java b/src/main/java/io/xdag/config/Constants.java
index eee651fb..7875eeac 100644
--- a/src/main/java/io/xdag/config/Constants.java
+++ b/src/main/java/io/xdag/config/Constants.java
@@ -24,6 +24,8 @@
package io.xdag.config;
+import io.xdag.core.XAmount;
+import io.xdag.core.XUnit;
import org.apache.tuweni.units.bigints.UInt64;
public class Constants {
@@ -95,4 +97,6 @@ public enum MessageType {
public static final short TESTNET_VERSION = 0;
public static final short DEVNET_VERSION = 0;
+ public static final XAmount minGas = XAmount.of(100, XUnit.MILLI_XDAG);
+
}
diff --git a/src/main/java/io/xdag/consensus/XdagPow.java b/src/main/java/io/xdag/consensus/XdagPow.java
index 8c76b432..44179012 100644
--- a/src/main/java/io/xdag/consensus/XdagPow.java
+++ b/src/main/java/io/xdag/consensus/XdagPow.java
@@ -28,12 +28,7 @@
import static io.xdag.utils.BytesUtils.equalBytes;
import io.xdag.Kernel;
-import io.xdag.core.Block;
-import io.xdag.core.BlockWrapper;
-import io.xdag.core.Blockchain;
-import io.xdag.core.XdagBlock;
-import io.xdag.core.XdagField;
-import io.xdag.core.XdagState;
+import io.xdag.core.*;
import io.xdag.crypto.Hash;
import io.xdag.listener.BlockMessage;
import io.xdag.listener.Listener;
@@ -181,7 +176,7 @@ public void newBlock() {
public Block generateRandomXBlock(long sendTime) {
- Block block = blockchain.createNewBlock(null, null, true, null);
+ Block block = blockchain.createNewBlock(null, null, true, null, XAmount.ZERO);
block.signOut(kernel.getWallet().getDefKey());
minShare.set(Bytes32.wrap(RandomUtils.nextBytes(32)));
@@ -192,7 +187,7 @@ public Block generateRandomXBlock(long sendTime) {
}
public Block generateBlock(long sendTime) {
- Block block = blockchain.createNewBlock(null, null, true, null);
+ Block block = blockchain.createNewBlock(null, null, true, null, XAmount.ZERO);
block.signOut(kernel.getWallet().getDefKey());
minShare.set(Bytes32.wrap(RandomUtils.nextBytes(32)));
diff --git a/src/main/java/io/xdag/core/Block.java b/src/main/java/io/xdag/core/Block.java
index 88bc4ba1..1930ee93 100644
--- a/src/main/java/io/xdag/core/Block.java
+++ b/src/main/java/io/xdag/core/Block.java
@@ -63,7 +63,6 @@
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SECPPublicKey;
import org.hyperledger.besu.crypto.SECPSignature;
-
import com.google.common.collect.Lists;
@Slf4j
@@ -122,11 +121,12 @@ public Block(
boolean mining,
List keys,
String remark,
- int defKeyIndex) {
+ int defKeyIndex,
+ XAmount fee) {
parsed = true;
info = new BlockInfo();
this.info.setTimestamp(timestamp);
- this.info.setFee(0);
+ this.info.setFee(fee);
int lenghth = 0;
setType(config.getXdagFieldHeader(), lenghth++);
@@ -206,7 +206,7 @@ public Block(
public Block(Config config, long timestamp,
List pendings,
boolean mining) {
- this(config, timestamp, null, pendings, mining, null, null, -1);
+ this(config, timestamp, null, pendings, mining, null, null, -1, XAmount.ZERO);
}
/**
@@ -257,7 +257,7 @@ public void parse() {
this.transportHeader = header.getLong(0, ByteOrder.LITTLE_ENDIAN);
this.info.type = header.getLong(8, ByteOrder.LITTLE_ENDIAN);
this.info.setTimestamp(header.getLong(16, ByteOrder.LITTLE_ENDIAN));
- this.info.setFee(header.getLong(24, ByteOrder.LITTLE_ENDIAN));
+ this.info.setFee(XAmount.of(header.getLong(24, ByteOrder.LITTLE_ENDIAN), XUnit.NANO_XDAG));
for (int i = 1; i < XdagBlock.XDAG_BLOCK_FIELDS; i++) {
XdagField field = xdagBlock.getField(i);
if (field == null) {
@@ -375,7 +375,8 @@ private byte[] getEncodedBody() {
}
private byte[] getEncodedHeader() {
- byte[] fee = BytesUtils.longToBytes(getFee(), true);
+ //byte[] fee = BytesUtils.longToBytes(getFee(), true);
+ byte[] fee = BytesUtils.longToBytes(Long.parseLong(getFee().toString()), true);
byte[] time = BytesUtils.longToBytes(getTimestamp(), true);
byte[] type = BytesUtils.longToBytes(getType(), true);
byte[] transport = new byte[8];
@@ -510,7 +511,7 @@ public long getType() {
return this.info.type;
}
- public long getFee() {
+ public XAmount getFee() {
return this.info.getFee();
}
diff --git a/src/main/java/io/xdag/core/BlockInfo.java b/src/main/java/io/xdag/core/BlockInfo.java
index 8a761172..490552de 100644
--- a/src/main/java/io/xdag/core/BlockInfo.java
+++ b/src/main/java/io/xdag/core/BlockInfo.java
@@ -41,7 +41,7 @@ public class BlockInfo {
private BigInteger difficulty;
private byte[] ref;
private byte[] maxDiffLink;
- private long fee;
+ private XAmount fee = XAmount.ZERO;
private byte[] remark;
private byte[] hash;
private byte[] hashlow;
@@ -64,7 +64,7 @@ public String toString() {
", ref=" + Arrays.toString(ref) +
", maxDiffLink=" + Arrays.toString(maxDiffLink) +
", flags=" + Integer.toHexString(flags) +
- ", fee=" + fee +
+ ", fee=" + fee.toString() +
", timestamp=" + timestamp +
", remark=" + Arrays.toString(remark) +
", isSnapshot=" + isSnapshot +
diff --git a/src/main/java/io/xdag/core/Blockchain.java b/src/main/java/io/xdag/core/Blockchain.java
index 0d727fec..9ec78315 100644
--- a/src/main/java/io/xdag/core/Blockchain.java
+++ b/src/main/java/io/xdag/core/Blockchain.java
@@ -39,7 +39,7 @@ public interface Blockchain {
ImportResult tryToConnect(Block block);
- Block createNewBlock(Map pairs, List to, boolean mining, String remark);
+ Block createNewBlock(Map pairs, List to, boolean mining, String remark, XAmount fee);
Block getBlockByHash(Bytes32 hash, boolean isRaw);
diff --git a/src/main/java/io/xdag/core/BlockchainImpl.java b/src/main/java/io/xdag/core/BlockchainImpl.java
index ef20a0cd..fd39da00 100644
--- a/src/main/java/io/xdag/core/BlockchainImpl.java
+++ b/src/main/java/io/xdag/core/BlockchainImpl.java
@@ -81,6 +81,7 @@
@Getter
public class BlockchainImpl implements Blockchain {
+ private static XAmount sumGas = XAmount.ZERO;
private static final ThreadFactory factory = new BasicThreadFactory.Builder()
.namingPattern("check-main-%d")
.daemon(true)
@@ -112,6 +113,7 @@ public class BlockchainImpl implements Blockchain {
private SnapshotStore snapshotStore;
private SnapshotStore snapshotAddressStore;
private final XdagExtStats xdagExtStats;
+// public Filter filter;
@Getter
private byte[] preSeed;
@@ -125,6 +127,7 @@ public BlockchainImpl(Kernel kernel) {
this.orphanBlockStore = kernel.getOrphanBlockStore();
this.txHistoryStore = kernel.getTxHistoryStore();
snapshotHeight = kernel.getConfig().getSnapshotSpec().getSnapshotHeight();
+// this.filter = new Filter(blockStore);
// 2. if enable snapshot, init snapshot from rocksdb
if (kernel.getConfig().getSnapshotSpec().isSnapshotEnabled()
@@ -279,7 +282,6 @@ public synchronized ImportResult tryToConnect(Block block) {
Now transactionBlock's outputs are new address so ref.isAddress == false which means no blocks
mainBlocks and linkBlocks are same as original
*/
-// System.out.println(ref.getAddress().toHexString() + " isaddress ==" + ref.isAddress);
if (ref != null && !ref.isAddress) {
if (ref.getType() == XDAG_FIELD_OUT && !ref.getAmount().isZero()) {
result = ImportResult.INVALID_BLOCK;
@@ -305,7 +307,14 @@ public synchronized ImportResult tryToConnect(Block block) {
log.debug("Ref block's time >= block's time");
return result;
}
-
+ //ensure TX block's amount is enough to subtract minGas, Amount must >= 0.1;
+ if(ref.getType() == XDAG_FIELD_IN && ref.getAmount().subtract(minGas).isNegative()){
+ result = ImportResult.INVALID_BLOCK;
+ result.setHashlow(ref.getAddress());
+ result.setErrorInfo("Ref block's balance < minGas");
+ log.debug("Ref block's balance < minGas");
+ return result;
+ }
}
} else {
if (ref != null && ref.type == XDAG_FIELD_INPUT && !addressStore.addressIsExist(BytesUtils.byte32ToArray(ref.getAddress()))) {
@@ -314,6 +323,14 @@ public synchronized ImportResult tryToConnect(Block block) {
log.debug("Address isn't exist " + WalletUtils.toBase58(BytesUtils.byte32ToArray(ref.getAddress())));
return result;
}
+ //ensure TX block's amount is enough to subtract minGas, Amount must >= 0.1;
+ if(ref != null && ref.getType() == XDAG_FIELD_INPUT && ref.getAmount().subtract(minGas).isNegative()){
+ result = ImportResult.INVALID_BLOCK;
+ result.setHashlow(ref.getAddress());
+ result.setErrorInfo("Ref block's balance < minGas");
+ log.debug("Ref block's balance < minGas");
+ return result;
+ }
}
/*
Determine if ref is a block
@@ -663,14 +680,18 @@ private boolean blockEqual(Block block1, Block block2) {
/**
* 执行区块并返回手续费 *
*/
- private XAmount applyBlock(Block block) {
+ private XAmount applyBlock(boolean flag, Block block) {
+ XAmount gas = XAmount.ZERO;
XAmount sumIn = XAmount.ZERO;
XAmount sumOut = XAmount.ZERO; // sumOut是用来支付其他区块link自己的手续费 现在先用0
-
- // 处理过
+ // 处理过的block
if ((block.getInfo().flags & BI_MAIN_REF) != 0) {
return XAmount.ZERO.subtract(XAmount.ONE);
}
+ //the TX block create by wallet or pool will not set fee = minGas, set in this.
+ if (block.getInputs().size() != 0 && block.getFee().equals(XAmount.ZERO)){
+ block.getInfo().setFee(minGas);
+ }
// 设置为已处理
MutableBytes32 blockHashLow = block.getHashLow();
@@ -689,22 +710,24 @@ private XAmount applyBlock(Block block) {
XAmount ret;
// 如果处理过
if ((ref.getInfo().flags & BI_MAIN_REF) != 0) {
- ret = XAmount.ZERO.subtract(XAmount.ONE); //-1
- } else {
+ ret = XAmount.ZERO.subtract(XAmount.ONE);
+ }else {
ref = getBlockByHash(link.getAddress(), true);
- ret = applyBlock(ref);
+ ret = applyBlock(false, ref);
}
if (ret.equals(XAmount.ZERO.subtract(XAmount.ONE))) {
continue;
}
+ sumGas = sumGas.add(ret);
updateBlockRef(ref, new Address(block));
-
- if (compareAmountTo(block.getInfo().getAmount().add(ret), block.getInfo().getAmount()) >= 0) {
- addAndAccept(block, ret);
+ if (flag && sumGas != XAmount.ZERO){//judge if block is mainBlock, true: add fee!
+ addAndAccept(block, sumGas);
+ sumGas = XAmount.ZERO;
}
}
}
+
for (Address link : links) {
MutableBytes32 linkAddress = link.getAddress();
if (link.getType() == XDAG_FIELD_IN) {
@@ -773,14 +796,16 @@ private XAmount applyBlock(Block block) {
allBalance = allBalance.add(link.getAmount());
addressStore.updateAllBalance(allBalance);
} else {
- addAndAccept(ref, link.getAmount());
+ addAndAccept(ref, link.getAmount().subtract(block.getInfo().getFee().multiply(block.getInputs().size())));
+ gas = gas.add(block.getInfo().getFee()); //Mark the output for Fee
}
// blockStore.saveBlockInfo(ref.getInfo()); // TODO:acceptAmount时已经保存了 这里还需要保存吗
} else {
if (link.getType() == XDAG_FIELD_INPUT) {
subtractAmount(BasicUtils.hash2byte(linkAddress), link.getAmount(), block);
} else if (link.getType() == XDAG_FIELD_OUTPUT) {
- addAmount(BasicUtils.hash2byte(linkAddress), link.getAmount(), block);
+ addAmount(BasicUtils.hash2byte(linkAddress), link.getAmount().subtract(block.getInfo().getFee()), block);
+ gas = gas.add(block.getInfo().getFee()); //Mark the output for Fee
}
}
}
@@ -788,7 +813,7 @@ private XAmount applyBlock(Block block) {
// 不一定大于0 因为可能部分金额扣除
// TODO:need determine what is data;
updateBlockFlag(block, BI_APPLIED, true);
- return XAmount.ZERO;
+ return gas;
}
// TODO: unapply block which in snapshot
@@ -862,7 +887,7 @@ public void setMain(Block block) {
xdagStats.nmain++;
// 递归执行主块引用的区块 并获取手续费
- acceptAmount(block, applyBlock(block));
+ applyBlock(true, block);
// 主块REF指向自身
// TODO:补充手续费
updateBlockRef(block, new Address(block));
@@ -899,9 +924,8 @@ public void unSetMain(Block block) {
block.getInfo().setHeight(0);
}
}
-
@Override
- public Block createNewBlock(Map pairs, List to, boolean mining, String remark) {
+ public Block createNewBlock(Map pairs, List to, boolean mining, String remark, XAmount fee) {
int hasRemark = remark == null ? 0 : 1;
@@ -938,7 +962,7 @@ public Block createNewBlock(Map pairs, List to, boole
sendTime[0] = XdagTime.getCurrentTimestamp();
List refs = Lists.newArrayList();
- return new Block(kernel.getConfig(), sendTime[0], all, refs, mining, keys, remark, defKeyIndex);
+ return new Block(kernel.getConfig(), sendTime[0], all, refs, mining, keys, remark, defKeyIndex, fee);
}
public Block createMainBlock() {
@@ -971,7 +995,7 @@ public Block createMainBlock() {
refs.addAll(orphans);
}
return new Block(kernel.getConfig(), sendTime[0], null, refs, true, null,
- kernel.getConfig().getNodeSpec().getNodeTag(), -1);
+ kernel.getConfig().getNodeSpec().getNodeTag(), -1, XAmount.ZERO);
}
public Block createLinkBlock(String remark) {
@@ -987,7 +1011,7 @@ public Block createLinkBlock(String remark) {
refs.addAll(orphans);
}
return new Block(kernel.getConfig(), sendTime[1], null, refs, false, null,
- remark, -1);
+ remark, -1, XAmount.ZERO);
}
/**
@@ -1315,6 +1339,10 @@ public boolean isExtraBlock(Block block) {
return (block.getTimestamp() & 0xffff) == 0xffff && block.getNonce() != null && !block.isSaved();
}
+ public boolean isMainBlock(Block block){
+ return ((block.getTimestamp() & 0xffff) == 0xffff && block.getNonce() != null);
+ }
+
@Override
public XdagStats getXdagStats() {
return this.xdagStats;
@@ -1512,7 +1540,7 @@ public void checkOrphan() {
nblk = nblk / 61 + (b ? 1 : 0);
}
while (nblk-- > 0) {
- Block linkBlock = createNewBlock(null, null, false, kernel.getConfig().getNodeSpec().getNodeTag());
+ Block linkBlock = createNewBlock(null, null, false, kernel.getConfig().getNodeSpec().getNodeTag(), XAmount.ZERO);
linkBlock.signOut(kernel.getWallet().getDefKey());
ImportResult result = this.tryToConnect(linkBlock);
if (result == IMPORTED_NOT_BEST || result == IMPORTED_BEST) {
@@ -1531,6 +1559,23 @@ public void checkMain() {
}
}
+ public SECPPublicKey getBlockPubKey(Block block){
+ List keys = block.verifiedKeys();
+ MutableBytes subData = block.getSubRawData(block.getOutsigIndex() - 2);
+// log.debug("verify encoded:{}", Hex.toHexString(subdata));
+ SECPSignature sig = block.getOutsig();
+ for (SECPPublicKey publicKey : keys) {
+ byte[] publicKeyBytes = publicKey.asEcPoint(Sign.CURVE).getEncoded(true);
+ Bytes digest = Bytes.wrap(subData, Bytes.wrap(publicKeyBytes));
+// log.debug("verify encoded:{}", Hex.toHexString(digest));
+ Bytes32 hash = Hash.hashTwice(digest);
+ if (Sign.SECP256K1.verify(hash, sig, publicKey)) {
+ return publicKey;
+ }
+ }
+ return null;
+ }
+
@Override
public void stopCheckMain() {
try {
@@ -1570,18 +1615,18 @@ private void addAndAccept(Block block, XAmount amount) {
log.error(e.getMessage(), e);
log.debug("balance {} amount {} block {}", oldAmount, amount, block.getHashLow().toHexString());
}
- XAmount finalAmount = blockStore.getBlockInfoByHash(block.getHashLow()).getInfo().getAmount();
- log.debug("Balance checker —— block:{} [old:{} add:{} fin:{}]",
- block.getHashLow().toHexString(),
- oldAmount.toDecimal(9, XUnit.XDAG).toPlainString(),
- amount.toDecimal(9, XUnit.XDAG).toPlainString(),
- finalAmount.toDecimal(9, XUnit.XDAG).toPlainString());
if (block.isSaved) {
blockStore.saveBlockInfo(block.getInfo());
}
if ((block.getInfo().flags & BI_OURS) != 0) {
xdagStats.setBalance(amount.add(xdagStats.getBalance()));
}
+ XAmount finalAmount = blockStore.getBlockInfoByHash(block.getHashLow()).getInfo().getAmount();
+ log.debug("Balance checker —— block:{} [old:{} add:{} fin:{}]",
+ block.getHashLow().toHexString(),
+ oldAmount.toDecimal(9, XUnit.XDAG).toPlainString(),
+ amount.toDecimal(9, XUnit.XDAG).toPlainString(),
+ finalAmount.toDecimal(9, XUnit.XDAG).toPlainString());
}
private void subtractAndAccept(Block block, XAmount amount) {
@@ -1592,18 +1637,18 @@ private void subtractAndAccept(Block block, XAmount amount) {
log.error(e.getMessage(), e);
log.debug("balance {} amount {} block {}", oldAmount, amount, block.getHashLow().toHexString());
}
- XAmount finalAmount = blockStore.getBlockInfoByHash(block.getHashLow()).getInfo().getAmount();
- log.debug("Balance checker —— block:{} [old:{} sub:{} fin:{}]",
- block.getHashLow().toHexString(),
- oldAmount.toDecimal(9, XUnit.XDAG).toPlainString(),
- amount.toDecimal(9, XUnit.XDAG).toPlainString(),
- finalAmount.toDecimal(9, XUnit.XDAG).toPlainString());
if (block.isSaved) {
blockStore.saveBlockInfo(block.getInfo());
}
if ((block.getInfo().flags & BI_OURS) != 0) {
xdagStats.setBalance(xdagStats.getBalance().subtract(amount));
}
+ XAmount finalAmount = blockStore.getBlockInfoByHash(block.getHashLow()).getInfo().getAmount();
+ log.debug("Balance checker —— block:{} [old:{} sub:{} fin:{}]",
+ block.getHashLow().toHexString(),
+ oldAmount.toDecimal(9, XUnit.XDAG).toPlainString(),
+ amount.toDecimal(9, XUnit.XDAG).toPlainString(),
+ finalAmount.toDecimal(9, XUnit.XDAG).toPlainString());
}
private void subtractAmount(byte[] addressHash, XAmount amount, Block block) {
@@ -1699,7 +1744,6 @@ public List listMainBlocksByHeight(int count) {
return res;
}
-
@Override
public List listMainBlocks(int count) {
return listMainBlocksByHeight(count);
diff --git a/src/main/java/io/xdag/core/Filter.java b/src/main/java/io/xdag/core/Filter.java
new file mode 100644
index 00000000..95e86bc1
--- /dev/null
+++ b/src/main/java/io/xdag/core/Filter.java
@@ -0,0 +1,45 @@
+package io.xdag.core;
+
+import io.xdag.db.BlockStore;
+import org.apache.tuweni.bytes.Bytes32;
+
+import java.util.List;
+
+public class Filter {
+
+ private BlockStore blockStore;
+
+ public Filter(BlockStore blockStore) {
+ this.blockStore = blockStore;
+ }
+
+ public boolean filterLinkBlock(Block block){
+ List links = block.getLinks();
+ for (Address link:links) {
+ if(link.getType() != XdagField.FieldType. XDAG_FIELD_OUT){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean filterTxBlock(Block block){
+ List links = block.getLinks();
+ for (Address link:links) {
+ if(link.getType() == XdagField.FieldType.XDAG_FIELD_IN || link.getType() == XdagField.FieldType.XDAG_FIELD_INPUT){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean filterOurLinkBlock(Bytes32 blockHashLow){
+ Block block = blockStore.getBlockByHash(blockHashLow,true);
+ if(!filterLinkBlock(block)){
+ return block.isOurs();
+ }else {
+ return true;
+ }
+ }
+
+}
diff --git a/src/main/java/io/xdag/core/PreBlockInfo.java b/src/main/java/io/xdag/core/PreBlockInfo.java
index bbb25055..e58c3914 100644
--- a/src/main/java/io/xdag/core/PreBlockInfo.java
+++ b/src/main/java/io/xdag/core/PreBlockInfo.java
@@ -42,7 +42,7 @@ public class PreBlockInfo {
private byte[] remark;
private byte[] hash;
private byte[] hashlow;
- private UInt64 amount;
+ private XAmount amount;
private long timestamp;
// snapshot
diff --git a/src/main/java/io/xdag/db/OrphanBlockStore.java b/src/main/java/io/xdag/db/OrphanBlockStore.java
index 3664d2c5..fd8f6f9a 100644
--- a/src/main/java/io/xdag/db/OrphanBlockStore.java
+++ b/src/main/java/io/xdag/db/OrphanBlockStore.java
@@ -26,6 +26,8 @@
import io.xdag.core.Address;
import io.xdag.core.Block;
import java.util.List;
+
+import io.xdag.core.Filter;
import org.bouncycastle.util.encoders.Hex;
public interface OrphanBlockStore {
diff --git a/src/main/java/io/xdag/db/rocksdb/OrphanBlockStoreImpl.java b/src/main/java/io/xdag/db/rocksdb/OrphanBlockStoreImpl.java
index 85b0ecf9..45bd27f6 100644
--- a/src/main/java/io/xdag/db/rocksdb/OrphanBlockStoreImpl.java
+++ b/src/main/java/io/xdag/db/rocksdb/OrphanBlockStoreImpl.java
@@ -26,6 +26,7 @@
import io.xdag.core.Address;
import io.xdag.core.Block;
+import io.xdag.core.Filter;
import io.xdag.core.XdagField;
import io.xdag.db.OrphanBlockStore;
import io.xdag.utils.BytesUtils;
@@ -84,6 +85,13 @@ public List getOrphan(long num, long[] sendtime) {
addNum--;
res.add(new Address(Bytes32.wrap(an.getKey(), 1), XdagField.FieldType.XDAG_FIELD_OUT,false));
sendtime[1] = Math.max(sendtime[1],time);
+// Bytes32 blockHashLow = Bytes32.wrap(an.getKey(),1);
+// if(filter.filterOurLinkBlock(blockHashLow)){
+// addNum--;
+// //TODO:通过address 获取区块 遍历连接块是否都是output如果是 则为链接块 判断是否是自己的是才链接
+// res.add(new Address(blockHashLow, XdagField.FieldType.XDAG_FIELD_OUT,false));
+// sendtime[1] = Math.max(sendtime[1],time);
+// }
}
}
sendtime[1] = Math.min(sendtime[1]+1,sendtime[0]);
diff --git a/src/main/java/io/xdag/db/rocksdb/SnapshotStoreImpl.java b/src/main/java/io/xdag/db/rocksdb/SnapshotStoreImpl.java
index 1dd1d660..0548c04c 100644
--- a/src/main/java/io/xdag/db/rocksdb/SnapshotStoreImpl.java
+++ b/src/main/java/io/xdag/db/rocksdb/SnapshotStoreImpl.java
@@ -98,10 +98,10 @@ public void reset() {
public void setBlockInfo(BlockInfo blockInfo, PreBlockInfo preBlockInfo) {
blockInfo.setSnapshot(preBlockInfo.isSnapshot());
blockInfo.setSnapshotInfo(preBlockInfo.getSnapshotInfo());
- blockInfo.setFee(preBlockInfo.getFee());
+ blockInfo.setFee(XAmount.of(preBlockInfo.getFee()));
blockInfo.setHash(preBlockInfo.getHash());
blockInfo.setDifficulty(preBlockInfo.getDifficulty());
- blockInfo.setAmount(XAmount.ofXAmount(preBlockInfo.getAmount().toLong()));
+ blockInfo.setAmount(preBlockInfo.getAmount());
blockInfo.setHashlow(preBlockInfo.getHashlow());
blockInfo.setFlags(preBlockInfo.getFlags());
blockInfo.setHeight(preBlockInfo.getHeight());
diff --git a/src/main/java/io/xdag/net/XdagP2pHandler.java b/src/main/java/io/xdag/net/XdagP2pHandler.java
index 2530964a..a8af0a18 100644
--- a/src/main/java/io/xdag/net/XdagP2pHandler.java
+++ b/src/main/java/io/xdag/net/XdagP2pHandler.java
@@ -333,9 +333,9 @@ private ReasonCode checkPeer(Peer peer, boolean newHandShake) {
}
// not connected
- if (client.getPeerId().equals(peer.getPeerId()) || channelMgr.isActivePeer(peer.getPeerId())) {
- return ReasonCode.DUPLICATED_PEER_ID;
- }
+// if (client.getPeerId().equals(peer.getPeerId()) || channelMgr.isActivePeer(peer.getPeerId())) {
+// return ReasonCode.DUPLICATED_PEER_ID;
+// }
// validator can't share IP address
if (channelMgr.isActiveIP(channel.getRemoteIp()) // already connected
diff --git a/src/main/java/io/xdag/net/websocket/ChannelSupervise.java b/src/main/java/io/xdag/net/websocket/ChannelSupervise.java
new file mode 100644
index 00000000..2940bf9e
--- /dev/null
+++ b/src/main/java/io/xdag/net/websocket/ChannelSupervise.java
@@ -0,0 +1,42 @@
+package io.xdag.net.websocket;
+
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelId;
+import io.netty.channel.group.ChannelGroup;
+import io.netty.channel.group.DefaultChannelGroup;
+import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
+import io.netty.util.concurrent.GlobalEventExecutor;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public class ChannelSupervise {//supervise channel
+ private static ChannelGroup GlobalGroup=new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
+ private static ConcurrentMap ChannelMap=new ConcurrentHashMap();
+ public static void addChannel(Channel channel, String tag){
+ GlobalGroup.add(channel);
+ ChannelMap.put(tag, channel.id());
+ }
+ public static void removeChannel(Channel channel, String tag){
+ GlobalGroup.remove(channel);
+ ChannelMap.remove(tag);
+ }
+ public static Channel findChannel(String id){
+ return GlobalGroup.find(ChannelMap.get(id));
+ }
+
+ public static String showChannel(){
+ StringBuilder sb = new StringBuilder();
+ // 遍历 ChannelMap 中的键值对并将它们添加到 StringBuilder
+ for (ConcurrentMap.Entry entry : ChannelMap.entrySet()) {
+ String key = entry.getKey();
+ ChannelId value = entry.getValue();
+ String host = findChannel(key).remoteAddress().toString();
+ sb.append("PoolTag: ").append(key).append(", PoolAddress: ").append(host).append(", ChannelId: ").append(value).append("\n");
+ }
+ return sb.toString();
+ }
+ public static void send2All(TextWebSocketFrame tws){
+ GlobalGroup.writeAndFlush(tws);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/io/xdag/net/websocket/PoolHandShakeHandler.java b/src/main/java/io/xdag/net/websocket/PoolHandShakeHandler.java
new file mode 100644
index 00000000..5afc4331
--- /dev/null
+++ b/src/main/java/io/xdag/net/websocket/PoolHandShakeHandler.java
@@ -0,0 +1,131 @@
+package io.xdag.net.websocket;
+
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.handler.codec.http.websocketx.WebSocketFrame;
+import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.*;
+import io.netty.handler.codec.http.DefaultFullHttpResponse;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import io.netty.handler.codec.http.HttpVersion;
+import io.netty.handler.codec.http.websocketx.*;
+import io.netty.util.CharsetUtil;
+import static io.netty.handler.codec.http.HttpUtil.isKeepAlive;
+import java.util.Date;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class PoolHandShakeHandler extends SimpleChannelInboundHandler