def __init__(self, main): self.searchThread = None self.passPhraseFinder = None self.isSearchOver = False def updateResults(resultStr): self.resultStr += resultStr def updateDisplay(): if len(self.resultStr) > 0: self.resultsDisplay.append(self.resultStr) self.resultStr = '' self.resultsDisplay.moveCursor(QtGui.QTextCursor.End) self.resultsDisplay.repaint() if self.isSearchOver: endSearch() # Call this from another thread to end the search def terminateSearch(): self.isSearchOver = True # Call this from the main thread to end the search def endSearch(): self.main.extraHeartbeatAlways.remove(updateDisplay) self.searchButton.setEnabled(True) self.stopButton.setEnabled(False) # If the thread is still searching tell the pass phrase finder to stop if self.passPhraseFinder and self.searchThread and not self.searchThread.isFinished(): self.passPhraseFinder.isStopped = True def searchForPassphrase(): # Get the selected wallet from the main screen wlt = self.getSelectedWlt() if wlt and not wlt.watchingOnly and wlt.isLocked: self.resultStr = '' self.passPhraseFinder = PassPhraseFinder(wlt) self.resultsDisplay.setText(QString('')) self.main.extraHeartbeatAlways.append(updateDisplay) if len(self.segOrdStrSet) > 0: # From self.segOrdStrList, create a list of lists of indexes that describe the segment orderings to search # In other words convert all of the strings in orderings list to lists of integers segOrdIntListList = [] for ordStr in self.segOrdStrSet: # The indexes provided by the users are 1 based, and the list indexes ought to be 0 based segOrdIntListList.append([int(indexStr)-1 for indexStr in ordStr.split(',')]) self.searchThread = PyBackgroundThread(self.passPhraseFinder.searchForPassPhrase, [segDef.getSegList() for segDef in self.segDefList], segOrdIntListList, updateResults, terminateSearch ) # Reset the isSearchOver flag self.isSearchOver = False self.searchThread.start() # Disable search button adn enabled stop button self.stopButton.setEnabled(True) self.searchButton.setEnabled(False) else: QMessageBox.warning(self.main, tr('Invalid'), tr(""" There are no valid segment combinations to search. Please add at least one segment and ordering to search."""), QMessageBox.Ok) else: QMessageBox.warning(self.main, tr('Invalid'), tr(""" No valid wallet is selected. Please select a locked non-watching-only from Available Wallets."""), QMessageBox.Ok) def addKnownSegment(): dlgEnterSegment = DlgEnterSegment(main, main) if dlgEnterSegment.exec_(): segmentText = str(dlgEnterSegment.editSegment.text()) if len(segmentText)>0: self.segDefList.append(KnownSeg(segmentText)) self.segDefTableModel.updateSegList(self.segDefList) def addUnknownCaseSegment(): dlgEnterSegment = DlgEnterSegment(main, main) if dlgEnterSegment.exec_(): segmentText = str(dlgEnterSegment.editSegment.text()) if len(segmentText)>0: self.segDefList.append(UnknownCaseSeg(segmentText)) self.segDefTableModel.updateSegList(self.segDefList) def addUnknownOrderSegment(): dlgEnterSegment = DlgEnterSegment(main, main, isUnknownOrder=True) if dlgEnterSegment.exec_(): segmentText = str(dlgEnterSegment.editSegment.text()) minLen = int(str(dlgEnterSegment.minSelector.currentText())) maxLen = int(str(dlgEnterSegment.maxSelector.currentText())) if len(segmentText)>0: self.segDefList.append(UnknownSeg(segmentText, minLen, maxLen)) self.segDefTableModel.updateSegList(self.segDefList) def addOrdering(): if len(self.segDefList) > 0: dlgSpecifyOrdering = DlgSpecifyOrdering(main, main, len(self.segDefList)) if dlgSpecifyOrdering.exec_(): self.segOrdStrSet.add(str(dlgSpecifyOrdering.parseOrderingList()).strip('[]')) self.updateOrderingListBox() else: QMessageBox.warning(self.main, tr('Not Ready'), tr(""" No segments have been entered. You must enter some segments before you can order them."""), QMessageBox.Ok) self.main = main self.segDefList = [] self.segOrdStrSet = set() segmentHeader = QRichLabel(tr("""<b>Build segments for pass phrase search: </b>"""), doWrap=False) self.knownButton = QPushButton("Add Known Segment") self.unknownCaseButton = QPushButton("Add Unknown Case Segment") self.unknownOrderButton = QPushButton("Add Unknown Order Segment") self.main.connect(self.knownButton, SIGNAL('clicked()'), addKnownSegment) self.main.connect(self.unknownCaseButton, SIGNAL('clicked()'), addUnknownCaseSegment) self.main.connect(self.unknownOrderButton, SIGNAL('clicked()'), addUnknownOrderSegment) topRow = makeHorizFrame([segmentHeader, self.knownButton, self.unknownCaseButton, self.unknownOrderButton, 'stretch']) self.segDefTableModel = SegDefDisplayModel() self.segDefTableView = QTableView() self.segDefTableView.setModel(self.segDefTableModel) self.segDefTableView.setSelectionBehavior(QTableView.SelectRows) self.segDefTableView.setSelectionMode(QTableView.SingleSelection) self.segDefTableView.verticalHeader().setDefaultSectionSize(20) self.segDefTableView.verticalHeader().hide() h = tightSizeNChar(self.segDefTableView, 1)[1] self.segDefTableView.setMinimumHeight(2 * (1.3 * h)) self.segDefTableView.setMaximumHeight(10 * (1.3 * h)) initialColResize(self.segDefTableView, [.1, .2, .4, .1, .1, .1]) self.segDefTableView.customContextMenuRequested.connect(self.showSegContextMenu) self.segDefTableView.setContextMenuPolicy(Qt.CustomContextMenu) segmentOrderingsHeader = QRichLabel(tr("""<b>Specify orderings for pass phrase search: </b>"""), doWrap=False) self.addOrderingButton = QPushButton("Add Ordering") self.main.connect(self.addOrderingButton, SIGNAL('clicked()'), addOrdering) orderingButtonPanel = makeHorizFrame([segmentOrderingsHeader, self.addOrderingButton, 'stretch']) self.segOrdListBox = QListWidget() self.segOrdListBox.customContextMenuRequested.connect(self.showOrdContextMenu) self.segOrdListBox.setContextMenuPolicy(Qt.CustomContextMenu) self.searchButton = QPushButton("Search") self.main.connect(self.searchButton, SIGNAL('clicked()'), searchForPassphrase) self.stopButton = QPushButton("Stop Searching") self.stopButton.setEnabled(False) self.main.connect(self.stopButton, SIGNAL('clicked()'), endSearch) totalSearchLabel = QRichLabel(tr("""<b>Total Passphrase Tries To Search: </b>"""), doWrap=False) self.totalSearchTriesDisplay = QLineEdit() self.totalSearchTriesDisplay.setReadOnly(True) self.totalSearchTriesDisplay.setText(QString('0')) self.totalSearchTriesDisplay.setFont(GETFONT('Fixed')) self.totalSearchTriesDisplay.setMinimumWidth(tightSizeNChar(self.totalSearchTriesDisplay, 6)[0]) self.totalSearchTriesDisplay.setMaximumWidth(tightSizeNChar(self.totalSearchTriesDisplay, 12)[0]) searchButtonPanel = makeHorizFrame([self.searchButton, self.stopButton, 'stretch', totalSearchLabel, self.totalSearchTriesDisplay]) self.resultsDisplay = QTextEdit() self.resultsDisplay.setReadOnly(True) self.resultsDisplay.setFont(GETFONT('Fixed')) self.resultsDisplay.setMinimumHeight(100) self.searchPanel = makeVertFrame([topRow, self.segDefTableView, orderingButtonPanel, self.segOrdListBox, searchButtonPanel, self.resultsDisplay, 'stretch']) # Now set the scrollarea widget to the layout self.tabToDisplay = QScrollArea() self.tabToDisplay.setWidgetResizable(True) self.tabToDisplay.setWidget(self.searchPanel)
def __init__(self, main): def updateDustLimit(): try: self.dustTableModel.updateDustList( self.getSelectedWlt(), str2coin(self.dustLimitText.text())) self.beGoneDustButton.setEnabled( len(self.dustTableModel.dustTxOutlist) > 0) if self.dustTableModel.wlt: self.lblHeader.setText( tr("""<b>Dust Outputs for Wallet: %s</b>""" % self.dustTableModel.wlt.labelName)) except NegativeValueError: pass except TooMuchPrecisionError: pass except: LOGEXCEPT("Unexpected exception") pass def sendDust(): try: utxiList = [] for utxo in self.dustTableModel.dustTxOutlist: # The PyCreateAndSignTx method require PyTx and PyBtcAddress objects rawTx = TheBDM.getTxByHash(utxo.getTxHash()).serialize() a160 = CheckHash160(utxo.getRecipientScrAddr()) for pyAddr in self.dustTableModel.wlt.addrMap.values(): if a160 == pyAddr.getAddr160(): pubKey = pyAddr.binPublicKey65.toBinStr() txoIdx = utxo.getTxOutIndex() utxiList.append( UnsignedTxInput(rawTx, txoIdx, None, pubKey)) break # Make copies, destroy them in the finally clause privKeyMap = {} for addrObj in self.dustTableModel.wlt.addrMap.values(): scrAddr = SCRADDR_P2PKH_BYTE + addrObj.getAddr160() if self.dustTableModel.wlt.useEncryption and self.dustTableModel.wlt.isLocked: # Target wallet is encrypted... unlockdlg = DlgUnlockWallet(self.dustTableModel.wlt, self.main, self.main, 'Unlock Wallet to Import') if not unlockdlg.exec_(): QMessageBox.critical(self, 'Wallet is Locked', \ 'Cannot send dust without unlocking the wallet!', \ QMessageBox.Ok) return privKeyMap[scrAddr] = addrObj.binPrivKey32_Plain.copy() signedTx = PyCreateAndSignTx( utxiList, [], privKeyMap, SIGHASH_NONE | SIGHASH_ANYONECANPAY) print "-------------" print binary_to_hex(signedTx.serialize()) # sock = socket.create_connection(('dust-b-gone.bitcoin.petertodd.org',80)) # sock.send(signedTx.serialize()) # sock.send(b'\n') # sock.close() except socket.error as err: QMessageBox.critical( self.main, tr('Negative Value'), tr(""" Failed to connect to dust-b-gone server: %s""" % err.strerror), QMessageBox.Ok) except NegativeValueError: QMessageBox.critical( self.main, tr('Negative Value'), tr(""" You must enter a positive value of at least 0.0000 0001 and less than %s for the dust limit.""" % MAX_DUST_LIMIT_STR), QMessageBox.Ok) except TooMuchPrecisionError: QMessageBox.critical( self.main.main, tr('Too much precision'), tr(""" Bitcoins can only be specified down to 8 decimal places. The smallest unit of a Bitcoin is 0.0000 0001 BTC. Please enter a dust limit of at least 0.0000 0001 and less than %s.""" % MAX_DUST_LIMIT_STR), QMessageBox.Ok) finally: for scraddr in privKeyMap: privKeyMap[scraddr].destroy() self.main = main self.lblHeader = QRichLabel( tr("""<b>Dust Outputs for Wallet: None Selected</b>"""), doWrap=False) self.beGoneDustButton = QPushButton("Remove Dust") self.beGoneDustButton.setEnabled(False) self.main.connect(self.beGoneDustButton, SIGNAL('clicked()'), sendDust) topRow = makeHorizFrame([self.lblHeader, 'stretch']) secondRow = makeHorizFrame([self.beGoneDustButton, 'stretch']) self.dustLimitLabel = QLabel("Max Dust Value (BTC): ") self.dustLimitText = QLineEdit() self.dustLimitText.setFont(GETFONT('Fixed')) self.dustLimitText.setMinimumWidth( tightSizeNChar(self.dustLimitText, 6)[0]) self.dustLimitText.setMaximumWidth( tightSizeNChar(self.dustLimitText, 12)[0]) self.dustLimitText.setAlignment(Qt.AlignRight) self.dustLimitText.setText(coin2str(DEFAULT_DUST_LIMIT)) self.main.connect(self.dustLimitText, SIGNAL('textChanged(QString)'), updateDustLimit) limitPanel = makeHorizFrame( [self.dustLimitLabel, self.dustLimitText, 'stretch']) self.dustTableModel = DustDisplayModel() self.dustTableView = QTableView() self.dustTableView.setModel(self.dustTableModel) self.dustTableView.setSelectionMode(QTableView.NoSelection) self.dustTableView.verticalHeader().setDefaultSectionSize(20) self.dustTableView.verticalHeader().hide() h = tightSizeNChar(self.dustTableView, 1)[1] self.dustTableView.setMinimumHeight(2 * (1.3 * h)) self.dustTableView.setMaximumHeight(10 * (1.3 * h)) initialColResize(self.dustTableView, [100, .7, .3]) self.dustTableView.setContextMenuPolicy(Qt.CustomContextMenu) self.lblTxioInfo = QRichLabel('') self.lblTxioInfo.setMinimumWidth( tightSizeNChar(self.lblTxioInfo, 30)[0]) self.main.connect(self.main.walletsView, SIGNAL('clicked(QModelIndex)'), updateDustLimit) self.dustBGoneFrame = makeVertFrame( [topRow, secondRow, limitPanel, self.dustTableView, 'stretch']) # Now set the scrollarea widget to the layout self.tabToDisplay = QScrollArea() self.tabToDisplay.setWidgetResizable(True) self.tabToDisplay.setWidget(self.dustBGoneFrame)
def __init__(self, main): def updateDustLimit(): try: self.dustTableModel.updateDustList(self.getSelectedWlt(), str2coin(self.dustLimitText.text())) self.beGoneDustButton.setEnabled(len(self.dustTableModel.dustTxOutlist)>0) if self.dustTableModel.wlt: self.lblHeader.setText(tr("""<b>Dust Outputs for Wallet: %s</b>""" % self.dustTableModel.wlt.labelName)) except NegativeValueError: pass except TooMuchPrecisionError: pass except: LOGEXCEPT("Unexpected exception") pass def sendDust(): try: utxiList = [] for utxo in self.dustTableModel.dustTxOutlist: # The PyCreateAndSignTx method require PyTx and PyBtcAddress objects rawTx = TheBDM.getTxByHash(utxo.getTxHash()).serialize() a160 = CheckHash160(utxo.getRecipientScrAddr()) for pyAddr in self.dustTableModel.wlt.addrMap.values(): if a160 == pyAddr.getAddr160(): pubKey = pyAddr.binPublicKey65.toBinStr() txoIdx = utxo.getTxOutIndex() utxiList.append(UnsignedTxInput(rawTx, txoIdx, None, pubKey)) break # Make copies, destroy them in the finally clause privKeyMap = {} for addrObj in self.dustTableModel.wlt.addrMap.values(): scrAddr = SCRADDR_P2PKH_BYTE + addrObj.getAddr160() if self.dustTableModel.wlt.useEncryption and self.dustTableModel.wlt.isLocked: # Target wallet is encrypted... unlockdlg = DlgUnlockWallet(self.dustTableModel.wlt, self.main, self.main, 'Unlock Wallet to Import') if not unlockdlg.exec_(): QMessageBox.critical(self, 'Wallet is Locked', \ 'Cannot send dust without unlocking the wallet!', \ QMessageBox.Ok) return privKeyMap[scrAddr] = addrObj.binPrivKey32_Plain.copy() signedTx = PyCreateAndSignTx(utxiList, [], privKeyMap, SIGHASH_NONE|SIGHASH_ANYONECANPAY ) print "-------------" print binary_to_hex(signedTx.serialize()) # sock = socket.create_connection(('dust-b-gone.bitcoin.petertodd.org',80)) # sock.send(signedTx.serialize()) # sock.send(b'\n') # sock.close() except socket.error as err: QMessageBox.critical(self.main, tr('Negative Value'), tr(""" Failed to connect to dust-b-gone server: %s""" % err.strerror), QMessageBox.Ok) except NegativeValueError: QMessageBox.critical(self.main, tr('Negative Value'), tr(""" You must enter a positive value of at least 0.0000 0001 and less than %s for the dust limit.""" % MAX_DUST_LIMIT_STR), QMessageBox.Ok) except TooMuchPrecisionError: QMessageBox.critical(self.main.main, tr('Too much precision'), tr(""" Bitcoins can only be specified down to 8 decimal places. The smallest unit of a Groestlcoin is 0.0000 0001 GRS. Please enter a dust limit of at least 0.0000 0001 and less than %s.""" % MAX_DUST_LIMIT_STR), QMessageBox.Ok) finally: for scraddr in privKeyMap: privKeyMap[scraddr].destroy() self.main = main self.lblHeader = QRichLabel(tr("""<b>Dust Outputs for Wallet: None Selected</b>"""), doWrap=False) self.beGoneDustButton = QPushButton("Remove Dust") self.beGoneDustButton.setEnabled(False) self.main.connect(self.beGoneDustButton, SIGNAL('clicked()'), sendDust) topRow = makeHorizFrame([self.lblHeader,'stretch']) secondRow = makeHorizFrame([self.beGoneDustButton, 'stretch']) self.dustLimitLabel = QLabel("Max Dust Value (GRS): ") self.dustLimitText = QLineEdit() self.dustLimitText.setFont(GETFONT('Fixed')) self.dustLimitText.setMinimumWidth(tightSizeNChar(self.dustLimitText, 6)[0]) self.dustLimitText.setMaximumWidth(tightSizeNChar(self.dustLimitText, 12)[0]) self.dustLimitText.setAlignment(Qt.AlignRight) self.dustLimitText.setText(coin2str(DEFAULT_DUST_LIMIT)) self.main.connect(self.dustLimitText, SIGNAL('textChanged(QString)'), updateDustLimit) limitPanel = makeHorizFrame([self.dustLimitLabel, self.dustLimitText, 'stretch']) self.dustTableModel = DustDisplayModel() self.dustTableView = QTableView() self.dustTableView.setModel(self.dustTableModel) self.dustTableView.setSelectionMode(QTableView.NoSelection) self.dustTableView.verticalHeader().setDefaultSectionSize(20) self.dustTableView.verticalHeader().hide() h = tightSizeNChar(self.dustTableView, 1)[1] self.dustTableView.setMinimumHeight(2 * (1.3 * h)) self.dustTableView.setMaximumHeight(10 * (1.3 * h)) initialColResize(self.dustTableView, [100, .7, .3]) self.dustTableView.setContextMenuPolicy(Qt.CustomContextMenu) self.lblTxioInfo = QRichLabel('') self.lblTxioInfo.setMinimumWidth(tightSizeNChar(self.lblTxioInfo, 30)[0]) self.main.connect(self.main.walletsView, SIGNAL('clicked(QModelIndex)'), updateDustLimit) self.dustBGoneFrame = makeVertFrame([topRow, secondRow, limitPanel, self.dustTableView, 'stretch']) # Now set the scrollarea widget to the layout self.tabToDisplay = QScrollArea() self.tabToDisplay.setWidgetResizable(True) self.tabToDisplay.setWidget(self.dustBGoneFrame)