Beispiel #1
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)
Beispiel #2
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)
Beispiel #3
0
    def _getPort(self) -> Tuple[Peer, int]:
        if self.peerList:
            peerinfo = random.sample(self.peerList, 1)[0]
            peer = Peer(peerinfo[0], peerinfo[1])
        else:
            peer = Peer('127.0.0.1', 9999)

        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind(("", 0))
        s.listen(1)
        port = s.getsockname()[1]
        s.close()
        return peer, port
Beispiel #4
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)
Beispiel #5
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)
Beispiel #6
0
    def __init__(self):

        # active_chain is initialized with a chain index and a list with genesis block in it
        self.active_chain: BlockChain = BlockChain(
            idx=Params.ACTIVE_CHAIN_IDX, chain=[Block.genesis_block()])
        self.side_branches: Iterable[BlockChain] = []
        self.orphan_blocks: Iterable[Block] = []
        self.utxo_set: UTXO_Set = UTXO_Set()
        self.mempool: MemPool = MemPool()
        self.wallet: Wallet = Wallet.init_wallet(Params.WALLET_FILE)

        # PeerManager use Peer.init_peer() to read peer from PEERS_FILE or peer list in Params.py
        self.peerManager: PeerManager = PeerManager(
            Peer.init_peers(Params.PEERS_FILE))

        self.mine_interrupt: threading.Event = threading.Event()
        self.ibd_done: threading.Event = threading.Event()
        self.chain_lock: threading.RLock = threading.RLock()
        self.peers_lock: threading.RLock = threading.RLock()

        self.gs = dict()
        (
            self.gs["Block"],
            self.gs["Transaction"],
            self.gs["UnspentTxOut"],
            self.gs["Message"],
            self.gs["TxIn"],
            self.gs["TxOut"],
            self.gs["Peer"],
            self.gs["OutPoint"],
        ) = (
            globals()["Block"],
            globals()["Transaction"],
            globals()["UnspentTxOut"],
            globals()["Message"],
            globals()["TxIn"],
            globals()["TxOut"],
            globals()["Peer"],
            globals()["OutPoint"],
        )
Beispiel #7
0
    def __init__(self):

        self.active_chain: BlockChain = BlockChain(
            idx=Params.ACTIVE_CHAIN_IDX, chain=[Block.genesis_block()])
        self.side_branches: Iterable[BlockChain] = []
        self.orphan_blocks: Iterable[Block] = []
        self.utxo_set: UTXO_Set = UTXO_Set()
        self.mempool: MemPool = MemPool()
        self.wallet: Wallet = Wallet.init_wallet(Params.WALLET_FILE)

        #self.peers: Iterable[Peer] = Peer.init_peers(Params.PEERS_FILE)
        self.peerManager: PeerManager = PeerManager(
            Peer.init_peers(Params.PEERS_FILE))

        self.mine_interrupt: threading.Event = threading.Event()
        self.ibd_done: threading.Event = threading.Event()
        self.chain_lock: _thread.RLock = threading.RLock()
        self.peers_lock: _thread.RLock = threading.RLock()

        self.gs = dict()
        self.gs['Block'], self.gs['Transaction'], self.gs['UnspentTxOut'], self.gs['Message'], self.gs['TxIn'], self.gs['TxOut'], self.gs['Peer'], self.gs['OutPoint']= \
                    globals()['Block'], globals()['Transaction'], globals()['UnspentTxOut'], globals()['Message'], \
                    globals()['TxIn'], globals()['TxOut'], globals()['Peer'], globals()['OutPoint']
Beispiel #8
0
            def work_to_do():
                logger.info(
                    f'begin to work in another new thread of initiative_sync')
                try:
                    with self.peers_lock:
                        self.peerManager.update()
                        peers = self.peerManager.getPeers()
                        Peer.save_peers(peers, Params.PEERS_FILE)
                except:
                    pass

                try:

                    time_now = time.time()
                    with self.chain_lock:
                        for block in self.orphan_blocks:
                            if time_now - block.timestamp > Params.MAXIMUM_ALLOWABLE_HEIGHT_DIFF * Params.TIME_BETWEEN_BLOCKS_IN_SECS_TARGET:
                                self.orphan_blocks.remove(block)
                except:
                    pass

                getpeers = self.peerManager.getPeers(2)
                if len(getpeers) > 0:
                    peer = random.sample(getpeers, 1)[0]
                    try:
                        message = Message(Actions.TopBlockReq, None,
                                          Params.PORT_CURRENT)

                        with socket.socket(
                                socket.AF_INET, socket.SOCK_STREAM
                        ) as s:  #socket.create_connection(peer(), timeout=25) as s:
                            #logger.info(f'[EdgenceChain] begin to connect to {peer}')
                            s.connect(peer())
                            #logger.info(f'[EdgenceChain] succeed to create socket connection with {peer}, and begin to send data ...')
                            s.sendall(Utils.encode_socket_data(message))
                            logger.info(
                                f'[EdgenceChain] succeed to send TopBlockReq 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()
                        message = Utils.deserialize(data.decode(),
                                                    self.gs) if data else None
                        if message:
                            logger.info(
                                f'[EdgenceChain] received top block from peer {peer}'
                            )
                            message = Message(Actions.BlockRev, 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'cannot send data to itself, and its port is {Params.PORT_CURRENT}'
                                )
                            else:
                                #logger.info(f'[EdgenceChain] send BlockRev to itself')
                                pass
                        else:
                            logger.info(
                                f'[EdgenceChain] recv nothing from peer {peer}'
                            )

                    except:
                        self.peerManager.addLog(peer, 1)
Beispiel #9
0
    def initial_block_download(self):
        self.ibd_done.clear()
        peers = self.peerManager.getPeers()
        if peers:
            logger.info(
                f'start initial block download from {len(peers)} peers')
            peer_sample = random.sample(peers, min(len(peers), 6))

            message = Message(Actions.BlocksSyncReq,
                              self.active_chain.chain[-1].id,
                              Params.PORT_CURRENT)
            for peer in peer_sample:
                try:
                    with socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM) as s:
                        s.settimeout(70)
                        s.connect(peer())
                        s.sendall(Utils.encode_socket_data(message))
                        logger.info(
                            f'sending BLockSyncReq successfully at {self.active_chain.chain[-1].id} 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()
                    message = Utils.deserialize(data.decode(),
                                                self.gs) if data else None
                    if message:
                        logger.info(
                            f'[EdgenceChain] received blocks in initial_block_download 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'cannot send data to itself, and its port is {Params.PORT_CURRENT}'
                            )
                    else:
                        logger.info(
                            f'[EdgenceChain] recv no new blocks when in initial_block_download from peer {peer}, and waiting for finishing'
                        )
                        time.sleep(Params.TIME_BETWEEN_BLOCKS_IN_SECS_TARGET)
                        self.ibd_done.set()
                        break
                except Exception as e:
                    #logger.exception(f'Error: {repr(e)}, and remove dead peer {peer}')
                    if peer in peers:
                        try:
                            with self.peers_lock:
                                self.peerManager.addLog(peer, 1)
                        except:
                            pass

        else:
            logger.info(f'no peer nodes existed, ibd_done is set')
            self.ibd_done.set()
Beispiel #10
0
    def initial_block_download(self):
        """
        Download blocks from peers in peerManager.
        """

        self.ibd_done.clear()
        peers = self.peerManager.getPeers()
        if peers:
            logger.info(
                f"start initial block download from {len(peers)} peers")
            # Select max 6 peers.
            peer_sample = random.sample(peers, min(len(peers), 6))

            message = Message(
                Actions.BlocksSyncReq,
                self.active_chain.chain[-1].id,
                Params.PORT_CURRENT,
            )

            for peer in peer_sample:
                try:
                    with socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM) as s:
                        s.settimeout(70)
                        s.connect(peer())
                        s.sendall(Utils.encode_socket_data(message))
                        logger.info(
                            f"sending BLockSyncReq successfully at {self.active_chain.chain[-1].id} 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)

                    # Useless below.
                    # s.close()

                    message = (Utils.deserialize(data.decode(), self.gs)
                               if data else None)

                    if message:
                        logger.info(
                            f"[EdgenceChain] received blocks in initial_block_download from peer {peer}"
                        )
                        message = Message(message.action, message.data,
                                          Params.PORT_CURRENT, peer)

                        # TODO: simplify it.
                        # Send received data to its TCP server, TCP handler will process received block.
                        ret = Utils.send_to_peer(message,
                                                 Peer("127.0.0.1",
                                                      Params.PORT_CURRENT),
                                                 itself=True)

                        if ret != 0:
                            logger.info(
                                f"cannot send data to itself, and its port is {Params.PORT_CURRENT}"
                            )
                    else:
                        logger.info(
                            f"[EdgenceChain] recv no new blocks when in initial_block_download from peer {peer}, and waiting for finishing"
                        )
                        time.sleep(Params.TIME_BETWEEN_BLOCKS_IN_SECS_TARGET)
                        self.ibd_done.set()
                        break

                except Exception as e:
                    # logger.exception(f'Error: {repr(e)}, and remove dead peer {peer}')
                    if peer in peers:
                        try:
                            with self.peers_lock:
                                # This peer is not success this time, add log: 1 to its log.
                                self.peerManager.addLog(peer, 1)
                        except:
                            pass

        else:
            logger.info(f"no peer nodes existed, ibd_done is set")
            self.ibd_done.set()
Beispiel #11
0
    def handle(self):

        # self.server is an instance of the ThreadedTCPServer
        self.active_chain = self.server.active_chain
        self.side_branches = self.server.side_branches
        self.orphan_blocks = self.server.orphan_blocks
        self.utxo_set = self.server.utxo_set
        self.mempool = self.server.mempool
        self.peerManager = self.server.peerManager
        self.mine_interrupt = self.server.mine_interrupt
        self.ibd_done = self.server.ibd_done
        self.chain_lock = self.server.chain_lock
        self.peers_lock = self.server.peers_lock

        self.gs = dict()
        self.gs['Block'], self.gs['Transaction'], self.gs['UnspentTxOut'], self.gs['Message'], self.gs['TxIn'], self.gs['TxOut'], self.gs['Peer'], self.gs['OutPoint']= \
                    globals()['Block'], globals()['Transaction'], globals()['UnspentTxOut'], globals()['Message'], \
                    globals()['TxIn'], globals()['TxOut'], globals()['Peer'], globals()['OutPoint']
        try:
            #logger.info(f'type of self.request is {type(self.request)} before read')
            message = Utils.read_all_from_socket(self.request, self.gs)
            #logger.info(f'message is {message}')
            #logger.info(f'type of self.request is {type(self.request)} after read')
        except:
            logger.exception(
                f'[p2p] invalid meassage from peer {self.request.getpeername()[0]}'
            )
            return

        if not isinstance(message, Message):
            logger.info(
                f'[p2p] not a valid Message from peer {self.request.getpeername()[0]}'
            )
            self.request.shutdown(socket.SHUT_RDWR)
            self.request.close()
            return
        else:
            peer = Peer(str(self.request.getpeername()[0]), int(message.port))

        action = int(message.action)

        if not self.ibd_done.is_set() and action != Actions.BlocksSyncGet:
            logger.info(
                f'ibd_done is not set, and action {action} is not {Actions.BlocksSyncGet}'
            )
            self.request.shutdown(socket.SHUT_RDWR)
            self.request.close()
            return

        if action == Actions.BlocksSyncReq:
            self.handleBlockSyncReq(message.data, peer)
        elif action == Actions.BlocksSyncGet:
            self.request.shutdown(socket.SHUT_RDWR)
            self.request.close()
            if message.srpeer is not None:
                peer = message.srpeer
            self.handleBlockSyncGet(message.data, peer)
        elif action == Actions.TxStatusReq:
            self.handleTxStatusReq(message.data, peer)
        elif action == Actions.UTXO4Addr:
            self.handleUTXO4Addr(message.data, peer)
        elif action == Actions.Balance4Addr:
            self.handleBalance4Addr(message.data, peer)
        elif action == Actions.TxRev:
            self.request.shutdown(socket.SHUT_RDWR)
            self.request.close()
            self.handleTxRev(message.data, peer)
        elif action == Actions.BlockRev:
            self.request.shutdown(socket.SHUT_RDWR)
            self.request.close()
            if message.srpeer is not None:
                peer = message.srpeer
            self.handleBlockRev(message.data, peer)
        elif action == Actions.PeerExtend:
            self.request.shutdown(socket.SHUT_RDWR)
            self.request.close()
            self.handlePeerExtendGet(message.data, peer)
        elif action == Actions.TopBlocksSyncReq:
            self.handleTopBlockSyncReq(message.data, peer)
        elif action == Actions.TopBlockReq:
            self.handleTopBlockReq(peer)
        elif action == Actions.BlockstatsReq:
            self.handleBlockstatsReq(peer)
        elif action == Actions.BlockAtHeightReq:
            self.handleBlockAtHeightReq(message.data, peer)
        else:
            self.request.shutdown(socket.SHUT_RDWR)
            self.request.close()
            logger.info(f'[p2p] received unwanted action request ')
Beispiel #12
0
    def handleBlockRev(self, block: Block, peer: Peer):
        if not isinstance(block, Block):
            logger.info(f'[p2p] {block} is not a Block')
            return
        else:
            if peer != Peer('127.0.0.1', Params.PORT_CURRENT):
                logger.info(
                    f"[p2p] received block {block.id} from peer {peer}")
            with self.chain_lock:

                chain_idx  = TCPHandler.check_block_place(block, self.active_chain, self.utxo_set, self.mempool, \
                                                          self.side_branches)
                ret_outside_lock = False
                if chain_idx is not None and chain_idx >= 0:
                    ret_outside_lock = TCPHandler.do_connect_block_and_after(block, chain_idx, self.active_chain, self.side_branches, \
                                                       self.mempool, self.utxo_set, self.mine_interrupt)
                    if not ret_outside_lock:
                        #logger.info(f'####### out of chain_lock: {chain_use_id} of handleBlockRev')
                        return
                    if not Block.locate_block(block.id, self.active_chain,
                                              self.side_branches)[0]:
                        return

                #logger.info(f'####### out of chain_lock: {chain_use_id} of handleBlockRev')

            if ret_outside_lock is True:
                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)

            if chain_idx is not None and chain_idx >= 0:
                peers = self.peerManager.getPeers()
                if len(peers) > 0:
                    for _peer in random.sample(peers, min(len(peers), 5)):
                        if _peer != peer:
                            ret = Utils.send_to_peer(
                                Message(Actions.BlockRev, block,
                                        Params.PORT_CURRENT), _peer)
                            if ret == 1:
                                if _peer in peers:
                                    try:
                                        with self.peers_lock:
                                            self.peerManager.block(_peer)
                                    except:
                                        pass
                            elif ret != 0:
                                with self.peers_lock:
                                    self.peerManager.addLog(_peer, 1)
                            else:
                                with self.peers_lock:
                                    self.peerManager.addLog(_peer, 0)

                self.sendPeerExtend()

            elif chain_idx is None:
                logger.info(
                    f'[p2p] already seen block {block.id}, and do nothing')
            elif chain_idx == -1:
                # case of orphan block
                message = Message(Actions.TopBlocksSyncReq, 50,
                                  Params.PORT_CURRENT)
                if peer == Peer('127.0.0.1', Params.PORT_CURRENT):
                    getpeers = self.peerManager.getPeers(2)
                    if len(getpeers) > 0:
                        peer = random.sample(getpeers, 1)[0]
                    else:
                        return

                try:
                    with socket.socket(
                            socket.AF_INET, socket.SOCK_STREAM
                    ) as s:  #socket.create_connection(peer(), timeout=25) as s:
                        s.connect(peer())
                        s.sendall(Utils.encode_socket_data(message))
                        logger.info(
                            f'[p2p] succeed to send TopBlocksSyncReq 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:
                        blocks = message.data
                        if blocks[0].prev_block_hash:
                            if not Block.locate_block(
                                    blocks[0].prev_block_hash,
                                    self.active_chain, self.side_branches)[0]:
                                logger.info(
                                    f"received sync blocks for the orphan block in handleBlockRev, but the first blocks's pre_block_hash cannot be seen on the chains"
                                )
                                self.peerManager.block(peer)
                                return
                        else:
                            blocks.pop(0)
                            if not Block.locate_block(
                                    blocks[0].prev_block_hash,
                                    self.active_chain, self.side_branches)[0]:
                                logger.info(
                                    f"received sync blocks for the orphan block in handleBlockRev, but the first blocks's pre_block_hash cannot be seen on the chains"
                                )
                                self.peerManager.block(peer)
                                return

                        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] send BlocksSyncGet to itself')
                            pass
                    else:
                        logger.info(f'[p2p] recv nothing from peer {peer}')
Beispiel #13
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}')
Beispiel #14
0
    def handle(self):

        # self.server is an instance of the ThreadedTCPServer
        self.active_chain = self.server.active_chain
        self.side_branches = self.server.side_branches
        self.orphan_blocks = self.server.orphan_blocks
        self.utxo_set = self.server.utxo_set
        self.mempool = self.server.mempool
        self.peerManager = self.server.peerManager
        self.mine_interrupt = self.server.mine_interrupt
        self.ibd_done = self.server.ibd_done
        self.chain_lock = self.server.chain_lock
        self.peers_lock = self.server.peers_lock

        self.gs = dict()
        (
            self.gs["Block"],
            self.gs["Transaction"],
            self.gs["UnspentTxOut"],
            self.gs["Message"],
            self.gs["TxIn"],
            self.gs["TxOut"],
            self.gs["Peer"],
            self.gs["OutPoint"],
        ) = (
            globals()["Block"],
            globals()["Transaction"],
            globals()["UnspentTxOut"],
            globals()["Message"],
            globals()["TxIn"],
            globals()["TxOut"],
            globals()["Peer"],
            globals()["OutPoint"],
        )
        try:
            # logger.info(f'type of self.request is {type(self.request)} before read')

            # Get request ip.
            req_ip = self.request.getpeername()[0]
            logger.info(f"[p2p] start handling message from {req_ip}")

            # If RECEIVE_LOCALHOST_MSG flag is True, check req_ip is 127.0.0.1 or not.
            # If not, shutdown this socket connection.
            if Params.RECEIVE_LOCALHOST_MSG and str(req_ip) != "127.0.0.1":
                logger.info(
                    f"[p2p] Only receive message from localhost, close socket connection. Caused by RECEIVE_LOCALHOST_MSG in params/Params.py"
                )
                self.request.shutdown(socket.SHUT_RDWR)
                self.request.close()
                return

            # If message is invalid from other peers,
            # like sending a meanningless info which will be translated by Utils.read_all_from_socket()
            # using our protocol into a random message length.
            # If message is invalid, Utils.read_all_from_socket() will return None.
            message = Utils.read_all_from_socket(self.request, self.gs)

            # If message is None, shutdown this socket connection.
            if message is None:
                logger.info(f"[p2p] message is None, close socket connection")
                self.request.shutdown(socket.SHUT_RDWR)
                self.request.close()
                return

            # logger.info(f"message is {message}")
            # logger.info(f"type of self.request is {type(self.request)} after read")
        except:
            logger.exception(f"[p2p] invalid meassage from peer {req_ip}")
            return

        if not isinstance(message, Message):
            logger.info(f"[p2p] not a valid Message from peer {req_ip}")
            self.request.shutdown(socket.SHUT_RDWR)
            self.request.close()
            return
        else:
            peer = Peer(str(req_ip), int(message.port))

        action = int(message.action)

        if not self.ibd_done.is_set() and action != Actions.BlocksSyncGet:
            logger.info(
                f"ibd_done is not set, and action {action} is not {Actions.BlocksSyncGet}"
            )
            self.request.shutdown(socket.SHUT_RDWR)
            self.request.close()
            return

        if action == Actions.BlocksSyncReq:
            self.handleBlockSyncReq(message.data, peer)
        elif action == Actions.BlocksSyncGet:
            self.request.shutdown(socket.SHUT_RDWR)
            self.request.close()
            if message.srpeer is not None:
                peer = message.srpeer
            self.handleBlockSyncGet(message.data, peer)
        elif action == Actions.TxStatusReq:
            self.handleTxStatusReq(message.data, peer)
        elif action == Actions.UTXO4Addr:
            self.handleUTXO4Addr(message.data, peer)
        elif action == Actions.Balance4Addr:
            self.handleBalance4Addr(message.data, peer)
        elif action == Actions.TxRev:
            self.request.shutdown(socket.SHUT_RDWR)
            self.request.close()
            self.handleTxRev(message.data, peer)
        elif action == Actions.BlockRev:
            self.request.shutdown(socket.SHUT_RDWR)
            self.request.close()
            if message.srpeer is not None:
                peer = message.srpeer
            self.handleBlockRev(message.data, peer)
        elif action == Actions.PeerExtend:
            self.request.shutdown(socket.SHUT_RDWR)
            self.request.close()
            self.handlePeerExtendGet(message.data, peer)
        elif action == Actions.TopBlocksSyncReq:
            self.handleTopBlockSyncReq(message.data, peer)
        elif action == Actions.TopBlockReq:
            self.handleTopBlockReq(peer)
        elif action == Actions.BlockstatsReq:
            self.handleBlockstatsReq(peer)
        elif action == Actions.BlockAtHeightReq:
            self.handleBlockAtHeightReq(message.data, peer)
        else:
            self.request.shutdown(socket.SHUT_RDWR)
            self.request.close()
            logger.info(f"[p2p] received unwanted action request ")
Beispiel #15
0
from p2p.Peer import Peer

peer1 = Peer()
print(peer1)
peer2 = Peer('10.108.01.13')
print(peer2)
peer3 = Peer('10.108.01.13', 18)
print(peer3)

print(peer1.__eq__(peer2))
print(peer2.__eq__(Peer('10.108.01.13', 9999)))
print(peer1 == peer2)
print(peer2 == Peer('10.108.01.13', 9999))

print(peer1.__eq__(peer2))
print(peer2.__eq__(Peer('10.108.01.13', 9999)))
print(peer1 == peer2)
print(peer2 == Peer('10.108.01.13', 9999))

print(Peer('127.0.0.1', 1000) == Peer('localhost', 1000))