tip: 388
title: Optimize light node synchronization logic
author:wb_bupt@163.com
discussions to: https://github.com/tronprotocol/TIPs/issues/388
status: Final
type: Standards Track
category: Core
created: 2022-03-14
This TIP mainly describes how to optimize light node synchronization logic.
This phenomenon can be found online. After the connection with a light node is established and the handshake is completed, the node enters the synchronous mode. However, when obtaining a block from the light node, the light node finds that the database cannot query the block, and then disconnects the connection.
When establishing a connection, the node may repeatedly connect to these light nodes and be repeatedly disconnected by the other party, which seriously affects the connection efficiency.
This article details how to optimize light node synchronization logic.
Make the node quickly find a node that can establish an effective connection, avoid repeatedly connecting invalid nodes, and improve the efficiency of connection establishment.
The light node only retains some blocks. If the lowest block of the light node is higher than the head block, the block cannot be synchronized, resulting in the connection interruption.
After the tcp connection is established, the handshake operation is first performed, and the interaction is completed by a pair of hello-message, including the blockchain information of the node. The data structure is as follows, type
and lowestBlockNum
are new fields.
message HelloMessage {
message BlockId {
bytes hash = 1;
int64 number = 2;
}
Endpoint from = 1;
int32 version = 2;
int64 timestamp = 3;
BlockId genesisBlockId = 4;
BlockId solidBlockId = 5;
BlockId headBlockId = 6;
bytes address = 7;
bytes signature = 8;
int32 type = 9;
int32 lowestBlockNum = 10;
}
There are currently no light node related information fields, which can be carried in the hello-message, mainly including the node type and the lowest block information, So need to add these two fields in hello-message.
The hello-message of each node needs to be saved. The cache definition is as follows, the key is the node ip.
private Cache<String, HelloMessage> helloMessageCache = CacheBuilder.newBuilder()
.maximumSize(2000).expireAfterWrite(24, TimeUnit.HOURS).recordStats().build();
During the handshake, if the lowest block of the neighbor node is higher than the head block, it should directly disconnect and the hello-message information of the node should be retained to obtain the node information. The logic implementation is as follows.
BlockCapsule.BlockId headBlockId = chainBaseManager.getHeadBlockId();
int nodeType = msg.getHelloMessage().getNodeType();
long lowestBlockNum = msg.getHelloMessage().getLowestBlockNum();
if (nodeType == NodeManager.NODE_TYPE_LIGHT_NODE && lowestBlockNum > headBlockId.getNum()) {
channel.disconnect(ReasonCode.LIGHT_NODE_SYNC_FAIL);
return;
}
When selecting a node to establish a p2p connection, first check whether the neighbor node is a light node. If it is a light node, check whether the lowest block is higher than the head block. If not, you can choose to establish a connection with it. The select logic implementation is as follows.
public boolean test(NodeHandler handler) {
long headNum = chainBaseManager.getHeadBlockNum();
InetAddress inetAddress = handler.getInetSocketAddress().getAddress();
HelloMessage message = channelManager.getHelloMessageCache().getIfPresent(inetAddress.getHostAddress());
return !(message != null && message.getNodeType() == 1
&& headNum < message.getLowestBlockNum());
}