use of org.tron.core.net.message.BlockMessage in project java-tron by tronprotocol.
the class NodeImpl method broadcast.
/**
* broadcast msg.
*
* @param msg msg to bradcast
*/
public void broadcast(Message msg) {
InventoryType type;
if (msg instanceof BlockMessage) {
logger.info("Ready to broadcast a block, Its hash is " + msg.getMessageId());
freshBlockId.offer(((BlockMessage) msg).getBlockId());
blockToAdvertise.add(((BlockMessage) msg).getBlockId());
type = InventoryType.BLOCK;
} else if (msg instanceof TransactionMessage) {
trxToAdvertise.add(msg.getMessageId());
type = InventoryType.TRX;
} else {
return;
}
// TODO: here need to cache fresh message to let peer fetch these data not from DB
advObjToSpread.put(msg.getMessageId(), type);
}
use of org.tron.core.net.message.BlockMessage in project java-tron by tronprotocol.
the class NodeImpl method processAdvBlock.
private void processAdvBlock(PeerConnection peer, BlockCapsule block) {
// TODO: lack the complete flow.
if (!freshBlockId.contains(block.getBlockId())) {
try {
LinkedList<Sha256Hash> trxIds = del.handleBlock(block, false);
freshBlockId.offer(block.getBlockId());
trxIds.forEach(trxId -> advObjToFetch.remove(trxId));
// TODO:save message cache again.
getActivePeer().stream().filter(p -> p.getAdvObjSpreadToUs().containsKey(block.getBlockId())).forEach(p -> {
p.setHeadBlockWeBothHave(block.getBlockId());
p.setHeadBlockTimeWeBothHave(block.getTimeStamp());
});
getActivePeer().forEach(p -> p.cleanInvGarbage());
// rebroadcast
broadcast(new BlockMessage(block));
} catch (BadBlockException e) {
badAdvObj.put(block.getBlockId(), System.currentTimeMillis());
} catch (UnLinkedBlockException e) {
// reSync
startSyncWithPeer(peer);
}
}
}
use of org.tron.core.net.message.BlockMessage in project java-tron by tronprotocol.
the class NodeImpl method onHandleFetchDataMessage.
private void onHandleFetchDataMessage(PeerConnection peer, FetchInvDataMessage fetchInvDataMsg) {
logger.info("on handle fetch block message");
MessageTypes type = fetchInvDataMsg.getInvMessageType();
// TODO:maybe can use message cache here
final BlockCapsule[] blocks = { del.getGenesisBlock() };
// get data and send it one by one
fetchInvDataMsg.getHashList().forEach(hash -> {
if (del.contain(hash, type)) {
Message msg = del.getData(hash, type);
if (type.equals(MessageTypes.BLOCK)) {
blocks[0] = ((BlockMessage) msg).getBlockCapsule();
}
peer.sendMessage(msg);
} else {
peer.sendMessage(new ItemNotFound());
}
});
if (blocks[0] != null) {
peer.setHeadBlockWeBothHave(blocks[0].getBlockId());
peer.setHeadBlockTimeWeBothHave(blocks[0].getTimeStamp());
}
}
use of org.tron.core.net.message.BlockMessage in project java-tron by tronprotocol.
the class NodeImpl method onHandleChainInventoryMessage.
private void onHandleChainInventoryMessage(PeerConnection peer, ChainInventoryMessage msg) {
// logger.info("on handle block chain inventory message");
try {
if (peer.getSyncChainRequested() != null) {
// List<BlockId> blockIds = msg.getBlockIds();
Deque<BlockId> blockIdWeGet = new LinkedList<>(msg.getBlockIds());
// 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 {
boolean isFound = false;
for (BlockId id : blockIdWeGet) {
if (id.equals(blockIdWeGet.peek())) {
isFound = true;
}
}
if (!isFound) {
throw new TraitorPeerException("We get a unlinked block chain from " + peer);
}
}
}
// check finish
// here this peer's answer is legal
peer.setSyncChainRequested(null);
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);
}
// TODO: if sync finish call del.syncToCli();
return;
}
if (!blockIdWeGet.isEmpty() && peer.getSyncBlockToFetch().isEmpty()) {
boolean isFound = false;
for (PeerConnection peerToCheck : getActivePeer()) {
if (!peerToCheck.equals(peer) && !peerToCheck.getSyncBlockToFetch().isEmpty() && peerToCheck.getSyncBlockToFetch().peekFirst().equals(blockIdWeGet.peekFirst())) {
isFound = true;
break;
}
}
if (!isFound) {
while (!blockIdWeGet.isEmpty() && del.containBlock(blockIdWeGet.peek())) {
peer.setHeadBlockWeBothHave(blockIdWeGet.peek());
peer.setHeadBlockTimeWeBothHave(del.getBlockTime(blockIdWeGet.peek()));
blockIdWeGet.poll();
}
}
} else if (!blockIdWeGet.isEmpty()) {
while (!peer.getSyncBlockToFetch().isEmpty()) {
if (!peer.getSyncBlockToFetch().peekLast().equals(blockIdWeGet.peekFirst())) {
blockIdWeGet.pop();
} else {
break;
}
}
if (peer.getSyncBlockToFetch().isEmpty()) {
updateBlockWeBothHave(peer, ((BlockMessage) del.getData(blockIdWeGet.peek(), MessageTypes.BLOCK)).getBlockCapsule());
}
// poll the block we both have.
blockIdWeGet.pop();
}
// sew it
peer.getSyncBlockToFetch().addAll(blockIdWeGet);
peer.setUnfetchSyncNum(msg.getRemainNum());
long newUnSyncNum = getUnSyncNum();
if (unSyncNum != newUnSyncNum) {
unSyncNum = newUnSyncNum;
del.syncToCli(unSyncNum);
}
if (msg.getRemainNum() == 0) {
if (!peer.getSyncBlockToFetch().isEmpty()) {
startFetchSyncBlock();
} else {
// let peer know we are sync.
syncNextBatchChainIds(peer);
}
} else {
if (peer.getSyncBlockToFetch().size() > NodeConstant.SYNC_FETCH_BATCH_NUM) {
// one batch by one batch.
startFetchSyncBlock();
} else {
syncNextBatchChainIds(peer);
}
}
// TODO: check head block time is legal here
// TODO: refresh sync status to cli. call del.syncToCli() here
} else {
throw new TraitorPeerException("We don't send sync request to " + peer);
}
} catch (TraitorPeerException e) {
banTraitorPeer(peer);
}
}
Aggregations