diff --git a/src/main/java/org/tron/common/application/Application.java b/src/main/java/org/tron/common/application/Application.java index d9279ddb25b..b408e15bd42 100644 --- a/src/main/java/org/tron/common/application/Application.java +++ b/src/main/java/org/tron/common/application/Application.java @@ -18,7 +18,6 @@ import org.tron.core.config.args.Args; import org.tron.core.db.BlockStore; import org.tron.core.db.Manager; -import org.tron.core.net.node.Node; public interface Application { @@ -36,8 +35,6 @@ public interface Application { void shutdownServices(); - Node getP2pNode(); - BlockStore getBlockStoreS(); void addService(Service service); diff --git a/src/main/java/org/tron/common/application/ApplicationImpl.java b/src/main/java/org/tron/common/application/ApplicationImpl.java index 417b41a558b..269c50eec05 100644 --- a/src/main/java/org/tron/common/application/ApplicationImpl.java +++ b/src/main/java/org/tron/common/application/ApplicationImpl.java @@ -7,33 +7,23 @@ import org.tron.core.config.args.Args; import org.tron.core.db.BlockStore; import org.tron.core.db.Manager; -import org.tron.core.net.node.Node; -import org.tron.core.net.node.NodeDelegate; -import org.tron.core.net.node.NodeDelegateImpl; -import org.tron.core.net.node.NodeImpl; +import org.tron.core.net.TronNetService; @Slf4j(topic = "app") @Component public class ApplicationImpl implements Application { - @Autowired - private NodeImpl p2pNode; - private BlockStore blockStoreDb; private ServiceContainer services; - private NodeDelegate nodeDelegate; + + @Autowired + private TronNetService tronNetService; @Autowired private Manager dbManager; private boolean isProducer; - - private void resetP2PNode() { - p2pNode.listen(); - p2pNode.syncFrom(null); - } - @Override public void setOptions(Args args) { // not used @@ -44,7 +34,6 @@ public void setOptions(Args args) { public void init(Args args) { blockStoreDb = dbManager.getBlockStore(); services = new ServiceContainer(); - nodeDelegate = new NodeDelegateImpl(dbManager); } @Override @@ -61,19 +50,17 @@ public void initServices(Args args) { * start up the app. */ public void startup() { - p2pNode.setNodeDelegate(nodeDelegate); - resetP2PNode(); + tronNetService.start(); } @Override public void shutdown() { logger.info("******** begin to shutdown ********"); - //p2pNode.shutDown(); + tronNetService.close(); synchronized (dbManager.getRevokingStore()) { closeRevokingStore(); closeAllStore(); } - closeConnection(); dbManager.stopRepushThread(); dbManager.stopRepushTriggerThread(); EventPluginLoader.getInstance().stopPlugin(); @@ -90,11 +77,6 @@ public void shutdownServices() { services.stop(); } - @Override - public Node getP2pNode() { - return p2pNode; - } - @Override public BlockStore getBlockStoreS() { return blockStoreDb; @@ -113,17 +95,6 @@ public void setIsProducer(boolean producer) { isProducer = producer; } - private void closeConnection() { - logger.info("******** begin to shutdown connection ********"); - try { - p2pNode.close(); - } catch (Exception e) { - logger.info("failed to close p2pNode. " + e); - } finally { - logger.info("******** end to shutdown connection ********"); - } - } - private void closeRevokingStore() { logger.info("******** begin to closeRevokingStore ********"); dbManager.getRevokingStore().shutdown(); diff --git a/src/main/java/org/tron/common/application/CliApplication.java b/src/main/java/org/tron/common/application/CliApplication.java index 9bcffd106b2..d63d227f212 100644 --- a/src/main/java/org/tron/common/application/CliApplication.java +++ b/src/main/java/org/tron/common/application/CliApplication.java @@ -17,7 +17,6 @@ import org.tron.core.config.args.Args; import org.tron.core.db.BlockStore; import org.tron.core.db.Manager; -import org.tron.core.net.node.Node; public class CliApplication implements Application { @@ -56,11 +55,6 @@ public void shutdownServices() { } - @Override - public Node getP2pNode() { - return null; - } - @Override public BlockStore getBlockStoreS() { return null; diff --git a/src/main/java/org/tron/common/overlay/client/PeerClient.java b/src/main/java/org/tron/common/overlay/client/PeerClient.java index 91a21e3ec78..3f1693769cf 100644 --- a/src/main/java/org/tron/common/overlay/client/PeerClient.java +++ b/src/main/java/org/tron/common/overlay/client/PeerClient.java @@ -13,13 +13,11 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import org.tron.common.overlay.discover.node.Node; import org.tron.common.overlay.discover.node.NodeHandler; import org.tron.common.overlay.server.TronChannelInitializer; import org.tron.core.config.args.Args; -import org.tron.core.net.node.NodeImpl; import org.tron.protos.Protocol.ReasonCode; @Slf4j(topic = "net") @@ -29,10 +27,6 @@ public class PeerClient { @Autowired private ApplicationContext ctx; - @Autowired - @Lazy - private NodeImpl node; - private EventLoopGroup workerGroup; public PeerClient() { @@ -61,7 +55,7 @@ public ChannelFuture connectAsync(NodeHandler nodeHandler, boolean discoveryMode return connectAsync(node.getHost(), node.getPort(), node.getHexId(), discoveryMode) .addListener((ChannelFutureListener) future -> { if (!future.isSuccess()) { - logger.error("connect to {}:{} fail,cause:{}", node.getHost(), node.getPort(), + logger.warn("connect to {}:{} fail,cause:{}", node.getHost(), node.getPort(), future.cause().getMessage()); nodeHandler.getNodeStatistics().nodeDisconnectedLocal(ReasonCode.CONNECT_FAIL); nodeHandler.getNodeStatistics().notifyDisconnect(); @@ -70,14 +64,13 @@ public ChannelFuture connectAsync(NodeHandler nodeHandler, boolean discoveryMode }); } - public ChannelFuture connectAsync(String host, int port, String remoteId, boolean discoveryMode) { + private ChannelFuture connectAsync(String host, int port, String remoteId, boolean discoveryMode) { logger.info("connect peer {} {} {}", host, port, remoteId); TronChannelInitializer tronChannelInitializer = ctx .getBean(TronChannelInitializer.class, remoteId); tronChannelInitializer.setPeerDiscoveryMode(discoveryMode); - tronChannelInitializer.setNodeImpl(node); Bootstrap b = new Bootstrap(); b.group(workerGroup); diff --git a/src/main/java/org/tron/common/overlay/server/Channel.java b/src/main/java/org/tron/common/overlay/server/Channel.java index 17de9e3b995..634f9b40df3 100644 --- a/src/main/java/org/tron/common/overlay/server/Channel.java +++ b/src/main/java/org/tron/common/overlay/server/Channel.java @@ -22,6 +22,7 @@ import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; import io.netty.handler.timeout.ReadTimeoutException; import io.netty.handler.timeout.ReadTimeoutHandler; +import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; @@ -39,8 +40,7 @@ import org.tron.common.overlay.message.StaticMessages; import org.tron.core.db.ByteArrayWrapper; import org.tron.core.exception.P2pException; -import org.tron.core.net.peer.PeerConnectionDelegate; -import org.tron.core.net.peer.TronHandler; +import org.tron.core.net.TronNetHandler; import org.tron.protos.Protocol.ReasonCode; @Slf4j(topic = "net") @@ -70,7 +70,7 @@ public class Channel { private P2pHandler p2pHandler; @Autowired - private TronHandler tronHandler; + private TronNetHandler tronNetHandler; private ChannelManager channelManager; @@ -82,8 +82,6 @@ public class Channel { private long startTime; - private PeerConnectionDelegate peerDel; - private TronState tronState = TronState.INIT; protected NodeStatistics nodeStatistics; @@ -99,7 +97,7 @@ public class Channel { private boolean isTrustPeer; public void init(ChannelPipeline pipeline, String remoteId, boolean discoveryMode, - ChannelManager channelManager, PeerConnectionDelegate peerDel) { + ChannelManager channelManager) { this.channelManager = channelManager; @@ -118,18 +116,14 @@ public void init(ChannelPipeline pipeline, String remoteId, boolean discoveryMod //handshake first pipeline.addLast("handshakeHandler", handshakeHandler); - this.peerDel = peerDel; - messageCodec.setChannel(this); msgQueue.setChannel(this); handshakeHandler.setChannel(this, remoteId); p2pHandler.setChannel(this); - tronHandler.setChannel(this); + tronNetHandler.setChannel(this); p2pHandler.setMsgQueue(msgQueue); - tronHandler.setMsgQueue(msgQueue); - tronHandler.setPeerDel(peerDel); - + tronNetHandler.setMsgQueue(msgQueue); } public void publicHandshakeFinished(ChannelHandlerContext ctx, HelloMessage msg) { @@ -138,7 +132,7 @@ public void publicHandshakeFinished(ChannelHandlerContext ctx, HelloMessage msg) msgQueue.activate(ctx); ctx.pipeline().addLast("messageCodec", messageCodec); ctx.pipeline().addLast("p2p", p2pHandler); - ctx.pipeline().addLast("data", tronHandler); + ctx.pipeline().addLast("data", tronNetHandler); setStartTime(msg.getTimestamp()); setTronState(TronState.HANDSHAKE_FINISHED); getNodeStatistics().p2pHandShake.add(); @@ -158,7 +152,10 @@ public void disconnect(ReasonCode reason) { this.isDisconnect = true; channelManager.processDisconnect(this, reason); DisconnectMessage msg = new DisconnectMessage(reason); - logger.info("Send to {}, {}", ctx.channel().remoteAddress(), msg); + logger.info("Send to {} online-time {}s, {}", + ctx.channel().remoteAddress(), + (System.currentTimeMillis() - startTime) / 1000, + msg); getNodeStatistics().nodeDisconnectedLocal(reason); ctx.writeAndFlush(msg.getSendData()).addListener(future -> close()); } @@ -168,17 +165,15 @@ public void processException(Throwable throwable) { while (baseThrowable.getCause() != null) { baseThrowable = baseThrowable.getCause(); } - String errMsg = throwable.getMessage(); SocketAddress address = ctx.channel().remoteAddress(); - if (throwable instanceof ReadTimeoutException) { - logger.error("Read timeout, {}", address); + if (throwable instanceof ReadTimeoutException || + throwable instanceof IOException) { + logger.warn("Close peer {}, reason: {}", address, throwable.getMessage()); } else if (baseThrowable instanceof P2pException) { - logger.error("type: {}, info: {}, {}", ((P2pException) baseThrowable).getType(), - baseThrowable.getMessage(), address); - } else if (errMsg != null && errMsg.contains("Connection reset by peer")) { - logger.error("{}, {}", errMsg, address); + logger.warn("Close peer {}, type: {}, info: {}", + address,((P2pException) baseThrowable).getType(), baseThrowable.getMessage()); } else { - logger.error("exception caught, {}", address, throwable); + logger.error("Close peer {}, exception caught", address, throwable); } close(); } @@ -224,10 +219,6 @@ public void setChannelHandlerContext(ChannelHandlerContext ctx) { this.inetSocketAddress = ctx == null ? null : (InetSocketAddress) ctx.channel().remoteAddress(); } - public ChannelHandlerContext getChannelHandlerContext() { - return this.ctx; - } - public InetAddress getInetAddress() { return ctx == null ? null : ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress(); } @@ -246,10 +237,7 @@ public long getStartTime() { public void setTronState(TronState tronState) { this.tronState = tronState; - } - - public TronState getTronState() { - return tronState; + logger.info("Peer {} status change to {}.", inetSocketAddress, tronState); } public boolean isActive() { @@ -260,10 +248,6 @@ public boolean isDisconnect() { return isDisconnect; } - public boolean isProtocolsInitialized() { - return tronState.ordinal() > TronState.INIT.ordinal(); - } - public boolean isTrustPeer() { return isTrustPeer; } diff --git a/src/main/java/org/tron/common/overlay/server/ChannelManager.java b/src/main/java/org/tron/common/overlay/server/ChannelManager.java index bea09a19e21..b7c1642459e 100644 --- a/src/main/java/org/tron/common/overlay/server/ChannelManager.java +++ b/src/main/java/org/tron/common/overlay/server/ChannelManager.java @@ -27,6 +27,17 @@ @Component public class ChannelManager { + @Autowired + private PeerServer peerServer; + + @Autowired + private PeerClient peerClient; + + @Autowired + private SyncPool syncPool; + + private Args args = Args.getInstance(); + private final Map activePeers = new ConcurrentHashMap<>(); private Cache badPeers = CacheBuilder.newBuilder().maximumSize(10000) @@ -38,25 +49,10 @@ public class ChannelManager { @Getter private Map trustPeers = new ConcurrentHashMap(); - private Args args = Args.getInstance(); - private int maxActivePeers = args.getNodeMaxActiveNodes(); private int getMaxActivePeersWithSameIp = args.getNodeMaxActiveNodesWithSameIp(); - private PeerServer peerServer; - - private PeerClient peerClient; - - @Autowired - private SyncPool syncPool; - - @Autowired - private ChannelManager(final PeerServer peerServer, final PeerClient peerClient) { - this.peerServer = peerServer; - this.peerClient = peerClient; - } - public void init() { if (this.args.getNodeListenPort() > 0) { new Thread(() -> peerServer.start(Args.getInstance().getNodeListenPort()), @@ -67,6 +63,8 @@ public void init() { trustPeers.put(new InetSocketAddress(node.getHost(), node.getPort()).getAddress(), node); } logger.info("Trust peer size {}", trustPeers.size()); + + syncPool.init(); } public void processDisconnect(Channel channel, ReasonCode reason) { @@ -164,5 +162,6 @@ public Cache getBadPeers() { public void close() { peerServer.close(); peerClient.close(); + syncPool.close(); } } diff --git a/src/main/java/org/tron/common/overlay/server/MessageQueue.java b/src/main/java/org/tron/common/overlay/server/MessageQueue.java index 236848436d2..6e983216848 100644 --- a/src/main/java/org/tron/common/overlay/server/MessageQueue.java +++ b/src/main/java/org/tron/common/overlay/server/MessageQueue.java @@ -71,7 +71,7 @@ public void activate(ChannelHandlerContext ctx) { } Message msg = msgQueue.take(); ctx.writeAndFlush(msg.getSendData()).addListener((ChannelFutureListener) future -> { - if (!future.isSuccess()) { + if (!future.isSuccess() && !channel.isDisconnect()) { logger.error("Fail send to {}, {}", ctx.channel().remoteAddress(), msg); } }); diff --git a/src/main/java/org/tron/common/overlay/server/PeerServer.java b/src/main/java/org/tron/common/overlay/server/PeerServer.java index bdca0cbe0c6..78e48235116 100644 --- a/src/main/java/org/tron/common/overlay/server/PeerServer.java +++ b/src/main/java/org/tron/common/overlay/server/PeerServer.java @@ -30,7 +30,6 @@ import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import org.tron.core.config.args.Args; -import org.tron.core.net.node.NodeImpl; @Slf4j(topic = "net") @Component @@ -44,9 +43,6 @@ public class PeerServer { private boolean listening; - @Autowired - private NodeImpl p2pNode; - private EventLoopGroup bossGroup; private EventLoopGroup workerGroup; private ChannelFuture channelFuture; @@ -62,8 +58,6 @@ public void start(int port) { workerGroup = new NioEventLoopGroup(args.getTcpNettyWorkThreadNum()); tronChannelInitializer = ctx.getBean(TronChannelInitializer.class, ""); - tronChannelInitializer.setNodeImpl(p2pNode); - try { ServerBootstrap b = new ServerBootstrap(); diff --git a/src/main/java/org/tron/common/overlay/server/SyncPool.java b/src/main/java/org/tron/common/overlay/server/SyncPool.java index b19918c8aa7..fae0de6c9e4 100644 --- a/src/main/java/org/tron/common/overlay/server/SyncPool.java +++ b/src/main/java/org/tron/common/overlay/server/SyncPool.java @@ -43,7 +43,6 @@ import org.tron.common.overlay.discover.node.statistics.NodeStatistics; import org.tron.core.config.args.Args; import org.tron.core.net.peer.PeerConnection; -import org.tron.core.net.peer.PeerConnectionDelegate; @Slf4j(topic = "net") @Component @@ -68,8 +67,6 @@ public class SyncPool { private ChannelManager channelManager; - private PeerConnectionDelegate peerDel; - private Args args = Args.getInstance(); private int maxActiveNodes = args.getNodeMaxActiveNodes(); @@ -82,11 +79,9 @@ public class SyncPool { private PeerClient peerClient; - public void init(PeerConnectionDelegate peerDel) { - this.peerDel = peerDel; + public void init() { channelManager = ctx.getBean(ChannelManager.class); - channelManager.init(); peerClient = ctx.getBean(PeerClient.class); @@ -128,12 +123,6 @@ private void fillUp() { }); } - // for test only - public void addActivePeers(PeerConnection p) { - activePeers.add(p); - } - - synchronized void logActivePeers() { logger.info("-------- active connect channel {}", activePeersCount.get()); @@ -149,7 +138,7 @@ synchronized void logActivePeers() { sb.append("============\n"); Set activeSet = new HashSet<>(); for (PeerConnection peer : new ArrayList<>(activePeers)) { - sb.append(peer.logSyncStats()).append('\n'); + sb.append(peer.log()).append('\n'); activeSet.add(peer.getNode()); } sb.append("Other connected peers\n"); @@ -174,27 +163,29 @@ public synchronized List getActivePeers() { } public synchronized void onConnect(Channel peer) { - if (!activePeers.contains(peer)) { - if (!peer.isActive()) { + PeerConnection peerConnection = (PeerConnection) peer; + if (!activePeers.contains(peerConnection)) { + if (!peerConnection.isActive()) { passivePeersCount.incrementAndGet(); } else { activePeersCount.incrementAndGet(); } - activePeers.add((PeerConnection) peer); + activePeers.add(peerConnection); activePeers.sort(Comparator.comparingDouble(c -> c.getPeerStats().getAvgLatency())); - peerDel.onConnectPeer((PeerConnection) peer); + peerConnection.onConnect(); } } public synchronized void onDisconnect(Channel peer) { - if (activePeers.contains(peer)) { - if (!peer.isActive()) { + PeerConnection peerConnection = (PeerConnection) peer; + if (activePeers.contains(peerConnection)) { + if (!peerConnection.isActive()) { passivePeersCount.decrementAndGet(); } else { activePeersCount.decrementAndGet(); } - activePeers.remove(peer); - peerDel.onDisconnectPeer((PeerConnection) peer); + activePeers.remove(peerConnection); + peerConnection.onDisconnect(); } } diff --git a/src/main/java/org/tron/common/overlay/server/TronChannelInitializer.java b/src/main/java/org/tron/common/overlay/server/TronChannelInitializer.java index 8624493a5bb..de6bedbff14 100644 --- a/src/main/java/org/tron/common/overlay/server/TronChannelInitializer.java +++ b/src/main/java/org/tron/common/overlay/server/TronChannelInitializer.java @@ -27,7 +27,6 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; -import org.tron.core.net.node.NodeImpl; import org.tron.core.net.peer.PeerConnection; /** @@ -45,8 +44,6 @@ public class TronChannelInitializer extends ChannelInitializer @Autowired ChannelManager channelManager; - private NodeImpl p2pNode; - private String remoteId; private boolean peerDiscoveryMode = false; @@ -60,7 +57,7 @@ public void initChannel(NioSocketChannel ch) throws Exception { try { final Channel channel = ctx.getBean(PeerConnection.class); - channel.init(ch.pipeline(), remoteId, peerDiscoveryMode, channelManager, p2pNode); + channel.init(ch.pipeline(), remoteId, peerDiscoveryMode, channelManager); // limit the size of receiving buffer to 1024 ch.config().setRecvByteBufAllocator(new FixedRecvByteBufAllocator(256 * 1024)); @@ -87,8 +84,4 @@ private boolean isInbound() { public void setPeerDiscoveryMode(boolean peerDiscoveryMode) { this.peerDiscoveryMode = peerDiscoveryMode; } - - public void setNodeImpl(NodeImpl p2pNode) { - this.p2pNode = p2pNode; - } } diff --git a/src/main/java/org/tron/core/Wallet.java b/src/main/java/org/tron/core/Wallet.java index 8cc80f6473e..b56f0772bd3 100755 --- a/src/main/java/org/tron/core/Wallet.java +++ b/src/main/java/org/tron/core/Wallet.java @@ -114,8 +114,9 @@ import org.tron.core.exception.TransactionExpirationException; import org.tron.core.exception.VMIllegalException; import org.tron.core.exception.ValidateSignatureException; +import org.tron.core.net.TronNetDelegate; +import org.tron.core.net.TronNetService; import org.tron.core.net.message.TransactionMessage; -import org.tron.core.net.node.NodeImpl; import org.tron.protos.Contract.AssetIssueContract; import org.tron.protos.Contract.CreateSmartContract; import org.tron.protos.Contract.TransferContract; @@ -145,7 +146,9 @@ public class Wallet { @Getter private final ECKey ecKey; @Autowired - private NodeImpl p2pNode; + private TronNetService tronNetService; + @Autowired + private TronNetDelegate tronNetDelegate; @Autowired private Manager dbManager; @Autowired @@ -415,14 +418,14 @@ public GrpcAPI.Return broadcastTransaction(Transaction signaturedTransaction) { try { if (minEffectiveConnection != 0) { - if (p2pNode.getActivePeer().isEmpty()) { + if (tronNetDelegate.getActivePeer().isEmpty()) { logger.warn("Broadcast transaction {} failed, no connection.", trx.getTransactionId()); return builder.setResult(false).setCode(response_code.NO_CONNECTION) .setMessage(ByteString.copyFromUtf8("no connection")) .build(); } - int count = (int) p2pNode.getActivePeer().stream() + int count = (int) tronNetDelegate.getActivePeer().stream() .filter(p -> !p.isNeedSyncFromUs() && !p.isNeedSyncFromPeer()) .count(); @@ -457,7 +460,7 @@ public GrpcAPI.Return broadcastTransaction(Transaction signaturedTransaction) { trx.resetResult(); } dbManager.pushTransaction(trx); - p2pNode.broadcast(message); + tronNetService.broadcast(message); logger.info("Broadcast transaction {} successfully.", trx.getTransactionId()); return builder.setResult(true).setCode(response_code.SUCCESS).build(); } catch (ValidateSignatureException e) { diff --git a/src/main/java/org/tron/core/config/Parameter.java b/src/main/java/org/tron/core/config/Parameter.java index 52795ec36e4..5d3e52533be 100644 --- a/src/main/java/org/tron/core/config/Parameter.java +++ b/src/main/java/org/tron/core/config/Parameter.java @@ -43,12 +43,13 @@ interface NetConstants { long GRPC_IDLE_TIME_OUT = 60000L; long ADV_TIME_OUT = 20000L; - long SYNC_TIME_OUT = 5000L; + long SYNC_TIME_OUT = 20000L; long HEAD_NUM_MAX_DELTA = 1000L; long HEAD_NUM_CHECK_TIME = 60000L; int MAX_INVENTORY_SIZE_IN_MINUTES = 2; long NET_MAX_TRX_PER_SECOND = 700L; - long MAX_TRX_PER_PEER = 200L; + int MAX_BLOCK_FETCH_PER_PEER = 100; + int MAX_TRX_FETCH_PER_PEER = 1000; int NET_MAX_INV_SIZE_IN_MINUTES = 2; int MSG_CACHE_DURATION_IN_BLOCKS = 5; } diff --git a/src/main/java/org/tron/core/db/Manager.java b/src/main/java/org/tron/core/db/Manager.java index be798defba4..fa35c9cae26 100644 --- a/src/main/java/org/tron/core/db/Manager.java +++ b/src/main/java/org/tron/core/db/Manager.java @@ -1248,6 +1248,7 @@ public boolean processTransaction(final TransactionCapsule trxCap, BlockCapsule if (isMultSignTransaction(trxCap.getInstance())) { ownerAddressSet.add(ByteArray.toHexString(TransactionCapsule.getOwner(contract))); } + return true; } diff --git a/src/main/java/org/tron/core/exception/P2pException.java b/src/main/java/org/tron/core/exception/P2pException.java index bd014d5d617..246c8e807e1 100644 --- a/src/main/java/org/tron/core/exception/P2pException.java +++ b/src/main/java/org/tron/core/exception/P2pException.java @@ -9,14 +9,35 @@ public P2pException(TypeEnum type, String errMsg){ this.type = type; } + public P2pException(TypeEnum type, Throwable throwable){ + super(throwable); + this.type = type; + } + + public P2pException(TypeEnum type, String errMsg, Throwable throwable){ + super(errMsg, throwable); + this.type = type; + } + public TypeEnum getType() { return type; } public enum TypeEnum { - NO_SUCH_MESSAGE (1, "No such message"), - PARSE_MESSAGE_FAILED (2, "Parse message failed"), - MESSAGE_WITH_WRONG_LENGTH (3, "Message with wrong length"), + NO_SUCH_MESSAGE (1, "no such message"), + PARSE_MESSAGE_FAILED (2, "parse message failed"), + MESSAGE_WITH_WRONG_LENGTH (3, "message with wrong length"), + BAD_MESSAGE (4, "bad message"), + DIFF_GENESIS_BLOCK (5, "different genesis block"), + HARD_FORKED (6, "hard forked"), + SYNC_FAILED (7, "sync failed"), + CHECK_FAILED (8, "check failed"), + UNLINK_BLOCK (9, "unlink block"), + BAD_BLOCK (10, "bad block"), + BAD_TRX (11, "bad trx"), + TRX_EXE_FAILED (12, "trx exe failed"), + DB_ITEM_NOT_FOUND (13, "DB item not found"), + DEFAULT (100, "default exception"); private Integer value; diff --git a/src/main/java/org/tron/core/net/TronNetDelegate.java b/src/main/java/org/tron/core/net/TronNetDelegate.java new file mode 100644 index 00000000000..ef621ce28ec --- /dev/null +++ b/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -0,0 +1,212 @@ +package org.tron.core.net; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.common.overlay.message.Message; +import org.tron.common.overlay.server.SyncPool; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.BlockCapsule.BlockId; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.db.Manager; +import org.tron.core.exception.AccountResourceInsufficientException; +import org.tron.core.exception.BadBlockException; +import org.tron.core.exception.BadItemException; +import org.tron.core.exception.BadNumberBlockException; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractSizeNotEqualToOneException; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.exception.DupTransactionException; +import org.tron.core.exception.ItemNotFoundException; +import org.tron.core.exception.NonCommonBlockException; +import org.tron.core.exception.P2pException; +import org.tron.core.exception.P2pException.TypeEnum; +import org.tron.core.exception.ReceiptCheckErrException; +import org.tron.core.exception.StoreException; +import org.tron.core.exception.TaposException; +import org.tron.core.exception.TooBigTransactionException; +import org.tron.core.exception.TooBigTransactionResultException; +import org.tron.core.exception.TransactionExpirationException; +import org.tron.core.exception.UnLinkedBlockException; +import org.tron.core.exception.VMIllegalException; +import org.tron.core.exception.ValidateScheduleException; +import org.tron.core.exception.ValidateSignatureException; +import org.tron.core.net.message.BlockMessage; +import org.tron.core.net.message.MessageTypes; +import org.tron.core.net.message.TransactionMessage; +import org.tron.core.net.peer.PeerConnection; +import org.tron.protos.Protocol.Inventory.InventoryType; + +@Slf4j +@Component +public class TronNetDelegate { + + @Autowired + private SyncPool syncPool; + + @Autowired + private Manager dbManager; + + @Getter + private Object blockLock = new Object(); + + private int blockIdCacheSize = 100; + + private Queue freshBlockId = new ConcurrentLinkedQueue() { + @Override + public boolean offer(BlockId blockId) { + if (size() > blockIdCacheSize) { + super.poll(); + } + return super.offer(blockId); + } + }; + + public Collection getActivePeer() { + return syncPool.getActivePeers(); + } + + public long getSyncBeginNumber() { + return dbManager.getSyncBeginNumber(); + } + + public long getBlockTime(BlockId id) throws P2pException { + try { + return dbManager.getBlockById(id).getTimeStamp(); + } catch (BadItemException | ItemNotFoundException e) { + throw new P2pException(TypeEnum.DB_ITEM_NOT_FOUND, id.getString()); + } + } + + public BlockId getHeadBlockId() { + return dbManager.getHeadBlockId(); + } + + public BlockId getSolidBlockId() { + return dbManager.getSolidBlockId(); + } + + public BlockId getGenesisBlockId() { + return dbManager.getGenesisBlockId(); + } + + public BlockId getBlockIdByNum(long num) throws P2pException { + try { + return dbManager.getBlockIdByNum(num); + }catch (ItemNotFoundException e) { + throw new P2pException(TypeEnum.DB_ITEM_NOT_FOUND, "num: " + num); + } + } + + public BlockCapsule getGenesisBlock() { + return dbManager.getGenesisBlock(); + } + + public long getHeadBlockTimeStamp() { + return dbManager.getHeadBlockTimeStamp(); + } + + public boolean containBlock(BlockId id) { + return dbManager.containBlock(id); + } + + public boolean containBlockInMainChain(BlockId id) { + return dbManager.containBlockInMainChain(id); + } + + public LinkedList getBlockChainHashesOnFork(BlockId forkBlockHash) throws P2pException { + try { + return dbManager.getBlockChainHashesOnFork(forkBlockHash); + }catch (NonCommonBlockException e){ + throw new P2pException(TypeEnum.HARD_FORKED, forkBlockHash.getString()); + } + } + + public boolean canChainRevoke(long num) { + return num >= dbManager.getSyncBeginNumber(); + } + + public boolean contain(Sha256Hash hash, MessageTypes type) { + if (type.equals(MessageTypes.BLOCK)) { + return dbManager.containBlock(hash); + } else if (type.equals(MessageTypes.TRX)) { + return dbManager.getTransactionStore().has(hash.getBytes()); + } + return false; + } + + public Message getData(Sha256Hash hash, InventoryType type) throws P2pException { + try { + switch (type) { + case BLOCK: + return new BlockMessage(dbManager.getBlockById(hash)); + case TRX: + TransactionCapsule tx = dbManager.getTransactionStore().get(hash.getBytes()); + if (tx != null) { + return new TransactionMessage(tx.getData()); + } + throw new StoreException(); + default: + throw new StoreException(); + } + }catch (StoreException e) { + throw new P2pException(TypeEnum.DB_ITEM_NOT_FOUND, + "type: " + type + ", hash: " + hash.getByteString()); + } + } + + public void processBlock(BlockCapsule block) throws P2pException { + synchronized (blockLock) { + try { + if (!freshBlockId.contains(block.getBlockId())) { + dbManager.pushBlock(block); + freshBlockId.add(block.getBlockId()); + logger.info("Success process block {}.", block.getBlockId().getString()); + } + } catch (ValidateSignatureException + | ContractValidateException + | ContractExeException + | UnLinkedBlockException + | ValidateScheduleException + | AccountResourceInsufficientException + | TaposException + | TooBigTransactionException + | TooBigTransactionResultException + | DupTransactionException + | TransactionExpirationException + | BadNumberBlockException + | BadBlockException + | NonCommonBlockException + | ReceiptCheckErrException + | VMIllegalException e) { + throw new P2pException(TypeEnum.BAD_BLOCK, e); + } + } + } + + public void pushTransaction (TransactionCapsule trx) throws P2pException { + try { + dbManager.pushTransaction(trx); + } catch (ContractSizeNotEqualToOneException + | ValidateSignatureException + | VMIllegalException e) { + throw new P2pException(TypeEnum.BAD_TRX, e); + } catch (ContractValidateException + | ContractExeException + | DupTransactionException + | TaposException + | TooBigTransactionException + | TransactionExpirationException + | ReceiptCheckErrException + | TooBigTransactionResultException + | AccountResourceInsufficientException e) { + throw new P2pException(TypeEnum.TRX_EXE_FAILED, e); + } + } +} diff --git a/src/main/java/org/tron/core/net/peer/TronHandler.java b/src/main/java/org/tron/core/net/TronNetHandler.java similarity index 61% rename from src/main/java/org/tron/core/net/peer/TronHandler.java rename to src/main/java/org/tron/core/net/TronNetHandler.java index fc2b482df83..87c23ba0b65 100644 --- a/src/main/java/org/tron/core/net/peer/TronHandler.java +++ b/src/main/java/org/tron/core/net/TronNetHandler.java @@ -1,31 +1,36 @@ -package org.tron.core.net.peer; +package org.tron.core.net; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import org.tron.common.overlay.server.Channel; import org.tron.common.overlay.server.MessageQueue; import org.tron.core.net.message.TronMessage; +import org.tron.core.net.peer.PeerConnection; @Component @Scope("prototype") -public class TronHandler extends SimpleChannelInboundHandler { +public class TronNetHandler extends SimpleChannelInboundHandler { protected PeerConnection peer; - private MessageQueue msgQueue = null; + private MessageQueue msgQueue; - public PeerConnectionDelegate peerDel; + @Autowired + private TronNetService tronNetService; - public void setPeerDel(PeerConnectionDelegate peerDel) { - this.peerDel = peerDel; - } +// @Autowired +// private TronNetHandler (final ApplicationContext ctx){ +// tronNetService = ctx.getBean(TronNetService.class); +// } @Override public void channelRead0(final ChannelHandlerContext ctx, TronMessage msg) throws Exception { msgQueue.receivedMessage(msg); - peerDel.onMessage(peer, msg); + tronNetService.onMessage(peer, msg); } @Override diff --git a/src/main/java/org/tron/core/net/TronNetService.java b/src/main/java/org/tron/core/net/TronNetService.java new file mode 100644 index 00000000000..0fd9da34c99 --- /dev/null +++ b/src/main/java/org/tron/core/net/TronNetService.java @@ -0,0 +1,146 @@ +package org.tron.core.net; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.common.overlay.message.Message; +import org.tron.common.overlay.server.ChannelManager; +import org.tron.core.exception.P2pException; +import org.tron.core.exception.P2pException.TypeEnum; +import org.tron.core.net.message.TronMessage; +import org.tron.core.net.messagehandler.BlockMsgHandler; +import org.tron.core.net.messagehandler.ChainInventoryMsgHandler; +import org.tron.core.net.messagehandler.FetchInvDataMsgHandler; +import org.tron.core.net.messagehandler.InventoryMsgHandler; +import org.tron.core.net.messagehandler.SyncBlockChainMsgHandler; +import org.tron.core.net.messagehandler.TransactionsMsgHandler; +import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.peer.PeerStatusCheck; +import org.tron.core.net.service.AdvService; +import org.tron.core.net.service.SyncService; +import org.tron.protos.Protocol.ReasonCode; + +@Slf4j +@Component +public class TronNetService { + + @Autowired + private ChannelManager channelManager; + + @Autowired + private AdvService advService; + + @Autowired + private SyncService syncService; + + @Autowired + private PeerStatusCheck peerStatusCheck; + + @Autowired + private SyncBlockChainMsgHandler syncBlockChainMsgHandler; + + @Autowired + private ChainInventoryMsgHandler chainInventoryMsgHandler; + + @Autowired + private InventoryMsgHandler inventoryMsgHandler; + + + @Autowired + private FetchInvDataMsgHandler fetchInvDataMsgHandler; + + @Autowired + private BlockMsgHandler blockMsgHandler; + + @Autowired + private TransactionsMsgHandler transactionsMsgHandler; + + public void start () { + channelManager.init(); + advService.init(); + syncService.init(); + peerStatusCheck.init(); + transactionsMsgHandler.init(); + logger.info("TronNetService start successfully."); + } + + public void close () { + channelManager.close(); + advService.close(); + syncService.close(); + peerStatusCheck.close(); + transactionsMsgHandler.close(); + logger.info("TronNetService closed successfully."); + } + + public void broadcast(Message msg) { + advService.broadcast(msg); + } + + protected void onMessage(PeerConnection peer, TronMessage msg) { + try { + switch (msg.getType()) { + case SYNC_BLOCK_CHAIN: + syncBlockChainMsgHandler.processMessage(peer, msg); + break; + case BLOCK_CHAIN_INVENTORY: + chainInventoryMsgHandler.processMessage(peer, msg); + break; + case INVENTORY: + inventoryMsgHandler.processMessage(peer, msg); + break; + case FETCH_INV_DATA: + fetchInvDataMsgHandler.processMessage(peer, msg); + break; + case BLOCK: + blockMsgHandler.processMessage(peer, msg); + break; + case TRXS: + transactionsMsgHandler.processMessage(peer, msg); + break; + default: + throw new P2pException(TypeEnum.NO_SUCH_MESSAGE, msg.getType().toString()); + } + }catch (Exception e) { + processException(peer, msg, e); + } + } + + private void processException (PeerConnection peer, TronMessage msg, Exception ex) { + ReasonCode code = null; + + if (ex instanceof P2pException) { + TypeEnum type = ((P2pException) ex).getType(); + switch (type) { + case BAD_TRX: + code = ReasonCode.BAD_TX; + break; + case BAD_BLOCK: + code = ReasonCode.BAD_BLOCK; + break; + case NO_SUCH_MESSAGE: + case MESSAGE_WITH_WRONG_LENGTH: + case BAD_MESSAGE: + code = ReasonCode.BAD_PROTOCOL; + break; + case SYNC_FAILED: + code = ReasonCode.SYNC_FAIL; + break; + case UNLINK_BLOCK: + code = ReasonCode.UNLINKABLE; + break; + case DEFAULT: + code = ReasonCode.UNKNOWN; + break; + } + logger.error("Message {} /n process failed from peer {}, type: {}, detail: {}.", + msg, peer.getInetAddress(), type, ex.getMessage()); + } else { + code = ReasonCode.UNKNOWN; + logger.error("Message {} /n process failed from peer {}.", + msg, peer.getInetAddress(), ex); + } + + peer.disconnect(code); + } +} diff --git a/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java b/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java new file mode 100644 index 00000000000..f1bef4e6d90 --- /dev/null +++ b/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java @@ -0,0 +1,92 @@ +package org.tron.core.net.messagehandler; + +import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; +import static org.tron.core.config.Parameter.ChainConstant.BLOCK_SIZE; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.BlockCapsule.BlockId; +import org.tron.core.exception.P2pException; +import org.tron.core.exception.P2pException.TypeEnum; +import org.tron.core.net.TronNetDelegate; +import org.tron.core.net.message.BlockMessage; +import org.tron.core.net.message.TronMessage; +import org.tron.core.net.peer.Item; +import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.service.AdvService; +import org.tron.core.net.service.SyncService; +import org.tron.core.services.WitnessProductBlockService; +import org.tron.protos.Protocol.Inventory.InventoryType; + +@Slf4j +@Component +public class BlockMsgHandler implements TronMsgHandler { + + @Autowired + private TronNetDelegate tronNetDelegate; + + @Autowired + private AdvService advService; + + @Autowired + private SyncService syncService; + + @Autowired + private WitnessProductBlockService witnessProductBlockService; + + private int maxBlockSize = BLOCK_SIZE + 1000; + + @Override + public void processMessage (PeerConnection peer, TronMessage msg) throws P2pException { + + BlockMessage blockMessage = (BlockMessage) msg; + + check(peer, blockMessage); + + BlockId blockId = blockMessage.getBlockId(); + Item item = new Item(blockId, InventoryType.BLOCK); + if (peer.getSyncBlockRequested().containsKey(blockId)) { + peer.getSyncBlockRequested().remove(blockId); + syncService.processBlock(peer, blockMessage); + } else { + peer.getAdvInvRequest().remove(item); + processBlock(peer, blockMessage.getBlockCapsule()); + } + } + + private void check (PeerConnection peer, BlockMessage msg) throws P2pException { + Item item = new Item(msg.getBlockId(), InventoryType.BLOCK); + if (!peer.getSyncBlockRequested().containsKey(msg.getBlockId()) && !peer.getAdvInvRequest().containsKey(item)) { + throw new P2pException(TypeEnum.BAD_MESSAGE, "no request"); + } + BlockCapsule blockCapsule = msg.getBlockCapsule(); + if (blockCapsule.getInstance().getSerializedSize() > maxBlockSize) { + throw new P2pException(TypeEnum.BAD_MESSAGE, "block size over limit"); + } + long gap = blockCapsule.getTimeStamp() - System.currentTimeMillis(); + if (gap >= BLOCK_PRODUCED_INTERVAL) { + throw new P2pException(TypeEnum.BAD_MESSAGE, "block time error"); + } + } + + private void processBlock(PeerConnection peer, BlockCapsule block) throws P2pException { + BlockId blockId = block.getBlockId(); + if (!tronNetDelegate.containBlock(block.getParentBlockId())) { + logger.warn("Get unlink block {} from {}, head is {}.", blockId.getString(), peer.getInetAddress(), tronNetDelegate + .getHeadBlockId().getString()); + syncService.startSync(peer); + return; + } + tronNetDelegate.processBlock(block); + witnessProductBlockService.validWitnessProductTwoBlock(block); + tronNetDelegate.getActivePeer().forEach(p -> { + if (p.getAdvInvReceive().getIfPresent(blockId) != null) { + p.setBlockBothHave(blockId); + } + }); + advService.broadcast(new BlockMessage(block)); + } + +} diff --git a/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java b/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java new file mode 100644 index 00000000000..1e82f2160df --- /dev/null +++ b/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java @@ -0,0 +1,127 @@ +package org.tron.core.net.messagehandler; + +import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; + +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.capsule.BlockCapsule.BlockId; +import org.tron.core.config.Parameter.ChainConstant; +import org.tron.core.config.Parameter.NodeConstant; +import org.tron.core.exception.P2pException; +import org.tron.core.exception.P2pException.TypeEnum; +import org.tron.core.net.TronNetDelegate; +import org.tron.core.net.message.ChainInventoryMessage; +import org.tron.core.net.message.TronMessage; +import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.service.SyncService; + +@Slf4j +@Component +public class ChainInventoryMsgHandler implements TronMsgHandler { + + @Autowired + private TronNetDelegate tronNetDelegate; + + @Autowired + private SyncService syncService; + + @Override + public void processMessage (PeerConnection peer, TronMessage msg) throws P2pException { + + ChainInventoryMessage chainInventoryMessage = (ChainInventoryMessage) msg; + + check(peer, chainInventoryMessage); + + peer.setNeedSyncFromPeer(true); + + peer.setSyncChainRequested(null); //todo thread sec + + Deque blockIdWeGet = new LinkedList<>(chainInventoryMessage.getBlockIds()); + + if (blockIdWeGet.size() == 1 && tronNetDelegate.containBlock(blockIdWeGet.peek())) { + peer.setNeedSyncFromPeer(false); + return; + } + + while (!peer.getSyncBlockToFetch().isEmpty()){ + if (peer.getSyncBlockToFetch().peekLast().equals(blockIdWeGet.peekFirst())) { + break; + } + peer.getSyncBlockToFetch().pollLast(); + } + + blockIdWeGet.poll(); + + peer.setRemainNum(chainInventoryMessage.getRemainNum()); + peer.getSyncBlockToFetch().addAll(blockIdWeGet); + + synchronized (tronNetDelegate.getBlockLock()) { + while (!peer.getSyncBlockToFetch().isEmpty() && tronNetDelegate + .containBlock(peer.getSyncBlockToFetch().peek())) { + BlockId blockId = peer.getSyncBlockToFetch().pop(); + logger.info("Block {} from {} is processed", blockId.getString(), peer.getNode().getHost()); + } + } +// +// if (chainInventoryMessage.getRemainNum() == 0 && peer.getSyncBlockToFetch().isEmpty()) { +// peer.setNeedSyncFromPeer(false); +// } + + if ((chainInventoryMessage.getRemainNum() == 0 && !peer.getSyncBlockToFetch().isEmpty()) || + (chainInventoryMessage.getRemainNum() != 0 && peer.getSyncBlockToFetch().size() > NodeConstant.SYNC_FETCH_BATCH_NUM)) { + syncService.setFetchFlag(true); + }else { + syncService.syncNext(peer); + } + } + + private void check(PeerConnection peer, ChainInventoryMessage msg) throws P2pException { + if (peer.getSyncChainRequested() == null) { + throw new P2pException(TypeEnum.BAD_MESSAGE, "not send syncBlockChainMsg"); + } + + List blockIds = msg.getBlockIds(); + if (CollectionUtils.isEmpty(blockIds)) { + throw new P2pException(TypeEnum.BAD_MESSAGE, "blockIds is empty"); + } + + if (blockIds.size() > NodeConstant.SYNC_FETCH_BATCH_NUM + 1) { + throw new P2pException(TypeEnum.BAD_MESSAGE, "big blockIds size: " + blockIds.size()); + } + + if (msg.getRemainNum() != 0 && blockIds.size() < NodeConstant.SYNC_FETCH_BATCH_NUM) { + throw new P2pException(TypeEnum.BAD_MESSAGE, + "remain: " + msg.getRemainNum() +", blockIds size: " + blockIds.size()); + } + + long num = blockIds.get(0).getNum(); + for (BlockId id : msg.getBlockIds()) { + if (id.getNum() != num++) { + throw new P2pException(TypeEnum.BAD_MESSAGE, "not continuous block"); + } + } + + if (!peer.getSyncChainRequested().getKey().contains(blockIds.get(0))) { + throw new P2pException(TypeEnum.BAD_MESSAGE, "unlinked block, my head: " + + peer.getSyncChainRequested().getKey().getLast().getString() + + ", peer: " + blockIds.get(0).getString()); + } + + if (tronNetDelegate.getHeadBlockId().getNum() > 0) { + long maxRemainTime = ChainConstant.CLOCK_MAX_DELAY + System.currentTimeMillis() - tronNetDelegate + .getBlockTime(tronNetDelegate.getSolidBlockId()); + long maxFutureNum = maxRemainTime / BLOCK_PRODUCED_INTERVAL + tronNetDelegate.getSolidBlockId().getNum(); + long lastNum = blockIds.get(blockIds.size() - 1).getNum(); + if (lastNum + msg.getRemainNum() > maxFutureNum) { + throw new P2pException(TypeEnum.BAD_MESSAGE, "lastNum: " + lastNum + " + remainNum: " + + msg.getRemainNum() + " > futureMaxNum: " + maxFutureNum); + } + } + } + +} diff --git a/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java b/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java new file mode 100644 index 00000000000..67c7dba5608 --- /dev/null +++ b/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java @@ -0,0 +1,143 @@ +package org.tron.core.net.messagehandler; + +import com.google.common.collect.Lists; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.common.overlay.discover.node.statistics.MessageCount; +import org.tron.common.overlay.message.Message; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.capsule.BlockCapsule.BlockId; +import org.tron.core.config.Parameter.ChainConstant; +import org.tron.core.config.Parameter.NodeConstant; +import org.tron.core.exception.P2pException; +import org.tron.core.exception.P2pException.TypeEnum; +import org.tron.core.net.TronNetDelegate; +import org.tron.core.net.message.BlockMessage; +import org.tron.core.net.message.FetchInvDataMessage; +import org.tron.core.net.message.MessageTypes; +import org.tron.core.net.message.TransactionMessage; +import org.tron.core.net.message.TransactionsMessage; +import org.tron.core.net.message.TronMessage; +import org.tron.core.net.peer.Item; +import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.service.AdvService; +import org.tron.core.net.service.SyncService; +import org.tron.protos.Protocol.Inventory.InventoryType; +import org.tron.protos.Protocol.ReasonCode; +import org.tron.protos.Protocol.Transaction; + +@Slf4j +@Component +public class FetchInvDataMsgHandler implements TronMsgHandler { + + @Autowired + private TronNetDelegate tronNetDelegate; + + @Autowired + private SyncService syncService; + + @Autowired + private AdvService advService; + + private int MAX_SIZE = 1_000_000; + + @Override + public void processMessage (PeerConnection peer, TronMessage msg) throws P2pException { + + FetchInvDataMessage fetchInvDataMsg = (FetchInvDataMessage) msg; + + check(peer, fetchInvDataMsg); + + InventoryType type = fetchInvDataMsg.getInventoryType(); + List transactions = Lists.newArrayList(); + + int size = 0; + + for (Sha256Hash hash : fetchInvDataMsg.getHashList()) { + Item item = new Item(hash, type); + Message message = advService.getMessage(item); + if (message == null) { + try { + message = tronNetDelegate.getData(hash, type); + } catch (Exception e) { + logger.error("Fetch item {} failed. reason: {}", item, hash, e.getMessage()); + peer.disconnect(ReasonCode.FETCH_FAIL); + return; + } + } + + if (type.equals(InventoryType.BLOCK)) { + BlockId blockId = ((BlockMessage) message).getBlockCapsule().getBlockId(); + if (peer.getBlockBothHave().getNum() < blockId.getNum()) { + peer.setBlockBothHave(blockId); + } + peer.sendMessage(message); + } else { + transactions.add(((TransactionMessage) message).getTransactionCapsule().getInstance()); + size += ((TransactionMessage) message).getTransactionCapsule().getInstance().getSerializedSize(); + if (size > MAX_SIZE) { + peer.sendMessage(new TransactionsMessage(transactions)); + transactions = Lists.newArrayList(); + size = 0; + } + } + } + if (transactions.size() > 0) { + peer.sendMessage(new TransactionsMessage(transactions)); + } + } + + private void check(PeerConnection peer, FetchInvDataMessage fetchInvDataMsg) throws P2pException{ + MessageTypes type = fetchInvDataMsg.getInvMessageType(); + + if (type == MessageTypes.TRX) { + for (Sha256Hash hash : fetchInvDataMsg.getHashList()) { + if (peer.getAdvInvSpread().getIfPresent(new Item(hash, InventoryType.TRX)) == null) { + throw new P2pException(TypeEnum.BAD_MESSAGE, "not spread inv: {}" + hash); + } + } + int fetchCount = peer.getNodeStatistics().messageStatistics.tronInTrxFetchInvDataElement + .getCount(10); + int maxCount = advService.getTrxCount().getCount(60); + if (fetchCount > maxCount) { + throw new P2pException(TypeEnum.BAD_MESSAGE, "maxCount: " + maxCount + ", fetchCount: " + fetchCount); + } + } else { + boolean isAdv = true; + for (Sha256Hash hash : fetchInvDataMsg.getHashList()) { + if (peer.getAdvInvSpread().getIfPresent(new Item(hash, InventoryType.BLOCK)) == null) { + isAdv = false; + break; + } + } + if (isAdv) { + MessageCount tronOutAdvBlock = peer.getNodeStatistics().messageStatistics.tronOutAdvBlock; + tronOutAdvBlock.add(fetchInvDataMsg.getHashList().size()); + int outBlockCountIn1min = tronOutAdvBlock.getCount(60); + int producedBlockIn2min = 120_000 / ChainConstant.BLOCK_PRODUCED_INTERVAL; + if (outBlockCountIn1min > producedBlockIn2min) { + throw new P2pException(TypeEnum.BAD_MESSAGE, "producedBlockIn2min: " + producedBlockIn2min + + ", outBlockCountIn1min: " + outBlockCountIn1min); + } + } else { + if (!peer.isNeedSyncFromUs()) { + throw new P2pException(TypeEnum.BAD_MESSAGE, "no need sync"); + } + for (Sha256Hash hash : fetchInvDataMsg.getHashList()) { + long blockNum = new BlockId(hash).getNum(); + long minBlockNum = peer.getLastSyncBlockId().getNum() - 2 * NodeConstant.SYNC_FETCH_BATCH_NUM; + if (blockNum < minBlockNum) { + throw new P2pException(TypeEnum.BAD_MESSAGE, "minBlockNum: " + minBlockNum + ", blockNum: " + blockNum); + } + if (peer.getSyncBlockIdCache().getIfPresent(hash) != null) { + throw new P2pException(TypeEnum.BAD_MESSAGE, new BlockId(hash).getString() + " is exist"); + } + peer.getSyncBlockIdCache().put(hash, System.currentTimeMillis()); + } + } + } + } + +} diff --git a/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java b/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java new file mode 100644 index 00000000000..618ccfc8523 --- /dev/null +++ b/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java @@ -0,0 +1,77 @@ +package org.tron.core.net.messagehandler; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.net.TronNetDelegate; +import org.tron.core.net.message.InventoryMessage; +import org.tron.core.net.message.TronMessage; +import org.tron.core.net.peer.Item; +import org.tron.core.net.peer.PeerConnection; +import org.tron.core.net.service.AdvService; +import org.tron.protos.Protocol.Inventory.InventoryType; + +@Slf4j +@Component +public class InventoryMsgHandler implements TronMsgHandler{ + + @Autowired + private TronNetDelegate tronNetDelegate; + + @Autowired + private AdvService advService; + + @Autowired + private TransactionsMsgHandler transactionsMsgHandler; + + private int maxCountIn10s = 10_000; + + @Override + public void processMessage (PeerConnection peer, TronMessage msg) { + InventoryMessage inventoryMessage = (InventoryMessage) msg; + InventoryType type = inventoryMessage.getInventoryType(); + + if (!check(peer, inventoryMessage)) { + return; + } + + for (Sha256Hash id : inventoryMessage.getHashList()) { + Item item = new Item(id, type); + peer.getAdvInvReceive().put(item, System.currentTimeMillis()); + advService.addInv(item); + } + } + + private boolean check (PeerConnection peer, InventoryMessage inventoryMessage) { + InventoryType type = inventoryMessage.getInventoryType(); + int size = inventoryMessage.getHashList().size(); + +// if (size > NetConstants.MAX_INV_FETCH_PER_PEER) { +// throw new P2pException(TypeEnum.BAD_MESSAGE, "size: " + size); +// } + + if (peer.isNeedSyncFromPeer() || peer.isNeedSyncFromUs()) { + logger.warn("Drop inv: {} size: {} from Peer {}, syncFromUs: {}, syncFromPeer: {}.", + type, size, peer.getInetAddress(), peer.isNeedSyncFromUs(), peer.isNeedSyncFromPeer()); + return false; + } + + if (type.equals(InventoryType.TRX)) { + int count = peer.getNodeStatistics().messageStatistics.tronInTrxInventoryElement.getCount(10); + if (count > maxCountIn10s) { + logger.warn("Drop inv: {} size: {} from Peer {}, Inv count: {} is overload.", + type, size, peer.getInetAddress(), count); + return false; + } + + if (transactionsMsgHandler.isBusy()) { + logger.warn("Drop inv: {} size: {} from Peer {}, transactionsMsgHandler is busy.", + type, size, peer.getInetAddress()); + return false; + } + } + + return true; + } +} diff --git a/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java b/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java new file mode 100644 index 00000000000..ff9a85efe1b --- /dev/null +++ b/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java @@ -0,0 +1,100 @@ +package org.tron.core.net.messagehandler; + +import java.util.LinkedList; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.capsule.BlockCapsule.BlockId; +import org.tron.core.config.Parameter.NodeConstant; +import org.tron.core.exception.P2pException; +import org.tron.core.exception.P2pException.TypeEnum; +import org.tron.core.net.TronNetDelegate; +import org.tron.core.net.message.ChainInventoryMessage; +import org.tron.core.net.message.SyncBlockChainMessage; +import org.tron.core.net.message.TronMessage; +import org.tron.core.net.peer.PeerConnection; + +@Slf4j +@Component +public class SyncBlockChainMsgHandler implements TronMsgHandler { + + @Autowired + private TronNetDelegate tronNetDelegate; + + @Override + public void processMessage(PeerConnection peer, TronMessage msg) throws P2pException { + + SyncBlockChainMessage syncBlockChainMessage = (SyncBlockChainMessage) msg; + + check(peer, syncBlockChainMessage); + + long remainNum = 0; + + List summaryChainIds = syncBlockChainMessage.getBlockIds(); + + LinkedList blockIds = getLostBlockIds(summaryChainIds); + + if (blockIds.size() == 1){ + peer.setNeedSyncFromUs(false); + }else { + peer.setNeedSyncFromUs(true); + remainNum = tronNetDelegate.getHeadBlockId().getNum() - blockIds.peekLast().getNum(); + } +// +// if (!peer.isNeedSyncFromPeer() +// && !tronNetDelegate.contain(Iterables.getLast(summaryChainIds), MessageTypes.BLOCK) +// && tronNetDelegate.canChainRevoke(summaryChainIds.get(0).getNum())) { +// //startSyncWithPeer(peer); +// } + + peer.setLastSyncBlockId(blockIds.peekLast()); + peer.setRemainNum(remainNum); + peer.sendMessage(new ChainInventoryMessage(blockIds, remainNum)); + } + + private void check(PeerConnection peer, SyncBlockChainMessage msg) throws P2pException { + List blockIds = msg.getBlockIds(); + if (CollectionUtils.isEmpty(blockIds)){ + throw new P2pException(TypeEnum.BAD_MESSAGE, "SyncBlockChain blockIds is empty"); + } + + BlockId firstId = blockIds.get(0); + if (!tronNetDelegate.containBlockInMainChain(firstId)){ + throw new P2pException(TypeEnum.BAD_MESSAGE, "No first block:" + firstId.getString()); + } + + long headNum = tronNetDelegate.getHeadBlockId().getNum(); + if (firstId.getNum() > headNum){ + throw new P2pException(TypeEnum.BAD_MESSAGE, "First blockNum:" + firstId.getNum() +" gt my head BlockNum:" + headNum); + } + + BlockId lastSyncBlockId = peer.getLastSyncBlockId(); + long lastNum = blockIds.get(blockIds.size() - 1).getNum(); + if (lastSyncBlockId != null && lastSyncBlockId.getNum() > lastNum) { + throw new P2pException(TypeEnum.BAD_MESSAGE, "lastSyncNum:" + lastSyncBlockId.getNum() + " gt lastNum:" + lastNum); + } + } + + private LinkedList getLostBlockIds(List blockIds) throws P2pException { + + BlockId unForkId = null; + for (int i = blockIds.size() - 1; i >= 0; i--){ + if (tronNetDelegate.containBlockInMainChain(blockIds.get(i))){ + unForkId = blockIds.get(i); + break; + } + } + + long len = Math.min(tronNetDelegate.getHeadBlockId().getNum(), unForkId.getNum() + NodeConstant.SYNC_FETCH_BATCH_NUM); + + LinkedList ids = new LinkedList<>(); + for (long i = unForkId.getNum(); i <= len; i++) { + BlockId id = tronNetDelegate.getBlockIdByNum(i); + ids.add(id); + } + return ids; + } + +} diff --git a/src/main/java/org/tron/core/net/node/TrxHandler.java b/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java similarity index 51% rename from src/main/java/org/tron/core/net/node/TrxHandler.java rename to src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java index 0f9defc3ad1..fe6b553fa73 100644 --- a/src/main/java/org/tron/core/net/node/TrxHandler.java +++ b/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java @@ -1,5 +1,6 @@ -package org.tron.core.net.node; +package org.tron.core.net.messagehandler; +import com.googlecode.cqengine.query.simple.In; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -9,11 +10,17 @@ import java.util.concurrent.TimeUnit; import lombok.Getter; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.core.config.args.Args; -import org.tron.core.exception.TraitorPeerException; +import org.tron.core.exception.P2pException; +import org.tron.core.exception.P2pException.TypeEnum; +import org.tron.core.net.TronNetDelegate; import org.tron.core.net.message.TransactionMessage; import org.tron.core.net.message.TransactionsMessage; +import org.tron.core.net.message.TronMessage; +import org.tron.core.net.peer.Item; +import org.tron.core.net.service.AdvService; import org.tron.core.net.peer.PeerConnection; import org.tron.protos.Protocol.Inventory.InventoryType; import org.tron.protos.Protocol.ReasonCode; @@ -22,15 +29,19 @@ @Slf4j(topic = "net") @Component -public class TrxHandler { +public class TransactionsMsgHandler implements TronMsgHandler { - private NodeImpl nodeImpl; + @Autowired + private TronNetDelegate tronNetDelegate; + + @Autowired + private AdvService advService; private static int MAX_TRX_SIZE = 50_000; private static int MAX_SMART_CONTRACT_SUBMIT_SIZE = 100; - private static int TIME_OUT = 10 * 60 * 1000; +// private static int TIME_OUT = 10 * 60 * 1000; private BlockingQueue smartContractQueue = new LinkedBlockingQueue(MAX_TRX_SIZE); @@ -42,67 +53,94 @@ public class TrxHandler { private ScheduledExecutorService smartContractExecutor = Executors.newSingleThreadScheduledExecutor(); - public void init(NodeImpl nodeImpl) { - this.nodeImpl = nodeImpl; + class TrxEvent { + @Getter + private PeerConnection peer; + @Getter + private TransactionMessage msg; + @Getter + private long time; + + public TrxEvent(PeerConnection peer, TransactionMessage msg) { + this.peer = peer; + this.msg = msg; + this.time = System.currentTimeMillis(); + } + } + + public void init() { handleSmartContract(); } - private void handleSmartContract() { - smartContractExecutor.scheduleWithFixedDelay(() -> { - try { - while (queue.size() < MAX_SMART_CONTRACT_SUBMIT_SIZE) { - TrxEvent event = smartContractQueue.take(); - if (System.currentTimeMillis() - event.getTime() > TIME_OUT) { - logger.warn("Drop smart contract {} from peer {}."); - continue; - } - trxHandlePool.submit(() -> nodeImpl.onHandleTransactionMessage(event.getPeer(), event.getMsg())); - } - } catch (Exception e) { - logger.error("Handle smart contract exception", e); - } - }, 1000, 20, TimeUnit.MILLISECONDS); + public void close() { + smartContractExecutor.shutdown(); } - public void handleTransactionsMessage(PeerConnection peer, TransactionsMessage msg) { - for (Transaction trx : msg.getTransactions().getTransactionsList()) { - Item item = new Item(new TransactionMessage(trx).getMessageId(), InventoryType.TRX); - if (!peer.getAdvObjWeRequested().containsKey(item)) { - logger.warn("Receive trx {} from peer {} without fetch request.", - msg.getMessageId(), peer.getInetAddress()); - peer.setSyncFlag(false); - peer.disconnect(ReasonCode.BAD_PROTOCOL); - return; - } - peer.getAdvObjWeRequested().remove(item); + public boolean isBusy() { + return queue.size() + smartContractQueue.size() > MAX_TRX_SIZE; + } + + @Override + public void processMessage(PeerConnection peer, TronMessage msg) throws P2pException { + TransactionsMessage transactionsMessage = (TransactionsMessage) msg; + check (peer, transactionsMessage); + for (Transaction trx : transactionsMessage.getTransactions().getTransactionsList()) { int type = trx.getRawData().getContract(0).getType().getNumber(); if (type == ContractType.TriggerSmartContract_VALUE || type == ContractType.CreateSmartContract_VALUE) { if (!smartContractQueue.offer(new TrxEvent(peer, new TransactionMessage(trx)))) { - logger.warn("Add smart contract failed, smartContractQueue size {} queueSize {}", - smartContractQueue.size(), queue.size()); + logger.warn("Add smart contract failed, queueSize {}:{}", smartContractQueue.size(), queue.size()); } } else { - trxHandlePool.submit(() -> nodeImpl.onHandleTransactionMessage(peer, new TransactionMessage(trx))); + trxHandlePool.submit(() -> handleTransaction(peer, new TransactionMessage(trx))); } } } - public boolean isBusy() { - return queue.size() + smartContractQueue.size() > MAX_TRX_SIZE; + private void check(PeerConnection peer, TransactionsMessage msg) throws P2pException { + for (Transaction trx : msg.getTransactions().getTransactionsList()) { + Item item = new Item(new TransactionMessage(trx).getMessageId(), InventoryType.TRX); + if (!peer.getAdvInvRequest().containsKey(item)) { + throw new P2pException(TypeEnum.BAD_MESSAGE, + "trx: " + msg.getMessageId() + " without request."); + } + peer.getAdvInvRequest().remove(item); + } } - class TrxEvent { - @Getter - private PeerConnection peer; - @Getter - private TransactionMessage msg; - @Getter - private long time; + private void handleSmartContract() { + smartContractExecutor.scheduleWithFixedDelay(() -> { + try { + while (queue.size() < MAX_SMART_CONTRACT_SUBMIT_SIZE) { + TrxEvent event = smartContractQueue.take(); + trxHandlePool.submit(() -> handleTransaction(event.getPeer(), event.getMsg())); + } + } catch (Exception e) { + logger.error("Handle smart contract exception.", e); + } + }, 1000, 20, TimeUnit.MILLISECONDS); + } - public TrxEvent(PeerConnection peer, TransactionMessage msg) { - this.peer = peer; - this.msg = msg; - this.time = System.currentTimeMillis(); + private void handleTransaction (PeerConnection peer, TransactionMessage trx) { + if (peer.isDisconnect()) { + logger.warn("Drop trx {} from {}, peer is disconnect.", trx.getMessageId(), peer.getInetAddress()); + return; + } + + if (advService.getMessage(new Item(trx.getMessageId(), InventoryType.TRX)) != null) { + return; + } + + try { + tronNetDelegate.pushTransaction(trx.getTransactionCapsule()); + advService.broadcast(trx); + }catch (P2pException e) { + logger.warn("Trx {} from peer {} process failed. type: {}, reason: {}", + trx.getMessageId(), peer.getInetAddress(), e.getType(), e.getMessage()); + if (e.getType().equals(TypeEnum.BAD_TRX)) { + peer.disconnect(ReasonCode.BAD_TX); + } + }catch (Exception e) { + logger.error("Trx {} from peer {} process failed.", trx.getMessageId(), peer.getInetAddress(), e); } } } \ No newline at end of file diff --git a/src/main/java/org/tron/core/net/messagehandler/TronMsgHandler.java b/src/main/java/org/tron/core/net/messagehandler/TronMsgHandler.java new file mode 100644 index 00000000000..e6052f49597 --- /dev/null +++ b/src/main/java/org/tron/core/net/messagehandler/TronMsgHandler.java @@ -0,0 +1,11 @@ +package org.tron.core.net.messagehandler; + +import org.tron.core.exception.P2pException; +import org.tron.core.net.message.TronMessage; +import org.tron.core.net.peer.PeerConnection; + +public interface TronMsgHandler { + + void processMessage(PeerConnection peer, TronMessage msg) throws P2pException; + +} diff --git a/src/main/java/org/tron/core/net/node/Node.java b/src/main/java/org/tron/core/net/node/Node.java deleted file mode 100644 index 21b964dfb3c..00000000000 --- a/src/main/java/org/tron/core/net/node/Node.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.tron.core.net.node; - -import org.tron.common.overlay.message.Message; -import org.tron.common.utils.Quitable; -import org.tron.common.utils.Sha256Hash; - -public interface Node extends Quitable { - - void setNodeDelegate(NodeDelegate nodeDel); - - void broadcast(Message msg); - - void listen(); - - void syncFrom(Sha256Hash myHeadBlockHash); - - void close() throws InterruptedException; -} diff --git a/src/main/java/org/tron/core/net/node/NodeDelegate.java b/src/main/java/org/tron/core/net/node/NodeDelegate.java deleted file mode 100644 index 2a3f6ccdc75..00000000000 --- a/src/main/java/org/tron/core/net/node/NodeDelegate.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.tron.core.net.node; - -import java.util.Deque; -import java.util.LinkedList; -import java.util.List; -import org.tron.common.overlay.message.Message; -import org.tron.common.utils.Sha256Hash; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.capsule.BlockCapsule.BlockId; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.exception.BadBlockException; -import org.tron.core.exception.BadTransactionException; -import org.tron.core.exception.NonCommonBlockException; -import org.tron.core.exception.StoreException; -import org.tron.core.exception.TronException; -import org.tron.core.exception.UnLinkedBlockException; -import org.tron.core.net.message.MessageTypes; - -public interface NodeDelegate { - - LinkedList handleBlock(BlockCapsule block, boolean syncMode) - throws BadBlockException, UnLinkedBlockException, InterruptedException, NonCommonBlockException; - - boolean handleTransaction(TransactionCapsule trx) throws BadTransactionException; - - LinkedList getLostBlockIds(List blockChainSummary) throws StoreException; - - Deque getBlockChainSummary(BlockId beginBLockId, Deque blockIds) - throws TronException; - - Message getData(Sha256Hash msgId, MessageTypes type) throws StoreException; - - void syncToCli(long unSyncNum); - - long getBlockTime(BlockId id); - - BlockId getHeadBlockId(); - - BlockId getSolidBlockId(); - - boolean contain(Sha256Hash hash, MessageTypes type); - - boolean containBlock(BlockId id); - - long getHeadBlockTimeStamp(); - - boolean containBlockInMainChain(BlockId id); - - BlockCapsule getGenesisBlock(); - - boolean canChainRevoke(long num); -} diff --git a/src/main/java/org/tron/core/net/node/NodeDelegateImpl.java b/src/main/java/org/tron/core/net/node/NodeDelegateImpl.java deleted file mode 100755 index 799615ca124..00000000000 --- a/src/main/java/org/tron/core/net/node/NodeDelegateImpl.java +++ /dev/null @@ -1,337 +0,0 @@ -package org.tron.core.net.node; - -import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; -import static org.tron.core.config.Parameter.ChainConstant.BLOCK_SIZE; - -import com.google.common.primitives.Longs; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Deque; -import java.util.LinkedList; -import java.util.List; -import java.util.stream.Collectors; -import lombok.extern.slf4j.Slf4j; -import org.tron.common.overlay.message.Message; -import org.tron.common.utils.Sha256Hash; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.capsule.BlockCapsule.BlockId; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.Parameter.NodeConstant; -import org.tron.core.db.Manager; -import org.tron.core.exception.AccountResourceInsufficientException; -import org.tron.core.exception.BadBlockException; -import org.tron.core.exception.BadItemException; -import org.tron.core.exception.BadNumberBlockException; -import org.tron.core.exception.BadTransactionException; -import org.tron.core.exception.ContractExeException; -import org.tron.core.exception.ContractSizeNotEqualToOneException; -import org.tron.core.exception.ContractValidateException; -import org.tron.core.exception.DupTransactionException; -import org.tron.core.exception.ItemNotFoundException; -import org.tron.core.exception.NonCommonBlockException; -import org.tron.core.exception.ReceiptCheckErrException; -import org.tron.core.exception.StoreException; -import org.tron.core.exception.TaposException; -import org.tron.core.exception.TooBigTransactionException; -import org.tron.core.exception.TooBigTransactionResultException; -import org.tron.core.exception.TransactionExpirationException; -import org.tron.core.exception.TronException; -import org.tron.core.exception.UnLinkedBlockException; -import org.tron.core.exception.VMIllegalException; -import org.tron.core.exception.ValidateScheduleException; -import org.tron.core.exception.ValidateSignatureException; -import org.tron.core.net.message.BlockMessage; -import org.tron.core.net.message.MessageTypes; -import org.tron.core.net.message.TransactionMessage; - -@Slf4j(topic = "net") -public class NodeDelegateImpl implements NodeDelegate { - - private Manager dbManager; - - public NodeDelegateImpl(Manager dbManager) { - this.dbManager = dbManager; - } - - @Override - public synchronized LinkedList handleBlock(BlockCapsule block, boolean syncMode) - throws BadBlockException, UnLinkedBlockException, InterruptedException, NonCommonBlockException { - - if (block.getInstance().getSerializedSize() > BLOCK_SIZE + 100) { - throw new BadBlockException("block size over limit"); - } - - long gap = block.getTimeStamp() - System.currentTimeMillis(); - if (gap >= BLOCK_PRODUCED_INTERVAL) { - throw new BadBlockException("block time error"); - } - try { - dbManager.pushBlock(block); - if (!syncMode) { - List trx = null; - trx = block.getTransactions(); - return trx.stream() - .map(TransactionCapsule::getTransactionId) - .collect(Collectors.toCollection(LinkedList::new)); - } else { - return null; - } - - } catch (AccountResourceInsufficientException e) { - throw new BadBlockException("AccountResourceInsufficientException," + e.getMessage()); - } catch (ValidateScheduleException e) { - throw new BadBlockException("validate schedule exception," + e.getMessage()); - } catch (ValidateSignatureException e) { - throw new BadBlockException("validate signature exception," + e.getMessage()); - } catch (ContractValidateException e) { - throw new BadBlockException("ContractValidate exception," + e.getMessage()); - } catch (ContractExeException e) { - throw new BadBlockException("Contract Execute exception," + e.getMessage()); - } catch (TaposException e) { - throw new BadBlockException("tapos exception," + e.getMessage()); - } catch (DupTransactionException e) { - throw new BadBlockException("DupTransaction exception," + e.getMessage()); - } catch (TooBigTransactionException e) { - throw new BadBlockException("TooBigTransaction exception," + e.getMessage()); - } catch (TooBigTransactionResultException e) { - throw new BadBlockException("TooBigTransaction exception," + e.getMessage()); - } catch (TransactionExpirationException e) { - throw new BadBlockException("Expiration exception," + e.getMessage()); - } catch (BadNumberBlockException e) { - throw new BadBlockException("bad number exception," + e.getMessage()); - } catch (ReceiptCheckErrException e) { - throw new BadBlockException("TransactionTrace Exception," + e.getMessage()); - } catch (VMIllegalException e) { - throw new BadBlockException(e.getMessage()); - } - - } - - - @Override - public boolean handleTransaction(TransactionCapsule trx) throws BadTransactionException { - if (dbManager.getDynamicPropertiesStore().supportVM()) { - trx.resetResult(); - } - logger.debug("handle transaction"); - if (dbManager.getTransactionIdCache().getIfPresent(trx.getTransactionId()) != null) { - logger.warn("This transaction has been processed"); - return false; - } else { - dbManager.getTransactionIdCache().put(trx.getTransactionId(), true); - } - try { - dbManager.pushTransaction(trx); - } catch (ContractSizeNotEqualToOneException - | ValidateSignatureException - | VMIllegalException e) { - throw new BadTransactionException(e.getMessage()); - } catch (ContractValidateException - | ContractExeException - | AccountResourceInsufficientException - | DupTransactionException - | TaposException - | TooBigTransactionException - | TransactionExpirationException - | ReceiptCheckErrException - | TooBigTransactionResultException e) { - logger.warn("Handle transaction {} failed, reason: {}", trx.getTransactionId(), e.getMessage()); - return false; - } - return true; - } - - @Override - public LinkedList getLostBlockIds(List blockChainSummary) - throws StoreException { - - if (dbManager.getHeadBlockNum() == 0) { - return new LinkedList<>(); - } - - BlockId unForkedBlockId; - - if (blockChainSummary.isEmpty() || - (blockChainSummary.size() == 1 - && blockChainSummary.get(0).equals(dbManager.getGenesisBlockId()))) { - unForkedBlockId = dbManager.getGenesisBlockId(); - } else if (blockChainSummary.size() == 1 - && blockChainSummary.get(0).getNum() == 0) { - return new LinkedList(Arrays.asList(dbManager.getGenesisBlockId())); - } else { - - Collections.reverse(blockChainSummary); - unForkedBlockId = blockChainSummary.stream() - .filter(blockId -> containBlockInMainChain(blockId)) - .findFirst().orElse(null); - if (unForkedBlockId == null) { - return new LinkedList<>(); - } - } - - long unForkedBlockIdNum = unForkedBlockId.getNum(); - long len = Longs - .min(dbManager.getHeadBlockNum(), unForkedBlockIdNum + NodeConstant.SYNC_FETCH_BATCH_NUM); - - LinkedList blockIds = new LinkedList<>(); - for (long i = unForkedBlockIdNum; i <= len; i++) { - BlockId id = dbManager.getBlockIdByNum(i); - blockIds.add(id); - } - return blockIds; - } - - @Override - public Deque getBlockChainSummary(BlockId beginBlockId, Deque blockIdsToFetch) - throws TronException { - - Deque retSummary = new LinkedList<>(); - List blockIds = new ArrayList<>(blockIdsToFetch); - long highBlkNum; - long highNoForkBlkNum; - long syncBeginNumber = dbManager.getSyncBeginNumber(); - long lowBlkNum = syncBeginNumber < 0 ? 0 : syncBeginNumber; - - LinkedList forkList = new LinkedList<>(); - - if (!beginBlockId.equals(getGenesisBlock().getBlockId())) { - if (containBlockInMainChain(beginBlockId)) { - highBlkNum = beginBlockId.getNum(); - if (highBlkNum == 0) { - throw new TronException( - "This block don't equal my genesis block hash, but it is in my DB, the block id is :" - + beginBlockId.getString()); - } - highNoForkBlkNum = highBlkNum; - if (beginBlockId.getNum() < lowBlkNum) { - lowBlkNum = beginBlockId.getNum(); - } - } else { - forkList = dbManager.getBlockChainHashesOnFork(beginBlockId); - if (forkList.isEmpty()) { - throw new UnLinkedBlockException( - "We want to find forkList of this block: " + beginBlockId.getString() - + " ,but in KhasoDB we can not find it, It maybe a very old beginBlockId, we are sync once," - + " we switch and pop it after that time. "); - } - highNoForkBlkNum = forkList.peekLast().getNum(); - forkList.pollLast(); - Collections.reverse(forkList); - highBlkNum = highNoForkBlkNum + forkList.size(); - if (highNoForkBlkNum < lowBlkNum) { - throw new UnLinkedBlockException( - "It is a too old block that we take it as a forked block long long ago" - + "\n lowBlkNum:" + lowBlkNum - + "\n highNoForkBlkNum" + highNoForkBlkNum); - } - } - } else { - highBlkNum = dbManager.getHeadBlockNum(); - highNoForkBlkNum = highBlkNum; - - } - - if (!blockIds.isEmpty() && highBlkNum != blockIds.get(0).getNum() - 1) { - logger.error("Check ERROR: highBlkNum:" + highBlkNum + ",blockIdToSyncFirstNum is " - + blockIds.get(0).getNum() + ",blockIdToSyncEnd is " + blockIds.get(blockIds.size() - 1) - .getNum()); - } - - long realHighBlkNum = highBlkNum + blockIds.size(); - do { - if (lowBlkNum <= highNoForkBlkNum) { - retSummary.offer(dbManager.getBlockIdByNum(lowBlkNum)); - } else if (lowBlkNum <= highBlkNum) { - retSummary.offer(forkList.get((int) (lowBlkNum - highNoForkBlkNum - 1))); - } else { - retSummary.offer(blockIds.get((int) (lowBlkNum - highBlkNum - 1))); - } - lowBlkNum += (realHighBlkNum - lowBlkNum + 2) / 2; - } while (lowBlkNum <= realHighBlkNum); - - return retSummary; - } - - @Override - public Message getData(Sha256Hash hash, MessageTypes type) - throws StoreException { - switch (type) { - case BLOCK: - return new BlockMessage(dbManager.getBlockById(hash)); - case TRX: - TransactionCapsule tx = dbManager.getTransactionStore().get(hash.getBytes()); - if (tx != null) { - return new TransactionMessage(tx.getData()); - } - throw new ItemNotFoundException("transaction is not found"); - default: - throw new BadItemException("message type not block or trx."); - } - } - - @Override - public void syncToCli(long unSyncNum) { - logger.info("There are " + unSyncNum + " blocks we need to sync."); - if (unSyncNum == 0) { - logger.info("Sync Block Completed !!!"); - } - dbManager.setSyncMode(unSyncNum == 0); - } - - @Override - public long getBlockTime(BlockId id) { - try { - return dbManager.getBlockById(id).getTimeStamp(); - } catch (BadItemException e) { - return dbManager.getGenesisBlock().getTimeStamp(); - } catch (ItemNotFoundException e) { - return dbManager.getGenesisBlock().getTimeStamp(); - } - } - - @Override - public BlockId getHeadBlockId() { - return dbManager.getHeadBlockId(); - } - - @Override - public BlockId getSolidBlockId() { - return dbManager.getSolidBlockId(); - } - - @Override - public long getHeadBlockTimeStamp() { - return dbManager.getHeadBlockTimeStamp(); - } - - @Override - public boolean containBlock(BlockId id) { - return dbManager.containBlock(id); - } - - @Override - public boolean containBlockInMainChain(BlockId id) { - return dbManager.containBlockInMainChain(id); - } - - @Override - public boolean contain(Sha256Hash hash, MessageTypes type) { - if (type.equals(MessageTypes.BLOCK)) { - return dbManager.containBlock(hash); - } else if (type.equals(MessageTypes.TRX)) { - return dbManager.getTransactionStore().has(hash.getBytes()); - } - return false; - } - - @Override - public BlockCapsule getGenesisBlock() { - return dbManager.getGenesisBlock(); - } - - @Override - public boolean canChainRevoke(long num) { - return num >= dbManager.getSyncBeginNumber(); - } -} diff --git a/src/main/java/org/tron/core/net/node/NodeImpl.java b/src/main/java/org/tron/core/net/node/NodeImpl.java deleted file mode 100644 index 9ce599e607e..00000000000 --- a/src/main/java/org/tron/core/net/node/NodeImpl.java +++ /dev/null @@ -1,1390 +0,0 @@ -package org.tron.core.net.node; - -import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; -import static org.tron.core.config.Parameter.NetConstants.MAX_TRX_PER_PEER; -import static org.tron.core.config.Parameter.NetConstants.MSG_CACHE_DURATION_IN_BLOCKS; -import static org.tron.core.config.Parameter.NodeConstant.MAX_BLOCKS_SYNC_FROM_ONE_PEER; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import java.util.Collection; -import java.util.Comparator; -import java.util.Deque; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Queue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; -import java.util.stream.Collectors; -import javafx.util.Pair; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.CollectionUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.tron.common.overlay.discover.node.statistics.MessageCount; -import org.tron.common.overlay.message.Message; -import org.tron.common.overlay.server.Channel.TronState; -import org.tron.common.overlay.server.SyncPool; -import org.tron.common.utils.ExecutorLoop; -import org.tron.common.utils.Sha256Hash; -import org.tron.common.utils.SlidingWindowCounter; -import org.tron.common.utils.Time; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.capsule.BlockCapsule.BlockId; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.Parameter.ChainConstant; -import org.tron.core.config.Parameter.NetConstants; -import org.tron.core.config.Parameter.NodeConstant; -import org.tron.core.config.args.Args; -import org.tron.core.exception.BadBlockException; -import org.tron.core.exception.BadTransactionException; -import org.tron.core.exception.NonCommonBlockException; -import org.tron.core.exception.P2pException; -import org.tron.core.exception.P2pException.TypeEnum; -import org.tron.core.exception.StoreException; -import org.tron.core.exception.TraitorPeerException; -import org.tron.core.exception.TronException; -import org.tron.core.exception.UnLinkedBlockException; -import org.tron.core.net.message.BlockMessage; -import org.tron.core.net.message.ChainInventoryMessage; -import org.tron.core.net.message.FetchInvDataMessage; -import org.tron.core.net.message.InventoryMessage; -import org.tron.core.net.message.ItemNotFound; -import org.tron.core.net.message.MessageTypes; -import org.tron.core.net.message.SyncBlockChainMessage; -import org.tron.core.net.message.TransactionMessage; -import org.tron.core.net.message.TransactionsMessage; -import org.tron.core.net.message.TronMessage; -import org.tron.core.net.peer.PeerConnection; -import org.tron.core.net.peer.PeerConnectionDelegate; -import org.tron.core.services.WitnessProductBlockService; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Inventory.InventoryType; -import org.tron.protos.Protocol.ReasonCode; - -@Slf4j(topic = "net") -@Component -public class NodeImpl extends PeerConnectionDelegate implements Node { - - @Autowired - private TrxHandler trxHandler; - - @Autowired - private SyncPool pool; - - @Autowired - private WitnessProductBlockService witnessProductBlockService; - - private MessageCount trxCount = new MessageCount(); - - private Cache TrxCache = CacheBuilder.newBuilder() - .maximumSize(50_000).expireAfterWrite(1, TimeUnit.HOURS).initialCapacity(50_000) - .recordStats().build(); - - private Cache BlockCache = CacheBuilder.newBuilder() - .maximumSize(10).expireAfterWrite(60, TimeUnit.SECONDS) - .recordStats().build(); - - private SlidingWindowCounter fetchWaterLine = - new SlidingWindowCounter(BLOCK_PRODUCED_INTERVAL * MSG_CACHE_DURATION_IN_BLOCKS / 100); - - private int maxTrxsSize = 1_000_000; - - private int maxTrxsCnt = 100; - - private long blockUpdateTimeout = 20_000; - - private Object syncBlock = new Object(); - - @Getter - class PriorItem implements java.lang.Comparable { - - private long count; - - private Item item; - - private long time; - - public Sha256Hash getHash() { - return item.getHash(); - } - - public InventoryType getType() { - return item.getType(); - } - - public PriorItem(Item item, long count) { - this.item = item; - this.count = count; - this.time = Time.getCurrentMillis(); - } - - public void refreshTime() { - this.time = Time.getCurrentMillis(); - } - - @Override - public int compareTo(final PriorItem o) { - if (!this.item.getType().equals(o.getItem().getType())) { - return this.item.getType().equals(InventoryType.BLOCK) ? -1 : 1; - } - return Long.compare(this.count, o.getCount()); - } - } - - class InvToSend { - - private HashMap>> send - = new HashMap<>(); - - public void clear() { - this.send.clear(); - } - - public void add(Entry id, PeerConnection peer) { - if (send.containsKey(peer) && !send.get(peer).containsKey(id.getValue())) { - send.get(peer).put(id.getValue(), new LinkedList<>()); - } else if (!send.containsKey(peer)) { - send.put(peer, new HashMap<>()); - send.get(peer).put(id.getValue(), new LinkedList<>()); - } - send.get(peer).get(id.getValue()).offer(id.getKey()); - } - - public void add(PriorItem id, PeerConnection peer) { - if (send.containsKey(peer) && !send.get(peer).containsKey(id.getType())) { - send.get(peer).put(id.getType(), new LinkedList<>()); - } else if (!send.containsKey(peer)) { - send.put(peer, new HashMap<>()); - send.get(peer).put(id.getType(), new LinkedList<>()); - } - send.get(peer).get(id.getType()).offer(id.getHash()); - } - - public int getSize(PeerConnection peer) { - if (send.containsKey(peer)) { - return send.get(peer).values().stream().mapToInt(LinkedList::size).sum(); - } - - return 0; - } - - void sendInv() { - send.forEach((peer, ids) -> - ids.forEach((key, value) -> { - if (key.equals(InventoryType.BLOCK)) { - value.sort(Comparator.comparingLong(value1 -> new BlockId(value1).getNum())); - } - peer.sendMessage(new InventoryMessage(value, key)); - })); - } - - void sendFetch() { - send.forEach((peer, ids) -> - ids.forEach((key, value) -> { - if (key.equals(InventoryType.BLOCK)) { - value.sort(Comparator.comparingLong(value1 -> new BlockId(value1).getNum())); - } - peer.sendMessage(new FetchInvDataMessage(value, key)); - })); - } - } - - private ScheduledExecutorService logExecutor = Executors.newSingleThreadScheduledExecutor(); - - private ExecutorService trxsHandlePool = Executors - .newFixedThreadPool(Args.getInstance().getValidateSignThreadNum(), - new ThreadFactoryBuilder() - .setNameFormat("TrxsHandlePool-%d").build()); - - private Queue freshBlockId = new ConcurrentLinkedQueue() { - @Override - public boolean offer(BlockId blockId) { - if (size() > 200) { - super.poll(); - } - return super.offer(blockId); - } - }; - - private ConcurrentHashMap syncMap = new ConcurrentHashMap<>(); - - private ConcurrentHashMap fetchMap = new ConcurrentHashMap<>(); - - private NodeDelegate del; - - private volatile boolean isAdvertiseActive; - - private volatile boolean isFetchActive; - - - private ScheduledExecutorService disconnectInactiveExecutor = Executors - .newSingleThreadScheduledExecutor(); - - private ScheduledExecutorService cleanInventoryExecutor = Executors - .newSingleThreadScheduledExecutor(); - - //broadcast - private ConcurrentHashMap advObjToSpread = new ConcurrentHashMap<>(); - - private HashMap advObjWeRequested = new HashMap<>(); - - private ConcurrentHashMap advObjToFetch = new ConcurrentHashMap(); - - private ExecutorService broadPool = Executors.newFixedThreadPool(2, new ThreadFactory() { - @Override - public Thread newThread(Runnable r) { - return new Thread(r, "broad-msg"); - } - }); - - private Cache syncBlockIdWeRequested = CacheBuilder.newBuilder() - .maximumSize(10000).expireAfterWrite(1, TimeUnit.HOURS).initialCapacity(10000) - .recordStats().build(); - - private Long unSyncNum = 0L; - - private Map blockWaitToProc = new ConcurrentHashMap<>(); - - private Map blockJustReceived = new ConcurrentHashMap<>(); - - private ExecutorLoop loopSyncBlockChain; - - private ExecutorLoop loopFetchBlocks; - - private ExecutorLoop loopAdvertiseInv; - - private ScheduledExecutorService fetchSyncBlocksExecutor = Executors - .newSingleThreadScheduledExecutor(); - - private ScheduledExecutorService handleSyncBlockExecutor = Executors - .newSingleThreadScheduledExecutor(); - - private ScheduledExecutorService fetchWaterLineExecutor = Executors - .newSingleThreadScheduledExecutor(); - - private volatile boolean isHandleSyncBlockActive = false; - - private AtomicLong fetchSequenceCounter = new AtomicLong(0L); - - private volatile boolean isSuspendFetch = false; - - private volatile boolean isFetchSyncActive = false; - - @Override - public void onMessage(PeerConnection peer, TronMessage msg) throws Exception { - switch (msg.getType()) { - case BLOCK: - onHandleBlockMessage(peer, (BlockMessage) msg); - break; - case TRXS: - trxHandler.handleTransactionsMessage(peer, (TransactionsMessage) msg); - break; - case SYNC_BLOCK_CHAIN: - onHandleSyncBlockChainMessage(peer, (SyncBlockChainMessage) msg); - break; - case FETCH_INV_DATA: - onHandleFetchDataMessage(peer, (FetchInvDataMessage) msg); - break; - case BLOCK_CHAIN_INVENTORY: - onHandleChainInventoryMessage(peer, (ChainInventoryMessage) msg); - break; - case INVENTORY: - onHandleInventoryMessage(peer, (InventoryMessage) msg); - break; - default: - throw new P2pException(TypeEnum.NO_SUCH_MESSAGE, "msg type: " + msg.getType()); - } - } - - @Override - public Message getMessage(Sha256Hash msgId) { - return null; - } - - - @Override - public void setNodeDelegate(NodeDelegate nodeDel) { - this.del = nodeDel; - } - - // for test only - public void setPool(SyncPool pool) { - this.pool = pool; - } - - public void broadcast(Message msg) { - try { - InventoryType type; - if (msg instanceof BlockMessage) { - logger.info("Ready to broadcast block {}", ((BlockMessage) msg).getBlockId()); - freshBlockId.offer(((BlockMessage) msg).getBlockId()); - BlockCache.put(msg.getMessageId(), (BlockMessage) msg); - type = InventoryType.BLOCK; - } else if (msg instanceof TransactionMessage) { - TrxCache.put(msg.getMessageId(), new TransactionMessage(msg.getData())); - type = InventoryType.TRX; - } else { - return; - } - synchronized (advObjToSpread) { - advObjToSpread.put(msg.getMessageId(), type); - } - } catch (Exception e) { - logger.error("Broadcast message failed, type: {}, reason: {}", msg.getType(), e.getMessage()); - } - } - - @Override - public void listen() { - pool.init(this); - trxHandler.init(this); - isAdvertiseActive = true; - isFetchActive = true; - activeTronPump(); - } - - @Override - public void close() { - getActivePeer().forEach(peer -> disconnectPeer(peer, ReasonCode.REQUESTED)); - } - - private void activeTronPump() { - loopAdvertiseInv = new ExecutorLoop<>(2, 10, b -> { - for (PeerConnection peer : getActivePeer()) { - if (!peer.isNeedSyncFromUs()) { - logger.info("Advertise adverInv to " + peer); - peer.sendMessage(b); - } - } - }, throwable -> logger.error("Unhandled exception: ", throwable)); - - // fetch blocks - loopFetchBlocks = new ExecutorLoop<>(2, 10, c -> { - logger.info("loop fetch blocks"); - if (fetchMap.containsKey(c.getMessageId())) { - fetchMap.get(c.getMessageId()).sendMessage(c); - } - }, throwable -> logger.error("Unhandled exception: ", throwable)); - - // sync block chain - loopSyncBlockChain = new ExecutorLoop<>(2, 10, d -> { - if (syncMap.containsKey(d.getMessageId())) { - syncMap.get(d.getMessageId()).sendMessage(d); - } - }, throwable -> logger.error("Unhandled exception: ", throwable)); - - broadPool.submit(() -> { - while (isAdvertiseActive) { - consumerAdvObjToSpread(); - } - }); - - broadPool.submit(() -> { - while (isFetchActive) { - consumerAdvObjToFetch(); - } - }); - - handleSyncBlockExecutor.scheduleWithFixedDelay(() -> { - try { - if (isHandleSyncBlockActive) { - isHandleSyncBlockActive = false; - handleSyncBlock(); - } - } catch (Throwable t) { - logger.error("Unhandled exception", t); - } - }, 10, 1, TimeUnit.SECONDS); - - //terminate inactive loop - disconnectInactiveExecutor.scheduleWithFixedDelay(() -> { - try { - disconnectInactive(); - } catch (Throwable t) { - logger.error("Unhandled exception", t); - } - }, 30000, BLOCK_PRODUCED_INTERVAL / 2, TimeUnit.MILLISECONDS); - - logExecutor.scheduleWithFixedDelay(() -> { - try { - logNodeStatus(); - } catch (Throwable t) { - logger.error("Exception in log worker", t); - } - }, 10, 10, TimeUnit.SECONDS); - - cleanInventoryExecutor.scheduleWithFixedDelay(() -> { - try { - getActivePeer().forEach(p -> p.cleanInvGarbage()); - } catch (Throwable t) { - logger.error("Unhandled exception", t); - } - }, 2, NetConstants.MAX_INVENTORY_SIZE_IN_MINUTES / 2, TimeUnit.MINUTES); - - fetchSyncBlocksExecutor.scheduleWithFixedDelay(() -> { - try { - if (isFetchSyncActive) { - if (!isSuspendFetch) { - startFetchSyncBlock(); - } else { - logger.debug("suspend"); - } - } - isFetchSyncActive = false; - } catch (Throwable t) { - logger.error("Unhandled exception", t); - } - }, 10, 1, TimeUnit.SECONDS); - - //fetchWaterLine: - fetchWaterLineExecutor.scheduleWithFixedDelay(() -> { - try { - fetchWaterLine.advance(); - } catch (Throwable t) { - logger.error("Unhandled exception", t); - } - }, 1000, 100, TimeUnit.MILLISECONDS); - } - - private void consumerAdvObjToFetch() { - Collection filterActivePeer = getActivePeer().stream() - .filter(peer -> !peer.isBusy()).collect(Collectors.toList()); - - if (advObjToFetch.isEmpty() || filterActivePeer.isEmpty()) { - try { - Thread.sleep(100); - return; - } catch (InterruptedException e) { - logger.debug(e.getMessage(), e); - } - } - InvToSend sendPackage = new InvToSend(); - long now = Time.getCurrentMillis(); - advObjToFetch.values().stream().sorted(PriorItem::compareTo).forEach(idToFetch -> { - Sha256Hash hash = idToFetch.getHash(); - if (idToFetch.getTime() < now - MSG_CACHE_DURATION_IN_BLOCKS * BLOCK_PRODUCED_INTERVAL) { - logger.info("This obj is too late to fetch, type: {} hash: {}.", idToFetch.getType(), - idToFetch.getHash()); - advObjToFetch.remove(hash); - return; - } - filterActivePeer.stream() - .filter(peer -> peer.getAdvObjSpreadToUs().containsKey(hash) - && sendPackage.getSize(peer) < MAX_TRX_PER_PEER) - .sorted(Comparator.comparingInt(peer -> sendPackage.getSize(peer))) - .findFirst().ifPresent(peer -> { - sendPackage.add(idToFetch, peer); - peer.getAdvObjWeRequested().put(idToFetch.getItem(), now); - advObjToFetch.remove(hash); - }); - }); - - sendPackage.sendFetch(); - } - - private void consumerAdvObjToSpread() { - if (advObjToSpread.isEmpty()) { - try { - Thread.sleep(100); - return; - } catch (InterruptedException e) { - logger.debug(e.getMessage(), e); - } - } - InvToSend sendPackage = new InvToSend(); - HashMap spread = new HashMap<>(); - synchronized (advObjToSpread) { - spread.putAll(advObjToSpread); - advObjToSpread.clear(); - } - for (InventoryType type : spread.values()) { - if (type == InventoryType.TRX) { - trxCount.add(); - } - } - getActivePeer().stream() - .filter(peer -> !peer.isNeedSyncFromUs()) - .forEach(peer -> - spread.entrySet().stream() - .filter(idToSpread -> - !peer.getAdvObjSpreadToUs().containsKey(idToSpread.getKey()) - && !peer.getAdvObjWeSpread().containsKey(idToSpread.getKey())) - .forEach(idToSpread -> { - peer.getAdvObjWeSpread().put(idToSpread.getKey(), Time.getCurrentMillis()); - sendPackage.add(idToSpread, peer); - })); - sendPackage.sendInv(); - } - - private synchronized void handleSyncBlock() { - if (isSuspendFetch) { - isSuspendFetch = false; - } - - final boolean[] isBlockProc = {true}; - - while (isBlockProc[0]) { - - isBlockProc[0] = false; - - synchronized (blockJustReceived) { - blockWaitToProc.putAll(blockJustReceived); - blockJustReceived.clear(); - } - - blockWaitToProc.forEach((msg, peerConnection) -> { - - if (peerConnection.isDisconnect()) { - logger.error("Peer {} is disconnect, drop block {}", peerConnection.getNode().getHost(), - msg.getBlockId().getString()); - blockWaitToProc.remove(msg); - syncBlockIdWeRequested.invalidate(msg.getBlockId()); - isFetchSyncActive = true; - return; - } - - synchronized (freshBlockId) { - final boolean[] isFound = {false}; - getActivePeer().stream() - .filter( - peer -> !peer.getSyncBlockToFetch().isEmpty() && peer.getSyncBlockToFetch() - .peek() - .equals(msg.getBlockId())) - .forEach(peer -> { - peer.getSyncBlockToFetch().pop(); - peer.getBlockInProc().add(msg.getBlockId()); - isFound[0] = true; - }); - if (isFound[0]) { - blockWaitToProc.remove(msg); - isBlockProc[0] = true; - if (freshBlockId.contains(msg.getBlockId()) || processSyncBlock( - msg.getBlockCapsule())) { - finishProcessSyncBlock(msg.getBlockCapsule()); - } - } - } - }); - } - } - - private synchronized void logNodeStatus() { - StringBuilder sb = new StringBuilder("LocalNode stats:\n"); - sb.append("============\n"); - - sb.append(String.format( - "MyHeadBlockNum: %d\n" - + "advObjToSpread: %d\n" - + "advObjToFetch: %d\n" - + "advObjWeRequested: %d\n" - + "unSyncNum: %d\n" - + "blockWaitToProc: %d\n" - + "blockJustReceived: %d\n" - + "syncBlockIdWeRequested: %d\n", - del.getHeadBlockId().getNum(), - advObjToSpread.size(), - advObjToFetch.size(), - advObjWeRequested.size(), - getUnSyncNum(), - blockWaitToProc.size(), - blockJustReceived.size(), - syncBlockIdWeRequested.size() - )); - - logger.info(sb.toString()); - } - - public synchronized void disconnectInactive() { - - getActivePeer().forEach(peer -> { - final boolean[] isDisconnected = {false}; - - if (peer.isNeedSyncFromPeer() - && peer.getLastBlockUpdateTime() < System.currentTimeMillis() - blockUpdateTimeout) { - logger.warn("Peer {} not sync for a long time.", peer.getInetAddress()); - isDisconnected[0] = true; - } - - peer.getAdvObjWeRequested().values().stream() - .filter(time -> time < Time.getCurrentMillis() - NetConstants.ADV_TIME_OUT) - .findFirst().ifPresent(time -> isDisconnected[0] = true); - - if (!isDisconnected[0]) { - peer.getSyncBlockRequested().values().stream() - .filter(time -> time < Time.getCurrentMillis() - NetConstants.SYNC_TIME_OUT) - .findFirst().ifPresent(time -> isDisconnected[0] = true); - } - - if (isDisconnected[0]) { - disconnectPeer(peer, ReasonCode.TIME_OUT); - } - }); - } - - - private void onHandleInventoryMessage(PeerConnection peer, InventoryMessage msg) { - int count = peer.getNodeStatistics().messageStatistics.tronInTrxInventoryElement.getCount(10); - if (count > 10_000) { - logger.warn("Inventory count {} from Peer {} is overload.", count, peer.getInetAddress()); - return; - } - if (trxHandler.isBusy() && msg.getInventoryType().equals(InventoryType.TRX)) { - logger.warn("Too many trx msg to handle, drop inventory msg from peer {}, size {}", - peer.getInetAddress(), msg.getHashList().size()); - return; - } - for (Sha256Hash id : msg.getHashList()) { - if (msg.getInventoryType().equals(InventoryType.TRX) && TrxCache.getIfPresent(id) != null) { - continue; - } - final boolean[] spreaded = {false}; - final boolean[] requested = {false}; - getActivePeer().forEach(p -> { - if (p.getAdvObjWeSpread().containsKey(id)) { - spreaded[0] = true; - } - if (p.getAdvObjWeRequested().containsKey(new Item(id, msg.getInventoryType()))) { - requested[0] = true; - } - }); - - if (!spreaded[0] - && !peer.isNeedSyncFromPeer() - && !peer.isNeedSyncFromUs()) { - - //avoid TRX flood attack here. -// if (msg.getInventoryType().equals(InventoryType.TRX) -// && (peer.isAdvInvFull() || isFlooded())) { -// logger.warn("A peer is flooding us, stop handle inv, the peer is: " + peer); -// return; -// } - - peer.getAdvObjSpreadToUs().put(id, System.currentTimeMillis()); - if (!requested[0]) { - PriorItem targetPriorItem = this.advObjToFetch.get(id); - if (targetPriorItem != null) { - //another peer tell this trx to us, refresh its time. - targetPriorItem.refreshTime(); - } else { - fetchWaterLine.increase(); - this.advObjToFetch.put(id, new PriorItem(new Item(id, msg.getInventoryType()), - fetchSequenceCounter.incrementAndGet())); - } - } - } - } - } - - private boolean isFlooded() { - return fetchWaterLine.totalCount() - > BLOCK_PRODUCED_INTERVAL - * Args.getInstance().getNetMaxTrxPerSecond() - * MSG_CACHE_DURATION_IN_BLOCKS - / 1000; - } - - @Override - public void syncFrom(Sha256Hash myHeadBlockHash) { - try { - while (getActivePeer().isEmpty()) { - logger.info("other peer is nil, please wait ... "); - Thread.sleep(10000L); - } - } catch (InterruptedException e) { - logger.debug(e.getMessage(), e); - } - logger.info("wait end"); - } - - private void onHandleBlockMessage(PeerConnection peer, BlockMessage blkMsg) { - Map advObjWeRequested = peer.getAdvObjWeRequested(); - Map syncBlockRequested = peer.getSyncBlockRequested(); - BlockId blockId = blkMsg.getBlockId(); - Item item = new Item(blockId, InventoryType.BLOCK); - boolean syncFlag = false; - if (syncBlockRequested.containsKey(blockId)) { - if (!peer.getSyncFlag()) { - logger.info("Received a block {} from no need sync peer {}", blockId.getNum(), - peer.getNode().getHost()); - return; - } - peer.getSyncBlockRequested().remove(blockId); - synchronized (blockJustReceived) { - blockJustReceived.put(blkMsg, peer); - } - isHandleSyncBlockActive = true; - syncFlag = true; - if (!peer.isBusy()) { - if (peer.getUnfetchSyncNum() > 0 - && peer.getSyncBlockToFetch().size() <= NodeConstant.SYNC_FETCH_BATCH_NUM) { - syncNextBatchChainIds(peer); - } else { - isFetchSyncActive = true; - } - } - } - if (advObjWeRequested.containsKey(item)) { - advObjWeRequested.remove(item); - if (!syncFlag) { - processAdvBlock(peer, blkMsg.getBlockCapsule()); - startFetchItem(); - } - } - } - - private void processAdvBlock(PeerConnection peer, BlockCapsule block) { - synchronized (freshBlockId) { - if (!freshBlockId.contains(block.getBlockId())) { - try { - witnessProductBlockService.validWitnessProductTwoBlock(block); - LinkedList trxIds = null; - trxIds = del.handleBlock(block, false); - freshBlockId.offer(block.getBlockId()); - - trxIds.forEach(trxId -> advObjToFetch.remove(trxId)); - - getActivePeer().stream() - .filter(p -> p.getAdvObjSpreadToUs().containsKey(block.getBlockId())) - .forEach(p -> updateBlockWeBothHave(p, block)); - - broadcast(new BlockMessage(block)); - - } catch (BadBlockException e) { - logger.error("We get a bad block {}, from {}, reason is {} ", - block.getBlockId().getString(), peer.getNode().getHost(), e.getMessage()); - disconnectPeer(peer, ReasonCode.BAD_BLOCK); - } catch (UnLinkedBlockException e) { - logger.error("We get a unlinked block {}, from {}, head is {}", block.getBlockId(). - getString(), peer.getNode().getHost(), del.getHeadBlockId().getString()); - startSyncWithPeer(peer); - } catch (NonCommonBlockException e) { - logger.error( - "We get a block {} that do not have the most recent common ancestor with the main chain, from {}, reason is {} ", - block.getBlockId().getString(), peer.getNode().getHost(), e.getMessage()); - disconnectPeer(peer, ReasonCode.FORKED); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } - - private boolean processSyncBlock(BlockCapsule block) { - boolean isAccept = false; - ReasonCode reason = null; - try { - try { - del.handleBlock(block, true); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - freshBlockId.offer(block.getBlockId()); - logger.info("Success handle block {}", block.getBlockId().getString()); - isAccept = true; - } catch (BadBlockException e) { - logger.error("We get a bad block {}, reason is {} ", block.getBlockId().getString(), - e.getMessage()); - reason = ReasonCode.BAD_BLOCK; - } catch (UnLinkedBlockException e) { - logger.error("We get a unlinked block {}, head is {}", block.getBlockId().getString(), - del.getHeadBlockId().getString()); - reason = ReasonCode.UNLINKABLE; - } catch (NonCommonBlockException e) { - logger.error( - "We get a block {} that do not have the most recent common ancestor with the main chain, head is {}", - block.getBlockId().getString(), - del.getHeadBlockId().getString()); - reason = ReasonCode.FORKED; - } - - if (!isAccept) { - ReasonCode finalReason = reason; - getActivePeer().stream() - .filter(peer -> peer.getBlockInProc().contains(block.getBlockId())) - .forEach(peer -> disconnectPeer(peer, finalReason)); - } - isHandleSyncBlockActive = true; - return isAccept; - } - - private void finishProcessSyncBlock(BlockCapsule block) { - getActivePeer().forEach(peer -> { - if (peer.getSyncBlockToFetch().isEmpty() - && peer.getBlockInProc().isEmpty() - && !peer.isNeedSyncFromPeer() - && !peer.isNeedSyncFromUs()) { - startSyncWithPeer(peer); - } else if (peer.getBlockInProc().remove(block.getBlockId())) { - updateBlockWeBothHave(peer, block); - if (peer.getSyncBlockToFetch().isEmpty()) { //send sync to let peer know we are sync. - syncNextBatchChainIds(peer); - } - } - }); - } - - synchronized boolean isTrxExist(TransactionMessage trxMsg) { - if (TrxCache.getIfPresent(trxMsg.getMessageId()) != null) { - return true; - } - TrxCache.put(trxMsg.getMessageId(), trxMsg); - return false; - } - - public void onHandleTransactionMessage(PeerConnection peer, TransactionMessage trxMsg) { - try { - if (isTrxExist(trxMsg)) { - logger.info("Trx {} from Peer {} already processed.", trxMsg.getMessageId(), - peer.getNode().getHost()); - return; - } - TransactionCapsule transactionCapsule = trxMsg.getTransactionCapsule(); - - if (del.handleTransaction(transactionCapsule)) { - broadcast(trxMsg); - } - } catch (BadTransactionException e) { - logger.error("Bad Trx {} from peer {}, error: {}", - trxMsg.getMessageId(), peer.getInetAddress(), e.getMessage()); - banTraitorPeer(peer, ReasonCode.BAD_TX); - } catch (Exception e) { - logger.error("Process trx {} from peer {} failed", - trxMsg.getMessageId(), peer.getInetAddress(), e); - } - } - - private boolean checkSyncBlockChainMessage(PeerConnection peer, SyncBlockChainMessage syncMsg) { - long lastBlockNum = syncMsg.getBlockIds().get(syncMsg.getBlockIds().size() - 1).getNum(); - BlockId lastSyncBlockId = peer.getLastSyncBlockId(); - if (lastSyncBlockId != null && lastBlockNum < lastSyncBlockId.getNum()) { - logger.warn("Peer {} receive bad SyncBlockChain message, firstNum {} lastSyncNum {}.", - peer.getInetAddress(), lastBlockNum, lastSyncBlockId.getNum()); - return false; - } - return true; - } - - private void onHandleSyncBlockChainMessage(PeerConnection peer, SyncBlockChainMessage syncMsg) { - peer.setTronState(TronState.SYNCING); - BlockId headBlockId = del.getHeadBlockId(); - long remainNum = 0; - LinkedList blockIds = new LinkedList<>(); - List summaryChainIds = syncMsg.getBlockIds(); - if (!checkSyncBlockChainMessage(peer, syncMsg)) { - disconnectPeer(peer, ReasonCode.BAD_PROTOCOL); - return; - } - try { - blockIds = del.getLostBlockIds(summaryChainIds); - } catch (StoreException e) { - logger.error(e.getMessage()); - } - - if (blockIds.isEmpty()) { - if (CollectionUtils.isNotEmpty(summaryChainIds) && !del - .canChainRevoke(summaryChainIds.get(0).getNum())) { - logger.info("Node sync block fail, disconnect peer {}, no block {}", peer, - summaryChainIds.get(0).getString()); - peer.disconnect(ReasonCode.SYNC_FAIL); - return; - } else { - peer.setNeedSyncFromUs(false); - } - } else if (blockIds.size() == 1 - && !summaryChainIds.isEmpty() - && (summaryChainIds.contains(blockIds.peekFirst()) - || blockIds.peek().getNum() == 0)) { - peer.setNeedSyncFromUs(false); - } else { - peer.setNeedSyncFromUs(true); - remainNum = del.getHeadBlockId().getNum() - blockIds.peekLast().getNum(); - } - - if (!peer.isNeedSyncFromPeer() - && CollectionUtils.isNotEmpty(summaryChainIds) - && !del.contain(Iterables.getLast(summaryChainIds), MessageTypes.BLOCK) - && del.canChainRevoke(summaryChainIds.get(0).getNum())) { - startSyncWithPeer(peer); - } - - if (blockIds.peekLast() == null) { - peer.setLastSyncBlockId(headBlockId); - } else { - peer.setLastSyncBlockId(blockIds.peekLast()); - } - peer.setRemainNum(remainNum); - peer.sendMessage(new ChainInventoryMessage(blockIds, remainNum)); - } - - private boolean checkFetchInvDataMsg(PeerConnection peer, FetchInvDataMessage fetchInvDataMsg) { - MessageTypes type = fetchInvDataMsg.getInvMessageType(); - if (type == MessageTypes.TRX) { - int elementCount = peer.getNodeStatistics().messageStatistics.tronInTrxFetchInvDataElement - .getCount(10); - int maxCount = trxCount.getCount(60); - if (elementCount > maxCount) { - logger.warn( - "Check FetchInvDataMsg failed: Peer {} request count {} in 10s gt trx count {} generate in 60s", - peer.getInetAddress(), elementCount, maxCount); - return false; - } - for (Sha256Hash hash : fetchInvDataMsg.getHashList()) { - if (!peer.getAdvObjWeSpread().containsKey(hash)) { - logger.warn("Check FetchInvDataMsg failed: Peer {} get trx {} we not spread.", - peer.getInetAddress(), hash); - return false; - } - } - } else { - boolean isAdv = true; - for (Sha256Hash hash : fetchInvDataMsg.getHashList()) { - if (!peer.getAdvObjWeSpread().containsKey(hash)) { - isAdv = false; - break; - } - } - if (isAdv) { - MessageCount tronOutAdvBlock = peer.getNodeStatistics().messageStatistics.tronOutAdvBlock; - tronOutAdvBlock.add(fetchInvDataMsg.getHashList().size()); - int outBlockCountIn1min = tronOutAdvBlock.getCount(60); - int producedBlockIn2min = 120_000 / ChainConstant.BLOCK_PRODUCED_INTERVAL; - if (outBlockCountIn1min > producedBlockIn2min) { - logger - .warn("Check FetchInvDataMsg failed: Peer {} outBlockCount {} producedBlockIn2min {}", - peer.getInetAddress(), outBlockCountIn1min, producedBlockIn2min); - return false; - } - } else { - if (!peer.isNeedSyncFromUs()) { - logger.warn("Check FetchInvDataMsg failed: Peer {} not need sync from us.", - peer.getInetAddress()); - return false; - } - for (Sha256Hash hash : fetchInvDataMsg.getHashList()) { - long blockNum = new BlockId(hash).getNum(); - long minBlockNum = - peer.getLastSyncBlockId().getNum() - 2 * NodeConstant.SYNC_FETCH_BATCH_NUM; - if (blockNum < minBlockNum) { - logger.warn("Check FetchInvDataMsg failed: Peer {} blockNum {} lt minBlockNum {}", - peer.getInetAddress(), blockNum, minBlockNum); - return false; - } - if (peer.getSyncBlockIdCache().getIfPresent(hash) != null) { - logger.warn("Check FetchInvDataMsg failed: Peer {} blockNum {} hash {} is exist", - peer.getInetAddress(), blockNum, hash); - return false; - } - peer.getSyncBlockIdCache().put(hash, 1); - } - } - } - return true; - } - - private void onHandleFetchDataMessage(PeerConnection peer, FetchInvDataMessage fetchInvDataMsg) { - - if (!checkFetchInvDataMsg(peer, fetchInvDataMsg)) { - disconnectPeer(peer, ReasonCode.BAD_PROTOCOL); - return; - } - - MessageTypes type = fetchInvDataMsg.getInvMessageType(); - BlockCapsule block = null; - List transactions = Lists.newArrayList(); - - int size = 0; - - for (Sha256Hash hash : fetchInvDataMsg.getHashList()) { - - Message msg; - - if (type == MessageTypes.BLOCK) { - msg = BlockCache.getIfPresent(hash); - } else { - msg = TrxCache.getIfPresent(hash); - } - - if (msg == null) { - try { - msg = del.getData(hash, type); - } catch (StoreException e) { - logger.error("fetch message {} {} failed.", type, hash); - peer.sendMessage(new ItemNotFound()); - //todo,should be disconnect? - return; - } - } - - if (type.equals(MessageTypes.BLOCK)) { - block = ((BlockMessage) msg).getBlockCapsule(); - peer.sendMessage(msg); - } else { - transactions.add(((TransactionMessage) msg).getTransactionCapsule().getInstance()); - size += ((TransactionMessage) msg).getTransactionCapsule().getInstance() - .getSerializedSize(); - if (transactions.size() % maxTrxsCnt == 0 || size > maxTrxsSize) { - peer.sendMessage(new TransactionsMessage(transactions)); - transactions = Lists.newArrayList(); - size = 0; - } - } - } - - if (block != null) { - updateBlockWeBothHave(peer, block); - } - if (transactions.size() > 0) { - peer.sendMessage(new TransactionsMessage(transactions)); - } - } - - private void banTraitorPeer(PeerConnection peer, ReasonCode reason) { - disconnectPeer(peer, reason); //TODO: ban it - } - - private void onHandleChainInventoryMessage(PeerConnection peer, ChainInventoryMessage msg) { - try { - if (peer.getSyncChainRequested() != null) { - Deque blockIdWeGet = new LinkedList<>(msg.getBlockIds()); - if (blockIdWeGet.size() > 0) { - peer.setNeedSyncFromPeer(true); - } - - //check if the peer is a traitor - if (!blockIdWeGet.isEmpty()) { - long num = blockIdWeGet.peek().getNum(); - for (BlockId id : blockIdWeGet) { - if (id.getNum() != num++) { - throw new TraitorPeerException("We get a not continuous block inv from " + peer); - } - } - - if (peer.getSyncChainRequested().getKey().isEmpty()) { - if (blockIdWeGet.peek().getNum() != 1) { - throw new TraitorPeerException( - "We want a block inv starting from beginning from " + peer); - } - } else { - if (!peer.getSyncChainRequested().getKey().contains(blockIdWeGet.peek())) { - throw new TraitorPeerException(String.format( - "We get a unlinked block chain from " + peer - + "\n Our head is " + peer.getSyncChainRequested().getKey().getLast() - .getString() - + "\n Peer give us is " + blockIdWeGet.peek().getString())); - } - } - - if (del.getHeadBlockId().getNum() > 0) { - long maxRemainTime = ChainConstant.CLOCK_MAX_DELAY + System.currentTimeMillis() - del - .getBlockTime(del.getSolidBlockId()); - long maxFutureNum = - maxRemainTime / BLOCK_PRODUCED_INTERVAL + del.getSolidBlockId().getNum(); - if (blockIdWeGet.peekLast().getNum() + msg.getRemainNum() > maxFutureNum) { - throw new TraitorPeerException( - "Block num " + blockIdWeGet.peekLast().getNum() + "+" + msg.getRemainNum() - + " is gt future max num " + maxFutureNum + " from " + peer - + ", maybe the local clock is not right."); - } - } - } - - if (msg.getRemainNum() == 0 - && (blockIdWeGet.isEmpty() || (blockIdWeGet.size() == 1 && del - .containBlock(blockIdWeGet.peek()))) - && peer.getSyncBlockToFetch().isEmpty() - && peer.getUnfetchSyncNum() == 0) { - peer.setNeedSyncFromPeer(false); - unSyncNum = getUnSyncNum(); - if (unSyncNum == 0) { - del.syncToCli(0); - } - peer.setSyncChainRequested(null); - return; - } - - if (!blockIdWeGet.isEmpty() && peer.getSyncBlockToFetch().isEmpty()) { - boolean isFound = false; - - for (PeerConnection peerToCheck : - getActivePeer()) { - BlockId blockId = peerToCheck.getSyncBlockToFetch().peekFirst(); - if (!peerToCheck.equals(peer) && blockId != null && blockId - .equals(blockIdWeGet.peekFirst())) { - isFound = true; - break; - } - } - - if (!isFound) { - while (!blockIdWeGet.isEmpty() && del.containBlock(blockIdWeGet.peek())) { - updateBlockWeBothHave(peer, blockIdWeGet.peek()); - blockIdWeGet.poll(); - } - } - } else if (!blockIdWeGet.isEmpty()) { - while (!peer.getSyncBlockToFetch().isEmpty()) { - if (!peer.getSyncBlockToFetch().peekLast().equals(blockIdWeGet.peekFirst())) { - peer.getSyncBlockToFetch().pollLast(); - } else { - break; - } - } - - if (peer.getSyncBlockToFetch().isEmpty() && del.containBlock(blockIdWeGet.peek())) { - updateBlockWeBothHave(peer, blockIdWeGet.peek()); - - } - blockIdWeGet.poll(); - } - - peer.setUnfetchSyncNum(msg.getRemainNum()); - peer.getSyncBlockToFetch().addAll(blockIdWeGet); - synchronized (freshBlockId) { - while (!peer.getSyncBlockToFetch().isEmpty() - && freshBlockId.contains(peer.getSyncBlockToFetch().peek())) { - BlockId blockId = peer.getSyncBlockToFetch().pop(); - updateBlockWeBothHave(peer, blockId); - logger.info("Block {} from {} is processed", blockId.getString(), - peer.getNode().getHost()); - } - } - - if (msg.getRemainNum() == 0 && peer.getSyncBlockToFetch().isEmpty()) { - peer.setNeedSyncFromPeer(false); - } - - long newUnSyncNum = getUnSyncNum(); - if (unSyncNum != newUnSyncNum) { - unSyncNum = newUnSyncNum; - del.syncToCli(unSyncNum); - } - - peer.setSyncChainRequested(null); - - if (msg.getRemainNum() == 0) { - if (!peer.getSyncBlockToFetch().isEmpty()) { - isFetchSyncActive = true; - } else { - //let peer know we are sync. - syncNextBatchChainIds(peer); - } - } else { - if (peer.getSyncBlockToFetch().size() > NodeConstant.SYNC_FETCH_BATCH_NUM) { - isFetchSyncActive = true; - } else { - syncNextBatchChainIds(peer); - } - } - - } else { - throw new TraitorPeerException("We don't send sync request to " + peer); - } - - } catch (TraitorPeerException e) { - logger.error(e.getMessage()); - banTraitorPeer(peer, ReasonCode.BAD_PROTOCOL); - } catch (StoreException e) { - //we try update our both known block but this block is null - //because when we try to switch to this block's fork then fail. - //The reason only is we get a bad block which peer broadcast to us. - logger.error(e.getMessage()); - banTraitorPeer(peer, ReasonCode.BAD_BLOCK); - } - } - - private void startFetchItem() { - - } - - private long getUnSyncNum() { - if (getActivePeer().isEmpty()) { - return 0; - } - return getActivePeer().stream() - .mapToLong(peer -> peer.getUnfetchSyncNum() + peer.getSyncBlockToFetch().size()) - .max() - .getAsLong(); - } - - private synchronized void startFetchSyncBlock() { - HashMap> send = new HashMap<>(); - HashSet request = new HashSet<>(); - - getActivePeer().stream() - .filter(peer -> peer.isNeedSyncFromPeer() && !peer.isBusy()) - .forEach(peer -> { - if (!send.containsKey(peer)) { - send.put(peer, new LinkedList<>()); - } - for (BlockId blockId : peer.getSyncBlockToFetch()) { - if (!request.contains(blockId) - && (syncBlockIdWeRequested.getIfPresent(blockId) == null)) { - send.get(peer).add(blockId); - request.add(blockId); - if (send.get(peer).size() - > MAX_BLOCKS_SYNC_FROM_ONE_PEER) { //Max Blocks peer get one time - break; - } - } - } - }); - - send.forEach((peer, blockIds) -> { - blockIds.forEach(blockId -> { - syncBlockIdWeRequested.put(blockId, System.currentTimeMillis()); - peer.getSyncBlockRequested().put(blockId, System.currentTimeMillis()); - }); - List ids = new LinkedList<>(); - ids.addAll(blockIds); - if (!ids.isEmpty()) { - peer.sendMessage(new FetchInvDataMessage(ids, InventoryType.BLOCK)); - } - }); - - send.clear(); - } - - private void updateBlockWeBothHave(PeerConnection peer, BlockCapsule block) { - logger.info("update peer {} block both we have {}", peer.getNode().getHost(), - block.getBlockId().getString()); - peer.setHeadBlockWeBothHave(block.getBlockId()); - peer.setHeadBlockTimeWeBothHave(block.getTimeStamp()); - peer.setLastBlockUpdateTime(System.currentTimeMillis()); - } - - private void updateBlockWeBothHave(PeerConnection peer, BlockId blockId) - throws StoreException { - logger.info("update peer {} block both we have, {}", peer.getNode().getHost(), - blockId.getString()); - peer.setHeadBlockWeBothHave(blockId); - long time = ((BlockMessage) del.getData(blockId, MessageTypes.BLOCK)).getBlockCapsule() - .getTimeStamp(); - peer.setHeadBlockTimeWeBothHave(time); - peer.setLastBlockUpdateTime(System.currentTimeMillis()); - } - - public Collection getActivePeer() { - return pool.getActivePeers(); - } - - private void startSyncWithPeer(PeerConnection peer) { - peer.setNeedSyncFromPeer(true); - peer.getSyncBlockToFetch().clear(); - peer.setUnfetchSyncNum(0); - updateBlockWeBothHave(peer, del.getGenesisBlock()); - peer.setBanned(false); - syncNextBatchChainIds(peer); - } - - private void syncNextBatchChainIds(PeerConnection peer) { - synchronized (syncBlock) { - if (peer.isDisconnect()) { - logger.warn("Peer {} is disconnect", peer.getInetAddress()); - return; - } - if (peer.getSyncChainRequested() != null) { - logger.info("Peer {} is in sync.", peer.getInetAddress()); - return; - } - try { - Deque chainSummary = - del.getBlockChainSummary(peer.getHeadBlockWeBothHave(), - peer.getSyncBlockToFetch()); - peer.setSyncChainRequested( - new Pair<>(chainSummary, System.currentTimeMillis())); - peer.sendMessage(new SyncBlockChainMessage((LinkedList) chainSummary)); - } catch (TronException e) { - logger.error("Peer {} sync next batch chainIds failed, error: {}.", - peer.getNode().getHost(), e.getMessage()); - disconnectPeer(peer, ReasonCode.FORKED); - } - } - } - - @Override - public void onConnectPeer(PeerConnection peer) { - if (peer.getHelloMessage().getHeadBlockId().getNum() > del.getHeadBlockId().getNum()) { - peer.setTronState(TronState.SYNCING); - startSyncWithPeer(peer); - } else { - peer.setTronState(TronState.SYNC_COMPLETED); - } - } - - @Override - public void onDisconnectPeer(PeerConnection peer) { - - if (!peer.getSyncBlockRequested().isEmpty()) { - peer.getSyncBlockRequested().keySet() - .forEach(blockId -> syncBlockIdWeRequested.invalidate(blockId)); - isFetchSyncActive = true; - } - - if (!peer.getAdvObjWeRequested().isEmpty()) { - peer.getAdvObjWeRequested().keySet().forEach(item -> { - if (getActivePeer().stream() - .filter(peerConnection -> !peerConnection.equals(peer)) - .filter(peerConnection -> peerConnection.getInvToUs().contains(item.getHash())) - .findFirst() - .isPresent()) { - advObjToFetch.put(item.getHash(), new PriorItem(item, - fetchSequenceCounter.incrementAndGet())); - } - }); - } - } - - private void shutdownExecutor(ExecutorService exec, String name) { - exec.shutdown(); - try { - if (!exec.awaitTermination(10, TimeUnit.SECONDS)) { - exec.shutdownNow(); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - if (!exec.isTerminated()) { - logger.warn("fail to shutdown {} ", name); - } else { - logger.info("success to shutdown {} ", name); - } - } - } - - public void shutDown() { - logger.info("begin shutdown nodeimpl"); - shutdownExecutor(logExecutor, "logExecutor"); - shutdownExecutor(trxsHandlePool, "trxsHandlePool"); - shutdownExecutor(disconnectInactiveExecutor, "disconnectInactiveExecutor"); - shutdownExecutor(cleanInventoryExecutor, "cleanInventoryExecutor"); - shutdownExecutor(broadPool, "broadPool"); - shutdownExecutor(fetchSyncBlocksExecutor, "fetchSyncBlocksExecutor"); - shutdownExecutor(handleSyncBlockExecutor, "handleSyncBlockExecutor"); - loopSyncBlockChain.shutdown(); - loopFetchBlocks.shutdown(); - loopAdvertiseInv.shutdown(); - } - - - private void disconnectPeer(PeerConnection peer, ReasonCode reason) { - peer.setSyncFlag(false); - peer.disconnect(reason); - } - -} - diff --git a/src/main/java/org/tron/core/net/node/Item.java b/src/main/java/org/tron/core/net/peer/Item.java similarity index 76% rename from src/main/java/org/tron/core/net/node/Item.java rename to src/main/java/org/tron/core/net/peer/Item.java index 89f7504bded..03155ad6acd 100644 --- a/src/main/java/org/tron/core/net/node/Item.java +++ b/src/main/java/org/tron/core/net/peer/Item.java @@ -1,4 +1,4 @@ -package org.tron.core.net.node; +package org.tron.core.net.peer; import lombok.Getter; import org.tron.common.utils.Sha256Hash; @@ -7,13 +7,18 @@ @Getter public class Item { + @Getter private Sha256Hash hash; - + @Getter private InventoryType type; + @Getter + private long time; + public Item(Sha256Hash hash, InventoryType type) { this.hash = hash; this.type = type; + this.time = System.currentTimeMillis(); } @Override @@ -33,4 +38,9 @@ public boolean equals(Object o) { public int hashCode() { return hash.hashCode(); } + + @Override + public String toString() { + return type + ":" + hash; + } } diff --git a/src/main/java/org/tron/core/net/peer/PeerConnection.java b/src/main/java/org/tron/core/net/peer/PeerConnection.java index c1c81f0372d..c74a14cf0df 100644 --- a/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -1,7 +1,5 @@ package org.tron.core.net.peer; -import static org.tron.core.config.Parameter.NetConstants.MAX_INVENTORY_SIZE_IN_MINUTES; - import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import java.util.Deque; @@ -9,292 +7,195 @@ import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; -import java.util.Queue; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedDeque; -import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; import javafx.util.Pair; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import org.tron.common.overlay.message.HelloMessage; import org.tron.common.overlay.message.Message; import org.tron.common.overlay.server.Channel; import org.tron.common.utils.Sha256Hash; -import org.tron.common.utils.Time; import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.core.config.Parameter.NodeConstant; -import org.tron.core.config.args.Args; -import org.tron.core.net.node.Item; +import org.tron.core.net.TronNetDelegate; +import org.tron.core.net.service.AdvService; +import org.tron.core.net.service.SyncService; @Slf4j(topic = "net") @Component @Scope("prototype") public class PeerConnection extends Channel { - private Cache syncBlockIdCache = CacheBuilder.newBuilder() - .maximumSize(2 * NodeConstant.SYNC_FETCH_BATCH_NUM).build(); + @Autowired + private TronNetDelegate tronNetDelegate; - @Setter - @Getter - private BlockId lastSyncBlockId; + @Autowired + private SyncService syncService; + + @Autowired + private AdvService advService; + + private int invCacheSize = 100_000; @Setter @Getter - private long remainNum; + private BlockId signUpErrorBlockId; @Setter @Getter - private long lastBlockUpdateTime = System.currentTimeMillis(); - - private volatile boolean syncFlag = true; - private HelloMessage helloMessage; - //broadcast - private Queue invToUs = new LinkedBlockingQueue<>(); - - private Queue invWeAdv = new LinkedBlockingQueue<>(); - - private Map advObjSpreadToUs = new ConcurrentHashMap<>(); - - private Map advObjWeSpread = new ConcurrentHashMap<>(); - - private Map advObjWeRequested = new ConcurrentHashMap<>(); + @Setter + @Getter + private Cache advInvReceive = CacheBuilder.newBuilder().maximumSize(invCacheSize) + .expireAfterWrite(1, TimeUnit.HOURS).recordStats().build(); - private boolean advInhibit = false; + @Setter + @Getter + private Cache advInvSpread = CacheBuilder.newBuilder().maximumSize(invCacheSize) + .expireAfterWrite(1, TimeUnit.HOURS).recordStats().build(); - public Map getAdvObjSpreadToUs() { - return advObjSpreadToUs; - } + @Setter + @Getter + private Map advInvRequest = new ConcurrentHashMap<>(); - public Map getAdvObjWeSpread() { - return advObjWeSpread; + @Getter + private BlockId blockBothHave = new BlockId(); + public void setBlockBothHave (BlockId blockId) { + this.blockBothHave = blockId; + this.blockBothHaveUpdateTime = System.currentTimeMillis(); } - public boolean isAdvInhibit() { - return advInhibit; - } + @Getter + private long blockBothHaveUpdateTime = System.currentTimeMillis(); - public void setAdvInhibit(boolean advInhibit) { - this.advInhibit = advInhibit; - } + @Setter + @Getter + private BlockId lastSyncBlockId; - //sync chain - private BlockId headBlockWeBothHave = new BlockId(); + @Setter + @Getter + private long remainNum; - private long headBlockTimeWeBothHave; + @Getter + private Cache syncBlockIdCache = CacheBuilder.newBuilder() + .maximumSize(2 * NodeConstant.SYNC_FETCH_BATCH_NUM).recordStats().build(); + @Setter + @Getter private Deque syncBlockToFetch = new ConcurrentLinkedDeque<>(); + @Setter + @Getter private Map syncBlockRequested = new ConcurrentHashMap<>(); + @Setter + @Getter private Pair, Long> syncChainRequested = null; - public Pair, Long> getSyncChainRequested() { - return syncChainRequested; - } - - public Cache getSyncBlockIdCache() { - return syncBlockIdCache; - } - - public void setSyncChainRequested( - Pair, Long> syncChainRequested) { - this.syncChainRequested = syncChainRequested; - } - - public Map getSyncBlockRequested() { - return syncBlockRequested; - } - - public void setSyncBlockRequested(ConcurrentHashMap syncBlockRequested) { - this.syncBlockRequested = syncBlockRequested; - } - - public long getUnfetchSyncNum() { - return unfetchSyncNum; - } - - public void setUnfetchSyncNum(long unfetchSyncNum) { - this.unfetchSyncNum = unfetchSyncNum; - } - - private long unfetchSyncNum = 0L; + @Setter + @Getter + private Set syncBlockInProcess = new HashSet<>(); + @Setter + @Getter private boolean needSyncFromPeer; + @Setter + @Getter private boolean needSyncFromUs; - public Set getBlockInProc() { - return blockInProc; + public boolean isIdle() { + return advInvRequest.isEmpty() && syncBlockRequested.isEmpty() && syncChainRequested == null; } - public void setBlockInProc(Set blockInProc) { - this.blockInProc = blockInProc; - } - - private boolean banned; - - private Set blockInProc = new HashSet<>(); - - public Map getAdvObjWeRequested() { - return advObjWeRequested; - } - - public void setAdvObjWeRequested(ConcurrentHashMap advObjWeRequested) { - this.advObjWeRequested = advObjWeRequested; - } - - public void setHelloMessage(HelloMessage helloMessage) { - this.helloMessage = helloMessage; - } - - public HelloMessage getHelloMessage() { - return this.helloMessage; - } - - public void cleanInvGarbage() { - long oldestTimestamp = - Time.getCurrentMillis() - MAX_INVENTORY_SIZE_IN_MINUTES * 60 * 1000; - - Iterator> iterator = this.advObjSpreadToUs.entrySet().iterator(); - - removeIterator(iterator, oldestTimestamp); - - iterator = this.advObjWeSpread.entrySet().iterator(); - - removeIterator(iterator, oldestTimestamp); + public void sendMessage(Message message) { + msgQueue.sendMessage(message); } - private void removeIterator(Iterator> iterator, long oldestTimestamp) { - while (iterator.hasNext()) { - Map.Entry entry = iterator.next(); - Long ts = (Long) entry.getValue(); - - if (ts < oldestTimestamp) { - iterator.remove(); - } + public void onConnect() { + if (getHelloMessage().getHeadBlockId().getNum() > tronNetDelegate.getHeadBlockId().getNum()) { + setTronState(TronState.SYNCING); + syncService.startSync(this); + } else { + setTronState(TronState.SYNC_COMPLETED); } } - public boolean isAdvInvFull() { - return advObjSpreadToUs.size() > MAX_INVENTORY_SIZE_IN_MINUTES - * 60 - * Args.getInstance().getNetMaxTrxPerSecond(); - } - - public boolean isBanned() { - return banned; - } - - public void setBanned(boolean banned) { - this.banned = banned; - } - - public BlockId getHeadBlockWeBothHave() { - return headBlockWeBothHave; - } - - public void setHeadBlockWeBothHave(BlockId headBlockWeBothHave) { - this.headBlockWeBothHave = headBlockWeBothHave; - } - - public long getHeadBlockTimeWeBothHave() { - return headBlockTimeWeBothHave; - } - - public void setHeadBlockTimeWeBothHave(long headBlockTimeWeBothHave) { - this.headBlockTimeWeBothHave = headBlockTimeWeBothHave; - } - - public Deque getSyncBlockToFetch() { - return syncBlockToFetch; - } - - public boolean isNeedSyncFromPeer() { - return needSyncFromPeer; - } - - public void setNeedSyncFromPeer(boolean needSyncFromPeer) { - this.needSyncFromPeer = needSyncFromPeer; - } - - public boolean isNeedSyncFromUs() { - return needSyncFromUs; - } - - public void setNeedSyncFromUs(boolean needSyncFromUs) { - this.needSyncFromUs = needSyncFromUs; - } - - public Queue getInvToUs() { - return invToUs; - } - - public void setInvToUs(Queue invToUs) { - this.invToUs = invToUs; - } - - public Queue getInvWeAdv() { - return invWeAdv; - } - - public void setInvWeAdv(Queue invWeAdv) { - this.invWeAdv = invWeAdv; - } - - public boolean getSyncFlag() { - return syncFlag; - } - - public void setSyncFlag(boolean syncFlag) { - this.syncFlag = syncFlag; - } - - public String logSyncStats() { + public void onDisconnect() { + syncService.onDisconnect(this); + advService.onDisconnect(this); + advInvReceive.cleanUp(); + advInvSpread.cleanUp(); + advInvRequest.clear(); + syncBlockIdCache.cleanUp(); + syncBlockToFetch.clear(); + syncBlockRequested.clear(); + syncBlockInProcess.clear(); + syncBlockInProcess.clear(); + } + + public String log () { + long now = System.currentTimeMillis(); +// logger.info("Peer {}:{} [ {}, ping {} ms]-----------\n" +// + "connect time: {}\n" +// + "last know block num: {}\n" +// + "needSyncFromPeer:{}\n" +// + "needSyncFromUs:{}\n" +// + "syncToFetchSize:{}\n" +// + "syncToFetchSizePeekNum:{}\n" +// + "syncBlockRequestedSize:{}\n" +// + "remainNum:{}\n" +// + "syncChainRequested:{}\n" +// + "blockInProcess:{}\n" +// + "{}", +// this.getNode().getHost(), this.getNode().getPort(), this.getNode().getHexIdShort(), +// (int) this.getPeerStats().getAvgLatency(), +// (now - super.getStartTime()) / 1000, +// blockBothHave.getNum(), +// isNeedSyncFromPeer(), +// isNeedSyncFromUs(), +// syncBlockToFetch.size(), +// syncBlockToFetch.size() > 0 ? syncBlockToFetch.peek().getNum() : -1, +// syncBlockRequested.size(), +// remainNum, +// syncChainRequested == null ? 0 : (now - syncChainRequested.getValue()) / 1000, +// syncBlockInProcess.size(), +// nodeStatistics.toString()); +//// return String.format( "Peer %s: [ %18s, ping %6s ms]-----------\n" - + "connect time: %s\n" + + "connect time: %ds\n" + "last know block num: %s\n" + "needSyncFromPeer:%b\n" + "needSyncFromUs:%b\n" + "syncToFetchSize:%d\n" + "syncToFetchSizePeekNum:%d\n" + "syncBlockRequestedSize:%d\n" - + "unFetchSynNum:%d\n" - + "syncChainRequested:%s\n" - + "blockInPorc:%d\n", + + "remainNum:%d\n" + + "syncChainRequested:%d\n" + + "blockInProcess:%d\n", this.getNode().getHost() + ":" + this.getNode().getPort(), this.getNode().getHexIdShort(), (int) this.getPeerStats().getAvgLatency(), - Time.getTimeString(super.getStartTime()), - headBlockWeBothHave.getNum(), + (now - super.getStartTime()) / 1000, + blockBothHave.getNum(), isNeedSyncFromPeer(), isNeedSyncFromUs(), syncBlockToFetch.size(), syncBlockToFetch.size() > 0 ? syncBlockToFetch.peek().getNum() : -1, syncBlockRequested.size(), - unfetchSyncNum, - syncChainRequested == null ? "NULL" : Time.getTimeString(syncChainRequested.getValue()), - blockInProc.size()) + remainNum, + syncChainRequested == null ? 0 : (now - syncChainRequested.getValue()) / 1000, + syncBlockInProcess.size()) + nodeStatistics.toString() + "\n"; } - public boolean isBusy() { - return !idle(); - } - - public boolean idle() { - return advObjWeRequested.isEmpty() - && syncBlockRequested.isEmpty() - && syncChainRequested == null; - } - - public void sendMessage(Message message) { - msgQueue.sendMessage(message); - } } diff --git a/src/main/java/org/tron/core/net/peer/PeerConnectionDelegate.java b/src/main/java/org/tron/core/net/peer/PeerConnectionDelegate.java deleted file mode 100644 index c0719adff05..00000000000 --- a/src/main/java/org/tron/core/net/peer/PeerConnectionDelegate.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.tron.core.net.peer; - -import org.tron.common.overlay.message.Message; -import org.tron.common.utils.Sha256Hash; -import org.tron.core.net.message.TronMessage; - -public abstract class PeerConnectionDelegate { - - public abstract void onMessage(PeerConnection peer, TronMessage msg) throws Exception; - - public abstract Message getMessage(Sha256Hash msgId); - - public abstract void onConnectPeer(PeerConnection peer); - - public abstract void onDisconnectPeer(PeerConnection peer); - -} diff --git a/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java b/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java new file mode 100644 index 00000000000..103dadabf94 --- /dev/null +++ b/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java @@ -0,0 +1,67 @@ +package org.tron.core.net.peer; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.config.Parameter.NetConstants; +import org.tron.core.net.TronNetDelegate; +import org.tron.protos.Protocol.ReasonCode; + +@Slf4j +@Component +public class PeerStatusCheck { + + @Autowired + private TronNetDelegate tronNetDelegate; + + private ScheduledExecutorService peerStatusCheckExecutor = Executors.newSingleThreadScheduledExecutor(); + + private int blockUpdateTimeout = 20_000; + + public void init () { + peerStatusCheckExecutor.scheduleWithFixedDelay(() -> { + try { + statusCheck(); + } catch (Throwable t) { + logger.error("Unhandled exception", t); + } + }, 5, 2, TimeUnit.SECONDS); + } + + public void close () { + peerStatusCheckExecutor.shutdown(); + } + + public void statusCheck() { + + long now = System.currentTimeMillis(); + + tronNetDelegate.getActivePeer().forEach(peer -> { + + boolean isDisconnected = false; + + if (peer.isNeedSyncFromPeer() && peer.getBlockBothHaveUpdateTime() < now - blockUpdateTimeout){ + logger.warn("Peer {} not sync for a long time.", peer.getInetAddress()); + isDisconnected = true; + } + + if (!isDisconnected) { + isDisconnected = peer.getAdvInvRequest().values().stream() + .anyMatch(time -> time < now - NetConstants.ADV_TIME_OUT); + } + + if (!isDisconnected) { + isDisconnected = peer.getSyncBlockRequested().values().stream() + .anyMatch(time -> time < now - NetConstants.SYNC_TIME_OUT); + } + + if (isDisconnected) { + peer.disconnect(ReasonCode.TIME_OUT); + } + }); + } + +} diff --git a/src/main/java/org/tron/core/net/service/AdvService.java b/src/main/java/org/tron/core/net/service/AdvService.java new file mode 100644 index 00000000000..9d0a826bcc8 --- /dev/null +++ b/src/main/java/org/tron/core/net/service/AdvService.java @@ -0,0 +1,263 @@ +package org.tron.core.net.service; + +import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; +import static org.tron.core.config.Parameter.NetConstants.MAX_TRX_FETCH_PER_PEER; +import static org.tron.core.config.Parameter.NetConstants.MSG_CACHE_DURATION_IN_BLOCKS; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.common.overlay.discover.node.statistics.MessageCount; +import org.tron.common.overlay.message.Message; +import org.tron.common.utils.Sha256Hash; +import org.tron.common.utils.Time; +import org.tron.core.capsule.BlockCapsule.BlockId; +import org.tron.core.net.TronNetDelegate; +import org.tron.core.net.message.BlockMessage; +import org.tron.core.net.message.FetchInvDataMessage; +import org.tron.core.net.message.InventoryMessage; +import org.tron.core.net.message.TransactionMessage; +import org.tron.core.net.peer.Item; +import org.tron.core.net.peer.PeerConnection; +import org.tron.protos.Protocol.Inventory.InventoryType; + +@Slf4j +@Component +public class AdvService { + + @Autowired + private TronNetDelegate tronNetDelegate; + + private ConcurrentHashMap invToFetch = new ConcurrentHashMap<>(); + + private ConcurrentHashMap invToSpread = new ConcurrentHashMap<>(); + + private Cache invToFetchCache = CacheBuilder.newBuilder() + .maximumSize(100_000).expireAfterWrite(1, TimeUnit.HOURS).recordStats().build(); + + private Cache trxCache = CacheBuilder.newBuilder() + .maximumSize(50_000).expireAfterWrite(1, TimeUnit.HOURS).recordStats().build(); + + private Cache blockCache = CacheBuilder.newBuilder() + .maximumSize(10).expireAfterWrite(1, TimeUnit.MINUTES).recordStats().build(); + + private ScheduledExecutorService spreadExecutor = Executors.newSingleThreadScheduledExecutor(); + + private ScheduledExecutorService fetchExecutor = Executors.newSingleThreadScheduledExecutor(); + + @Getter + private MessageCount trxCount = new MessageCount(); + + public void init () { + spreadExecutor.scheduleWithFixedDelay(() -> { + try { + consumerInvToSpread(); + } catch (Throwable t) { + logger.error("Spread thread error.", t); + } + }, 100, 30, TimeUnit.MILLISECONDS); + + fetchExecutor.scheduleWithFixedDelay(() -> { + try { + consumerInvToFetch(); + } catch (Throwable t) { + logger.error("Fetch thread error.", t); + } + }, 100, 30, TimeUnit.MILLISECONDS); + } + + public void close () { + spreadExecutor.shutdown(); + fetchExecutor.shutdown(); + } + + synchronized public boolean addInv (Item item) { + if (invToFetchCache.getIfPresent(item) != null) { + return false; + } + + if (item.getType().equals(InventoryType.TRX)) { + if (trxCache.getIfPresent(item) != null) { + return false; + } + } else { + if (blockCache.getIfPresent(item) != null) { + return false; + } + } + + invToFetchCache.put(item, System.currentTimeMillis()); + invToFetch.put(item, System.currentTimeMillis()); + return true; + } + + public Message getMessage (Item item) { + if (item.getType().equals(InventoryType.TRX)) { + return trxCache.getIfPresent(item); + } else { + return blockCache.getIfPresent(item); + } + } + + public void broadcast(Message msg) { + Item item; + if (msg instanceof BlockMessage) { + BlockMessage blockMsg = (BlockMessage) msg; + item = new Item(blockMsg.getMessageId(), InventoryType.BLOCK); + logger.info("Ready to broadcast block {}", blockMsg.getBlockId().getString()); + blockMsg.getBlockCapsule().getTransactions().forEach(transactionCapsule ->{ + Sha256Hash tid = transactionCapsule.getTransactionId(); + invToSpread.remove(tid); + trxCache.put(new Item(tid, InventoryType.TRX), new TransactionMessage(transactionCapsule.getInstance())); + }); + blockCache.put(item, msg); + } else if (msg instanceof TransactionMessage) { + TransactionMessage trxMsg = (TransactionMessage) msg; + item = new Item(trxMsg.getMessageId(), InventoryType.TRX); + trxCount.add(); + trxCache.put(item, new TransactionMessage(((TransactionMessage) msg).getTransactionCapsule().getInstance())); + } else { + logger.error("Adv item is neither block nor trx, type: {}", msg.getType()); + return; + } + synchronized (invToSpread) { + invToSpread.put(item, System.currentTimeMillis()); + } + } + + public void onDisconnect (PeerConnection peer) { + if (!peer.getAdvInvRequest().isEmpty()) { + peer.getAdvInvRequest().keySet().forEach(item -> { + if (tronNetDelegate.getActivePeer().stream() + .anyMatch(p -> !p.equals(peer) && p.getAdvInvReceive().getIfPresent(item) != null)){ + invToFetch.put(item, System.currentTimeMillis()); + } else { + invToFetchCache.invalidate(item); + } + }); + } + } + + private void consumerInvToFetch() { + Collection peers = tronNetDelegate.getActivePeer().stream() + .filter(peer -> peer.isIdle()) + .collect(Collectors.toList()); + + if (invToFetch.isEmpty() || peers.isEmpty()) { + return; + } + + InvSender invSender = new InvSender(); + long now = System.currentTimeMillis(); + invToFetch.forEach((item, time) -> { + if (time < now - MSG_CACHE_DURATION_IN_BLOCKS * BLOCK_PRODUCED_INTERVAL) { + logger.info("This obj is too late to fetch, type: {} hash: {}.", item.getType(), item.getHash()); + invToFetch.remove(item); + invToFetchCache.invalidate(item); + return; + } + peers.stream() + .filter(peer -> peer.getAdvInvReceive().getIfPresent(item) != null && invSender.getSize(peer) < MAX_TRX_FETCH_PER_PEER) + .sorted(Comparator.comparingInt(peer -> invSender.getSize(peer))) + .findFirst().ifPresent(peer -> { + invSender.add(item, peer); + peer.getAdvInvRequest().put(item, now); + invToFetch.remove(item); + }); + }); + + invSender.sendFetch(); + } + + private void consumerInvToSpread() { + if (invToSpread.isEmpty()) { + return; + } + + InvSender invSender = new InvSender(); + HashMap spread = new HashMap<>(); + synchronized (invToSpread) { + spread.putAll(invToSpread); + invToSpread.clear(); + } + + tronNetDelegate.getActivePeer().stream() + .filter(peer -> !peer.isNeedSyncFromPeer() && !peer.isNeedSyncFromUs()) + .forEach(peer -> spread.entrySet().stream() + .filter(entry -> peer.getAdvInvReceive().getIfPresent(entry.getKey()) == null && peer.getAdvInvSpread().getIfPresent(entry.getKey()) == null) + .forEach(entry -> { + peer.getAdvInvSpread().put(entry.getKey(), Time.getCurrentMillis()); + invSender.add(entry.getKey(), peer); + })); + + invSender.sendInv(); + } + + class InvSender { + + private HashMap>> send = new HashMap<>(); + + public void clear() { + this.send.clear(); + } + + public void add(Entry id, PeerConnection peer) { + if (send.containsKey(peer) && !send.get(peer).containsKey(id.getValue())) { + send.get(peer).put(id.getValue(), new LinkedList<>()); + } else if (!send.containsKey(peer)) { + send.put(peer, new HashMap<>()); + send.get(peer).put(id.getValue(), new LinkedList<>()); + } + send.get(peer).get(id.getValue()).offer(id.getKey()); + } + + public void add(Item id, PeerConnection peer) { + if (send.containsKey(peer) && !send.get(peer).containsKey(id.getType())) { + send.get(peer).put(id.getType(), new LinkedList<>()); + } else if (!send.containsKey(peer)) { + send.put(peer, new HashMap<>()); + send.get(peer).put(id.getType(), new LinkedList<>()); + } + send.get(peer).get(id.getType()).offer(id.getHash()); + } + + public int getSize(PeerConnection peer) { + if (send.containsKey(peer)) { + return send.get(peer).values().stream().mapToInt(LinkedList::size).sum(); + } + return 0; + } + + public void sendInv() { + send.forEach((peer, ids) -> ids.forEach((key, value) -> { + if (key.equals(InventoryType.BLOCK)) { + value.sort(Comparator.comparingLong(value1 -> new BlockId(value1).getNum())); + } + peer.sendMessage(new InventoryMessage(value, key)); + })); + } + + void sendFetch() { + send.forEach((peer, ids) -> ids.forEach((key, value) -> { + if (key.equals(InventoryType.BLOCK)) { + value.sort(Comparator.comparingLong(value1 -> new BlockId(value1).getNum())); + } + peer.sendMessage(new FetchInvDataMessage(value, key)); + })); + } + } + +} diff --git a/src/main/java/org/tron/core/net/service/SyncService.java b/src/main/java/org/tron/core/net/service/SyncService.java new file mode 100644 index 00000000000..85c7a321716 --- /dev/null +++ b/src/main/java/org/tron/core/net/service/SyncService.java @@ -0,0 +1,276 @@ +package org.tron.core.net.service; + +import static org.tron.core.config.Parameter.NetConstants.MAX_BLOCK_FETCH_PER_PEER; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import javafx.util.Pair; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.common.overlay.server.Channel.TronState; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.BlockCapsule.BlockId; +import org.tron.core.config.Parameter.NodeConstant; +import org.tron.core.exception.P2pException; +import org.tron.core.exception.P2pException.TypeEnum; +import org.tron.core.net.TronNetDelegate; +import org.tron.core.net.message.BlockMessage; +import org.tron.core.net.message.FetchInvDataMessage; +import org.tron.core.net.message.SyncBlockChainMessage; +import org.tron.core.net.peer.PeerConnection; +import org.tron.protos.Protocol.Inventory.InventoryType; +import org.tron.protos.Protocol.ReasonCode; + +@Slf4j +@Component +public class SyncService { + + @Autowired + private TronNetDelegate tronNetDelegate; + + private Map blockWaitToProcess = new ConcurrentHashMap<>(); + + private Map blockJustReceived = new ConcurrentHashMap<>(); + + private Cache requestBlockIds = CacheBuilder.newBuilder().maximumSize(10_000) + .expireAfterWrite(1, TimeUnit.HOURS).initialCapacity(10_000) + .recordStats().build(); + + private ScheduledExecutorService fetchExecutor = Executors.newSingleThreadScheduledExecutor(); + + private ScheduledExecutorService blockHandleExecutor = Executors.newSingleThreadScheduledExecutor(); + + private boolean syncHandleFlag = false; + + @Setter + private boolean fetchFlag = false; + + public void init () { + fetchExecutor.scheduleWithFixedDelay(() -> { + try { + if (fetchFlag) { + startFetchSyncBlock(); + } + fetchFlag = false; + } catch (Throwable t) { + logger.error("Fetch sync block error.", t); + } + }, 10, 1, TimeUnit.SECONDS); + + blockHandleExecutor.scheduleWithFixedDelay(() -> { + try { + if (syncHandleFlag) { + syncHandleFlag = false; + handleSyncBlock(); + } + } catch (Throwable t) { + logger.error("Handle sync block error.", t); + } + }, 10, 1, TimeUnit.SECONDS); + } + + public void close () { + fetchExecutor.shutdown(); + blockHandleExecutor.shutdown(); + } + + public void startSync(PeerConnection peer) { + peer.setTronState(TronState.SYNCING); + peer.setNeedSyncFromPeer(true); + peer.getSyncBlockToFetch().clear(); + peer.setRemainNum(0); + peer.setBlockBothHave(tronNetDelegate.getGenesisBlockId()); + syncNext(peer); + } + + public void syncNext(PeerConnection peer) { + try { + if (peer.getSyncChainRequested() != null) { + logger.warn("Peer {} is in sync.", peer.getNode().getHost()); + return; + } + LinkedList chainSummary = getBlockChainSummary(peer); + peer.setSyncChainRequested(new Pair<>(chainSummary, System.currentTimeMillis())); + peer.sendMessage(new SyncBlockChainMessage(chainSummary)); + }catch (Exception e) { + logger.error("Peer {} sync failed, reason: {}", peer.getInetAddress(), e.getMessage()); + peer.disconnect(ReasonCode.SYNC_FAIL); + } + } + + public void processBlock(PeerConnection peer, BlockMessage blockMessage) { + synchronized (blockJustReceived) { + blockJustReceived.put(blockMessage, peer); + } + syncHandleFlag = true; + if (peer.isIdle()) { + if (peer.getRemainNum() > 0 && peer.getSyncBlockToFetch().size() <= NodeConstant.SYNC_FETCH_BATCH_NUM) { + syncNext(peer); + } else { + fetchFlag = true; + } + } + } + + public void onDisconnect (PeerConnection peer) { + if (!peer.getSyncBlockRequested().isEmpty()) { + peer.getSyncBlockRequested().keySet().forEach(blockId -> invalid(blockId)); + } + } + + private void invalid (BlockId blockId) { + requestBlockIds.invalidate(blockId); + fetchFlag = true; + } + + private LinkedList getBlockChainSummary(PeerConnection peer) throws Exception { + + BlockId beginBlockId = peer.getBlockBothHave(); + List blockIds = new ArrayList<>(peer.getSyncBlockToFetch()); + LinkedList forkList = new LinkedList<>(); + LinkedList summary = new LinkedList<>(); + long syncBeginNumber = tronNetDelegate.getSyncBeginNumber(); + long low = syncBeginNumber < 0 ? 0 : syncBeginNumber; + long highNoFork; + long high; + + if (beginBlockId.getNum() == 0){ + highNoFork = high = tronNetDelegate.getHeadBlockId().getNum(); + }else { + if (tronNetDelegate.containBlockInMainChain(beginBlockId)) { + highNoFork = high = beginBlockId.getNum(); + } else { + forkList = tronNetDelegate.getBlockChainHashesOnFork(beginBlockId); + if (forkList.isEmpty()) { + throw new P2pException(TypeEnum.SYNC_FAILED, "can't find blockId: " + beginBlockId.getString()); + } + highNoFork = forkList.peekLast().getNum(); + forkList.pollLast(); + Collections.reverse(forkList); + high = highNoFork + forkList.size(); + } + } + + if (low > highNoFork){ + throw new P2pException(TypeEnum.SYNC_FAILED, "low: " + low + " gt highNoFork: " + highNoFork); + } + + long realHigh = high + blockIds.size(); + + logger.info("Get block chain summary, low: {}, highNoFork: {}, high: {}, realHigh: {}", + low, highNoFork, high, realHigh); + + while (low <= realHigh) { + if (low <= highNoFork) { + summary.offer(tronNetDelegate.getBlockIdByNum(low)); + } else if (low <= high) { + summary.offer(forkList.get((int) (low - highNoFork - 1))); + } else { + summary.offer(blockIds.get((int) (low - high - 1))); + } + low += (realHigh - low + 2) / 2; + } + + return summary; + } + + private void startFetchSyncBlock() { + HashMap> send = new HashMap<>(); + + tronNetDelegate.getActivePeer().stream() + .filter(peer -> peer.isNeedSyncFromPeer() && peer.isIdle()) + .forEach(peer -> { + if (!send.containsKey(peer)) { + send.put(peer, new LinkedList<>()); + } + for (BlockId blockId : peer.getSyncBlockToFetch()) { + if (requestBlockIds.getIfPresent(blockId) == null) { + requestBlockIds.put(blockId, System.currentTimeMillis()); + peer.getSyncBlockRequested().put(blockId, System.currentTimeMillis()); + send.get(peer).add(blockId); + if (send.get(peer).size() >= MAX_BLOCK_FETCH_PER_PEER) { + break; + } + } + } + }); + + send.forEach((peer, blockIds) -> { + if (!blockIds.isEmpty()) { + peer.sendMessage(new FetchInvDataMessage(new LinkedList<>(blockIds), InventoryType.BLOCK)); + } + }); + } + + private synchronized void handleSyncBlock() { + + synchronized (blockJustReceived) { + blockWaitToProcess.putAll(blockJustReceived); + blockJustReceived.clear(); + } + + final boolean[] isProcessed = {true}; + + while (isProcessed[0]) { + + isProcessed[0] = false; + + blockWaitToProcess.forEach((msg, peerConnection) -> { + if (peerConnection.isDisconnect()) { + blockWaitToProcess.remove(msg); + invalid(msg.getBlockId()); + return; + } + final boolean[] isFound = {false}; + tronNetDelegate.getActivePeer().stream() + .filter(peer -> msg.getBlockId().equals(peer.getSyncBlockToFetch().peek())) + .forEach(peer -> { + peer.getSyncBlockToFetch().pop(); + peer.getSyncBlockInProcess().add(msg.getBlockId()); + isFound[0] = true; + }); + if (isFound[0]) { + blockWaitToProcess.remove(msg); + isProcessed[0] = true; + processSyncBlock(msg.getBlockCapsule()); + } + }); + } + } + + private void processSyncBlock (BlockCapsule block) { + boolean flag = true; + BlockId blockId = block.getBlockId(); + try { + tronNetDelegate.processBlock(block); + } catch (Exception e) { + logger.error("Process sync block {} failed.", blockId.getString(), e); + flag = false; + } + for (PeerConnection peer: tronNetDelegate.getActivePeer()) { + if (peer.getSyncBlockInProcess().remove(blockId)) { + if (flag){ + peer.setBlockBothHave(blockId); + if (peer.getSyncBlockToFetch().isEmpty()) { + syncNext(peer); + } + }else { + peer.disconnect(ReasonCode.BAD_BLOCK); + } + } + } + } + +} diff --git a/src/main/java/org/tron/core/services/NodeInfoService.java b/src/main/java/org/tron/core/services/NodeInfoService.java index 71125bfeade..b7ba67ece30 100644 --- a/src/main/java/org/tron/core/services/NodeInfoService.java +++ b/src/main/java/org/tron/core/services/NodeInfoService.java @@ -125,16 +125,16 @@ private void setConnectInfo(NodeInfo nodeInfo) { List peerInfoList = new ArrayList<>(); for (PeerConnection peerConnection : syncPool.getActivePeers()) { PeerInfo peerInfo = new PeerInfo(); - peerInfo.setHeadBlockWeBothHave(peerConnection.getHeadBlockWeBothHave().getString()); + peerInfo.setHeadBlockWeBothHave(peerConnection.getBlockBothHave().getString()); peerInfo.setActive(peerConnection.isActive()); peerInfo.setAvgLatency(peerConnection.getPeerStats().getAvgLatency()); - peerInfo.setBlockInPorcSize(peerConnection.getBlockInProc().size()); + peerInfo.setBlockInPorcSize(peerConnection.getSyncBlockInProcess().size()); peerInfo.setConnectTime(peerConnection.getStartTime()); peerInfo.setDisconnectTimes(peerConnection.getNodeStatistics().getDisconnectTimes()); - peerInfo.setHeadBlockTimeWeBothHave(peerConnection.getHeadBlockTimeWeBothHave()); + //peerInfo.setHeadBlockTimeWeBothHave(peerConnection.getHeadBlockTimeWeBothHave()); peerInfo.setHost(peerConnection.getNode().getHost()); peerInfo.setInFlow(peerConnection.getNodeStatistics().tcpFlow.getTotalCount()); - peerInfo.setLastBlockUpdateTime(peerConnection.getLastBlockUpdateTime()); + peerInfo.setLastBlockUpdateTime(peerConnection.getBlockBothHaveUpdateTime()); peerInfo.setLastSyncBlock(peerConnection.getLastSyncBlockId() == null ? "" : peerConnection.getLastSyncBlockId().getString()); ReasonCode reasonCode = peerConnection.getNodeStatistics() @@ -150,11 +150,11 @@ private void setConnectInfo(NodeInfo nodeInfo) { peerInfo.setRemainNum(peerConnection.getRemainNum()); peerInfo.setScore(peerConnection.getNodeStatistics().getReputation()); peerInfo.setSyncBlockRequestedSize(peerConnection.getSyncBlockRequested().size()); - peerInfo.setSyncFlag(peerConnection.getSyncFlag()); + peerInfo.setSyncFlag(peerConnection.isDisconnect()); peerInfo.setSyncToFetchSize(peerConnection.getSyncBlockToFetch().size()); peerInfo.setSyncToFetchSizePeekNum(peerConnection.getSyncBlockToFetch().size() > 0 ? peerConnection.getSyncBlockToFetch().peek().getNum() : -1); - peerInfo.setUnFetchSynNum(peerConnection.getUnfetchSyncNum()); + peerInfo.setUnFetchSynNum(peerConnection.getRemainNum()); totalFlow += peerConnection.getNodeStatistics().tcpFlow.getTotalCount(); peerInfoList.add(peerInfo); } diff --git a/src/main/java/org/tron/core/services/WitnessService.java b/src/main/java/org/tron/core/services/WitnessService.java index 7c59282bbdf..9d762cb4d26 100755 --- a/src/main/java/org/tron/core/services/WitnessService.java +++ b/src/main/java/org/tron/core/services/WitnessService.java @@ -34,6 +34,7 @@ import org.tron.core.exception.UnLinkedBlockException; import org.tron.core.exception.ValidateScheduleException; import org.tron.core.exception.ValidateSignatureException; +import org.tron.core.net.TronNetService; import org.tron.core.net.message.BlockMessage; import org.tron.core.witness.BlockProductionCondition; import org.tron.core.witness.WitnessController; @@ -67,6 +68,8 @@ public class WitnessService implements Service { private BackupServer backupServer; + private TronNetService tronNetService; + private AtomicInteger dupBlockCount = new AtomicInteger(0); private AtomicLong dupBlockTime = new AtomicLong(0); private long blockCycle = @@ -80,6 +83,7 @@ public WitnessService(Application tronApp, TronApplicationContext context) { this.context = context; backupManager = context.getBean(BackupManager.class); backupServer = context.getBean(BackupServer.class); + tronNetService = context.getBean(TronNetService.class); generateThread = new Thread(scheduleProductionLoop); manager = tronApp.getDbManager(); manager.setWitnessService(this); @@ -306,7 +310,7 @@ public boolean validateWitnessPermission(ByteString scheduledWitness) { private void broadcastBlock(BlockCapsule block) { try { - tronApp.getP2pNode().broadcast(new BlockMessage(block.getData())); + tronNetService.broadcast(new BlockMessage(block.getData())); } catch (Exception ex) { throw new RuntimeException("BroadcastBlock error"); } diff --git a/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index a2f8943a06c..76c60fe659f 100644 --- a/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -140,6 +140,8 @@ public class FullNodeHttpApiService implements Service { @Autowired private GetAccountResourceServlet getAccountResourceServlet; @Autowired + private GetNodeInfoServlet getNodeInfoServlet; + @Autowired private AddTransactionSignServlet addTransactionSignServlet; @Autowired private GetTransactionSignWeightServlet getTransactionSignWeightServlet; @@ -148,8 +150,6 @@ public class FullNodeHttpApiService implements Service { @Autowired private AccountPermissionUpdateServlet accountPermissionUpdateServlet; @Autowired - private GetNodeInfoServlet getNodeInfoServlet; - @Autowired private UpdateSettingServlet updateSettingServlet; @Autowired private UpdateEnergyLimitServlet updateEnergyLimitServlet; diff --git a/src/main/java/org/tron/program/SolidityNode.java b/src/main/java/org/tron/program/SolidityNode.java index 0c8169373b7..3c7fbccff83 100644 --- a/src/main/java/org/tron/program/SolidityNode.java +++ b/src/main/java/org/tron/program/SolidityNode.java @@ -215,4 +215,4 @@ public static void main(String[] args) { rpcApiService.blockUntilShutdown(); } -} +} \ No newline at end of file diff --git a/src/test/java/org/tron/core/net/node/BaseNetTest.java b/src/test/java/org/tron/core/net/BaseNet.java similarity index 63% rename from src/test/java/org/tron/core/net/node/BaseNetTest.java rename to src/test/java/org/tron/core/net/BaseNet.java index 4bf680d22ff..1ff00528b7c 100644 --- a/src/test/java/org/tron/core/net/node/BaseNetTest.java +++ b/src/test/java/org/tron/core/net/BaseNet.java @@ -1,4 +1,4 @@ -package org.tron.core.net.node; +package org.tron.core.net; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; @@ -24,47 +24,31 @@ import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; -import org.tron.common.overlay.client.PeerClient; -import org.tron.common.overlay.server.ChannelManager; -import org.tron.common.overlay.server.SyncPool; import org.tron.common.utils.FileUtil; import org.tron.common.utils.ReflectUtils; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.net.peer.PeerConnection; import org.tron.core.services.RpcApiService; -import org.tron.core.services.WitnessService; @Slf4j -public abstract class BaseNetTest { +public abstract class BaseNet { - protected TronApplicationContext context; - protected NodeImpl node; - protected RpcApiService rpcApiService; - protected PeerClient peerClient; - protected ChannelManager channelManager; - protected SyncPool pool; - protected Manager manager; - private Application appT; + private static String dbPath = "output-net"; + private static String dbDirectory = "net-database"; + private static String indexDirectory = "net-index"; + private static int port = 10000; - private String dbPath; - private String dbDirectory; - private String indexDirectory; + protected TronApplicationContext context; - private int port; + private RpcApiService rpcApiService; + private Application appT; + private TronNetDelegate tronNetDelegate; private ExecutorService executorService = Executors.newFixedThreadPool(1); - public BaseNetTest(String dbPath, String dbDirectory, String indexDirectory, int port) { - this.dbPath = dbPath; - this.dbDirectory = dbDirectory; - this.indexDirectory = indexDirectory; - this.port = port; - } - @Before - public void init() { + public void init() throws Exception { executorService.execute(new Runnable() { @Override public void run() { @@ -79,62 +63,32 @@ public void run() { ); Args cfgArgs = Args.getInstance(); cfgArgs.setNodeListenPort(port); - cfgArgs.setNodeDiscoveryEnable(false); cfgArgs.getSeedNode().getIpList().clear(); - cfgArgs.setNeedSyncCheck(false); cfgArgs.setNodeExternalIp("127.0.0.1"); - context = new TronApplicationContext(DefaultConfig.class); - - if (cfgArgs.isHelp()) { - logger.info("Here is the help message"); - return; - } appT = ApplicationFactory.create(context); rpcApiService = context.getBean(RpcApiService.class); appT.addService(rpcApiService); - if (cfgArgs.isWitness()) { - appT.addService(new WitnessService(appT, context)); - } appT.initServices(cfgArgs); appT.startServices(); - - node = context.getBean(NodeImpl.class); - peerClient = context.getBean(PeerClient.class); - channelManager = context.getBean(ChannelManager.class); - pool = context.getBean(SyncPool.class); - manager = context.getBean(Manager.class); - NodeDelegate nodeDelegate = new NodeDelegateImpl(manager); - node.setNodeDelegate(nodeDelegate); - appT.startup(); + tronNetDelegate = context.getBean(TronNetDelegate.class); rpcApiService.blockUntilShutdown(); } }); - int tryTimes = 1; - while (tryTimes <= 30 && (node == null || peerClient == null - || channelManager == null || pool == null)) { - try { - logger.info("node:{},peerClient:{},channelManager:{},pool:{}", node, peerClient, - channelManager, pool); - Thread.sleep(1000 * tryTimes); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - ++tryTimes; - } + int tryTimes = 0; + while (++tryTimes < 100 && tronNetDelegate == null) { + Thread.sleep(3000); } } - protected Channel createClient(ByteToMessageDecoder decoder) - throws InterruptedException { + public static Channel connect(ByteToMessageDecoder decoder) throws InterruptedException { NioEventLoopGroup group = new NioEventLoopGroup(1); Bootstrap b = new Bootstrap(); b.group(group).channel(NioSocketChannel.class) .handler(new ChannelInitializer() { @Override protected void initChannel(Channel ch) throws Exception { - // limit the size of receiving buffer to 1024 ch.config().setRecvByteBufAllocator(new FixedRecvByteBufAllocator(256 * 1024)); ch.config().setOption(ChannelOption.SO_RCVBUF, 256 * 1024); ch.config().setOption(ChannelOption.SO_BACKLOG, 1024); @@ -144,8 +98,6 @@ protected void initChannel(Channel ch) throws Exception { ch.pipeline().addLast("protoPender", new ProtobufVarint32LengthFieldPrepender()); ch.pipeline().addLast("lengthDecode", new ProtobufVarint32FrameDecoder()); ch.pipeline().addLast("handshakeHandler", decoder); - - // be aware of channel closing ch.closeFuture(); } }).option(ChannelOption.SO_KEEPALIVE, true) @@ -156,16 +108,11 @@ protected void initChannel(Channel ch) throws Exception { @After public void destroy() { - executorService.shutdownNow(); - Args.clearParam(); - Collection peerConnections = ReflectUtils.invokeMethod(node, "getActivePeer"); + Collection peerConnections = ReflectUtils.invokeMethod(tronNetDelegate, "getActivePeer"); for (PeerConnection peer : peerConnections) { peer.close(); } context.destroy(); - node.shutDown(); - appT.shutdownServices(); - appT.shutdown(); FileUtil.deleteDir(new File(dbPath)); } } diff --git a/src/test/java/org/tron/core/net/BaseNetTest.java b/src/test/java/org/tron/core/net/BaseNetTest.java new file mode 100644 index 00000000000..41bd1fad027 --- /dev/null +++ b/src/test/java/org/tron/core/net/BaseNetTest.java @@ -0,0 +1,16 @@ +package org.tron.core.net; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; +import org.tron.core.services.NodeInfoServiceTest; + +@Slf4j +public class BaseNetTest extends BaseNet { + + @Test + public void test() throws Exception { + new NodeInfoServiceTest(context).test(); + new UdpTest(context).test(); + new TcpTest(context).test(); + } +} diff --git a/src/test/java/org/tron/core/net/node/TcpNetTest.java b/src/test/java/org/tron/core/net/TcpTest.java similarity index 76% rename from src/test/java/org/tron/core/net/node/TcpNetTest.java rename to src/test/java/org/tron/core/net/TcpTest.java index b4dcbf7d9fb..7a042495439 100644 --- a/src/test/java/org/tron/core/net/node/TcpNetTest.java +++ b/src/test/java/org/tron/core/net/TcpTest.java @@ -1,4 +1,4 @@ -package org.tron.core.net.node; +package org.tron.core.net; import static org.tron.core.net.message.MessageTypes.P2P_DISCONNECT; import static org.tron.core.net.message.MessageTypes.P2P_HELLO; @@ -14,51 +14,49 @@ import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; +import java.util.Collection; import java.util.List; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; -import org.junit.After; -import org.junit.AfterClass; import org.junit.Assert; -import org.junit.Test; +import org.tron.common.application.TronApplicationContext; import org.tron.common.overlay.discover.node.Node; import org.tron.common.overlay.message.DisconnectMessage; import org.tron.common.overlay.message.HelloMessage; import org.tron.common.overlay.message.Message; import org.tron.common.overlay.message.P2pMessage; import org.tron.common.overlay.message.P2pMessageFactory; -import org.tron.common.utils.FileUtil; +import org.tron.common.overlay.server.ChannelManager; +import org.tron.common.overlay.server.SyncPool; import org.tron.common.utils.ReflectUtils; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; import org.tron.core.net.message.BlockMessage; import org.tron.core.net.peer.PeerConnection; import org.tron.protos.Protocol.Block; @Slf4j -public class TcpNetTest extends BaseNetTest { +public class TcpTest { - private static final String dbPath = "output-nodeImplTest-tcpNet"; - private static final String dbDirectory = "db_tcp_test"; - private static final String indexDirectory = "index_tcp_test"; - public static final int sleepTime = 1000; - private boolean finish = false; - private final static int tryTimes = 10; - private final static int port = 17899; + private ChannelManager channelManager; + private Manager manager; + private SyncPool pool; + private TronNetDelegate tronNetDelegate; - Node node = new Node( - "enode://e437a4836b77ad9d9ffe73ee782ef2614e6d8370fcf62191a6e488276e23717147073a7ce0b444d485fff5a0c34c4577251a7a990cf80d8542e21b95aa8c5e6c@127.0.0.1:17889"); + private int tryTimes = 10; + private int sleepTime = 1000; + private boolean finish = false; + Node node = Node.instanceOf("127.0.0.1:" + Args.getInstance().getNodeListenPort()); - public TcpNetTest() { - super(dbPath, dbDirectory, indexDirectory, port); + public TcpTest(TronApplicationContext context) { + channelManager = context.getBean(ChannelManager.class); + manager = context.getBean(Manager.class); + pool = context.getBean(SyncPool.class); + tronNetDelegate = context.getBean(TronNetDelegate.class); } private enum TestType { @@ -81,19 +79,6 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List ou byte[] encoded = new byte[buffer.readableBytes()]; buffer.readBytes(encoded); P2pMessage msg = messageFactory.create(encoded); - - logger.info("Handshake Receive from {}, {}", ctx.channel().remoteAddress(), msg); - switch (msg.getType()) { - case P2P_HELLO: - logger.info("HandshakeHandler success"); - break; - case P2P_DISCONNECT: - logger.info("getReasonCode : {}", ((DisconnectMessage) msg).getReasonCode()); - break; - default: - return; - } - switch (testType) { case normal: Assert.assertEquals(msg.getType(), P2P_HELLO); @@ -122,67 +107,57 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List ou } } - //Unpooled.wrappedBuffer(ArrayUtils.add("nihao".getBytes(), 0, (byte) 1)) - - // @Test public void normalTest() throws InterruptedException { - Channel channel = createClient(new HandshakeHandler(TestType.normal)); + Channel channel = BaseNet.connect(new HandshakeHandler(TestType.normal)); HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), manager.getGenesisBlockId(), manager.getSolidBlockId(), manager.getHeadBlockId()); sendMessage(channel, message); validResultCloseConnect(channel); } - // @Test public void errorGenesisBlockIdTest() throws InterruptedException { - Channel channel = createClient(new HandshakeHandler(TestType.errorGenesisBlock)); + Channel channel = BaseNet.connect(new HandshakeHandler(TestType.errorGenesisBlock)); BlockId genesisBlockId = new BlockId(); HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), genesisBlockId, manager.getSolidBlockId(), manager.getHeadBlockId()); sendMessage(channel, message); - validResultCloseConnect(channel); } - // @Test public void errorVersionTest() throws InterruptedException { - Channel channel = createClient(new HandshakeHandler(TestType.errorVersion)); + Channel channel = BaseNet.connect(new HandshakeHandler(TestType.errorVersion)); Args.getInstance().setNodeP2pVersion(1); HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), manager.getGenesisBlockId(), manager.getSolidBlockId(), manager.getHeadBlockId()); Args.getInstance().setNodeP2pVersion(2); sendMessage(channel, message); - validResultCloseConnect(channel); } - // @Test public void errorSolidBlockIdTest() throws InterruptedException { - Channel channel = createClient(new HandshakeHandler(TestType.errorSolid)); + Channel channel = BaseNet.connect(new HandshakeHandler(TestType.errorSolid)); HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), manager.getGenesisBlockId(), new BlockId(), manager.getHeadBlockId()); sendMessage(channel, message); validResultCloseConnect(channel); } - // @Test public void repeatConnectTest() throws InterruptedException { - Channel channel = createClient(new HandshakeHandler(TestType.normal)); + Channel channel = BaseNet.connect(new HandshakeHandler(TestType.normal)); HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), manager.getGenesisBlockId(), manager.getSolidBlockId(), manager.getHeadBlockId()); sendMessage(channel, message); validResultUnCloseConnect(); - Channel repeatChannel = createClient(new HandshakeHandler(TestType.repeatConnect)); + Channel repeatChannel = BaseNet.connect(new HandshakeHandler(TestType.repeatConnect)); sendMessage(repeatChannel, message); validResultCloseConnect(repeatChannel); clearConnect(channel); } - // @Test public void unHandshakeTest() throws InterruptedException { List beforeActivePeers = ReflectUtils.getFieldValue(pool, "activePeers"); int beforeSize = beforeActivePeers.size(); - Channel channel = createClient(new HandshakeHandler(TestType.normal)); + Channel channel = BaseNet.connect(new HandshakeHandler(TestType.normal)); BlockMessage message = new BlockMessage(new BlockCapsule(Block.getDefaultInstance())); sendMessage(channel, message); List afterActivePeers = ReflectUtils.getFieldValue(pool, "activePeers"); @@ -191,9 +166,8 @@ public void unHandshakeTest() throws InterruptedException { clearConnect(channel); } - // @Test public void errorMsgTest() throws InterruptedException { - Channel channel = createClient(new HandshakeHandler(TestType.normal)); + Channel channel = BaseNet.connect(new HandshakeHandler(TestType.normal)); HelloMessage message = new HelloMessage(node, System.currentTimeMillis(), manager.getGenesisBlockId(), manager.getSolidBlockId(), manager.getHeadBlockId()); sendMessage(channel, message); @@ -237,16 +211,17 @@ private void validResultCloseConnect(Channel channel) throws InterruptedExceptio finish = false; channel.close(); Thread.sleep(sleepTime); + Collection peerConnections = ReflectUtils.invokeMethod(tronNetDelegate, "getActivePeer"); + for (PeerConnection peer : peerConnections) { + peer.close(); + } ReflectUtils.setFieldValue(channelManager, "recentlyDisconnected", CacheBuilder.newBuilder().maximumSize(1000) .expireAfterWrite(30, TimeUnit.SECONDS).recordStats().build()); - ReflectUtils.setFieldValue(pool, "activePeers", - Collections.synchronizedList(new ArrayList())); - ReflectUtils.setFieldValue(channelManager, "activePeers", new ConcurrentHashMap<>()); } private void validResultUnCloseConnect() throws InterruptedException { - int trys = 0; - while (!finish && ++trys < tryTimes) { + int n = 0; + while (!finish && ++n < tryTimes) { Thread.sleep(sleepTime); } Assert.assertEquals(finish, true); @@ -256,15 +231,15 @@ private void validResultUnCloseConnect() throws InterruptedException { private void clearConnect(Channel channel) throws InterruptedException { channel.close(); Thread.sleep(sleepTime); + Collection peerConnections = ReflectUtils.invokeMethod(tronNetDelegate, "getActivePeer"); + for (PeerConnection peer : peerConnections) { + peer.close(); + } ReflectUtils.setFieldValue(channelManager, "recentlyDisconnected", CacheBuilder.newBuilder().maximumSize(1000) .expireAfterWrite(30, TimeUnit.SECONDS).recordStats().build()); - ReflectUtils.setFieldValue(pool, "activePeers", - Collections.synchronizedList(new ArrayList())); - ReflectUtils.setFieldValue(channelManager, "activePeers", new ConcurrentHashMap<>()); } - @Test - public void testAll() throws InterruptedException { + public void test() throws InterruptedException { logger.info("begin normal test "); normalTest(); logger.info("begin errorGenesisBlockId test "); diff --git a/src/test/java/org/tron/core/net/UdpTest.java b/src/test/java/org/tron/core/net/UdpTest.java index 35fdf75b080..4763f1c1be9 100644 --- a/src/test/java/org/tron/core/net/UdpTest.java +++ b/src/test/java/org/tron/core/net/UdpTest.java @@ -30,34 +30,38 @@ @Slf4j public class UdpTest { - ApplicationContext context; - - NodeManager nodeManager; - - //@Before - public void before(){ - new Thread(() -> { - Args.setParam( - new String[]{ "--output-directory", "udp_test", "--storage-db-directory", "database", - "--storage-index-directory", "index"},"config.conf" - ); - Args cfgArgs = Args.getInstance(); - cfgArgs.getSeedNode().setIpList(Lists.newArrayList()); - cfgArgs.setNodeP2pVersion(100); - cfgArgs.setNodeListenPort(10001); - context = new TronApplicationContext(DefaultConfig.class); - }).start(); - } + private NodeManager nodeManager; + private int port = Args.getInstance().getNodeListenPort(); + private volatile boolean finishFlag = false; + private long timeOut = 30_000; - @Test - public void test() {} + public UdpTest(TronApplicationContext context) { + nodeManager = context.getBean(NodeManager.class); + } - //@Test - public void udpTest() throws Exception { + public void test() throws Exception { + /* + Thread thread = new Thread(() -> { + try { + discover(); + } catch (Exception e) { + logger.info("Discover test failed.", e); + } + }); + thread.start(); - Thread.sleep(10000); + long time = System.currentTimeMillis(); + while (!finishFlag && System.currentTimeMillis() - time < timeOut) { + Thread.sleep(1000); + } + if (!finishFlag) { + thread.interrupt(); + Assert.assertTrue(false); + } + */ + } - nodeManager = context.getBean(NodeManager.class); + public void discover() throws Exception { InetAddress server = InetAddress.getByName("127.0.0.1"); @@ -81,16 +85,16 @@ public void udpTest() throws Exception { DatagramSocket socket = new DatagramSocket(); DatagramPacket pingPacket = new DatagramPacket(pingMessage.getSendData(), - pingMessage.getSendData().length, server, 10001); + pingMessage.getSendData().length, server, port); DatagramPacket pongPacket = new DatagramPacket(pongMessage.getSendData(), - pongMessage.getSendData().length, server, 10001); + pongMessage.getSendData().length, server, port); DatagramPacket findNodePacket = new DatagramPacket(findNodeMessage.getSendData(), - findNodeMessage.getSendData().length, server, 10001); + findNodeMessage.getSendData().length, server, port); DatagramPacket neighborsPacket = new DatagramPacket(neighborsMessage.getSendData(), - neighborsMessage.getSendData().length, server, 10001); + neighborsMessage.getSendData().length, server, port); // send ping msg socket.send(pingPacket); @@ -130,11 +134,8 @@ public void udpTest() throws Exception { Assert.assertTrue(nodeManager.getTable().getAllNodes().size() == 1); socket.close(); - } - //@After - public void after() { - FileUtil.deleteDir(new File("udp_test")); + finishFlag = true; } } diff --git a/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java b/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java new file mode 100644 index 00000000000..2dbd55db147 --- /dev/null +++ b/src/test/java/org/tron/core/net/messagehandler/BlockMsgHandlerTest.java @@ -0,0 +1,62 @@ +package org.tron.core.net.messagehandler; + +import java.util.List; +import org.junit.Assert; +import org.junit.Test; +import org.testng.collections.Lists; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.exception.P2pException; +import org.tron.core.net.message.BlockMessage; +import org.tron.core.net.peer.Item; +import org.tron.core.net.peer.PeerConnection; +import org.tron.protos.Protocol.Inventory.InventoryType; +import org.tron.protos.Protocol.Transaction; + +public class BlockMsgHandlerTest { + + private BlockMsgHandler handler = new BlockMsgHandler(); + private PeerConnection peer = new PeerConnection(); + private BlockCapsule blockCapsule; + private BlockMessage msg; + + @Test + public void testProcessMessage() { + try { + blockCapsule = new BlockCapsule(1, Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), Sha256Hash.ZERO_HASH.getByteString()); + msg = new BlockMessage(blockCapsule); + handler.processMessage(peer, new BlockMessage(blockCapsule)); + }catch (P2pException e) { + Assert.assertTrue(e.getMessage().equals("no request")); + } + + try { + List transactionList = Lists.newArrayList(); + for (int i = 0; i < 1100000; i++) { + transactionList.add(Transaction.newBuilder().build()); + } + blockCapsule = new BlockCapsule(1, Sha256Hash.ZERO_HASH.getByteString(), + System.currentTimeMillis() + 10000,transactionList); + msg = new BlockMessage(blockCapsule); + System.out.println("len = " + blockCapsule.getInstance().getSerializedSize()); + peer.getAdvInvRequest().put(new Item(msg.getBlockId(), InventoryType.BLOCK), System.currentTimeMillis()); + handler.processMessage(peer, msg); + }catch (P2pException e) { + System.out.println(e); + Assert.assertTrue(e.getMessage().equals("block size over limit")); + } + + try { + blockCapsule = new BlockCapsule(1, Sha256Hash.ZERO_HASH, + System.currentTimeMillis() + 10000, Sha256Hash.ZERO_HASH.getByteString()); + msg = new BlockMessage(blockCapsule); + peer.getAdvInvRequest().put(new Item(msg.getBlockId(), InventoryType.BLOCK), System.currentTimeMillis()); + handler.processMessage(peer, msg); + }catch (P2pException e) { + System.out.println(e); + Assert.assertTrue(e.getMessage().equals("block time error")); + } + } + +} diff --git a/src/test/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandlerTest.java b/src/test/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandlerTest.java new file mode 100644 index 00000000000..e26444b2fe4 --- /dev/null +++ b/src/test/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandlerTest.java @@ -0,0 +1,65 @@ +package org.tron.core.net.messagehandler; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import javafx.util.Pair; +import org.junit.Assert; +import org.junit.Test; +import org.tron.core.capsule.BlockCapsule.BlockId; +import org.tron.core.config.Parameter.NodeConstant; +import org.tron.core.exception.P2pException; +import org.tron.core.net.message.ChainInventoryMessage; +import org.tron.core.net.peer.PeerConnection; + +public class ChainInventoryMsgHandlerTest { + + private ChainInventoryMsgHandler handler = new ChainInventoryMsgHandler(); + private PeerConnection peer = new PeerConnection(); + private ChainInventoryMessage msg = new ChainInventoryMessage(new ArrayList<>(), 0l); + private List blockIds = new ArrayList<>(); + + @Test + public void testProcessMessage() { + try { + handler.processMessage(peer, msg); + }catch (P2pException e) { + Assert.assertTrue(e.getMessage().equals("not send syncBlockChainMsg")); + } + + peer.setSyncChainRequested(new Pair<>(new LinkedList<>(), System.currentTimeMillis())); + + try { + handler.processMessage(peer, msg); + }catch (P2pException e) { + Assert.assertTrue(e.getMessage().equals("blockIds is empty")); + } + + + long size = NodeConstant.SYNC_FETCH_BATCH_NUM + 2; + for (int i = 0; i < size; i++) { + blockIds.add(new BlockId()); + } + msg = new ChainInventoryMessage(blockIds, 0l); + + try { + handler.processMessage(peer, msg); + }catch (P2pException e) { + Assert.assertTrue(e.getMessage().equals("big blockIds size: " + size)); + } + + blockIds.clear(); + size = NodeConstant.SYNC_FETCH_BATCH_NUM / 100; + for (int i = 0; i < size; i++) { + blockIds.add(new BlockId()); + } + msg = new ChainInventoryMessage(blockIds, 100l); + + try { + handler.processMessage(peer, msg); + }catch (P2pException e) { + Assert.assertTrue(e.getMessage().equals("remain: 100, blockIds size: " + size)); + } + } + +} diff --git a/src/test/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandlerTest.java b/src/test/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandlerTest.java new file mode 100644 index 00000000000..e885741c29c --- /dev/null +++ b/src/test/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandlerTest.java @@ -0,0 +1,5 @@ +package org.tron.core.net.messagehandler; + +public class FetchInvDataMsgHandlerTest { + +} diff --git a/src/test/java/org/tron/core/net/messagehandler/InventoryMsgHandlerTest.java b/src/test/java/org/tron/core/net/messagehandler/InventoryMsgHandlerTest.java new file mode 100644 index 00000000000..b6942efdd19 --- /dev/null +++ b/src/test/java/org/tron/core/net/messagehandler/InventoryMsgHandlerTest.java @@ -0,0 +1,30 @@ +package org.tron.core.net.messagehandler; + +import java.util.ArrayList; +import org.junit.Test; +import org.tron.core.net.message.InventoryMessage; +import org.tron.core.net.peer.PeerConnection; +import org.tron.protos.Protocol.Inventory.InventoryType; + +public class InventoryMsgHandlerTest { + private InventoryMsgHandler handler = new InventoryMsgHandler(); + private PeerConnection peer = new PeerConnection(); + + @Test + public void testProcessMessage() { + InventoryMessage msg = new InventoryMessage(new ArrayList<>(), InventoryType.TRX); + + peer.setNeedSyncFromPeer(true); + peer.setNeedSyncFromUs(true); + handler.processMessage(peer, msg); + + peer.setNeedSyncFromPeer(true); + peer.setNeedSyncFromUs(false); + handler.processMessage(peer, msg); + + peer.setNeedSyncFromPeer(false); + peer.setNeedSyncFromUs(true); + handler.processMessage(peer, msg); + + } +} diff --git a/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java b/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java new file mode 100644 index 00000000000..ff4c116c98f --- /dev/null +++ b/src/test/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandlerTest.java @@ -0,0 +1,23 @@ +package org.tron.core.net.messagehandler; + +import java.util.ArrayList; +import org.junit.Assert; +import org.junit.Test; +import org.tron.core.exception.P2pException; +import org.tron.core.net.message.SyncBlockChainMessage; +import org.tron.core.net.peer.PeerConnection; + +public class SyncBlockChainMsgHandlerTest { + private SyncBlockChainMsgHandler handler = new SyncBlockChainMsgHandler(); + private PeerConnection peer = new PeerConnection(); + + @Test + public void testProcessMessage() { + try { + handler.processMessage(peer, new SyncBlockChainMessage(new ArrayList<>())); + }catch (P2pException e) { + Assert.assertTrue(e.getMessage().equals("SyncBlockChain blockIds is empty")); + } + } + +} diff --git a/src/test/java/org/tron/core/net/node/BroadTest.java b/src/test/java/org/tron/core/net/node/BroadTest.java deleted file mode 100644 index fb7910c9a92..00000000000 --- a/src/test/java/org/tron/core/net/node/BroadTest.java +++ /dev/null @@ -1,304 +0,0 @@ -package org.tron.core.net.node; - -import com.google.common.cache.Cache; -import java.io.File; -import java.util.Collection; -import java.util.Map; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.MapUtils; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.overlay.message.Message; -import org.tron.common.overlay.server.Channel; -import org.tron.common.overlay.server.ChannelManager; -import org.tron.common.overlay.server.MessageQueue; -import org.tron.common.overlay.server.SyncPool; -import org.tron.common.utils.FileUtil; -import org.tron.common.utils.ReflectUtils; -import org.tron.common.utils.Sha256Hash; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.config.DefaultConfig; -import org.tron.core.config.args.Args; -import org.tron.core.db.ByteArrayWrapper; -import org.tron.core.db.Manager; -import org.tron.core.net.message.BlockMessage; -import org.tron.core.net.message.MessageTypes; -import org.tron.core.net.message.TransactionMessage; -import org.tron.core.net.node.NodeImpl.PriorItem; -import org.tron.core.net.node.override.HandshakeHandlerTest; -import org.tron.core.net.node.override.PeerClientTest; -import org.tron.core.net.node.override.TronChannelInitializerTest; -import org.tron.core.net.peer.PeerConnection; -import org.tron.core.services.RpcApiService; -import org.tron.core.services.WitnessService; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.Inventory.InventoryType; -import org.tron.protos.Protocol.Transaction; - -@Slf4j -public class BroadTest { - - private TronApplicationContext context; - private NodeImpl nodeImpl; - private RpcApiService rpcApiService; - private PeerClientTest peerClient; - private ChannelManager channelManager; - private SyncPool pool; - private Application appT; - private static final String dbPath = "output-nodeImplTest-broad"; - private static final String dbDirectory = "db_Broad_test"; - private static final String indexDirectory = "index_Broad_test"; - - private HandshakeHandlerTest handshakeHandlerTest; - private Node node; - - private class Condition { - - private Sha256Hash blockId; - private Sha256Hash transactionId; - - public Condition(Sha256Hash blockId, Sha256Hash transactionId) { - this.blockId = blockId; - this.transactionId = transactionId; - } - - public Sha256Hash getBlockId() { - return blockId; - } - - public Sha256Hash getTransactionId() { - return transactionId; - } - - } - - private Sha256Hash testBlockBroad() { - Block block = Block.getDefaultInstance(); - BlockMessage blockMessage = new BlockMessage(new BlockCapsule(block)); - nodeImpl.broadcast(blockMessage); - ConcurrentHashMap advObjToSpread = ReflectUtils - .getFieldValue(nodeImpl, "advObjToSpread"); - Assert.assertEquals(advObjToSpread.get(blockMessage.getMessageId()), InventoryType.BLOCK); - return blockMessage.getMessageId(); - } - - private Sha256Hash testTransactionBroad() { - Transaction transaction = Transaction.getDefaultInstance(); - TransactionMessage transactionMessage = new TransactionMessage(transaction); - nodeImpl.broadcast(transactionMessage); - ConcurrentHashMap advObjToSpread = ReflectUtils - .getFieldValue(nodeImpl, "advObjToSpread"); - Assert.assertEquals(advObjToSpread.get(transactionMessage.getMessageId()), InventoryType.TRX); - return transactionMessage.getMessageId(); - } - - private Condition testConsumerAdvObjToSpread() { - Sha256Hash blockId = testBlockBroad(); - Sha256Hash transactionId = testTransactionBroad(); - //remove the tx and block - removeTheTxAndBlock(blockId, transactionId); - - ReflectUtils.invokeMethod(nodeImpl, "consumerAdvObjToSpread"); - Collection activePeers = ReflectUtils.invokeMethod(nodeImpl, "getActivePeer"); - - boolean result = true; - for (PeerConnection peerConnection : activePeers) { - if (!peerConnection.getAdvObjWeSpread().containsKey(blockId)) { - result &= false; - } - if (!peerConnection.getAdvObjWeSpread().containsKey(transactionId)) { - result &= false; - } - } - for (PeerConnection peerConnection : activePeers) { - peerConnection.getAdvObjWeSpread().clear(); - } - Assert.assertTrue(result); - return new Condition(blockId, transactionId); - } - - private void removeTheTxAndBlock(Sha256Hash blockId, Sha256Hash transactionId) { - Cache trxCache = ReflectUtils - .getFieldValue(nodeImpl, "TrxCache"); - Cache blockCache = ReflectUtils.getFieldValue(nodeImpl, "BlockCache"); - trxCache.invalidate(transactionId); - blockCache.invalidate(blockId); - } - - @Test - public void testConsumerAdvObjToFetch() throws InterruptedException { - Condition condition = testConsumerAdvObjToSpread(); - Thread.sleep(1000); - // - Map advObjToFetch = ReflectUtils - .getFieldValue(nodeImpl, "advObjToFetch"); - logger.info("advObjToFetch:{}", advObjToFetch); - logger.info("advObjToFetchSize:{}", advObjToFetch.size()); - //Assert.assertEquals(advObjToFetch.get(condition.getBlockId()), InventoryType.BLOCK); - //Assert.assertEquals(advObjToFetch.get(condition.getTransactionId()), InventoryType.TRX); - //To avoid writing the database, manually stop the sending of messages. - Collection activePeers = ReflectUtils.invokeMethod(nodeImpl, "getActivePeer"); - Thread.sleep(1000); - if(activePeers.size() < 1){ - return; - } - for (PeerConnection peerConnection : activePeers) { - MessageQueue messageQueue = ReflectUtils.getFieldValue(peerConnection, "msgQueue"); - ReflectUtils.setFieldValue(messageQueue, "sendMsgFlag", false); - } - // - ReflectUtils.invokeMethod(nodeImpl, "consumerAdvObjToFetch"); - Thread.sleep(1000); - boolean result = true; - int count = 0; - for (PeerConnection peerConnection : activePeers) { - if (peerConnection.getAdvObjWeRequested() - .containsKey(new Item(condition.getTransactionId(), InventoryType.TRX))) { - ++count; - } - if (peerConnection.getAdvObjWeRequested() - .containsKey(new Item(condition.getBlockId(), InventoryType.BLOCK))) { - ++count; - } - MessageQueue messageQueue = ReflectUtils.getFieldValue(peerConnection, "msgQueue"); - BlockingQueue msgQueue = ReflectUtils.getFieldValue(messageQueue, "msgQueue"); - for (Message message : msgQueue) { - if (message.getType() == MessageTypes.BLOCK) { - Assert.assertEquals(message.getMessageId(), condition.getBlockId()); - } - if (message.getType() == MessageTypes.TRX) { - Assert.assertEquals(message.getMessageId(), condition.getTransactionId()); - } - } - } - Assert.assertTrue(count >= 1); - } - - private static boolean go = false; - - @Before - public void init() { - node = new Node( - "enode://e437a4836b77ad9d9ffe73ee782ef2614e6d8370fcf62191a6e488276e23717147073a7ce0b444d485fff5a0c34c4577251a7a990cf80d8542e21b95aa8c5e6c@127.0.0.1:17889"); - - new Thread(new Runnable() { - @Override - public void run() { - logger.info("Full node running."); - Args.setParam( - new String[]{ - "--output-directory", dbPath, - "--storage-db-directory", dbDirectory, - "--storage-index-directory", indexDirectory - }, - "config.conf" - ); - Args cfgArgs = Args.getInstance(); - cfgArgs.setNodeListenPort(17889); - cfgArgs.setNodeDiscoveryEnable(false); - cfgArgs.getSeedNode().getIpList().clear(); - cfgArgs.setNeedSyncCheck(false); - cfgArgs.setNodeExternalIp("127.0.0.1"); - - context = new TronApplicationContext(DefaultConfig.class); - - if (cfgArgs.isHelp()) { - logger.info("Here is the help message."); - return; - } - appT = ApplicationFactory.create(context); - rpcApiService = context.getBean(RpcApiService.class); - appT.addService(rpcApiService); - if (cfgArgs.isWitness()) { - appT.addService(new WitnessService(appT, context)); - } -// appT.initServices(cfgArgs); -// appT.startServices(); -// appT.startup(); - nodeImpl = context.getBean(NodeImpl.class); - peerClient = context.getBean(PeerClientTest.class); - channelManager = context.getBean(ChannelManager.class); - pool = context.getBean(SyncPool.class); - Manager dbManager = context.getBean(Manager.class); - handshakeHandlerTest = context.getBean(HandshakeHandlerTest.class); - handshakeHandlerTest.setNode(node); - NodeDelegate nodeDelegate = new NodeDelegateImpl(dbManager); - nodeImpl.setNodeDelegate(nodeDelegate); - pool.init(nodeImpl); - prepare(); - rpcApiService.blockUntilShutdown(); - } - }).start(); - int tryTimes = 1; - while (tryTimes <= 30 && (nodeImpl == null || peerClient == null - || channelManager == null || pool == null || !go)) { - try { - logger.info("nodeImpl:{},peerClient:{},channelManager:{},pool:{},{}", nodeImpl, peerClient, - channelManager, pool, go); - Thread.sleep(1000 * tryTimes); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - ++tryTimes; - } - } - } - - private void prepare() { - try { - ExecutorService advertiseLoopThread = ReflectUtils.getFieldValue(nodeImpl, "broadPool"); - advertiseLoopThread.shutdownNow(); - - peerClient.prepare(node.getHexId()); - - ReflectUtils.setFieldValue(nodeImpl, "isAdvertiseActive", false); - ReflectUtils.setFieldValue(nodeImpl, "isFetchActive", false); - TronChannelInitializerTest tronChannelInitializer = ReflectUtils - .getFieldValue(peerClient, "tronChannelInitializer"); - tronChannelInitializer.prepare(); - Channel channel = ReflectUtils.getFieldValue(tronChannelInitializer, "channel"); - ReflectUtils.setFieldValue(channel, "handshakeHandler", handshakeHandlerTest); - new Thread(new Runnable() { - @Override - public void run() { - peerClient.connect(node.getHost(), node.getPort(), node.getHexId()); - } - }).start(); - Thread.sleep(2000); - Map activePeers = ReflectUtils - .getFieldValue(channelManager, "activePeers"); - int tryTimes = 0; - while (MapUtils.isEmpty(activePeers) && ++tryTimes < 10) { - Thread.sleep(1000); - } - go = true; - } catch (Exception e) { - e.printStackTrace(); - } - } - - @After - public void destroy() { - Args.clearParam(); - Collection peerConnections = ReflectUtils - .invokeMethod(nodeImpl, "getActivePeer"); - for (PeerConnection peer : peerConnections) { - peer.close(); - } - context.destroy(); - handshakeHandlerTest.close(); - appT.shutdownServices(); - appT.shutdown(); - FileUtil.deleteDir(new File(dbPath)); - } - -} diff --git a/src/test/java/org/tron/core/net/node/FinishProcessSyncBlockTest.java b/src/test/java/org/tron/core/net/node/FinishProcessSyncBlockTest.java deleted file mode 100644 index 76b4e934d13..00000000000 --- a/src/test/java/org/tron/core/net/node/FinishProcessSyncBlockTest.java +++ /dev/null @@ -1,222 +0,0 @@ -package org.tron.core.net.node; - -import com.google.protobuf.ByteString; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.MapUtils; -import org.junit.*; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.crypto.ECKey; -import org.tron.common.overlay.client.PeerClient; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.overlay.server.Channel; -import org.tron.common.overlay.server.ChannelManager; -import org.tron.common.overlay.server.SyncPool; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; -import org.tron.common.utils.ReflectUtils; -import org.tron.core.Constant; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.config.DefaultConfig; -import org.tron.core.config.args.Args; -import org.tron.core.db.ByteArrayWrapper; -import org.tron.core.db.Manager; -import org.tron.core.net.node.override.HandshakeHandlerTest; -import org.tron.core.net.node.override.PeerClientTest; -import org.tron.core.net.node.override.TronChannelInitializerTest; -import org.tron.core.net.peer.PeerConnection; -import org.tron.core.services.RpcApiService; -import org.tron.core.services.WitnessService; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.BlockHeader; - -import java.io.File; -import java.util.Collection; -import java.util.Map; -import java.util.concurrent.ExecutorService; - -@Slf4j -public class FinishProcessSyncBlockTest { - - private static TronApplicationContext context; - private static NodeImpl node; - private RpcApiService rpcApiService; - private static PeerClientTest peerClient; - private ChannelManager channelManager; - private SyncPool pool; - private static Application appT; - private Manager dbManager; - private Node nodeEntity; - private static HandshakeHandlerTest handshakeHandlerTest; - - private static final String dbPath = "output-FinishProcessSyncBlockTest"; - private static final String dbDirectory = "db_FinishProcessSyncBlock_test"; - private static final String indexDirectory = "index_FinishProcessSyncBlock_test"; - - @Test - public void testFinishProcessSyncBlock() throws Exception { - Collection activePeers = ReflectUtils.invokeMethod(node, "getActivePeer"); - Thread.sleep(5000); - if (activePeers.size() < 1) { - return; - } - PeerConnection peer = (PeerConnection) activePeers.toArray()[1]; - BlockCapsule headBlockCapsule = dbManager.getHead(); - BlockCapsule blockCapsule = generateOneBlockCapsule(headBlockCapsule); - Class[] cls = {BlockCapsule.class}; - Object[] params = {blockCapsule}; - peer.getBlockInProc().add(blockCapsule.getBlockId()); - ReflectUtils.invokeMethod(node, "finishProcessSyncBlock", cls, params); - Assert.assertEquals(peer.getBlockInProc().isEmpty(), true); - } - - // generate ong block by parent block - private BlockCapsule generateOneBlockCapsule(BlockCapsule parentCapsule) { - ByteString witnessAddress = ByteString.copyFrom( - ECKey.fromPrivate( - ByteArray.fromHexString( - Args.getInstance().getLocalWitnesses().getPrivateKey())) - .getAddress()); - BlockHeader.raw raw = BlockHeader.raw.newBuilder() - .setTimestamp(System.currentTimeMillis()) - .setParentHash(parentCapsule.getBlockId().getByteString()) - .setNumber(parentCapsule.getNum() + 1) - .setWitnessAddress(witnessAddress) - .setWitnessId(1).build(); - BlockHeader blockHeader = BlockHeader.newBuilder() - .setRawData(raw) - .build(); - - Block block = Block.newBuilder().setBlockHeader(blockHeader).build(); - - BlockCapsule blockCapsule = new BlockCapsule(block); - blockCapsule.setMerkleRoot(); - blockCapsule.sign( - ByteArray.fromHexString(Args.getInstance().getLocalWitnesses().getPrivateKey())); - blockCapsule.setMerkleRoot(); - blockCapsule.sign( - ByteArray.fromHexString(Args.getInstance().getLocalWitnesses().getPrivateKey())); - - return blockCapsule; - } - - private static boolean go = false; - - @Before - public void init() { - nodeEntity = new Node( - "enode://e437a4836b77ad9d9ffe73ee782ef2614e6d8370fcf62191a6e488276e23717147073a7ce0b444d485fff5a0c34c4577251a7a990cf80d8542e21b95aa8c5e6c@127.0.0.1:17895"); - - new Thread(new Runnable() { - @Override - public void run() { - logger.info("Full node running."); - Args.setParam( - new String[]{ - "--output-directory", dbPath, - "--storage-db-directory", dbDirectory, - "--storage-index-directory", indexDirectory - }, - Constant.TEST_CONF - ); - Args cfgArgs = Args.getInstance(); - cfgArgs.setNodeListenPort(17895); - cfgArgs.setNodeDiscoveryEnable(false); - cfgArgs.getSeedNode().getIpList().clear(); - cfgArgs.setNeedSyncCheck(false); - cfgArgs.setNodeExternalIp("127.0.0.1"); - - context = new TronApplicationContext(DefaultConfig.class); - - if (cfgArgs.isHelp()) { - logger.info("Here is the help message."); - return; - } - appT = ApplicationFactory.create(context); - rpcApiService = context.getBean(RpcApiService.class); - appT.addService(rpcApiService); - if (cfgArgs.isWitness()) { - appT.addService(new WitnessService(appT, context)); - } -// appT.initServices(cfgArgs); -// appT.startServices(); -// appT.startup(); - node = context.getBean(NodeImpl.class); - peerClient = context.getBean(PeerClientTest.class); - channelManager = context.getBean(ChannelManager.class); - pool = context.getBean(SyncPool.class); - dbManager = context.getBean(Manager.class); - handshakeHandlerTest = context.getBean(HandshakeHandlerTest.class); - handshakeHandlerTest.setNode(nodeEntity); - NodeDelegate nodeDelegate = new NodeDelegateImpl(dbManager); - node.setNodeDelegate(nodeDelegate); - pool.init(node); - prepare(); - rpcApiService.blockUntilShutdown(); - } - }).start(); - int tryTimes = 0; - while (tryTimes < 10 && (node == null || peerClient == null - || channelManager == null || pool == null || !go)) { - try { - logger.info("node:{},peerClient:{},channelManager:{},pool:{},{}", node, peerClient, - channelManager, pool, go); - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - ++tryTimes; - } - } - } - - private void prepare() { - try { - ExecutorService advertiseLoopThread = ReflectUtils.getFieldValue(node, "broadPool"); - advertiseLoopThread.shutdownNow(); - - peerClient.prepare(nodeEntity.getHexId()); - - ReflectUtils.setFieldValue(node, "isAdvertiseActive", false); - ReflectUtils.setFieldValue(node, "isFetchActive", false); - - TronChannelInitializerTest tronChannelInitializer = ReflectUtils - .getFieldValue(peerClient, "tronChannelInitializer"); - tronChannelInitializer.prepare(); - Channel channel = ReflectUtils.getFieldValue(tronChannelInitializer, "channel"); - ReflectUtils.setFieldValue(channel, "handshakeHandler", handshakeHandlerTest); - - new Thread(new Runnable() { - @Override - public void run() { - peerClient.connect(nodeEntity.getHost(), nodeEntity.getPort(), nodeEntity.getHexId()); - } - }).start(); - Thread.sleep(1000); - Map activePeers = ReflectUtils - .getFieldValue(channelManager, "activePeers"); - int tryTimes = 0; - while (MapUtils.isEmpty(activePeers) && ++tryTimes < 10) { - Thread.sleep(1000); - } - go = true; - } catch (Exception e) { - e.printStackTrace(); - } - } - - @AfterClass - public static void destroy() { - Args.clearParam(); - Collection peerConnections = ReflectUtils.invokeMethod(node, "getActivePeer"); - for (PeerConnection peer : peerConnections) { - peer.close(); - } - handshakeHandlerTest.close(); - appT.shutdownServices(); - appT.shutdown(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } -} diff --git a/src/test/java/org/tron/core/net/node/GetBlockChainSummaryTest.java b/src/test/java/org/tron/core/net/node/GetBlockChainSummaryTest.java deleted file mode 100644 index 74e53bed873..00000000000 --- a/src/test/java/org/tron/core/net/node/GetBlockChainSummaryTest.java +++ /dev/null @@ -1,350 +0,0 @@ -package org.tron.core.net.node; - -import com.google.common.collect.Maps; -import com.google.protobuf.ByteString; -import java.io.File; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Deque; -import java.util.Map; -import java.util.concurrent.ConcurrentLinkedDeque; -import java.util.concurrent.ExecutorService; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.MapUtils; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.crypto.ECKey; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.overlay.server.Channel; -import org.tron.common.overlay.server.ChannelManager; -import org.tron.common.overlay.server.SyncPool; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; -import org.tron.common.utils.ReflectUtils; -import org.tron.common.utils.Sha256Hash; -import org.tron.common.utils.Utils; -import org.tron.core.capsule.AccountCapsule; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.config.DefaultConfig; -import org.tron.core.config.args.Args; -import org.tron.core.db.BlockStore; -import org.tron.core.db.ByteArrayWrapper; -import org.tron.core.db.Manager; -import org.tron.core.net.node.override.HandshakeHandlerTest; -import org.tron.core.net.node.override.PeerClientTest; -import org.tron.core.net.node.override.TronChannelInitializerTest; -import org.tron.core.net.peer.PeerConnection; -import org.tron.core.services.RpcApiService; -import org.tron.core.services.WitnessService; -import org.tron.core.witness.WitnessController; -import org.tron.protos.Protocol; - -@Slf4j -public class GetBlockChainSummaryTest { - - private static TronApplicationContext context; - private static NodeImpl node; - private RpcApiService rpcApiService; - private static PeerClientTest peerClient; - private ChannelManager channelManager; - private SyncPool pool; - private static Application appT; - private Manager dbManager; - private Node nodeEntity; - private static HandshakeHandlerTest handshakeHandlerTest; - - private static final String dbPath = "output-GetBlockChainSummary"; - private static final String dbDirectory = "db_GetBlockChainSummary_test"; - private static final String indexDirectory = "index_GetBlockChainSummary_test"; - - @Test - public void testGetBlockChainSummary() { - NodeDelegate del = ReflectUtils.getFieldValue(node, "del"); - Collection activePeers = ReflectUtils.invokeMethod(node, "getActivePeer"); - BlockStore blkstore = dbManager.getBlockStore(); - - Object[] peers = activePeers.toArray(); - if (peers == null || peers.length <= 0) { - return; - } - PeerConnection peer_he = (PeerConnection) peers[0]; - Deque toFetch = new ConcurrentLinkedDeque<>(); - - ArrayList scenes = new ArrayList<>(); - scenes.add("genesis"); - scenes.add("genesis_fetch"); - scenes.add("nongenesis_fetch"); - - long number = dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() + 1; - Map addressToProvateKeys = addTestWitnessAndAccount(); - BlockCapsule capsule = createTestBlockCapsule(1533529947843L, number, - dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString(), - addressToProvateKeys); - try { - dbManager.pushBlock(capsule); - } catch (Exception e) { - e.printStackTrace(); - } - for (int i = 1; i < 5; i++) { - number = dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() + 1; - capsule = createTestBlockCapsule(1533529947843L + 3000L * i, number, - dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString(), - addressToProvateKeys); - try { - dbManager.pushBlock(capsule); - } catch (Exception e) { - e.printStackTrace(); - } - } - - BlockCapsule.BlockId commonBlockId = null; - - //the common block is genesisblock,syncBlockToFetch is empty。 - try { - commonBlockId = del.getGenesisBlock().getBlockId(); - peer_he.getSyncBlockToFetch().clear(); - ReflectUtils.setFieldValue(peer_he, "headBlockWeBothHave", commonBlockId); - ReflectUtils.setFieldValue(peer_he, "headBlockTimeWeBothHave", System.currentTimeMillis()); - Deque retSummary = del - .getBlockChainSummary(peer_he.getHeadBlockWeBothHave(), peer_he.getSyncBlockToFetch()); - Assert.assertTrue(retSummary.size() == 3); - } catch (Exception e) { - System.out.println("exception!"); - } - - //the common block is genesisblock,syncBlockToFetch is not empty。 - peer_he.getSyncBlockToFetch().addAll(toFetch); - try { - toFetch.clear(); - peer_he.getSyncBlockToFetch().clear(); - for (int i = 0; i < 4; i++) { - number = dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() + 1; - capsule = createTestBlockCapsule(1533529947843L + 3000L * i, number, - dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString(), - addressToProvateKeys); - toFetch.add(capsule.getBlockId()); - } - - commonBlockId = del.getGenesisBlock().getBlockId(); - peer_he.getSyncBlockToFetch().addAll(toFetch); - ReflectUtils.setFieldValue(peer_he, "headBlockWeBothHave", commonBlockId); - ReflectUtils.setFieldValue(peer_he, "headBlockTimeWeBothHave", System.currentTimeMillis()); - Deque retSummary = del - .getBlockChainSummary(peer_he.getHeadBlockWeBothHave(), peer_he.getSyncBlockToFetch()); - Assert.assertTrue(retSummary.size() == 4); - } catch (Exception e) { - System.out.println("exception!"); - } - - //the common block is a normal block(not genesisblock),syncBlockToFetc is not empty. - try { - toFetch.clear(); - peer_he.getSyncBlockToFetch().clear(); - number = dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() + 1; - BlockCapsule capsule1 = createTestBlockCapsule(1533529947843L + 3000L * 6, number, - dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString(), - addressToProvateKeys); - dbManager.pushBlock(capsule1); - - number = dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() + 1; - BlockCapsule capsule2 = createTestBlockCapsule(1533529947843L + 3000L * 7, number, - dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString(), - addressToProvateKeys); - dbManager.pushBlock(capsule2); - - for (int i = 0; i < 2; i++) { - number = dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() + 1; - capsule = createTestBlockCapsule(1533529947843L + 3000L * 8 + 3000L * i, number, - dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString(), - addressToProvateKeys); - toFetch.add(capsule.getBlockId()); - } - commonBlockId = capsule2.getBlockId(); - peer_he.getSyncBlockToFetch().addAll(toFetch); - toFetch.forEach(block -> blkstore.delete(block.getBytes())); - ReflectUtils.setFieldValue(peer_he, "headBlockWeBothHave", commonBlockId); - ReflectUtils.setFieldValue(peer_he, "headBlockTimeWeBothHave", System.currentTimeMillis()); - Deque retSummary = del - .getBlockChainSummary(peer_he.getHeadBlockWeBothHave(), peer_he.getSyncBlockToFetch()); - Assert.assertTrue(retSummary.size() == 4); - } catch (Exception e) { - System.out.println("exception!"); - } - logger.info("finish1"); - } - - - private static boolean go = false; - - private Map addTestWitnessAndAccount() { - dbManager.getWitnesses().clear(); - return IntStream.range(0, 2) - .mapToObj( - i -> { - ECKey ecKey = new ECKey(Utils.getRandom()); - String privateKey = ByteArray.toHexString(ecKey.getPrivKey().toByteArray()); - ByteString address = ByteString.copyFrom(ecKey.getAddress()); - - WitnessCapsule witnessCapsule = new WitnessCapsule(address); - dbManager.getWitnessStore().put(address.toByteArray(), witnessCapsule); - dbManager.getWitnessController().addWitness(address); - - AccountCapsule accountCapsule = - new AccountCapsule(Protocol.Account.newBuilder().setAddress(address).build()); - dbManager.getAccountStore().put(address.toByteArray(), accountCapsule); - - return Maps.immutableEntry(address, privateKey); - }) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - } - - private BlockCapsule createTestBlockCapsule( - long number, ByteString hash, Map addressToProvateKeys) { - long time = System.currentTimeMillis(); - return createTestBlockCapsule(time, number, hash, addressToProvateKeys); - } - - private BlockCapsule createTestBlockCapsule(long time, - long number, ByteString hash, Map addressToProvateKeys) { - WitnessController witnessController = dbManager.getWitnessController(); - ByteString witnessAddress = - witnessController.getScheduledWitness(witnessController.getSlotAtTime(time)); - BlockCapsule blockCapsule = new BlockCapsule(number, Sha256Hash.wrap(hash), time, - witnessAddress); - blockCapsule.generatedByMyself = true; - blockCapsule.setMerkleRoot(); - blockCapsule.sign(ByteArray.fromHexString(addressToProvateKeys.get(witnessAddress))); - return blockCapsule; - } - - @Before - public void init() { - nodeEntity = new Node( - "enode://e437a4836b77ad9d9ffe73ee782ef2614e6d8370fcf62191a6e488276e23717147073a7ce0b444d485fff5a0c34c4577251a7a990cf80d8542e21b95aa8c5e6c@127.0.0.1:17896"); - - Thread thread = new Thread(new Runnable() { - @Override - public void run() { - logger.info("Full node running."); - Args.setParam( - new String[]{ - "--output-directory", dbPath, - "--storage-db-directory", dbDirectory, - "--storage-index-directory", indexDirectory - }, - "config.conf" - ); - Args cfgArgs = Args.getInstance(); - cfgArgs.setNodeListenPort(17896); - cfgArgs.setNodeDiscoveryEnable(false); - cfgArgs.getSeedNode().getIpList().clear(); - cfgArgs.setNeedSyncCheck(false); - cfgArgs.setNodeExternalIp("127.0.0.1"); - - context = new TronApplicationContext(DefaultConfig.class); - - if (cfgArgs.isHelp()) { - logger.info("Here is the help message."); - return; - } - appT = ApplicationFactory.create(context); - rpcApiService = context.getBean(RpcApiService.class); - appT.addService(rpcApiService); - if (cfgArgs.isWitness()) { - appT.addService(new WitnessService(appT, context)); - } -// appT.initServices(cfgArgs); -// appT.startServices(); -// appT.startup(); - node = context.getBean(NodeImpl.class); - peerClient = context.getBean(PeerClientTest.class); - channelManager = context.getBean(ChannelManager.class); - pool = context.getBean(SyncPool.class); - dbManager = context.getBean(Manager.class); - handshakeHandlerTest = context.getBean(HandshakeHandlerTest.class); - handshakeHandlerTest.setNode(nodeEntity); - NodeDelegate nodeDelegate = new NodeDelegateImpl(dbManager); - node.setNodeDelegate(nodeDelegate); - pool.init(node); - prepare(); - rpcApiService.blockUntilShutdown(); - } - }); - thread.start(); - try { - thread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - int tryTimes = 0; - while (tryTimes < 10 && (node == null || peerClient == null - || channelManager == null || pool == null || !go)) { - try { - logger.info("node:{},peerClient:{},channelManager:{},pool:{},{}", node, peerClient, - channelManager, pool, go); - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - ++tryTimes; - } - } - } - - private void prepare() { - try { - ExecutorService advertiseLoopThread = ReflectUtils.getFieldValue(node, "broadPool"); - advertiseLoopThread.shutdownNow(); - - peerClient.prepare(nodeEntity.getHexId()); - - ReflectUtils.setFieldValue(node, "isAdvertiseActive", false); - ReflectUtils.setFieldValue(node, "isFetchActive", false); - - TronChannelInitializerTest tronChannelInitializer = ReflectUtils - .getFieldValue(peerClient, "tronChannelInitializer"); - tronChannelInitializer.prepare(); - Channel channel = ReflectUtils.getFieldValue(tronChannelInitializer, "channel"); - ReflectUtils.setFieldValue(channel, "handshakeHandler", handshakeHandlerTest); - - new Thread(new Runnable() { - @Override - public void run() { - peerClient.connect(nodeEntity.getHost(), nodeEntity.getPort(), nodeEntity.getHexId()); - } - }).start(); - Thread.sleep(1000); - Map activePeers = ReflectUtils - .getFieldValue(channelManager, "activePeers"); - int tryTimes = 0; - while (MapUtils.isEmpty(activePeers) && ++tryTimes < 10) { - Thread.sleep(1000); - } - go = true; - } catch (Exception e) { - e.printStackTrace(); - } - } - - @AfterClass - public static void destroy() { - Args.clearParam(); - Collection peerConnections = ReflectUtils.invokeMethod(node, "getActivePeer"); - for (PeerConnection peer : peerConnections) { - peer.close(); - } - handshakeHandlerTest.close(); - appT.shutdownServices(); - appT.shutdown(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } -} diff --git a/src/test/java/org/tron/core/net/node/GetLostBlockIdsTest.java b/src/test/java/org/tron/core/net/node/GetLostBlockIdsTest.java deleted file mode 100644 index 94dd6bdb186..00000000000 --- a/src/test/java/org/tron/core/net/node/GetLostBlockIdsTest.java +++ /dev/null @@ -1,332 +0,0 @@ -package org.tron.core.net.node; - -import com.google.common.collect.Maps; -import com.google.protobuf.ByteString; -import io.grpc.Channel; -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.MapUtils; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.crypto.ECKey; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.overlay.server.ChannelManager; -import org.tron.common.overlay.server.SyncPool; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; -import org.tron.common.utils.ReflectUtils; -import org.tron.common.utils.Sha256Hash; -import org.tron.common.utils.Utils; -import org.tron.core.capsule.AccountCapsule; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.capsule.BlockCapsule.BlockId; -import org.tron.core.capsule.WitnessCapsule; -import org.tron.core.config.DefaultConfig; -import org.tron.core.config.args.Args; -import org.tron.core.db.ByteArrayWrapper; -import org.tron.core.db.Manager; -import org.tron.core.exception.StoreException; -import org.tron.core.net.node.override.HandshakeHandlerTest; -import org.tron.core.net.node.override.PeerClientTest; -import org.tron.core.net.node.override.TronChannelInitializerTest; -import org.tron.core.net.peer.PeerConnection; -import org.tron.core.services.RpcApiService; -import org.tron.core.services.WitnessService; -import org.tron.core.witness.WitnessController; -import org.tron.protos.Protocol; - -@Slf4j -public class GetLostBlockIdsTest { - - private static TronApplicationContext context; - private static NodeImpl node; - private RpcApiService rpcApiService; - private static PeerClientTest peerClient; - private ChannelManager channelManager; - private SyncPool pool; - private static Application appT; - private Manager dbManager; - private Node nodeEntity; - private static HandshakeHandlerTest handshakeHandlerTest; - - private static final String dbPath = "output-GetLostBlockIdsTest"; - private static final String dbDirectory = "db_GetLostBlockIds_test"; - private static final String indexDirectory = "index_GetLostBlockIds_test"; - - @Test - public void testGetLostBlockIds() { - NodeDelegate del = ReflectUtils.getFieldValue(node, "del"); - List blockChainSummary; - LinkedList blockIds = null; - - long number; - Map addressToProvateKeys = addTestWitnessAndAccount(); - BlockCapsule capsule; - for (int i = 0; i < 5; i++) { - number = dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() + 1; - capsule = createTestBlockCapsule(1533529947843L + 3000L * i, number, - dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString(), - addressToProvateKeys); - try { - dbManager.pushBlock(capsule); - } catch (Exception e) { - e.printStackTrace(); - } - } - - //blockChainSummary is empty - try { - blockChainSummary = new ArrayList(); - blockIds = del.getLostBlockIds(blockChainSummary); - } catch (StoreException e) { - e.printStackTrace(); - } - Assert.assertTrue(blockIds.size() == 6); - - //blockChainSummary only have a genesis block - try { - blockChainSummary = new ArrayList(); - blockChainSummary.add(dbManager.getGenesisBlockId()); - blockIds = del.getLostBlockIds(blockChainSummary); - } catch (StoreException e) { - e.printStackTrace(); - } - Assert.assertTrue(blockIds.size() == 6); - - //blockChainSummary have genesis block、2nd block、3rd block - BlockId except_first_block = null; - try { - blockChainSummary = new ArrayList(); - blockChainSummary.add(dbManager.getGenesisBlockId()); - blockChainSummary.add(dbManager.getBlockIdByNum(2)); - blockChainSummary.add(dbManager.getBlockIdByNum(3)); - except_first_block = dbManager.getBlockIdByNum(3); - blockIds = del.getLostBlockIds(blockChainSummary); - } catch (StoreException e) { - e.printStackTrace(); - } - Assert.assertTrue(blockIds.size() == 3 && Arrays - .equals(blockIds.peekFirst().getBytes(), except_first_block.getBytes())); - - //blockChainSummary have 2nd block、4th block,and they are on fork chain - try { - BlockCapsule capsule2 = new BlockCapsule(2, - Sha256Hash.wrap(ByteString.copyFrom( - ByteArray.fromHexString( - "0000000000000002498b464ac0292229938a342238077182498b464ac0292222"))), - 1234, ByteString.copyFrom("1234567".getBytes())); - BlockCapsule capsule4 = new BlockCapsule(4, - Sha256Hash.wrap(ByteString.copyFrom( - ByteArray.fromHexString( - "00000000000000042498b464ac0292229938a342238077182498b464ac029222"))), - 1234, ByteString.copyFrom("abcdefg".getBytes())); - blockChainSummary = new ArrayList(); - blockChainSummary.add(capsule2.getBlockId()); - blockChainSummary.add(capsule4.getBlockId()); - blockIds = del.getLostBlockIds(blockChainSummary); - } catch (StoreException e) { - e.printStackTrace(); - } - Assert.assertTrue(blockIds.size() == 0); - - //blockChainSummary have 2nd block(main chain)、4th block(fork chain) - try { - BlockCapsule capsule4 = new BlockCapsule(4, - Sha256Hash.wrap(ByteString.copyFrom( - ByteArray.fromHexString( - "00000000000000042498b464ac0292229938a342238077182498b464ac029222"))), - 1234, ByteString.copyFrom("abcdefg".getBytes())); - blockChainSummary = new ArrayList(); - blockChainSummary.add(dbManager.getBlockIdByNum(2)); - blockChainSummary.add(capsule4.getBlockId()); - except_first_block = dbManager.getBlockIdByNum(2); - blockIds = del.getLostBlockIds(blockChainSummary); - } catch (StoreException e) { - e.printStackTrace(); - } - Assert.assertTrue(blockIds.size() == 4 && Arrays - .equals(blockIds.peekFirst().getBytes(), except_first_block.getBytes())); - logger.info("finish2"); - } - - private boolean go = false; - - private Map addTestWitnessAndAccount() { - dbManager.getWitnesses().clear(); - return IntStream.range(0, 2) - .mapToObj( - i -> { - ECKey ecKey = new ECKey(Utils.getRandom()); - String privateKey = ByteArray.toHexString(ecKey.getPrivKey().toByteArray()); - ByteString address = ByteString.copyFrom(ecKey.getAddress()); - - WitnessCapsule witnessCapsule = new WitnessCapsule(address); - dbManager.getWitnessStore().put(address.toByteArray(), witnessCapsule); - dbManager.getWitnessController().addWitness(address); - - AccountCapsule accountCapsule = - new AccountCapsule(Protocol.Account.newBuilder().setAddress(address).build()); - dbManager.getAccountStore().put(address.toByteArray(), accountCapsule); - - return Maps.immutableEntry(address, privateKey); - }) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - } - - private BlockCapsule createTestBlockCapsule( - long number, ByteString hash, Map addressToProvateKeys) { - long time = System.currentTimeMillis(); - return createTestBlockCapsule(time, number, hash, addressToProvateKeys); - } - - private BlockCapsule createTestBlockCapsule(long time, - long number, ByteString hash, Map addressToProvateKeys) { - WitnessController witnessController = dbManager.getWitnessController(); - ByteString witnessAddress = - witnessController.getScheduledWitness(witnessController.getSlotAtTime(time)); - BlockCapsule blockCapsule = new BlockCapsule(number, Sha256Hash.wrap(hash), time, - witnessAddress); - blockCapsule.generatedByMyself = true; - blockCapsule.setMerkleRoot(); - blockCapsule.sign(ByteArray.fromHexString(addressToProvateKeys.get(witnessAddress))); - return blockCapsule; - } - - @Before - public void init() { - nodeEntity = new Node( - "enode://e437a4836b77ad9d9ffe73ee782ef2614e6d8370fcf62191a6e488276e23717147073a7ce0b444d485fff5a0c34c4577251a7a990cf80d8542e21b95aa8c5e6c@127.0.0.1:17892"); - - Thread thread = new Thread(new Runnable() { - @Override - public void run() { - logger.info("Full node running."); - Args.setParam( - new String[]{ - "--output-directory", dbPath, - "--storage-db-directory", dbDirectory, - "--storage-index-directory", indexDirectory - }, - "config.conf" - ); - Args cfgArgs = Args.getInstance(); - cfgArgs.setNodeListenPort(17892); - cfgArgs.setNodeDiscoveryEnable(false); - cfgArgs.getSeedNode().getIpList().clear(); - cfgArgs.setNeedSyncCheck(false); - cfgArgs.setNodeExternalIp("127.0.0.1"); - - context = new TronApplicationContext(DefaultConfig.class); - - if (cfgArgs.isHelp()) { - logger.info("Here is the help message."); - return; - } - appT = ApplicationFactory.create(context); - rpcApiService = context.getBean(RpcApiService.class); - appT.addService(rpcApiService); - if (cfgArgs.isWitness()) { - appT.addService(new WitnessService(appT, context)); - } -// appT.initServices(cfgArgs); -// appT.startServices(); -// appT.startup(); - node = context.getBean(NodeImpl.class); - peerClient = context.getBean(PeerClientTest.class); - channelManager = context.getBean(ChannelManager.class); - pool = context.getBean(SyncPool.class); - dbManager = context.getBean(Manager.class); - handshakeHandlerTest = context.getBean(HandshakeHandlerTest.class); - handshakeHandlerTest.setNode(nodeEntity); - NodeDelegate nodeDelegate = new NodeDelegateImpl(dbManager); - node.setNodeDelegate(nodeDelegate); - pool.init(node); - prepare(); - rpcApiService.blockUntilShutdown(); - } - }); - thread.start(); - try { - thread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - int tryTimes = 0; - while (tryTimes < 10 && (node == null || peerClient == null - || channelManager == null || pool == null || !go)) { - try { - logger.info("node:{},peerClient:{},channelManager:{},pool:{},{}", node, peerClient, - channelManager, pool, go); - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - ++tryTimes; - } - } - } - - private void prepare() { - try { - ExecutorService advertiseLoopThread = ReflectUtils.getFieldValue(node, "broadPool"); - advertiseLoopThread.shutdownNow(); - - peerClient.prepare(nodeEntity.getHexId()); - - ReflectUtils.setFieldValue(node, "isAdvertiseActive", false); - ReflectUtils.setFieldValue(node, "isFetchActive", false); - - TronChannelInitializerTest tronChannelInitializer = ReflectUtils - .getFieldValue(peerClient, "tronChannelInitializer"); - tronChannelInitializer.prepare(); - org.tron.common.overlay.server.Channel channel = ReflectUtils - .getFieldValue(tronChannelInitializer, "channel"); - ReflectUtils.setFieldValue(channel, "handshakeHandler", handshakeHandlerTest); - - new Thread(new Runnable() { - @Override - public void run() { - peerClient.connect(nodeEntity.getHost(), nodeEntity.getPort(), nodeEntity.getHexId()); - } - }).start(); - Thread.sleep(1000); - Map activePeers = ReflectUtils - .getFieldValue(channelManager, "activePeers"); - int tryTimes = 0; - while (MapUtils.isEmpty(activePeers) && ++tryTimes < 10) { - Thread.sleep(1000); - } - go = true; - } catch (Exception e) { - e.printStackTrace(); - } - } - - @AfterClass - public static void destroy() { - Args.clearParam(); - Collection peerConnections = ReflectUtils.invokeMethod(node, "getActivePeer"); - for (PeerConnection peer : peerConnections) { - peer.close(); - } - handshakeHandlerTest.close(); - appT.shutdownServices(); - appT.shutdown(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } -} diff --git a/src/test/java/org/tron/core/net/node/HandleBlockMessageTest.java b/src/test/java/org/tron/core/net/node/HandleBlockMessageTest.java deleted file mode 100644 index 9b920c990a9..00000000000 --- a/src/test/java/org/tron/core/net/node/HandleBlockMessageTest.java +++ /dev/null @@ -1,245 +0,0 @@ -package org.tron.core.net.node; - -import com.google.protobuf.ByteString; -import java.io.File; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.MapUtils; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.crypto.ECKey; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.overlay.server.Channel; -import org.tron.common.overlay.server.ChannelManager; -import org.tron.common.overlay.server.SyncPool; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; -import org.tron.common.utils.ReflectUtils; -import org.tron.core.Constant; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.config.DefaultConfig; -import org.tron.core.config.args.Args; -import org.tron.core.db.ByteArrayWrapper; -import org.tron.core.db.Manager; -import org.tron.core.net.message.BlockMessage; -import org.tron.core.net.node.override.HandshakeHandlerTest; -import org.tron.core.net.node.override.PeerClientTest; -import org.tron.core.net.node.override.TronChannelInitializerTest; -import org.tron.core.net.peer.PeerConnection; -import org.tron.core.services.RpcApiService; -import org.tron.core.services.WitnessService; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.BlockHeader; -import org.tron.protos.Protocol.Inventory.InventoryType; - -@Slf4j -public class HandleBlockMessageTest { - - private static TronApplicationContext context; - private static NodeImpl node; - private RpcApiService rpcApiService; - private static PeerClientTest peerClient; - private ChannelManager channelManager; - private SyncPool pool; - private static Application appT; - private Manager dbManager; - private Node nodeEntity; - private static HandshakeHandlerTest handshakeHandlerTest; - - private static final String dbPath = "output-HandleBlockMessageTest"; - private static final String dbDirectory = "db_HandleBlockMessage_test"; - private static final String indexDirectory = "index_HandleBlockMessage_test"; - - @Test - public void testHandleBlockMessage() throws Exception { - List activePeers = ReflectUtils.getFieldValue(pool, "activePeers"); - Thread.sleep(5000); - if (activePeers.size() < 1) { - return; - } - PeerConnection peer = activePeers.get(0); - - //receive a sync block - BlockCapsule headBlockCapsule = dbManager.getHead(); - BlockCapsule syncblockCapsule = generateOneBlockCapsule(headBlockCapsule); - BlockMessage blockMessage = new BlockMessage(syncblockCapsule); - peer.getSyncBlockRequested().put(blockMessage.getBlockId(), System.currentTimeMillis()); - node.onMessage(peer, blockMessage); - Assert.assertEquals(peer.getSyncBlockRequested().isEmpty(), true); - - //receive a advertise block - BlockCapsule advblockCapsule = generateOneBlockCapsule(headBlockCapsule); - BlockMessage advblockMessage = new BlockMessage(advblockCapsule); - peer.getAdvObjWeRequested().put(new Item(advblockMessage.getBlockId(), InventoryType.BLOCK), - System.currentTimeMillis()); - node.onMessage(peer, advblockMessage); - Assert.assertEquals(peer.getAdvObjWeRequested().size(), 0); - - //receive a sync block but not requested - BlockCapsule blockCapsule = generateOneBlockCapsule(headBlockCapsule); - blockMessage = new BlockMessage(blockCapsule); - BlockCapsule blockCapsuleOther = generateOneBlockCapsule(blockCapsule); - BlockMessage blockMessageOther = new BlockMessage(blockCapsuleOther); - - peer.getSyncBlockRequested().put(blockMessage.getBlockId(), System.currentTimeMillis()); - node.onMessage(peer, blockMessageOther); - Assert.assertEquals(peer.getSyncBlockRequested().isEmpty(), false); - } - - // generate ong block by parent block - private BlockCapsule generateOneBlockCapsule(BlockCapsule parentCapsule) { - ByteString witnessAddress = ByteString.copyFrom( - ECKey.fromPrivate( - ByteArray.fromHexString( - Args.getInstance().getLocalWitnesses().getPrivateKey())) - .getAddress()); - BlockHeader.raw raw = BlockHeader.raw.newBuilder() - .setTimestamp(System.currentTimeMillis()) - .setParentHash(parentCapsule.getBlockId().getByteString()) - .setNumber(parentCapsule.getNum() + 1) - .setWitnessAddress(witnessAddress) - .setWitnessId(1).build(); - BlockHeader blockHeader = BlockHeader.newBuilder() - .setRawData(raw) - .build(); - - Block block = Block.newBuilder().setBlockHeader(blockHeader).build(); - - BlockCapsule blockCapsule = new BlockCapsule(block); - blockCapsule.setMerkleRoot(); - blockCapsule.sign( - ByteArray.fromHexString(Args.getInstance().getLocalWitnesses().getPrivateKey())); - blockCapsule.setMerkleRoot(); - blockCapsule.sign( - ByteArray.fromHexString(Args.getInstance().getLocalWitnesses().getPrivateKey())); - - return blockCapsule; - } - - private static boolean go = false; - - @Before - public void init() { - nodeEntity = new Node( - "enode://e437a4836b77ad9d9ffe73ee782ef2614e6d8370fcf62191a6e488276e23717147073a7ce0b444d485fff5a0c34c4577251a7a990cf80d8542e21b95aa8c5e6c@127.0.0.1:17894"); - - new Thread(new Runnable() { - @Override - public void run() { - logger.info("Full node running."); - Args.setParam( - new String[]{ - "--output-directory", dbPath, - "--storage-db-directory", dbDirectory, - "--storage-index-directory", indexDirectory - }, - Constant.TEST_CONF - ); - Args cfgArgs = Args.getInstance(); - cfgArgs.setNodeListenPort(17894); - cfgArgs.setNodeDiscoveryEnable(false); - cfgArgs.getSeedNode().getIpList().clear(); - cfgArgs.setNeedSyncCheck(false); - cfgArgs.setNodeExternalIp("127.0.0.1"); - - context = new TronApplicationContext(DefaultConfig.class); - - if (cfgArgs.isHelp()) { - logger.info("Here is the help message."); - return; - } - appT = ApplicationFactory.create(context); - rpcApiService = context.getBean(RpcApiService.class); - appT.addService(rpcApiService); - if (cfgArgs.isWitness()) { - appT.addService(new WitnessService(appT, context)); - } -// appT.initServices(cfgArgs); -// appT.startServices(); -// appT.startup(); - node = context.getBean(NodeImpl.class); - peerClient = context.getBean(PeerClientTest.class); - channelManager = context.getBean(ChannelManager.class); - pool = context.getBean(SyncPool.class); - dbManager = context.getBean(Manager.class); - handshakeHandlerTest = context.getBean(HandshakeHandlerTest.class); - handshakeHandlerTest.setNode(nodeEntity); - NodeDelegate nodeDelegate = new NodeDelegateImpl(dbManager); - node.setNodeDelegate(nodeDelegate); - pool.init(node); - prepare(); - rpcApiService.blockUntilShutdown(); - } - }).start(); - int tryTimes = 0; - while (tryTimes < 10 && (node == null || peerClient == null - || channelManager == null || pool == null || !go)) { - try { - logger.info("node:{},peerClient:{},channelManager:{},pool:{},{}", node, peerClient, - channelManager, pool, go); - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - ++tryTimes; - } - } - } - - private void prepare() { - try { - ExecutorService advertiseLoopThread = ReflectUtils.getFieldValue(node, "broadPool"); - advertiseLoopThread.shutdownNow(); - - peerClient.prepare(nodeEntity.getHexId()); - - ReflectUtils.setFieldValue(node, "isAdvertiseActive", false); - ReflectUtils.setFieldValue(node, "isFetchActive", false); - - TronChannelInitializerTest tronChannelInitializer = ReflectUtils - .getFieldValue(peerClient, "tronChannelInitializer"); - tronChannelInitializer.prepare(); - Channel channel = ReflectUtils.getFieldValue(tronChannelInitializer, "channel"); - ReflectUtils.setFieldValue(channel, "handshakeHandler", handshakeHandlerTest); - - new Thread(new Runnable() { - @Override - public void run() { - peerClient.connect(nodeEntity.getHost(), nodeEntity.getPort(), nodeEntity.getHexId()); - } - }).start(); - Thread.sleep(1000); - Map activePeers = ReflectUtils - .getFieldValue(channelManager, "activePeers"); - int tryTimes = 0; - while (MapUtils.isEmpty(activePeers) && ++tryTimes < 10) { - Thread.sleep(1000); - } - go = true; - } catch (Exception e) { - e.printStackTrace(); - } - } - - @AfterClass - public static void destroy() { - Args.clearParam(); - Collection peerConnections = ReflectUtils.invokeMethod(node, "getActivePeer"); - for (PeerConnection peer : peerConnections) { - peer.close(); - } - handshakeHandlerTest.close(); - appT.shutdownServices(); - appT.shutdown(); - context.destroy(); - FileUtil.deleteDir(new File(dbPath)); - } -} diff --git a/src/test/java/org/tron/core/net/node/HandleSyncBlockTest.java b/src/test/java/org/tron/core/net/node/HandleSyncBlockTest.java deleted file mode 100644 index 41bc23f3ec9..00000000000 --- a/src/test/java/org/tron/core/net/node/HandleSyncBlockTest.java +++ /dev/null @@ -1,271 +0,0 @@ -package org.tron.core.net.node; - -import com.google.protobuf.ByteString; -import java.io.File; -import java.util.Collection; -import java.util.Map; -import java.util.Queue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.MapUtils; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.crypto.ECKey; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.overlay.server.Channel; -import org.tron.common.overlay.server.ChannelManager; -import org.tron.common.overlay.server.SyncPool; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; -import org.tron.common.utils.ReflectUtils; -import org.tron.common.utils.Sha256Hash; -import org.tron.core.Constant; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.capsule.utils.BlockUtil; -import org.tron.core.config.DefaultConfig; -import org.tron.core.config.args.Args; -import org.tron.core.db.ByteArrayWrapper; -import org.tron.core.db.Manager; -import org.tron.core.net.message.BlockMessage; -import org.tron.core.net.node.override.HandshakeHandlerTest; -import org.tron.core.net.node.override.PeerClientTest; -import org.tron.core.net.node.override.TronChannelInitializerTest; -import org.tron.core.net.peer.PeerConnection; -import org.tron.core.services.RpcApiService; -import org.tron.core.services.WitnessService; -import org.tron.protos.Protocol; - -@Slf4j -public class HandleSyncBlockTest { - - private static TronApplicationContext context; - private static NodeImpl node; - private RpcApiService rpcApiService; - private static PeerClientTest peerClient; - private ChannelManager channelManager; - private SyncPool pool; - private static Application appT; - private Node nodeEntity; - private static HandshakeHandlerTest handshakeHandlerTest; - private static final String dbPath = "output-nodeImplTest-handleSyncBlock"; - private static final String dbDirectory = "db_HandleSyncBlock_test"; - private static final String indexDirectory = "index_HandleSyncBlock_test"; - - private class Condition { - - private Sha256Hash blockId; - - public Condition(Sha256Hash blockId) { - this.blockId = blockId; - } - - public Sha256Hash getBlockId() { - return blockId; - } - } - - private Sha256Hash testBlockBroad() { - Protocol.Block block = Protocol.Block.getDefaultInstance(); - BlockMessage blockMessage = new BlockMessage(new BlockCapsule(block)); - node.broadcast(blockMessage); - ConcurrentHashMap advObjToSpread = ReflectUtils - .getFieldValue(node, "advObjToSpread"); - Assert.assertEquals(advObjToSpread.get(blockMessage.getMessageId()), - Protocol.Inventory.InventoryType.BLOCK); - return blockMessage.getMessageId(); - } - - private Condition testConsumerAdvObjToSpread() { - Sha256Hash blockId = testBlockBroad(); - - ReflectUtils.invokeMethod(node, "consumerAdvObjToSpread"); - Collection activePeers = ReflectUtils.invokeMethod(node, "getActivePeer"); - - boolean result = true; - for (PeerConnection peerConnection : activePeers) { - if (!peerConnection.getAdvObjWeSpread().containsKey(blockId)) { - result &= false; - } - } - for (PeerConnection peerConnection : activePeers) { - peerConnection.getAdvObjWeSpread().clear(); - } - Assert.assertTrue(result); - return new Condition(blockId); - } - - private BlockMessage buildBlockMessage() throws Exception { - BlockCapsule genesisBlockCapsule = BlockUtil.newGenesisBlockCapsule(); - - ByteString witnessAddress = ByteString.copyFrom( - ECKey.fromPrivate( - ByteArray.fromHexString( - Args.getInstance().getLocalWitnesses().getPrivateKey())) - .getAddress()); - Protocol.BlockHeader.raw raw = Protocol.BlockHeader.raw.newBuilder() - .setTimestamp(System.currentTimeMillis()) - .setParentHash(genesisBlockCapsule.getBlockId().getByteString()) - .setNumber(genesisBlockCapsule.getNum() + 1) - .setWitnessAddress(witnessAddress) - .setWitnessId(1).build(); - Protocol.BlockHeader blockHeader = Protocol.BlockHeader.newBuilder() - .setRawData(raw) - .build(); - - Protocol.Block block = Protocol.Block.newBuilder().setBlockHeader(blockHeader).build(); - - BlockCapsule blockCapsule = new BlockCapsule(block); - blockCapsule.setMerkleRoot(); - blockCapsule.sign(ByteArray.fromHexString(Args.getInstance().getLocalWitnesses().getPrivateKey())); - BlockMessage blockMessage = new BlockMessage(blockCapsule); - return blockMessage; - } - - @Test - public void testHandleSyncBlock() throws Exception { - testConsumerAdvObjToSpread(); - // build block Message - BlockMessage blockMessage = buildBlockMessage(); - // build blockJustReceived - Map blockJustReceived = new ConcurrentHashMap<>(); - blockJustReceived.put(blockMessage, new PeerConnection()); - ReflectUtils.setFieldValue(node, "blockJustReceived", blockJustReceived); - Thread.sleep(1000); - // retrieve the first active peer - Collection activePeers = ReflectUtils.invokeMethod(node, "getActivePeer"); - activePeers.iterator().next().getSyncBlockToFetch().push(blockMessage.getBlockId()); - // clean up freshBlockId - Queue freshBlockId = ReflectUtils - .getFieldValue(node, "freshBlockId"); - freshBlockId.poll(); - // trigger handlesyncBlock method - ReflectUtils.invokeMethod(node, "handleSyncBlock"); - - Assert.assertTrue(freshBlockId.contains(blockMessage.getBlockId())); - } - - private static boolean go = false; - - @Before - public void init() { - nodeEntity = new Node( - "enode://e437a4836b77ad9d9ffe73ee782ef2614e6d8370fcf62191a6e488276e23717147073a7ce0b444d485fff5a0c34c4577251a7a990cf80d8542e21b95aa8c5e6c@127.0.0.1:17893"); - - new Thread(new Runnable() { - @Override - public void run() { - logger.info("Full node running."); - Args.setParam( - new String[]{ - "--output-directory", dbPath, - "--storage-db-directory", dbDirectory, - "--storage-index-directory", indexDirectory - }, - Constant.TEST_CONF - ); - Args cfgArgs = Args.getInstance(); - cfgArgs.setNodeListenPort(17893); - cfgArgs.setNodeDiscoveryEnable(false); - cfgArgs.getSeedNode().getIpList().clear(); - cfgArgs.setNeedSyncCheck(false); - cfgArgs.setNodeExternalIp("127.0.0.1"); - - context = new TronApplicationContext(DefaultConfig.class); - - if (cfgArgs.isHelp()) { - logger.info("Here is the help message."); - return; - } - appT = ApplicationFactory.create(context); - rpcApiService = context.getBean(RpcApiService.class); - appT.addService(rpcApiService); - if (cfgArgs.isWitness()) { - appT.addService(new WitnessService(appT, context)); - } -// appT.initServices(cfgArgs); -// appT.startServices(); -// appT.startup(); - node = context.getBean(NodeImpl.class); - peerClient = context.getBean(PeerClientTest.class); - channelManager = context.getBean(ChannelManager.class); - pool = context.getBean(SyncPool.class); - Manager dbManager = context.getBean(Manager.class); - handshakeHandlerTest = context.getBean(HandshakeHandlerTest.class); - handshakeHandlerTest.setNode(nodeEntity); - NodeDelegate nodeDelegate = new NodeDelegateImpl(dbManager); - node.setNodeDelegate(nodeDelegate); - pool.init(node); - prepare(); - rpcApiService.blockUntilShutdown(); - } - }).start(); - int tryTimes = 0; - while (tryTimes < 10 && (node == null || peerClient == null - || channelManager == null || pool == null || !go)) { - try { - logger.info("node:{},peerClient:{},channelManager:{},pool:{},{}", node, peerClient, - channelManager, pool, go); - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - ++tryTimes; - } - } - } - - private void prepare() { - try { - ExecutorService advertiseLoopThread = ReflectUtils.getFieldValue(node, "broadPool"); - advertiseLoopThread.shutdownNow(); - - peerClient.prepare(nodeEntity.getHexId()); - - ReflectUtils.setFieldValue(node, "isAdvertiseActive", false); - ReflectUtils.setFieldValue(node, "isFetchActive", false); - - TronChannelInitializerTest tronChannelInitializer = ReflectUtils - .getFieldValue(peerClient, "tronChannelInitializer"); - tronChannelInitializer.prepare(); - Channel channel = ReflectUtils.getFieldValue(tronChannelInitializer, "channel"); - ReflectUtils.setFieldValue(channel, "handshakeHandler", handshakeHandlerTest); - - new Thread(new Runnable() { - @Override - public void run() { - peerClient.connect(nodeEntity.getHost(), nodeEntity.getPort(), nodeEntity.getHexId()); - } - }).start(); - Thread.sleep(1000); - Map activePeers = ReflectUtils - .getFieldValue(channelManager, "activePeers"); - int tryTimes = 0; - while (MapUtils.isEmpty(activePeers) && ++tryTimes < 10) { - Thread.sleep(1000); - } - go = true; - } catch (Exception e) { - e.printStackTrace(); - } - } - - @AfterClass - public static void destroy() { - Args.clearParam(); - Collection peerConnections = ReflectUtils.invokeMethod(node, "getActivePeer"); - for (PeerConnection peer : peerConnections) { - peer.close(); - } - handshakeHandlerTest.close(); - context.destroy(); - appT.shutdownServices(); - appT.shutdown(); - FileUtil.deleteDir(new File(dbPath)); - } -} diff --git a/src/test/java/org/tron/core/net/node/HandleTransactionTest.java b/src/test/java/org/tron/core/net/node/HandleTransactionTest.java deleted file mode 100644 index 41960b83fd2..00000000000 --- a/src/test/java/org/tron/core/net/node/HandleTransactionTest.java +++ /dev/null @@ -1,233 +0,0 @@ -package org.tron.core.net.node; - -import com.google.protobuf.ByteString; -import java.io.File; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.MapUtils; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.Test; -import org.testng.collections.Lists; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.overlay.server.Channel; -import org.tron.common.overlay.server.ChannelManager; -import org.tron.common.overlay.server.SyncPool; -import org.tron.common.utils.FileUtil; -import org.tron.common.utils.ReflectUtils; -import org.tron.core.Constant; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.config.DefaultConfig; -import org.tron.core.config.args.Args; -import org.tron.core.db.ByteArrayWrapper; -import org.tron.core.db.Manager; -import org.tron.core.net.message.TransactionMessage; -import org.tron.core.net.message.TransactionsMessage; -import org.tron.core.net.node.override.HandshakeHandlerTest; -import org.tron.core.net.node.override.PeerClientTest; -import org.tron.core.net.node.override.TronChannelInitializerTest; -import org.tron.core.net.peer.PeerConnection; -import org.tron.core.services.RpcApiService; -import org.tron.core.services.WitnessService; -import org.tron.protos.Contract.TransferContract; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Inventory.InventoryType; -import org.tron.protos.Protocol.Transaction.Contract.ContractType; - - -@Slf4j -public class HandleTransactionTest { - - private static TronApplicationContext context; - private static NodeImpl node; - private RpcApiService rpcApiService; - private static PeerClientTest peerClient; - private ChannelManager channelManager; - private SyncPool pool; - private static Application appT; - private static Manager dbManager; - private Node nodeEntity; - private static HandshakeHandlerTest handshakeHandlerTest; - - private static final String dbPath = "output-HandleTransactionTest"; - private static final String dbDirectory = "db_HandleTransaction_test"; - private static final String indexDirectory = "index_HandleTransaction_test"; - - private static Boolean deleteFolder(File index) { - if (!index.isDirectory() || index.listFiles().length <= 0) { - return index.delete(); - } - for (File file : index.listFiles()) { - if (null != file && !deleteFolder(file)) { - return false; - } - } - return index.delete(); - } - - @Test - public void testHandleTransactionMessage() throws Exception{ - - TransferContract tc = - TransferContract.newBuilder() - .setAmount(10) - .setOwnerAddress(ByteString.copyFromUtf8("aaa")) - .setToAddress(ByteString.copyFromUtf8("bbb")) - .build(); - - TransactionCapsule trx = new TransactionCapsule(tc, ContractType.TransferContract); - - Protocol.Transaction transaction = trx.getInstance(); - - TransactionMessage transactionMessage = new TransactionMessage(transaction); - List list = Lists.newArrayList(); - list.add(transaction); - TransactionsMessage transactionsMessage = new TransactionsMessage(list); - - PeerConnection peer = new PeerConnection(); - //没有向peer广播请求过交易信息 - peer.getAdvObjWeRequested().clear(); - peer.setSyncFlag(true); - //nodeImpl.onMessage(peer, transactionMessage); - //Assert.assertEquals(peer.getSyncFlag(), false); - - //向peer广播请求过交易信息 - peer.getAdvObjWeRequested().put(new Item(transactionMessage.getMessageId(), InventoryType.TRX), System.currentTimeMillis()); - peer.setSyncFlag(true); - node.onMessage(peer, transactionsMessage); - //Assert.assertEquals(peer.getAdvObjWeRequested().isEmpty(), true); - //ConcurrentHashMap advObjToSpread = ReflectUtils.getFieldValue(nodeImpl, "advObjToSpread"); - //Assert.assertEquals(advObjToSpread.contains(transactionMessage.getMessageId()), true); - } - - private static boolean go = false; - - @Before - public void init() { - nodeEntity = new Node( - "enode://e437a4836b77ad9d9ffe73ee782ef2614e6d8370fcf62191a6e488276e23717147073a7ce0b444d485fff5a0c34c4577251a7a990cf80d8542e21b95aa8c5e6c@127.0.0.1:17891"); - - new Thread(new Runnable() { - @Override - public void run() { - logger.info("Full node running."); - Args.setParam( - new String[]{ - "--output-directory", dbPath, - "--storage-db-directory", dbDirectory, - "--storage-index-directory", indexDirectory - }, - Constant.TEST_CONF - ); - Args cfgArgs = Args.getInstance(); - cfgArgs.setNodeListenPort(17891); - cfgArgs.setNodeDiscoveryEnable(false); - cfgArgs.getSeedNode().getIpList().clear(); - cfgArgs.setNeedSyncCheck(false); - cfgArgs.setNodeExternalIp("127.0.0.1"); - - context = new TronApplicationContext(DefaultConfig.class); - - if (cfgArgs.isHelp()) { - logger.info("Here is the help message."); - return; - } - appT = ApplicationFactory.create(context); - rpcApiService = context.getBean(RpcApiService.class); - appT.addService(rpcApiService); - if (cfgArgs.isWitness()) { - appT.addService(new WitnessService(appT, context)); - } -// appT.initServices(cfgArgs); -// appT.startServices(); -// appT.startup(); - node = context.getBean(NodeImpl.class); - peerClient = context.getBean(PeerClientTest.class); - channelManager = context.getBean(ChannelManager.class); - pool = context.getBean(SyncPool.class); - dbManager = context.getBean(Manager.class); - handshakeHandlerTest = context.getBean(HandshakeHandlerTest.class); - handshakeHandlerTest.setNode(nodeEntity); - NodeDelegate nodeDelegate = new NodeDelegateImpl(dbManager); - node.setNodeDelegate(nodeDelegate); - pool.init(node); - prepare(); - rpcApiService.blockUntilShutdown(); - } - }).start(); - int tryTimes = 0; - while (tryTimes < 10 && (node == null || peerClient == null - || channelManager == null || pool == null || !go)) { - try { - logger.info("node:{},peerClient:{},channelManager:{},pool:{},{}", node, peerClient, - channelManager, pool, go); - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - ++tryTimes; - } - } - } - - private void prepare() { - try { - ExecutorService advertiseLoopThread = ReflectUtils.getFieldValue(node, "broadPool"); - advertiseLoopThread.shutdownNow(); - - peerClient.prepare(nodeEntity.getHexId()); - - ReflectUtils.setFieldValue(node, "isAdvertiseActive", false); - ReflectUtils.setFieldValue(node, "isFetchActive", false); - - TronChannelInitializerTest tronChannelInitializer = ReflectUtils - .getFieldValue(peerClient, "tronChannelInitializer"); - tronChannelInitializer.prepare(); - Channel channel = ReflectUtils.getFieldValue(tronChannelInitializer, "channel"); - ReflectUtils.setFieldValue(channel, "handshakeHandler", handshakeHandlerTest); - - new Thread(new Runnable() { - @Override - public void run() { - peerClient.connect(nodeEntity.getHost(), nodeEntity.getPort(), nodeEntity.getHexId()); - } - }).start(); - Thread.sleep(1000); - Map activePeers = ReflectUtils - .getFieldValue(channelManager, "activePeers"); - int tryTimes = 0; - while (MapUtils.isEmpty(activePeers) && ++tryTimes < 10) { - Thread.sleep(1000); - } - go = true; - } catch (Exception e) { - e.printStackTrace(); - } - } - - @AfterClass - public static void destroy() { - Args.clearParam(); - Collection peerConnections = ReflectUtils.invokeMethod(node, "getActivePeer"); - for (PeerConnection peer : peerConnections) { - peer.close(); - } - handshakeHandlerTest.close(); - appT.shutdownServices(); - appT.shutdown(); - context.destroy(); - dbManager.getSession().reset(); - try { - Thread.sleep(10000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - FileUtil.deleteDir(new File(dbPath)); - } -} diff --git a/src/test/java/org/tron/core/net/node/NodeImplTest.java b/src/test/java/org/tron/core/net/node/NodeImplTest.java deleted file mode 100644 index 227888f3d68..00000000000 --- a/src/test/java/org/tron/core/net/node/NodeImplTest.java +++ /dev/null @@ -1,204 +0,0 @@ -package org.tron.core.net.node; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import com.google.protobuf.ByteString; -import java.io.File; -import java.util.concurrent.ConcurrentHashMap; -import lombok.extern.slf4j.Slf4j; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.crypto.ECKey; -import org.tron.common.overlay.server.SyncPool; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; -import org.tron.common.utils.Sha256Hash; -import org.tron.core.Constant; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.capsule.BlockCapsule.BlockId; -import org.tron.core.capsule.utils.BlockUtil; -import org.tron.core.config.DefaultConfig; -import org.tron.core.config.Parameter.NetConstants; -import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; -import org.tron.core.net.message.BlockMessage; -import org.tron.core.net.peer.PeerConnection; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.BlockHeader; -import org.tron.protos.Protocol.Inventory.InventoryType; - - -@Slf4j -public class NodeImplTest { - - private static TronApplicationContext context; - - private static Application appT; - private static String dbPath = "output_nodeimpl_test"; - private static NodeImpl nodeImpl; - private static Manager dbManager; - private static NodeDelegateImpl nodeDelegate; - - static { - Args.setParam(new String[]{"-d", dbPath}, Constant.TEST_CONF); - context = new TronApplicationContext(DefaultConfig.class); - Args.getInstance().setSolidityNode(true); - appT = ApplicationFactory.create(context); - } - - @Test - public void testSyncBlockMessage() throws Exception { - PeerConnection peer = new PeerConnection(); - BlockCapsule genesisBlockCapsule = BlockUtil.newGenesisBlockCapsule(); - - ByteString witnessAddress = ByteString.copyFrom( - ECKey.fromPrivate( - ByteArray.fromHexString( - Args.getInstance().getLocalWitnesses().getPrivateKey())) - .getAddress()); - BlockHeader.raw raw = BlockHeader.raw.newBuilder() - .setTimestamp(System.currentTimeMillis()) - .setParentHash(genesisBlockCapsule.getParentHash().getByteString()) - .setNumber(genesisBlockCapsule.getNum() + 1) - .setWitnessAddress(witnessAddress) - .setWitnessId(1).build(); - BlockHeader blockHeader = BlockHeader.newBuilder() - .setRawData(raw) - .build(); - - Block block = Block.newBuilder().setBlockHeader(blockHeader).build(); - - BlockCapsule blockCapsule = new BlockCapsule(block); - blockCapsule.sign( - ByteArray.fromHexString(Args.getInstance().getLocalWitnesses().getPrivateKey())); - blockCapsule.setMerkleRoot(); - BlockMessage blockMessage = new BlockMessage(blockCapsule); - peer.getSyncBlockRequested().put(blockMessage.getBlockId(), System.currentTimeMillis()); - nodeImpl.onMessage(peer, blockMessage); - Assert.assertEquals(peer.getSyncBlockRequested().size(), 0); - } - - @Test - public void testAdvBlockMessage() throws Exception { - PeerConnection peer = new PeerConnection(); - BlockCapsule genesisBlockCapsule = BlockUtil.newGenesisBlockCapsule(); - - ByteString witnessAddress = ByteString.copyFrom( - ECKey.fromPrivate( - ByteArray.fromHexString( - Args.getInstance().getLocalWitnesses().getPrivateKey())) - .getAddress()); - BlockHeader.raw raw = BlockHeader.raw.newBuilder() - .setTimestamp(System.currentTimeMillis()) - .setParentHash(genesisBlockCapsule.getBlockId().getByteString()) - .setNumber(genesisBlockCapsule.getNum() + 1) - .setWitnessAddress(witnessAddress) - .setWitnessId(1).build(); - BlockHeader blockHeader = BlockHeader.newBuilder() - .setRawData(raw) - .build(); - - Block block = Block.newBuilder().setBlockHeader(blockHeader).build(); - - BlockCapsule blockCapsule = new BlockCapsule(block); - blockCapsule.setMerkleRoot(); - blockCapsule.sign( - ByteArray.fromHexString(Args.getInstance().getLocalWitnesses().getPrivateKey())); - BlockMessage blockMessage = new BlockMessage(blockCapsule); - peer.getAdvObjWeRequested() - .put(new Item(blockMessage.getBlockId(), InventoryType.BLOCK), System.currentTimeMillis()); - nodeImpl.onMessage(peer, blockMessage); - Assert.assertEquals(peer.getAdvObjWeRequested().size(), 0); - } - - // @Test - public void testDisconnectInactive() { - // generate test data - ConcurrentHashMap advObjWeRequested1 = new ConcurrentHashMap<>(); - ConcurrentHashMap advObjWeRequested2 = new ConcurrentHashMap<>(); - ConcurrentHashMap advObjWeRequested3 = new ConcurrentHashMap<>(); - ConcurrentHashMap syncBlockRequested1 = new ConcurrentHashMap<>(); - ConcurrentHashMap syncBlockRequested2 = new ConcurrentHashMap<>(); - ConcurrentHashMap syncBlockRequested3 = new ConcurrentHashMap<>(); - - advObjWeRequested1.put(new Item(new Sha256Hash(1, Sha256Hash.ZERO_HASH), InventoryType.TRX), - System.currentTimeMillis() - NetConstants.ADV_TIME_OUT); - syncBlockRequested1.put(new BlockId(), - System.currentTimeMillis()); - advObjWeRequested2.put(new Item(new Sha256Hash(1, Sha256Hash.ZERO_HASH), InventoryType.TRX), - System.currentTimeMillis()); - syncBlockRequested2.put(new BlockId(), - System.currentTimeMillis() - NetConstants.SYNC_TIME_OUT); - advObjWeRequested3.put(new Item(new Sha256Hash(1, Sha256Hash.ZERO_HASH), InventoryType.TRX), - System.currentTimeMillis()); - syncBlockRequested3.put(new BlockId(), - System.currentTimeMillis()); - - PeerConnection peer1 = new PeerConnection(); - PeerConnection peer2 = new PeerConnection(); - PeerConnection peer3 = new PeerConnection(); - - peer1.setAdvObjWeRequested(advObjWeRequested1); - peer1.setSyncBlockRequested(syncBlockRequested1); - peer2.setAdvObjWeRequested(advObjWeRequested2); - peer2.setSyncBlockRequested(syncBlockRequested2); - peer3.setAdvObjWeRequested(advObjWeRequested3); - peer3.setSyncBlockRequested(syncBlockRequested3); - - // fetch failed - SyncPool pool = new SyncPool(); - pool.addActivePeers(peer1); - nodeImpl.setPool(pool); - try { - nodeImpl.disconnectInactive(); - fail("disconnectInactive failed"); - } catch (RuntimeException e) { - assertTrue("disconnect successfully, reason is fetch failed", true); - } - - // sync failed - pool = new SyncPool(); - pool.addActivePeers(peer2); - nodeImpl.setPool(pool); - try { - nodeImpl.disconnectInactive(); - fail("disconnectInactive failed"); - } catch (RuntimeException e) { - assertTrue("disconnect successfully, reason is sync failed", true); - } - - // should not disconnect - pool = new SyncPool(); - pool.addActivePeers(peer3); - nodeImpl.setPool(pool); - try { - nodeImpl.disconnectInactive(); - assertTrue("not disconnect", true); - } catch (RuntimeException e) { - fail("should not disconnect!"); - } - } - - @BeforeClass - public static void init() { - nodeImpl = context.getBean(NodeImpl.class); - dbManager = context.getBean(Manager.class); - nodeDelegate = new NodeDelegateImpl(dbManager); - nodeImpl.setNodeDelegate(nodeDelegate); - } - - @AfterClass - public static void destroy() { - Args.clearParam(); - context.destroy(); - appT.shutdownServices(); - appT.shutdown(); - FileUtil.deleteDir(new File(dbPath)); - } -} diff --git a/src/test/java/org/tron/core/net/node/StartFetchSyncBlockTest.java b/src/test/java/org/tron/core/net/node/StartFetchSyncBlockTest.java deleted file mode 100644 index 672b0fde837..00000000000 --- a/src/test/java/org/tron/core/net/node/StartFetchSyncBlockTest.java +++ /dev/null @@ -1,257 +0,0 @@ -package org.tron.core.net.node; - -import com.google.common.cache.Cache; -import java.io.File; -import java.util.Collection; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.MapUtils; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.overlay.server.Channel; -import org.tron.common.overlay.server.ChannelManager; -import org.tron.common.overlay.server.SyncPool; -import org.tron.common.utils.FileUtil; -import org.tron.common.utils.ReflectUtils; -import org.tron.common.utils.Sha256Hash; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.config.DefaultConfig; -import org.tron.core.config.args.Args; -import org.tron.core.db.ByteArrayWrapper; -import org.tron.core.db.Manager; -import org.tron.core.net.message.BlockMessage; -import org.tron.core.net.node.override.HandshakeHandlerTest; -import org.tron.core.net.node.override.PeerClientTest; -import org.tron.core.net.node.override.TronChannelInitializerTest; -import org.tron.core.net.peer.PeerConnection; -import org.tron.core.services.RpcApiService; -import org.tron.core.services.WitnessService; -import org.tron.protos.Protocol; - -@Slf4j -public class StartFetchSyncBlockTest { - - private static TronApplicationContext context; - private NodeImpl node; - private RpcApiService rpcApiService; - private static PeerClientTest peerClient; - private ChannelManager channelManager; - private SyncPool pool; - private static Application appT; - private Node nodeEntity; - private static HandshakeHandlerTest handshakeHandlerTest; - private static final String dbPath = "output-nodeImplTest-startFetchSyncBlockTest"; - private static final String dbDirectory = "db_StartFetchSyncBlock_test"; - private static final String indexDirectory = "index_StartFetchSyncBlock_test"; - - private class Condition { - - private Sha256Hash blockId; - - public Condition(Sha256Hash blockId) { - this.blockId = blockId; - } - - public Sha256Hash getBlockId() { - return blockId; - } - - } - - private Sha256Hash testBlockBroad() { - Protocol.Block block = Protocol.Block.getDefaultInstance(); - BlockMessage blockMessage = new BlockMessage(new BlockCapsule(block)); - node.broadcast(blockMessage); - ConcurrentHashMap advObjToSpread = ReflectUtils - .getFieldValue(node, "advObjToSpread"); - Assert.assertEquals(advObjToSpread.get(blockMessage.getMessageId()), - Protocol.Inventory.InventoryType.BLOCK); - return blockMessage.getMessageId(); - } - - private BlockMessage removeTheBlock(Sha256Hash blockId) { - Cache blockCache = ReflectUtils.getFieldValue(node, "BlockCache"); - BlockMessage blockMessage = blockCache.getIfPresent(blockId); - if (blockMessage != null) { - blockCache.invalidate(blockId); - } - return blockMessage; - } - - private void addTheBlock(BlockMessage blockMessag) { - Cache blockCache = ReflectUtils.getFieldValue(node, "BlockCache"); - blockCache.put(blockMessag.getMessageId(), blockMessag); - } - - private Condition testConsumerAdvObjToSpread() { - Sha256Hash blockId = testBlockBroad(); - //remove the block - BlockMessage blockMessage = removeTheBlock(blockId); - ReflectUtils.invokeMethod(node, "consumerAdvObjToSpread"); - Collection activePeers = ReflectUtils.invokeMethod(node, "getActivePeer"); - - boolean result = true; - for (PeerConnection peerConnection : activePeers) { - if (!peerConnection.getAdvObjWeSpread().containsKey(blockId)) { - result &= false; - } - } - for (PeerConnection peerConnection : activePeers) { - peerConnection.getAdvObjWeSpread().clear(); - } - Assert.assertTrue(result); - return new Condition(blockId); - } - - @Test - public void testStartFetchSyncBlock() throws InterruptedException { - testConsumerAdvObjToSpread(); - Collection activePeers = ReflectUtils.invokeMethod(node, "getActivePeer"); - Thread.sleep(5000); - if (activePeers.size() < 1) { - return; - } - ReflectUtils.setFieldValue(activePeers.iterator().next(), "needSyncFromPeer", true); - // construct a block - Protocol.Block block = Protocol.Block.getDefaultInstance(); - BlockMessage blockMessage = new BlockMessage(new BlockCapsule(block)); - // push the block to syncBlockToFetch - activePeers.iterator().next().getSyncBlockToFetch().push(blockMessage.getBlockId()); - // invoke testing method - addTheBlock(blockMessage); - ReflectUtils.invokeMethod(node, "startFetchSyncBlock"); - Cache syncBlockIdWeRequested = ReflectUtils - .getFieldValue(node, "syncBlockIdWeRequested"); - Assert.assertTrue(syncBlockIdWeRequested.size() == 1); - } - - - private static boolean go = false; - - @Before - public void init() { - nodeEntity = new Node( - "enode://e437a4836b77ad9d9ffe73ee782ef2614e6d8370fcf62191a6e488276e23717147073a7ce0b444d485fff5a0c34c4577251a7a990cf80d8542e21b95aa8c5e6c@127.0.0.1:17890"); - - Thread thread = new Thread(new Runnable() { - @Override - public void run() { - logger.info("Full node running."); - Args.setParam( - new String[]{ - "--output-directory", dbPath, - "--storage-db-directory", dbDirectory, - "--storage-index-directory", indexDirectory - }, - "config.conf" - ); - Args cfgArgs = Args.getInstance(); - cfgArgs.setNodeListenPort(17890); - cfgArgs.setNodeDiscoveryEnable(false); - cfgArgs.getSeedNode().getIpList().clear(); - cfgArgs.setNeedSyncCheck(false); - cfgArgs.setNodeExternalIp("127.0.0.1"); - - context = new TronApplicationContext(DefaultConfig.class); - - if (cfgArgs.isHelp()) { - logger.info("Here is the help message."); - return; - } - appT = ApplicationFactory.create(context); - rpcApiService = context.getBean(RpcApiService.class); - appT.addService(rpcApiService); - if (cfgArgs.isWitness()) { - appT.addService(new WitnessService(appT, context)); - } -// appT.initServices(cfgArgs); -// appT.startServices(); -// appT.startup(); - node = context.getBean(NodeImpl.class); - peerClient = context.getBean(PeerClientTest.class); - channelManager = context.getBean(ChannelManager.class); - pool = context.getBean(SyncPool.class); - Manager dbManager = context.getBean(Manager.class); - handshakeHandlerTest = context.getBean(HandshakeHandlerTest.class); - handshakeHandlerTest.setNode(nodeEntity); - NodeDelegate nodeDelegate = new NodeDelegateImpl(dbManager); - node.setNodeDelegate(nodeDelegate); - pool.init(node); - prepare(); - rpcApiService.blockUntilShutdown(); - } - }); - thread.start(); - try { - thread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - int tryTimes = 0; - while (tryTimes < 10 && (node == null || peerClient == null - || channelManager == null || pool == null || !go)) { - try { - logger.info("node:{},peerClient:{},channelManager:{},pool:{},{}", node, peerClient, - channelManager, pool, go); - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - ++tryTimes; - } - } - } - - private void prepare() { - try { - ExecutorService advertiseLoopThread = ReflectUtils.getFieldValue(node, "broadPool"); - advertiseLoopThread.shutdownNow(); - - peerClient.prepare(nodeEntity.getHexId()); - - ReflectUtils.setFieldValue(node, "isAdvertiseActive", false); - ReflectUtils.setFieldValue(node, "isFetchActive", false); - - TronChannelInitializerTest tronChannelInitializer = ReflectUtils - .getFieldValue(peerClient, "tronChannelInitializer"); - tronChannelInitializer.prepare(); - Channel channel = ReflectUtils.getFieldValue(tronChannelInitializer, "channel"); - ReflectUtils.setFieldValue(channel, "handshakeHandler", handshakeHandlerTest); - - new Thread(new Runnable() { - @Override - public void run() { - peerClient.connect(nodeEntity.getHost(), nodeEntity.getPort(), nodeEntity.getHexId()); - } - }).start(); - Thread.sleep(1000); - Map activePeers = ReflectUtils - .getFieldValue(channelManager, "activePeers"); - int tryTimes = 0; - while (MapUtils.isEmpty(activePeers) && ++tryTimes < 10) { - Thread.sleep(1000); - } - go = true; - } catch (Exception e) { - e.printStackTrace(); - } - } - - @AfterClass - public static void destroy() { - Args.clearParam(); - handshakeHandlerTest.close(); - context.destroy(); - appT.shutdownServices(); - appT.shutdown(); - FileUtil.deleteDir(new File(dbPath)); - } -} diff --git a/src/test/java/org/tron/core/net/node/override/HandshakeHandlerTest.java b/src/test/java/org/tron/core/net/node/override/HandshakeHandlerTest.java deleted file mode 100644 index c7c94350817..00000000000 --- a/src/test/java/org/tron/core/net/node/override/HandshakeHandlerTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.tron.core.net.node.override; - -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; -import org.tron.common.overlay.discover.node.Node; -import org.tron.common.overlay.message.HelloMessage; -import org.tron.common.overlay.server.HandshakeHandler; - -@Slf4j(topic = "test") -@Component -@Scope("prototype") -public class HandshakeHandlerTest extends HandshakeHandler { - - private Node node; - - public HandshakeHandlerTest() { - } - - public HandshakeHandlerTest setNode(Node node) { - this.node = node; - return this; - } - - @Override - protected void sendHelloMsg(ChannelHandlerContext ctx, long time) { - HelloMessage message = new HelloMessage(node, time, - manager.getGenesisBlockId(), manager.getSolidBlockId(), manager.getHeadBlockId()); - ctx.writeAndFlush(message.getSendData()); - channel.getNodeStatistics().messageStatistics.addTcpOutMessage(message); - logger.info("Handshake Send to {}, {}", ctx.channel().remoteAddress(), message); - } - - public void close() { - manager.closeAllStore(); - } -} diff --git a/src/test/java/org/tron/core/net/node/override/PeerClientTest.java b/src/test/java/org/tron/core/net/node/override/PeerClientTest.java deleted file mode 100644 index dafc3c2d9b7..00000000000 --- a/src/test/java/org/tron/core/net/node/override/PeerClientTest.java +++ /dev/null @@ -1,87 +0,0 @@ -package org.tron.core.net.node.override; - -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.DefaultMessageSizeEstimator; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Lazy; -import org.springframework.stereotype.Component; -import org.tron.core.config.args.Args; -import org.tron.core.net.node.NodeImpl; - -@Component -public class PeerClientTest { - - private static final Logger logger = LoggerFactory.getLogger("PeerClient"); - - @Autowired - private ApplicationContext ctx; - - @Autowired - @Lazy - private NodeImpl node; - - private EventLoopGroup workerGroup; - - private TronChannelInitializerTest tronChannelInitializer; - - public PeerClientTest() { - workerGroup = new NioEventLoopGroup(0, new ThreadFactory() { - AtomicInteger cnt = new AtomicInteger(0); - - @Override - public Thread newThread(Runnable r) { - return new Thread(r, "TronJClientWorker-test-" + cnt.getAndIncrement()); - } - }); - } - - public void prepare(String remoteId) { - tronChannelInitializer = ctx.getBean(TronChannelInitializerTest.class, remoteId); - tronChannelInitializer.setNodeImpl(node); - } - - public void connect(String host, int port, String remoteId) { - try { - ChannelFuture f = connectAsync(host, port, remoteId, false); - f.sync().channel().closeFuture().sync(); - } catch (Exception e) { - logger - .info("PeerClient: Can't connect to " + host + ":" + port + " (" + e.getMessage() + ")"); - } - } - - public ChannelFuture connectAsync(String host, int port, String remoteId, boolean discoveryMode) { - - logger.info("connect peer {} {} {}", host, port, remoteId); - - Bootstrap b = new Bootstrap(); - b.group(workerGroup); - b.channel(NioSocketChannel.class); - - b.option(ChannelOption.SO_KEEPALIVE, true); - b.option(ChannelOption.MESSAGE_SIZE_ESTIMATOR, DefaultMessageSizeEstimator.DEFAULT); - b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, Args.getInstance().getNodeConnectionTimeout()); - b.remoteAddress(host, port); - - b.handler(tronChannelInitializer); - - // Start the client. - return b.connect(); - } - - public void close() { - tronChannelInitializer.close(); - workerGroup.shutdownGracefully(); - workerGroup.terminationFuture().syncUninterruptibly(); - } -} diff --git a/src/test/java/org/tron/core/net/node/override/TronChannelInitializerTest.java b/src/test/java/org/tron/core/net/node/override/TronChannelInitializerTest.java deleted file mode 100644 index 32630b6600b..00000000000 --- a/src/test/java/org/tron/core/net/node/override/TronChannelInitializerTest.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.tron.core.net.node.override; - -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelOption; -import io.netty.channel.FixedRecvByteBufAllocator; -import io.netty.channel.socket.nio.NioSocketChannel; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; -import org.tron.common.overlay.server.Channel; -import org.tron.common.overlay.server.ChannelManager; -import org.tron.core.net.node.NodeImpl; -import org.tron.core.net.peer.PeerConnection; - -@Component -@Scope("prototype") -public class TronChannelInitializerTest extends ChannelInitializer { - - private static final Logger logger = LoggerFactory.getLogger("TronChannelInitializer"); - - @Autowired - private ApplicationContext ctx; - - @Autowired - ChannelManager channelManager; - - private NodeImpl p2pNode; - - private String remoteId; - - private boolean peerDiscoveryMode = false; - - private Channel channel; - - public TronChannelInitializerTest(String remoteId) { - this.remoteId = remoteId; - } - - public void prepare() { - channel = ctx.getBean(PeerConnection.class); - } - - @Override - public void initChannel(NioSocketChannel ch) throws Exception { - try { - channel.init(ch.pipeline(), remoteId, peerDiscoveryMode, channelManager, p2pNode); - - // limit the size of receiving buffer to 1024 - ch.config().setRecvByteBufAllocator(new FixedRecvByteBufAllocator(256 * 1024)); - ch.config().setOption(ChannelOption.SO_RCVBUF, 256 * 1024); - ch.config().setOption(ChannelOption.SO_BACKLOG, 1024); - - // be aware of channel closing - ch.closeFuture().addListener((ChannelFutureListener) future -> { - logger.info("Close channel:" + channel); - if (!peerDiscoveryMode) { - channelManager.notifyDisconnect(channel); - } - }); - - } catch (Exception e) { - logger.error("Unexpected error: ", e); - } - } - - private boolean isInbound() { - return remoteId == null || remoteId.isEmpty(); - } - - public void setPeerDiscoveryMode(boolean peerDiscoveryMode) { - this.peerDiscoveryMode = peerDiscoveryMode; - } - - public void setNodeImpl(NodeImpl p2pNode) { - this.p2pNode = p2pNode; - } - - public void close() { - channelManager.close(); - channel.close(); - } -} diff --git a/src/test/java/org/tron/core/net/services/AdvServiceTest.java b/src/test/java/org/tron/core/net/services/AdvServiceTest.java new file mode 100644 index 00000000000..650f1701f96 --- /dev/null +++ b/src/test/java/org/tron/core/net/services/AdvServiceTest.java @@ -0,0 +1,34 @@ +package org.tron.core.net.services; + +import org.junit.Assert; +import org.junit.Test; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.net.message.BlockMessage; +import org.tron.core.net.peer.Item; +import org.tron.core.net.service.AdvService; +import org.tron.protos.Protocol.Inventory.InventoryType; + +public class AdvServiceTest { + AdvService service = new AdvService(); + + @Test + public void testAddInv () { + boolean flag; + Item item = new Item(Sha256Hash.ZERO_HASH, InventoryType.BLOCK); + flag = service.addInv(item); + Assert.assertTrue(flag); + flag = service.addInv(item); + Assert.assertTrue(!flag); + } + + @Test + public void testBroadcast () { + BlockCapsule blockCapsule = new BlockCapsule(1, Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), Sha256Hash.ZERO_HASH.getByteString()); + BlockMessage msg = new BlockMessage(blockCapsule); + service.broadcast(msg); + Item item = new Item(blockCapsule.getBlockId(), InventoryType.BLOCK); + Assert.assertTrue(service.getMessage(item) != null); + } +} diff --git a/src/test/java/org/tron/core/services/NodeInfoServiceTest.java b/src/test/java/org/tron/core/services/NodeInfoServiceTest.java index 0efab5b0279..265f256265d 100644 --- a/src/test/java/org/tron/core/services/NodeInfoServiceTest.java +++ b/src/test/java/org/tron/core/services/NodeInfoServiceTest.java @@ -5,36 +5,28 @@ import io.grpc.ManagedChannelBuilder; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; -import org.junit.Test; import org.tron.api.GrpcAPI.EmptyMessage; import org.tron.api.WalletGrpc; import org.tron.api.WalletGrpc.WalletBlockingStub; +import org.tron.common.application.TronApplicationContext; import org.tron.common.entity.NodeInfo; import org.tron.common.utils.Sha256Hash; import org.tron.core.capsule.BlockCapsule; -import org.tron.core.net.node.BaseNetTest; import org.tron.program.Version; import stest.tron.wallet.common.client.Configuration; @Slf4j -public class NodeInfoServiceTest extends BaseNetTest { - - private static final String dbPath = "output-nodeImplTest-nodeinfo"; - private static final String dbDirectory = "db_nodeinfo_test"; - private static final String indexDirectory = "index_nodeinfo_test"; - private final static int port = 15899; +public class NodeInfoServiceTest { private NodeInfoService nodeInfoService; private WitnessProductBlockService witnessProductBlockService; - public NodeInfoServiceTest() { - super(dbPath, dbDirectory, indexDirectory, port); + public NodeInfoServiceTest(TronApplicationContext context) { + nodeInfoService = context.getBean("nodeInfoService", NodeInfoService.class); + witnessProductBlockService = context.getBean(WitnessProductBlockService.class); } - @Test public void test() { - nodeInfoService = context.getBean("nodeInfoService", NodeInfoService.class); - witnessProductBlockService = context.getBean(WitnessProductBlockService.class); BlockCapsule blockCapsule1 = new BlockCapsule(1, Sha256Hash.ZERO_HASH, 100, ByteString.EMPTY); BlockCapsule blockCapsule2 = new BlockCapsule(1, Sha256Hash.ZERO_HASH, @@ -57,8 +49,4 @@ public void testGrpc() { logger.info("getNodeInfo: {}",walletStub.getNodeInfo(EmptyMessage.getDefaultInstance())); } - public static void main(String[] args) { - NodeInfoServiceTest test = new NodeInfoServiceTest(); - test.testGrpc(); - } } diff --git a/src/test/java/org/tron/core/services/RpcApiServiceTest.java b/src/test/java/org/tron/core/services/RpcApiServiceTest.java deleted file mode 100644 index 0b95c342bf0..00000000000 --- a/src/test/java/org/tron/core/services/RpcApiServiceTest.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.tron.core.services; - -public class RpcApiServiceTest { - -}