use of org.tron.core.capsule.BlockCapsule.BlockId in project java-tron by tronprotocol.
the class NodeImpl method onHandleBlockMessage.
private void onHandleBlockMessage(PeerConnection peer, BlockMessage blkMsg) {
// logger.info("on handle block message");
// peer.setLastBlockPeerKnow((BlockId) blkMsg.getMessageId());
HashMap<Sha256Hash, Long> advObjWeRequested = peer.getAdvObjWeRequested();
HashMap<BlockId, Long> syncBlockRequested = peer.getSyncBlockRequested();
BlockId blockId = blkMsg.getBlockId();
if (advObjWeRequested.containsKey(blockId)) {
// broadcast mode
advObjWeRequested.remove(blockId);
processAdvBlock(peer, blkMsg.getBlockCapsule());
startFetchItem();
} else if (syncBlockRequested.containsKey(blockId)) {
// sync mode
syncBlockRequested.remove(blockId);
// peer.getSyncBlockToFetch().remove(blockId);
syncBlockIdWeRequested.remove(blockId);
// TODO: maybe use consume pipe here better
blockWaitToProcBak.add(blkMsg);
// processSyncBlock(blkMsg.getBlockCapsule());
if (!peer.isBusy()) {
if (peer.getUnfetchSyncNum() > 0 && peer.getSyncBlockToFetch().size() < NodeConstant.SYNC_FETCH_BATCH_NUM) {
syncNextBatchChainIds(peer);
} else {
// TODO: here should be a loop do this thing
// startFetchSyncBlock();
}
}
}
}
use of org.tron.core.capsule.BlockCapsule.BlockId in project java-tron by tronprotocol.
the class NodeImpl method onHandleSyncBlockChainMessage.
private void onHandleSyncBlockChainMessage(PeerConnection peer, SyncBlockChainMessage syncMsg) {
// logger.info("on handle sync block chain message");
peer.setTronState(TronState.SYNCING);
LinkedList<BlockId> blockIds;
List<BlockId> summaryChainIds = syncMsg.getBlockIds();
long remainNum = 0;
try {
blockIds = del.getLostBlockIds(summaryChainIds);
} catch (UnReachBlockException e) {
// TODO: disconnect this peer casue this peer can not switch
logger.debug(e.getMessage(), e);
return;
}
if (blockIds.isEmpty()) {
peer.setNeedSyncFromUs(false);
} else if (blockIds.size() == 1 && !summaryChainIds.isEmpty() && summaryChainIds.contains(blockIds.peekFirst())) {
peer.setNeedSyncFromUs(false);
} else {
peer.setNeedSyncFromUs(true);
remainNum = del.getHeadBlockId().getNum() - blockIds.peekLast().getNum();
}
if (!peer.isNeedSyncFromPeer() && !summaryChainIds.isEmpty() && !del.contain(Iterables.getLast(summaryChainIds), MessageTypes.BLOCK)) {
startSyncWithPeer(peer);
}
peer.sendMessage(new ChainInventoryMessage(blockIds, remainNum));
}
use of org.tron.core.capsule.BlockCapsule.BlockId 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);
}
}
use of org.tron.core.capsule.BlockCapsule.BlockId in project java-tron by tronprotocol.
the class NodeImpl method startFetchSyncBlock.
private synchronized void startFetchSyncBlock() {
// TODO: check how many block is processing and decide if fetch more
HashMap<PeerConnection, List<BlockId>> send = new HashMap<>();
HashSet<BlockId> request = new HashSet<>();
getActivePeer().stream().filter(peer -> peer.isNeedSyncFromPeer() && !peer.isBusy()).forEach(peer -> {
if (!send.containsKey(peer)) {
// TODO: Attention multi thread here
send.put(peer, new LinkedList<>());
}
for (BlockId blockId : peer.getSyncBlockToFetch()) {
if (// TODO: clean processing block
!request.contains(blockId) && !syncBlockIdWeRequested.containsKey(blockId)) {
send.get(peer).add(blockId);
request.add(blockId);
// TODO: check max block num to fetch from one peer.
// if (send.get(peer).size() > 200) { //Max Blocks peer get one time
// break;
// }
}
}
});
send.forEach((peer, blockIds) -> {
// TODO: use collector
blockIds.forEach(blockId -> {
syncBlockIdWeRequested.put(blockId, System.currentTimeMillis());
peer.getSyncBlockRequested().put(blockId, System.currentTimeMillis());
});
List<Sha256Hash> ids = new LinkedList<>();
ids.addAll(blockIds);
peer.sendMessage(new FetchInvDataMessage(ids, InventoryType.BLOCK));
});
send.clear();
}
use of org.tron.core.capsule.BlockCapsule.BlockId in project java-tron by tronprotocol.
the class NodeImpl method syncNextBatchChainIds.
private void syncNextBatchChainIds(PeerConnection peer) {
try {
Deque<BlockId> chainSummary = del.getBlockChainSummary(peer.getHeadBlockWeBothHave(), ((LinkedList<BlockId>) peer.getSyncBlockToFetch()));
peer.setSyncChainRequested(new Pair<>((LinkedList<BlockId>) chainSummary, System.currentTimeMillis()));
peer.sendMessage(new SyncBlockChainMessage((LinkedList<BlockId>) chainSummary));
} catch (Exception e) {
// TODO: use tron excpetion here
logger.debug(e.getMessage(), e);
// TODO: unlink?
disconnectPeer(peer, ReasonCode.BAD_PROTOCOL);
}
}
Aggregations