class EmulatorModeServer(QtNetwork.QLocalServer):
    signal_data_received = QtCore.pyqtSignal(object)

    _SOCKET_TIMEOUT = 2000

    def __init__(self):
        super().__init__()
        self.setSocketOptions(QtNetwork.QLocalServer.WorldAccessOption)
        self.newConnection.connect(self._handleConnection)

    def listen(self):
        if not super().listen(Emulator.GUI_PLUGIN_SERVER_NAME):
            raise RuntimeError(
                f'Could not start server: {Emulator.GUI_PLUGIN_SERVER_NAME}')

    def close(self):
        super().close()
        self.removeServer(self.fullServerName())

    def _handleConnection(self):
        socket = self.nextPendingConnection()
        if socket is not None:
            data = None
            if socket.waitForReadyRead(self._SOCKET_TIMEOUT):
                data = socket.readAll().data().decode('utf-8')
                logger.debug(f'Read data from emulator: {data}')
                socket.disconnectFromServer()
            socket.deleteLater()
            if data is not None:
                self.signal_data_received.emit(data)
                logger.debug('Data emitted.')
Exemplo n.º 2
0
class GraphView(QGraphicsView):

    positionsChanged = QtCore.pyqtSignal(np.ndarray)
    # Emitted when nodes' selected or highlighted state changes
    selectionChanged = QtCore.pyqtSignal()
    # Emitted when the relayout() animation finishes
    animationFinished = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self.nodes = []
        self.edges = []
        self._selection = []
        self._clicked_node = None
        self.is_animating = False

        scene = QGraphicsScene(self)
        scene.setItemIndexMethod(scene.BspTreeIndex)
        scene.setBspTreeDepth(2)
        self.setScene(scene)
        self.setText('')

        self.setCacheMode(self.CacheBackground)
        self.setViewportUpdateMode(
            self.FullViewportUpdate
        )  # BoundingRectViewportUpdate doesn't work on Mac

        self.setTransformationAnchor(self.AnchorUnderMouse)
        self.setResizeAnchor(self.AnchorViewCenter)

        self.setDragMode(self.RubberBandDrag)

        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        self.positionsChanged.connect(self._update_positions,
                                      type=Qt.BlockingQueuedConnection)
        self.animationFinished.connect(
            lambda: setattr(self, 'is_animating', False))

    def mousePressEvent(self, event):
        self._selection = []
        if event.button() == Qt.LeftButton:
            if self.is_animating:
                self.is_animating = False
                return
            # Save the current selection and restore it on mouse{Move,Release}
            self._clicked_node = self.itemAt(event.pos())
            if event.modifiers() & Qt.ShiftModifier:
                self._selection = self.scene().selectedItems()
        # On right mouse button, switch to pan mode
        elif event.button() == Qt.RightButton:
            self.setDragMode(self.ScrollHandDrag)
            # Forge left mouse button event
            event = QtGui.QMouseEvent(event.type(), event.pos(),
                                      event.globalPos(), Qt.LeftButton,
                                      event.buttons(), event.modifiers())
        super().mousePressEvent(event)
        # Reselect the selection that had just been discarded
        for node in self._selection:
            node.setSelected(True)

    def mouseMoveEvent(self, event):
        super().mouseMoveEvent(event)
        if not self._clicked_node:
            for node in self._selection:
                node.setSelected(True)

    def mouseReleaseEvent(self, event):
        super().mouseReleaseEvent(event)
        if self.dragMode() == self.RubberBandDrag:
            for node in self._selection:
                node.setSelected(True)
            self.selectionChanged.emit()
        if self._clicked_node:
            self.selectionChanged.emit()
        # The following line is required (QTBUG-48443)
        self.setDragMode(self.NoDrag)
        # Restore default drag mode
        self.setDragMode(self.RubberBandDrag)

    def setText(self, text):
        text = self._text = QtGui.QStaticText(text or '')
        text.setPerformanceHint(text.AggressiveCaching)
        option = QtGui.QTextOption()
        option.setWrapMode(QtGui.QTextOption.NoWrap)
        text.setTextOption(option)
        scene = self.scene()
        scene.invalidate(layers=scene.BackgroundLayer)

    def drawForeground(self, painter, rect):
        painter.resetTransform()
        painter.drawStaticText(10, 10, self._text)
        super().drawForeground(painter, rect)

    def scrollContentsBy(self, dx, dy):
        scene = self.scene()
        scene.invalidate(layers=scene.BackgroundLayer)
        super().scrollContentsBy(dx, dy)

    def _setState(self, nodes, extend, state_setter):
        nodes = set(nodes)
        if extend:
            for node in self.nodes:
                if node.id in nodes:
                    getattr(node, state_setter)(True)
        else:
            for node in self.nodes:
                getattr(node, state_setter)(node.id in nodes)
        self.selectionChanged.emit()

    def getSelected(self):
        return [node.id for node in self.scene().selectedItems()]

    def getUnselected(self):
        return [
            node.id for node in (set(self.scene().items()) -
                                 set(self.scene().selectedItems()))
            if isinstance(node, Node)
        ]

    def setSelected(self, nodes, extend=False):
        self._setState(nodes, extend, 'setSelected')

    def getHighlighted(self):
        return [
            node.id for node in self.nodes
            if node.isHighlighted() and not node.isSelected()
        ]

    def setHighlighted(self, nodes):
        self._setState(nodes, False, 'setHighlighted')

    def clear(self):
        self.scene().clear()
        self.scene().setSceneRect(QRectF())
        self.nodes.clear()
        self.edges.clear()

    def set_graph(self, graph, relayout=True):
        assert not graph or isinstance(graph, nx.Graph)
        self.graph = graph
        if not graph:
            self.clear()
            return
        large_graph = IS_LARGE_GRAPH(graph)
        very_large_graph = IS_VERY_LARGE_GRAPH(graph)
        self.setViewport(
            QtOpenGL.QGLWidget()
            # FIXME: Try reenable the following test after Qt5 port
            if large_graph and HAVE_OPENGL else QWidget())
        self.setRenderHints(QtGui.QPainter.RenderHint(
        ) if very_large_graph else (QtGui.QPainter.Antialiasing
                                    | QtGui.QPainter.TextAntialiasing))
        self.clear()
        nodes = {}
        for v in sorted(graph.nodes()):
            node = Node(v, view=self)
            self.addNode(node)
            nodes[v] = node
        for u, v in graph.edges():
            self.addEdge(Edge(nodes[u], nodes[v], view=self))
        self.selectionChanged.emit()
        if relayout: self.relayout()

    def addNode(self, node):
        assert isinstance(node, Node)
        self.nodes.append(node)
        self.scene().addItem(node)

    def addEdge(self, edge):
        assert isinstance(edge, Edge)
        self.edges.append(edge)
        self.scene().addItem(edge)

    def wheelEvent(self, event):
        if event.angleDelta().x() != 0: return
        self.scaleView(2**(event.angleDelta().y() / 240))

    def scaleView(self, factor):
        magnitude = self.transform().scale(factor,
                                           factor).mapRect(QRectF(0, 0, 1,
                                                                  1)).width()
        if 0.2 < magnitude < 30:
            self.scale(factor, factor)
        # Reposition nodes' labela and edges, both of which are node-dependend
        # (and nodes just "moved")
        for node in self.nodes:
            node.adjust()
        for edge in self.edges:
            edge.adjust()

    @property
    def is_animating(self):
        return self._is_animating

    @is_animating.setter
    def is_animating(self, value):
        self.setCursor(Qt.ForbiddenCursor if value else Qt.ArrowCursor)
        self._is_animating = value

    def relayout(self, randomize=True, weight=None):
        if self.is_animating: return
        self.is_animating = True
        if weight is None: weight = 'weight'
        pos, graphview = None, self
        if not randomize:
            pos = [[pos.x(), pos.y()]
                   for pos in (node.pos() for node in self.nodes)]

        class AnimationThread(Thread):
            def __init__(self, iterations, callback):
                super().__init__()
                self.iterations = iterations
                self.callback = callback

            def run(self):
                newpos = fruchterman_reingold_layout(
                    graphview.graph,
                    pos=pos,
                    weight=weight,
                    iterations=self.iterations,
                    callback=self.callback)
                if not self.callback:  # update once at the end
                    graphview.update_positions(newpos)
                graphview.animationFinished.emit()

        iterations, callback = FR_ITERATIONS, self.update_positions
        if IS_VERY_LARGE_GRAPH(self.graph):
            # Don't animate very large graphs
            iterations, callback = 5, None
        AnimationThread(iterations, callback).start()

    def update_positions(self, positions):
        self.positionsChanged.emit(positions)
        return self._is_animating

    def _update_positions(self, positions):
        for node, pos in zip(self.nodes, positions * 300):
            node.setPos(*pos)
        qApp.processEvents()
Exemplo n.º 3
0
class wallet_functions(QtCore.QThread):
    data_output = QtCore.pyqtSignal(object)
    def __init__(self, coin_list):
        QtCore.QThread.__init__(self)
        self.coin_list = coin_list
    def run(self):
        LOG_PATH = 'RPC.log'
        logging.basicConfig(filename=LOG_PATH, level=logging.INFO)
        log = logging.getLogger(__name__)

        output = self.check_for_stake(self.coin_list, log)
        self.data_output.emit('{0}: {1}'.format(self.coin_list['coin_name'], output))


    def check_for_stake(self, RPC, log):
        try:
            rpc_connection = AuthServiceProxy("http://%s:%[email protected]:%s"%(RPC['user'], RPC['pw'], RPC['port']))
            # Check integrity of wallet before getting wallet info
            check_wallet = rpc_connection.checkwallet()
        except:
            return "Unable to connect to wallet. Verify that it's running and your RPC settings are correct"

        if 'wallet check passed' not in check_wallet:
            log.info(check_wallet)
            rpc_connection.repairwallet()
            log.info("**Wallet was repaired**")

        try:
            txs = rpc_connection.listunspent(int(RPC['min_conf']), int(RPC['max_conf'])) # Only work with inputs that aren't mature
        except:
            return "Unable to run 'listunspent' over RPC, check that the wallet is still running"
        input_sum = 0
        utxo_size = Decimal(RPC['UTXO_size'])
        input_tx = []
        addresses_to_reuse = []
        for each_tx in txs:
            # Check out each existing transaction for desired size, sum up inputs that aren't
            if each_tx['amount'] != utxo_size:
                input_sum += each_tx['amount']
                input_tx.append({"txid":each_tx['txid'],"vout":each_tx['vout']})
                if 'account' in each_tx and each_tx['account'] == 'stake_script' and each_tx['address'] not in addresses_to_reuse:
                    # reuse input addresses for a new output if they have the label 'stake_script'
                    addresses_to_reuse.append(each_tx['address'])

        if input_sum < utxo_size:
            log.debug("DEBUG: Total coins: {0} is not enough to make a new packet of {1}".format(input_sum, utxo_size))
            return "Total coins: {0} is not enough to make a new packet of {1} :DEBUG".format(input_sum, utxo_size)

        # Reuse or make a new change and stake addresses
        change_address = rpc_connection.getaddressesbyaccount("change")
        if len(change_address) == 0:
            change_address = [rpc_connection.getnewaddress("change")]
        stake_addresses = rpc_connection.getaddressesbyaccount("stake_script")
        for addr in stake_addresses:
            amount = rpc_connection.getreceivedbyaddress(addr)
            if amount == 0 and addr not in addresses_to_reuse:
                # Only reuse addresses with the label stake_script and zero balance for safety
                addresses_to_reuse.append(addr)

        output_addresses = {}
        number_of_splits = int(input_sum / utxo_size)
        if len(addresses_to_reuse) < number_of_splits:
            # Make as many new addresses as needed to split inputs into 'size' outputs
            num_to_make = number_of_splits - len(addresses_to_reuse)
            #if not arg.noconfirm:
                # TODO implement
            #    print("About to make {0} new stake address(es), confirm".format(num_to_make))
            #    get_permission()
            for _ in range(num_to_make):
                addresses_to_reuse.append(rpc_connection.getnewaddress('stake_script'))

        for _ in range(number_of_splits):
            output_addresses[addresses_to_reuse.pop()] = utxo_size

        #print(output_addresses)
        assert(int(input_sum / utxo_size) == len(output_addresses)), "Not enough output addresses for number of UTXO splits!"

        number_of_splits = len(output_addresses)
        numbytes = 181 * len(input_tx) + 34* (number_of_splits+1) + 10
        numKB = math.ceil(numbytes / 1000)
        TX_FEE = Decimal(RPC['transaction_fee']) * numKB
        log.debug("transaction fee is %d : %d bytes, fee multiple is %d"%(TX_FEE, numbytes,numKB))

        change_amount = input_sum - (utxo_size * number_of_splits) - TX_FEE
        output_addresses[change_address[0]] = change_amount
        assert (change_amount > 0), "Change amount cannot be less than zero"
        assert(change_amount + TX_FEE + (utxo_size*number_of_splits) == input_sum), "Coins will be lost if the total output != input"

        log.debug("{0} Inputs {1}".format(len(input_tx),input_tx))
        log.debug("{0} Outputs {1}".format(len(output_addresses), output_addresses))
        log.info("{0} (Input total) = {2} ({1}_UTXO packets) + {3} (change) + {4} (fee)".format(input_sum,number_of_splits,utxo_size*number_of_splits,change_amount, TX_FEE))

        # Generate, sign, and send the raw transaction
        raw_tx = rpc_connection.createrawtransaction(input_tx, output_addresses)
        signed_tx = rpc_connection.signrawtransaction(raw_tx)
        if not signed_tx['complete']:
            log.error("Signing failed of raw tranaction: {0}\nInputs: {1}\nOutputs: {2}".format(raw_tx, input_tx, output_addresses))
            return "Signing of raw transaction did not complete successfully, make sure wallet is functioning properly"

        #if not arg.noconfirm:
        #    print("About to send transaction, confirm")
        #    get_permission()

        log.info("Attempting to send: {0} (Total inputs) = {2} ({1} new UTXO) + {3} (change) + {4} (fee)".format(input_sum,number_of_splits,utxo_size*number_of_splits,change_amount, TX_FEE))
        try:
            sent = rpc_connection.sendrawtransaction(signed_tx['hex'])
        except Exception as e:
            return "Sending transaction failed (Your wallet might need more time to update): {0}".format(str(e))
        log.info("TX successful: transaction ID: {0}".format(sent))
        now = datetime.datetime.now().strftime("%m-%d %H:%M")
        return "{6} TX {5} successful: {0} (Total inputs) = {2} ({1} new UTXO) + {3} (change) + {4} (fee)".format(input_sum,number_of_splits,utxo_size*number_of_splits,change_amount, TX_FEE, sent, now)