예제 #1
0
    def handleTopBlockSyncReq(self, topN: int, peer: Peer):
        #with self.chain_lock:
        logger.info(
            f"[p2p] to handle TopBlockSyncReq with length {topN} from peer {peer}"
        )
        with self.chain_lock:
            blocks = copy.deepcopy(self.active_chain.chain[-topN:])

        message = Message(Actions.BlocksSyncGet, blocks, Params.PORT_CURRENT)
        ret = self.request.sendall(Utils.encode_socket_data(message))
        logger.info(
            f"[p2p] sent {len(blocks)} blocks in handleTopBlockSyncReq to {peer}"
        )

        if ret is None:
            if peer not in self.peerManager.getAllPeers():
                if peer== Peer('127.0.0.1', Params.PORT_CURRENT) or \
                                peer == Peer('localhost', Params.PORT_CURRENT) or \
                                    peer.ip == '0.0.0.0' or \
                                    peer == Peer(Params.PUBLIC_IP, Params.PORT_CURRENT):
                    return
                if Utils.is_peer_valid(peer):
                    with self.peers_lock:
                        self.peerManager.add(peer)  #self.peers.append(peer)
                    #Peer.save_peers(self.peers)
                    self.sendPeerExtend()
                else:
                    self.peerManager.block(peer)
예제 #2
0
    def handleTopBlockReq(self, peer: Peer):
        logger.info(f"[p2p] to handle TopBlokReq from peer {peer}")

        with self.chain_lock:
            block = copy.deepcopy(self.active_chain.chain[-1])
        message = Message(Actions.BlockRev, block, Params.PORT_CURRENT)
        ret = self.request.sendall(Utils.encode_socket_data(message))
        logger.info(f"[p2p] sent top block in handleTopBlockReq to {peer}")

        if ret is None:
            #if self.request.sendall(Utils.encode_socket_data(message)) is None:
            if peer not in self.peerManager.getAllPeers():
                if peer== Peer('127.0.0.1', Params.PORT_CURRENT) or \
                                peer == Peer('localhost', Params.PORT_CURRENT) or \
                                    peer.ip == '0.0.0.0' or \
                                    peer == Peer(Params.PUBLIC_IP, Params.PORT_CURRENT):
                    return
                if Utils.is_peer_valid(peer):
                    with self.peers_lock:
                        self.peerManager.add(peer)  #self.peers.append(peer)
                    #logger.info(f'[p2p] add peer {peer} into peer list')
                    #Peer.save_peers(self.peers)
                    self.sendPeerExtend()
                else:
                    self.peerManager.block(peer)
예제 #3
0
    def handlePeerExtendGet(self, peer_samples: Iterable[Peer], peer: Peer):
        peer_samples.append(peer)
        for peer_sample in peer_samples:
            if not isinstance(peer_sample, Peer):
                continue

            if peer_sample == Peer('127.0.0.1', Params.PORT_CURRENT) or \
                peer_sample == Peer('localhost', Params.PORT_CURRENT) or \
                    peer_sample.ip == '0.0.0.0' or \
                    peer_sample == Peer(Params.PUBLIC_IP, Params.PORT_CURRENT):
                continue
            if peer_sample in self.peerManager.getAllPeers():
                continue
            if Utils.is_peer_valid(peer_sample):
                with self.peers_lock:
                    self.peerManager.add(peer_sample)
            else:
                self.peerManager.block(peer_sample)
예제 #4
0
    def handleBlockSyncReq(self, blockid: str, peer: Peer):

        logger.info(f"[p2p] receive BlockSyncReq from peer {peer}")

        #with self.chain_lock:
        height = Block.locate_block(blockid, self.active_chain)[1]
        if height is None:
            logger.info(
                f'[p2p] cannot find blockid {blockid}, and do nothing for this BlockSyncReq from peer {peer}'
            )
            with self.chain_lock:
                block = copy.deepcopy(self.active_chain.chain[-1])

            message = Message(Actions.BlockRev, block, Params.PORT_CURRENT)
            self.request.sendall(Utils.encode_socket_data(message))

            return
        else:
            logger.info(
                f"[p2p] receive BlockSyncReq at height {height} from peer {peer}"
            )

        with self.chain_lock:
            blocks = copy.deepcopy(
                self.active_chain.chain[height:(height + Params.CHUNK_SIZE)])

        logger.info(f"[p2p] sending {len(blocks)} blocks to {peer}")

        message = Message(Actions.BlocksSyncGet, blocks, Params.PORT_CURRENT)
        self.request.sendall(Utils.encode_socket_data(message))

        if (peer not in self.peerManager.getAllPeers()) and not (peer == Peer('127.0.0.1', Params.PORT_CURRENT) or \
                peer == Peer('localhost', Params.PORT_CURRENT) or \
                    peer.ip == '0.0.0.0' or \
                    peer == Peer(Params.PUBLIC_IP, Params.PORT_CURRENT)):

            if Utils.is_peer_valid(peer):
                with self.peers_lock:
                    self.peerManager.add(peer)
                self.sendPeerExtend()
            else:
                self.peerManager.block(peer)
예제 #5
0
    def handleBlockSyncGet(self, blocks: Iterable[Block], peer: Peer):
        if peer != Peer('127.0.0.1', Params.PORT_CURRENT):
            logger.info(
                f"[p2p] receive {len(blocks)} blocks for BlockSyncGet from {peer}"
            )
        new_blocks = [
            block for block in blocks if not Block.locate_block(
                block.id, self.active_chain, self.side_branches)[0]
        ]
        logger.info(
            f'[p2p] {len(new_blocks)} of {len(blocks)} blocks from {peer} is new'
        )

        #if not new_blocks:
        #    logger.info('[p2p] initial block download complete')
        #    self.ibd_done.set()
        #    return
        #else:
        #    self.ibd_done.clear()

        if not TCPHandler.check_blocks_headers(new_blocks):
            return

        with self.chain_lock:

            for block in new_blocks:
                if Block.locate_block(block.id, self.active_chain,
                                      self.side_branches)[0]:
                    new_blocks.pop(0)
                else:
                    break
            if not new_blocks:
                return

            chain_idx  = TCPHandler.check_block_place(new_blocks[0], self.active_chain, self.utxo_set, \
                                                          self.mempool, self.side_branches)
            if chain_idx is None:
                logger.info(
                    f'received blocks have been seen in BlockSyncGet, do nothing and return'
                )
                return
            if chain_idx <= -1:
                logger.info(f'[p2p] orphan or wrong blocks')
                if peer != Peer('127.0.0.1', Params.PORT_CURRENT):
                    with self.peers_lock:
                        self.peerManager.block(peer)
                return

            if chain_idx >= 1:
                # if is side branches, append the blocks (one block left) to the side branches directly
                logger.info(
                    f'[p2p] just append {len(new_blocks)-1} blocks to side branch {chain_idx}, leaving one block to '
                    f'be coped with method do_connect_block_and_after')
                while len(new_blocks) >= 2:
                    self.side_branches[chain_idx - 1].chain.append(
                        new_blocks.pop(0))

            for block in new_blocks:
                if not TCPHandler.do_connect_block_and_after(block, chain_idx, self.active_chain, self.side_branches, \
                                                self.mempool, self.utxo_set, self.mine_interrupt):
                    return

        if chain_idx == Params.ACTIVE_CHAIN_IDX:
            if len(self.active_chain.chain) % Params.SAVE_PER_SIZE == 0 or len(
                    self.active_chain.chain) <= 5:
                Persistence.save_to_disk(self.active_chain)

            logger.info(
                f'[p2p] current chain height {self.active_chain.height}, and continue initial block download ... '
            )

        if peer not in self.peerManager.getAllPeers():
            if peer== Peer('127.0.0.1', Params.PORT_CURRENT) or \
                            peer == Peer('localhost', Params.PORT_CURRENT) or \
                                peer.ip == '0.0.0.0' or \
                                peer == Peer(Params.PUBLIC_IP, Params.PORT_CURRENT):
                return
            if Utils.is_peer_valid(peer):
                with self.peers_lock:
                    self.peerManager.add(peer)  #self.peers.append(peer)
                self.sendPeerExtend()
            else:
                self.peerManager.block(peer)

        if peer == Peer('127.0.0.1', Params.PORT_CURRENT):
            logger.info(f'peer in handleBlockSyncGet cannot be itself')
            return

        top_id_chain_idx = new_blocks[-1].id
        message = Message(Actions.BlocksSyncReq, top_id_chain_idx,
                          Params.PORT_CURRENT)
        try:
            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
                s.connect(peer())
                s.sendall(Utils.encode_socket_data(message))
                logger.info(f'[p2p] succeed to send BlocksSyncReq to {peer}')
                msg_len = int(binascii.hexlify(s.recv(4) or b'\x00'), 16)
                data = b''
                while msg_len > 0:
                    tdat = s.recv(1024)
                    data += tdat
                    msg_len -= len(tdat)
            s.close()
        except ConnectionRefusedError:
            self.peerManager.block(peer)
        except:
            self.peerManager.addLog(peer, 1)
        else:
            self.peerManager.addLog(peer, 0)

            message = Utils.deserialize(data.decode(),
                                        self.gs) if data else None
            if message:
                logger.info(
                    f'[p2p] received blocks for sync blocks from peer {peer}')
                message = Message(message.action, message.data,
                                  Params.PORT_CURRENT, peer)
                ret = Utils.send_to_peer(message,
                                         Peer('127.0.0.1',
                                              Params.PORT_CURRENT),
                                         itself=True)
                if ret != 0:
                    logger.info(
                        f'[p2p] cannot send data to itself, and its current port is {Params.PORT_CURRENT}'
                    )

            else:
                logger.info(f'[p2p] recv nothing from peer {peer}')