def findPubKey(self): printDbg("Computing public key...") currSpath = self.ui.edt_spath.value() currHwAcc = self.ui.edt_hwAccount.value() # Check HW device if self.caller.hwStatus != 2: myPopUp_sb(self.caller, "crit", 'SPMT - hw device check', "Connect to HW device first") printDbg("Unable to connect to hardware device. The device status is: %d" % self.caller.hwStatus) return None result = self.caller.hwdevice.scanForPubKey(currHwAcc, currSpath, self.isTestnet()) # Connection pop-up warningText = "Unable to find public key. The action was refused on the device or another application " warningText += "might have taken over the USB communication with the device.<br><br>" warningText += "To continue click the <b>Retry</b> button.\nTo cancel, click the <b>Abort</b> button." mBox = QMessageBox(QMessageBox.Critical, "WARNING", warningText, QMessageBox.Retry) mBox.setStandardButtons(QMessageBox.Retry | QMessageBox.Abort); while result is None: ans = mBox.exec_() if ans == QMessageBox.Abort: return # we need to reconnect the device self.caller.hwdevice.clearDevice() self.caller.hwdevice.initDevice(self.caller.header.hwDevices.currentIndex()) result = self.caller.hwdevice.scanForPubKey(currHwAcc, currSpath, self.isTestnet()) mess = "Found public key:\n%s" % result myPopUp_sb(self.caller, "info", "SPMT - findPubKey", mess) printOK("Public Key: %s" % result) self.ui.edt_pubKey.setText(result)
def initDevice(self): printDbg("Initializing Trezor") with self.lock: self.status = 0 devices = enumerate_devices() if not len(devices): # No device connected return # Use the first device for now d = devices[0] ui = TrezorUi() try: self.client = TrezorClient(d, ui) except IOError: raise Exception("TREZOR device is currently in use") printOK("Trezor HW device connected [v. %s.%s.%s]" % (self.client.features.major_version, self.client.features.minor_version, self.client.features.patch_version)) self.status = 1 model = self.client.features.model or "1" if not self.checkModel(model): self.status = 3 self.messages[ 3] = "Wrong device model (%s) detected.\nLooking for model %s." % ( HW_devices[self.model][0], model) return required_version = MINIMUM_FIRMWARE_VERSION[model] printDbg("Current version is %s (minimum required: %s)" % (str(self.client.version), str(required_version))) # Check device is unlocked bip32_path = parse_path(MPATH + "%d'/0/%d" % (0, 0)) _ = btc.get_address(self.client, 'PIVX', bip32_path, False) self.status = 2
def onStartAllMN(self): printOK("Start-All pressed") # Check RPC & dongle if not self.caller.rpcConnected: self.caller.myPopUp2(QMessageBox.Critical, 'QMT - hw/rpc device check', "Connect to RPC server and HW device first") printDbg("Hardware device or RPC server not connected") return None try: reply = self.caller.myPopUp( QMessageBox.Question, 'Confirm START', "Are you sure you want to start ALL masternodes?", QMessageBox.Yes) if reply == QMessageBox.Yes: mnList = [ x for x in self.caller.masternode_list if x['isHardware'] ] for mn_conf in mnList: self.masternodeToStart = Masternode( self, mn_conf['name'], mn_conf['ip'], mn_conf['port'], mn_conf['mnPrivKey'], mn_conf['hwAcc'], mn_conf['collateral']) # connect signal self.masternodeToStart.sigdone.connect(self.sendBroadcast) self.mnToStartList.append(self.masternodeToStart) self.startMN() except Exception as e: err_msg = "error before starting node" printException(getCallerName(), getFunctionName(), err_msg, e)
def __init__(self, tab_main, name, ip, port, mnPrivKey, hwAcc, collateral=None, isTestnet=False, *args, **kwargs): QObject.__init__(self, *args, **kwargs) if collateral is None: collateral = {} self.tab_main = tab_main self.name = name self.ip = ip self.port = str(port) self.mnPrivKey = wif_to_privkey(mnPrivKey) self.mnWIF = mnPrivKey self.mnPubKey = bitcoin.privkey_to_pubkey(self.mnPrivKey) self.hwAcc = hwAcc self.spath = collateral['spath'] self.nodePath = "%d'/0/%d" % (self.hwAcc, self.spath) self.collateral = collateral self.isTestnet = isTestnet self.currHeight = 0 Masternode.mnCount += 1 printOK("Initializing MNode with collateral: %s" % self.nodePath)
def displayMNlistUpdated(self): for masternode in self.caller.masternode_list: printOK( "Checking %s (%s)..." % (masternode['name'], masternode['collateral'].get('address'))) self.displayMNStatus(masternode) time.sleep(0.2)
def finalizeStartMessage(self, text): sig1 = text if sig1=="None": # Signature refused by the user self.sigdone.emit("None") return printOK("first signature: %s" % sig1) # ------ some default config scriptSig = '' sequence = 0xffffffff try: # block_hash = hash(currBlock-12) currBlock = self.rpcClient.getBlockCount() if currBlock is None: raise Exception('Unable to get current block number') block_hash = self.rpcClient.getBlockHash(currBlock - 12) if block_hash is None: raise Exception('Unable to get blockhash for block %d' % currBlock - 12) printDbg("Current block from PIVX client: %s" % str(currBlock)) printDbg("Hash of 12 blocks ago: %s" % block_hash) vintx = bytes.fromhex(self.collateral['txid'])[::-1].hex() vinno = self.collateral['txidn'].to_bytes(4, byteorder='big')[::-1].hex() vinsig = num_to_varint(len(scriptSig) / 2).hex() + bytes.fromhex(scriptSig)[::-1].hex() vinseq = sequence.to_bytes(4, byteorder='big')[::-1].hex() ipv6map = ipmap(self.ip, self.port) #printDbg("ipv6map: %s" % ipv6map) collateral_in = num_to_varint(len(self.collateral['pubKey'])/2).hex() + self.collateral['pubKey'] delegate_in = num_to_varint(len(self.mnPubKey)/2).hex() + self.mnPubKey except Exception as e: err_msg = "error in startMessage" printException(getCallerName(), getFunctionName(), err_msg, e) return work_sig_time = self.sig_time.to_bytes(8, byteorder='big')[::-1].hex() work_protoversion = self.protocol_version.to_bytes(4, byteorder='big')[::-1].hex() last_ping_block_hash = bytes.fromhex(block_hash)[::-1].hex() serializedData = serialize_input_str(self.collateral['txid'], self.collateral['txidn'], sequence, scriptSig) + block_hash + str(self.sig_time) printDbg("serializedData: %s" % serializedData) sig2 = self.signature2(serializedData) printOK("second signature: %s" % sig2) work = vintx + vinno + vinsig + vinseq work += ipv6map + collateral_in + delegate_in work += num_to_varint(len(sig1) / 2).hex() + sig1 work += work_sig_time + work_protoversion work += vintx + vinno + vinsig + vinseq work += last_ping_block_hash + work_sig_time work += num_to_varint(len(sig2) / 2).hex() + sig2 # nnLastDsq to zero work += "0"*16 # Emit signal self.sigdone.emit(work)
def signMessageFinish(self): with self.lock: self.mBox.accept() if self.signature != None: if len(self.signature) > 4: rLength = self.signature[3] r = self.signature[4 : 4 + rLength] if len(self.signature) > 4 + rLength + 1: sLength = self.signature[4 + rLength + 1] if len(self.signature) > 4 + rLength + 2: s = self.signature[4 + rLength + 2:] if rLength == 33: r = r[1:] if sLength == 33: s = s[1:] work = bytes(chr(27 + 4 + (self.signature[0] & 0x01)), "utf-8") + r + s printOK("Message signed") sig1 = work.hex() else: printDbg('client.signMessageSign() returned invalid response (code 3): ' + self.signature.hex()) sig1 = "None" else: printDbg('client.signMessageSign() returned invalid response (code 2): ' + self.signature.hex()) sig1 = "None" else: printDbg('client.signMessageSign() returned invalid response (code 1): ' + self.signature.hex()) sig1 = "None" else: printOK("Signature refused by the user") sig1 = "None" self.sig1done.emit(sig1)
def scanForBip32(self, account, address, starting_spath=0, spath_count=10, isTestnet=False): found = False spath = -1 printOK("Scanning for Bip32 path of address: %s" % address) for i in range(starting_spath, starting_spath+spath_count): curr_path = MPATH + "%d'/0/%d" % (account, i) printDbg("checking path... %s" % curr_path) self.lock.acquire() try: if not isTestnet: curr_addr = self.chip.getWalletPublicKey(curr_path).get('address')[12:-2] else: pubkey = compress_public_key(self.chip.getWalletPublicKey(curr_path).get('publicKey')).hex() curr_addr = pubkey_to_address(pubkey, isTestnet) if curr_addr == address: found = True spath = i break sleep(0.01) except Exception as e: err_msg = 'error in scanForBip32' printException(getCallerName(), getFunctionName(), err_msg, e.args) finally: self.lock.release() return (found, spath)
def findSpath_done(self): currAddr = self.ui.edt_address.text().strip() currHwAcc = self.ui.edt_hwAccount.value() spath = self.spath starting_spath = self.curr_starting_spath spath_count = self.curr_spath_count if self.spath_found: printOK("spath is %d" % spath) mess = "Found address %s in HW account %s with spath_id %s" % ( currAddr, currHwAcc, spath) self.caller.myPopUp2(QMessageBox.Information, 'QMT - spath search', mess) self.ui.edt_spath.setValue(spath) self.findPubKey() else: mess = "Scanned addresses <b>%d</b> to <b>%d</b> of HW account <b>%d</b>.<br>" % ( starting_spath, starting_spath + spath_count - 1, currHwAcc) mess += "Unable to find the address <i>%s</i>.<br>Maybe it's on a different account.<br><br>" % currAddr mess += "Do you want to scan %d more addresses of account n.<b>%d</b> ?" % ( spath_count, currHwAcc) ans = self.caller.myPopUp(QMessageBox.Critical, 'QMT - spath search', mess) if ans == QMessageBox.Yes: starting_spath += spath_count self.runInThread(self.findSpath, (starting_spath, spath_count), self.findSpath_done)
def onStartMN(self, data=None): # Check RPC & dongle if not self.caller.rpcConnected or self.caller.hwStatus != 2: self.caller.myPopUp2(QMessageBox.Critical, 'SPMT - hw/rpc device check', "Connect to RPC server and HW device first") printDbg("Hardware device or RPC server not connected") return None try: if not data: target = self.ui.sender() masternode_alias = target.alias printOK("Start-masternode %s pressed" % masternode_alias) for mn_conf in self.caller.masternode_list: if mn_conf['name'] == masternode_alias: reply = self.caller.myPopUp( QMessageBox.Question, 'Confirm START', "Are you sure you want to start masternoode:\n'%s'?" % mn_conf['name'], QMessageBox.Yes) if reply == QMessageBox.Yes: self.masternodeToStart = Masternode( self, mn_conf['name'], mn_conf['ip'], mn_conf['port'], mn_conf['mnPrivKey'], mn_conf['hwAcc'], mn_conf['collateral']) # connect signal self.masternodeToStart.sigdone.connect( self.sendBroadcast) self.mnToStartList.append(self.masternodeToStart) self.startMN() break except Exception as e: err_msg = "error before starting node" printException(getCallerName(), getFunctionName(), err_msg, e)
def sendBroadcast(self, text): if text == "None": self.sendBroadcastCheck() return printOK("Start Message: %s" % text) ret = self.caller.rpcClient.decodemasternodebroadcast(text) if ret is None: self.caller.myPopUp2(QMessageBox.Critical, 'message decoding failed', 'message decoding failed') self.sendBroadcastCheck() return msg = "Broadcast START message?\n" + json.dumps( ret, indent=4, sort_keys=True) reply = self.caller.myPopUp(QMessageBox.Question, 'message decoded', msg, QMessageBox.Yes) if reply == QMessageBox.No: self.sendBroadcastCheck() return ret2 = self.caller.rpcClient.relaymasternodebroadcast(text) if json.dumps(ret2)[1:26] == "Masternode broadcast sent": message = "Start-message was successfully sent to the network.<br>" message += "If your remote server is correctly configured and connected to the network, " message += "the output of the <b>./pivx-cli masternode status</b> command on the VPS should show:<br>" message += "<br><em>\"message\": \"Masternode successfully started\"</em>" self.caller.myPopUp2(QMessageBox.Information, 'message relayed', message, QMessageBox.Ok) else: print(json.dumps(ret2)[1:26]) print("\n") self.sendBroadcastCheck()
def signMessageFinish(self): with self.lock: self.mBox.accept() if self.signature is None: printOK("Signature refused by the user") self.sig1done.emit("None") else: self.sig1done.emit(self.signature.hex())
def findSpath(self, ctrl, starting_spath, spath_count): currAddr = self.ui.edt_address.text().strip() currHwAcc = self.ui.edt_hwAccount.value() # first scan. Subsequent called by findSpath_done self.spath_found, self.spath = self.caller.hwdevice.scanForBip32(currHwAcc, currAddr, starting_spath, spath_count, self.isTestnet()) printOK("Bip32 scan complete. result=%s spath=%s" % (self.spath_found, self.spath)) self.curr_starting_spath = starting_spath self.curr_spath_count = spath_count
def addressToSpath(self): printOK("addressToSpath pressed") self.spath_found = False # Check HW device if self.caller.hwStatus != 2: myPopUp_sb(self.caller, "crit", 'SPMT - hw device check', "Connect to HW device first") printDbg("Unable to connect to hardware device. The device status is: %d" % self.caller.hwStatus) return None self.runInThread(self.findSpath, (0, 10), self.findSpath_done)
def signTxFinish(self): self.mBox2.accept() if self.tx_raw is not None: # Signal to be catched by FinishSend on TabRewards / dlg_sewwpAll self.sigTxdone.emit(self.tx_raw, str(round(self.amount / 1e8, 8))) else: printOK("Transaction refused by the user") self.sigTxabort.emit()
def scanForPubKey(self, account, spath): result = None printOK("Scanning for PubKey of address n. %d on account n. %d" % (spath, account)) curr_path = MPATH + "%d'/0/%d" % (account, spath) with self.lock: nodeData = self.chip.getWalletPublicKey(curr_path) result = compress_public_key(nodeData.get('publicKey')).hex() return result
def run(self): while not self.shutdown_flag.is_set(): # update status without printing on debug self.control_tab.updateRPCstatus(self.ctrl_obj, False) if not self.control_tab.rpcConnected: sleep(self.timer_off) else: sleep(self.timer_on) printOK("Exiting Rpc Watchdog Thread")
def signTxFinish(self): self.mBox2.accept() try: if self.tx_raw is not None: # Signal to be catched by FinishSend on TabRewards self.sigTxdone.emit(self.tx_raw, str(round(self.amount / 1e8, 8))) else: printOK("Transaction refused by the user") except Exception as e: printDbg(e)
def checkApp(self): printDbg("Checking app") try: firstAddress = self.chip.getWalletPublicKey(MPATH + "0'/0/0").get( 'address')[12:-2] if firstAddress[0] == 'D': printOK("found PIVX app on ledger device") return True except Exception as e: err_msg = 'error in checkApp' printException(getCallerName(), getFunctionName(), err_msg, e.args) return False
def onCheckAllMN(self): if not self.caller.rpcConnected: self.caller.myPopUp2(QMessageBox.Critical, 'SPMT - hw device check', "RPC server must be connected to perform this action.") printDbg("Unable to connect: %s" % self.caller.rpcStatusMess) return try: printOK("Check-All pressed") ThreadFuns.runInThread(self.updateAllMasternodes_thread, (), self.displayMNlistUpdated) except Exception as e: err_msg = "error in checkAllMN" printException(getCallerName(), getFunctionName(), err_msg, e)
def run(self): while not self.shutdown_flag.is_set(): self.control_tab.updateRPCstatus(self.ctrl_obj) QApplication.processEvents() self.control_tab.updateRPCled() if not self.control_tab.rpcConnected: sleep(self.timer_off) else: sleep(self.timer_on) printOK("Exiting Rpc Watchdog Thread")
def initDevice(self, hw_index): printDbg("HW: initializing hw device with index %d" % hw_index) if hw_index >= len(HW_devices): raise Exception("Invalid HW index") # Select API self.api = LedgerApi() # Init device & connect signals self.api.initDevice() self.sig1done = self.api.sig1done self.sig_disconnected.connect(self.main_wnd.clearHWstatus) printOK("HW: hw device with index %d initialized" % hw_index)
def addressToSpath(self): printOK("addressToSpath pressed") self.spath_found = False # Check dongle printDbg("Checking HW device") if self.caller.hwStatus != 2: self.caller.myPopUp2(QMessageBox.Critical, 'QMT - hw device check', "Connect to HW device first") printDbg( "Unable to connect to hardware device. The device status is: %d" % self.caller.hwStatus) return None self.runInThread(self.findSpath, (0, 10), self.findSpath_done)
def scanForAddress(self, account, spath, isTestnet=False): curr_addr = None curr_path = MPATH + "%d'/0/%d" % (account, spath) printOK("Scanning for Address n. %d on account n. %d" % (spath, account)) with self.lock: if not isTestnet: curr_addr = self.chip.getWalletPublicKey(curr_path).get('address')[12:-2] else: pubkey = compress_public_key(self.chip.getWalletPublicKey(curr_path).get('publicKey')).hex() curr_addr = pubkey_to_address(pubkey, isTestnet) return curr_addr
def spathToAddress(self): printOK("spathToAddress pressed") currHwAcc = self.ui.edt_hwAccount.value() currSpath = self.ui.edt_spath.value() # Check HW device if self.caller.hwStatus != 2: myPopUp_sb(self.caller, "crit", 'SPMT - hw device check', "Connect to HW device first") printDbg("Unable to connect to hardware device. The device status is: %d" % self.caller.hwStatus) return None addr = self.caller.hwdevice.scanForAddress(currHwAcc, currSpath, self.isTestnet()) if addr: self.ui.edt_address.setText(addr) self.findPubKey()
def scanForPubKey(self, account, spath): printOK("Scanning for Address of path_id %s on account n° %s" % (str(spath), str(account))) curr_path = MPATH + "%d'/0/%d" % (account, spath) try: nodeData = self.chip.getWalletPublicKey(curr_path) except Exception as e: err_msg = 'error in scanForPubKey' printException(getCallerName(), getFunctionName(), err_msg, e.args) return None return compress_public_key(nodeData.get('publicKey')).hex()
def displayMNStatus(self, currMN): statusData = None for mn in self.all_masternodes.get('masternodes'): #if mn.get('addr') == currMN['collateral'].get('address'): if mn.get('txhash') == currMN['collateral'].get('txid') and mn.get('outidx') == currMN['collateral'].get('txidn'): statusData = mn if statusData is not None: try: statusData['balance'] = self.caller.apiClient.getBalance(mn.get('addr')) except Exception as e: err_msg = "error getting balance of %s" % mn.get('addr') printException(getCallerName(), getFunctionName(), err_msg, e) masternode_alias = currMN['name'] self.ui.btn_details[masternode_alias].disconnect() self.ui.btn_details[masternode_alias].clicked.connect(lambda: self.onDisplayStatusDetails(masternode_alias, statusData)) self.ui.btn_details[masternode_alias].show() if statusData is None: printOK("%s Not Found" % (masternode_alias)) self.ui.mnLed[masternode_alias].setPixmap(self.caller.ledGrayV_icon) msg = "<b>Masternode not found.</b>" self.ui.mnStatusLabel[masternode_alias].setText(msg) self.ui.mnStatusLabel[masternode_alias].show() self.ui.btn_details[masternode_alias].setEnabled(False) else: display_text = "" if statusData['balance'] is not None: self.ui.mnBalance[masternode_alias].setText(' <span style="color:purple">%s PIV</span>' % str(statusData['balance'])) self.ui.mnBalance[masternode_alias].show() printOK("Got status %s for %s" % (statusData['status'], masternode_alias)) if statusData['status'] == 'ENABLED': self.ui.mnLed[masternode_alias].setPixmap(self.caller.ledGreenV_icon) display_text += '<span style="color:green">%s</span> ' % statusData['status'] position = statusData.get('queue_pos') total_count = len(self.all_masternodes.get('masternodes')) display_text += '%d/%d' % (position, total_count) self.ui.mnStatusProgress[masternode_alias].setRange(0, total_count) self.ui.mnStatusProgress[masternode_alias].setValue(total_count-position) self.ui.mnStatusProgress[masternode_alias].show() else: self.ui.mnLed[masternode_alias].setPixmap(self.caller.ledRedV_icon) display_text += '<span style="color:red">%s</span> ' % statusData['status'] self.ui.mnStatusLabel[masternode_alias].setText(display_text) self.ui.mnStatusLabel[masternode_alias].show() self.ui.btn_details[masternode_alias].setEnabled(True) QApplication.processEvents()
def initDevice(self): with self.lock: self.status = 0 self.clearDevice() self.dongle = getDongle(False) printOK('Ledger Nano S drivers found') self.chip = btchip(self.dongle) printDbg("Ledger Initialized") ver = self.chip.getFirmwareVersion() printOK("Ledger HW device connected [v. %s]" % str(ver.get('version'))) # Check device is unlocked bip32_path = MPATH + "%d'/0/%d" % (0, 0) self.status = 1 firstKey = self.chip.getWalletPublicKey(bip32_path) self.status = 2
def __init__(self, caller, name, ip, port, mnPrivKey, hwAcc, collateral = {}, *args, **kwargs): QObject.__init__(self, *args, **kwargs) self.caller = caller self.name = name self.ip = ip self.port = str(port) self.mnPrivKey = wif_to_privkey(mnPrivKey) self.mnWIF = mnPrivKey self.mnPubKey = bitcoin.privkey_to_pubkey(self.mnPrivKey) self.hwAcc = hwAcc self.spath = collateral['spath'] self.nodePath = MPATH + "%d'/0/%d" % (self.hwAcc, self.spath) self.collateral = collateral Masternode.mnCount += 1 printOK("Initializing MNode with collateral: %s" % self.nodePath)
def process_trezor_exceptions_int(*args, **kwargs): hwDevice = args[0] try: return func(*args, **kwargs) except exceptions.Cancelled: printDbg("Action cancelled on the device") return except exceptions.PinException: hwDevice.status = 4 printOK("WRONG PIN") return except Exception as e: err_mess = "Trezor Exception" printException(getCallerName(True), getFunctionName(True), err_mess, str(e)) raise DisconnectedException(str(e), hwDevice)