def send_upd_tx(self): try: funding_address = '' if self.dmn_new_ip: dmn_new_ip_port = self.dmn_new_ip + ':' + str( self.dmn_new_port) else: dmn_new_ip_port = '"0"' params = [ 'update_service', self.dmn_protx_hash, dmn_new_ip_port, self.masternode.dmn_operator_private_key, self.dmn_new_operator_payout_address, funding_address ] try: upd_service_support = self.dashd_intf.checkfeaturesupport( 'protx_update_service', self.app_config.app_version) if not upd_service_support.get('enabled'): if upd_service_support.get('message'): raise Exception(upd_service_support.get('message')) else: raise Exception( 'The \'protx_update_service\' function is not supported by the RPC node ' 'you are connected to.') public_proxy_node = True active = self.app_config.feature_update_service_automatic.get_value( ) if not active: msg = self.app_config.feature_update_service_automatic.get_message( ) if not msg: msg = 'The functionality of the automatic execution of the update_service command on the ' \ '"public" RPC nodes is inactive. Use the manual method or contact the program author ' \ 'for details.' raise Exception(msg) except JSONRPCException as e: public_proxy_node = False if not public_proxy_node: try: # find an address to be used as the source of the transaction fees min_fee = round(1024 * FEE_DUFF_PER_BYTE / 1e8, 8) balances = self.dashd_intf.listaddressbalances(min_fee) bal_list = [] for addr in balances: bal_list.append({ 'address': addr, 'amount': balances[addr] }) bal_list.sort(key=lambda x: x['amount']) if not bal_list: raise Exception( "No address can be found in the node's wallet with sufficient funds to " "cover the transaction fees.") params[5] = bal_list[0]['address'] except JSONRPCException as e: logging.warning( "Couldn't list the node address balances. We assume you are using a " "public RPC node and the funding address for the transaction fee will " "be estimated during the `update_registrar` call") upd_tx_hash = self.dashd_intf.rpc_call(True, False, 'protx', *params) if upd_tx_hash: logging.info( 'update_service successfully executed, tx hash: ' + upd_tx_hash) self.btnSendUpdateTx.setDisabled(True) self.edtOperatorPayoutAddress.setReadOnly(True) self.edtIP.setReadOnly(True) self.edtPort.setReadOnly(True) self.btnClose.show() url = self.app_config.get_block_explorer_tx() if url: url = url.replace('%TXID%', upd_tx_hash) upd_tx_hash = f'<a href="{url}">{upd_tx_hash}</a>' msg = 'The update_service transaction has been successfully sent. ' \ f'Tx hash: {upd_tx_hash}. <br><br>' \ f'The new values will be visible on the network after the transaction is confirmed, i.e. in ' \ f'about 2.5 minutes.' if bool(dmn_new_ip_port ) and self.dmn_prev_ip_port != dmn_new_ip_port: msg += '\n\nYou have changed the masternode IP/port. Do you want to automatically update ' \ 'this in the app configuration?' if self.query_dlg( msg, buttons=QMessageBox.Yes | QMessageBox.No, default_button=QMessageBox.Yes, icon=QMessageBox.Information) == QMessageBox.Yes: self.masternode.ip = self.dmn_new_ip self.masternode.port = str(self.dmn_new_port) if self.on_mn_config_updated_callback: self.on_mn_config_updated_callback(self.masternode) else: WndUtils.info_msg(msg) except Exception as e: if str(e).find('protx-dup') >= 0: WndUtils.error_msg( 'The previous protx transaction has not been confirmed yet. Wait until it is ' 'confirmed before sending a new transaction.') else: logging.error( 'Exception occurred while sending protx update_service: ' + str(e)) WndUtils.error_msg(str(e))
def send_revoke_tx(self): try: funding_address = '' params = [ 'revoke', self.dmn_protx_hash, self.masternode.dmn_operator_private_key, self.revocation_reason, funding_address ] try: revoke_support = self.dashd_intf.checkfeaturesupport( 'protx_revoke', self.app_config.app_version) if not revoke_support.get('enabled'): if revoke_support.get('message'): raise Exception(revoke_support.get('message')) else: raise Exception( 'The \'protx_revoke\' function is not supported by the RPC node ' 'you are connected to.') public_proxy_node = True active = self.app_config.feature_revoke_operator_automatic.get_value( ) if not active: msg = self.app_config.feature_revoke_operator_automatic.get_message( ) if not msg: msg = 'The functionality of the automatic execution of the revoke command on the ' \ '"public" RPC nodes is inactive. Use the manual method or contact the program author ' \ 'for details.' raise Exception(msg) except JSONRPCException as e: public_proxy_node = False if not public_proxy_node: try: # find an address to be used as the source of the transaction fees min_fee = round(1024 * FEE_DUFF_PER_BYTE / 1e8, 8) balances = self.dashd_intf.listaddressbalances(min_fee) bal_list = [] for addr in balances: bal_list.append({ 'address': addr, 'amount': balances[addr] }) bal_list.sort(key=lambda x: x['amount']) if not bal_list: raise Exception( "No address can be found in the node's wallet with sufficient funds to " "cover the transaction fees.") params[5] = bal_list[0]['address'] except JSONRPCException as e: logging.warning( "Couldn't list the node address balances. We assume you are using a " "public RPC node and the funding address for the transaction fee will " "be estimated during the `update_registrar` call") upd_tx_hash = self.dashd_intf.rpc_call(True, False, 'protx', *params) if upd_tx_hash: logging.info('revoke successfully executed, tx hash: ' + upd_tx_hash) self.btnSendRevokeTx.setDisabled(True) self.cboReason.setDisabled(True) self.btnClose.show() url = self.app_config.get_block_explorer_tx() if url: url = url.replace('%TXID%', upd_tx_hash) upd_tx_hash = f'<a href="{url}">{upd_tx_hash}</a>' msg = 'The revoke transaction has been successfully sent. ' \ f'Tx hash: {upd_tx_hash}. <br><br>' \ f'The new values will be visible on the network after the transaction is confirmed, i.e. in ' \ f'about 2.5 minutes.' WndUtils.info_msg(msg) except Exception as e: if str(e).find('protx-dup') >= 0: WndUtils.error_msg( 'The previous protx transaction has not been confirmed yet. Wait until it is ' 'confirmed before sending a new transaction.') else: logging.error( 'Exception occurred while sending protx revoke: ' + str(e)) WndUtils.error_msg(str(e))
def send_upd_tx(self): # verify the owner key used in the configuration if self.masternode.dmn_owner_key_type == InputKeyType.PRIVATE and self.masternode.dmn_owner_private_key: owner_address = wif_privkey_to_address( self.masternode.dmn_owner_private_key, self.app_config.dash_network) if owner_address != self.dmn_owner_address: raise Exception( 'Inconsistency of the owner key between the app configuration and the data ' 'on the Dash network.') else: raise Exception( 'To use this feature, you need to have the owner private key in your masternode ' 'configuration.') try: funding_address = '' params = [ 'update_registrar', self.dmn_protx_hash, self.dmn_new_operator_pubkey, self.dmn_new_voting_address, self.dmn_new_payout_address, funding_address ] try: upd_reg_support = self.dashd_intf.checkfeaturesupport( 'protx_update_registrar', self.app_config.app_version) if not upd_reg_support.get('enabled'): if upd_reg_support.get('message'): raise Exception(upd_reg_support.get('message')) else: raise Exception( 'The \'protx_update_registrar\' function is not supported by the RPC node ' 'you are connected to.') public_proxy_node = True active = self.app_config.feature_update_registrar_automatic.get_value( ) if not active: msg = self.app_config.feature_update_registrar_automatic.get_message( ) if not msg: msg = 'The functionality of the automatic execution of the update_registrar command on the ' \ '"public" RPC nodes is inactive. Use the manual method or contact the program author ' \ 'for details.' raise Exception(msg) except JSONRPCException as e: public_proxy_node = False if not public_proxy_node: try: # find an address to be used as the source of the transaction fees min_fee = round(1024 * FEE_DUFF_PER_BYTE / 1e8, 8) balances = self.dashd_intf.listaddressbalances(min_fee) bal_list = [] for addr in balances: bal_list.append({ 'address': addr, 'amount': balances[addr] }) bal_list.sort(key=lambda x: x['amount']) if not bal_list: raise Exception( "No address can be found in the node's wallet with sufficient funds to " "cover the transaction fees.") params[5] = bal_list[0]['address'] except JSONRPCException as e: logging.warning( "Couldn't list the node address balances. We assume you are using a " "public RPC node and the funding address for the transaction fee will " "be estimated during the `update_registrar` call") else: params.append(self.masternode.dmn_owner_private_key) upd_tx_hash = self.dashd_intf.rpc_call(True, False, 'protx', *params) if upd_tx_hash: logging.info( 'update_registrar successfully executed, tx hash: ' + upd_tx_hash) changed = False if self.dmn_new_voting_address != self.dmn_prev_voting_address: changed = self.masternode.dmn_voting_key_type != self.dmn_voting_key_type self.masternode.dmn_voting_key_type = self.dmn_voting_key_type if self.dmn_voting_key_type == InputKeyType.PRIVATE: changed = changed or self.masternode.dmn_voting_private_key != self.dmn_new_voting_privkey self.masternode.dmn_voting_private_key = self.dmn_new_voting_privkey else: changed = changed or self.masternode.dmn_voting_address != self.dmn_new_voting_address self.masternode.dmn_voting_address = self.dmn_new_voting_address if self.dmn_new_operator_pubkey != self.dmn_prev_operator_pubkey: changed = changed or self.masternode.dmn_operator_key_type != self.dmn_operator_key_type self.masternode.dmn_operator_key_type = self.dmn_operator_key_type if self.dmn_operator_key_type == InputKeyType.PRIVATE: changed = changed or self.masternode.dmn_operator_private_key != self.dmn_new_operator_privkey self.masternode.dmn_operator_private_key = self.dmn_new_operator_privkey else: changed = changed or self.masternode.dmn_operator_public_key != self.dmn_new_operator_pubkey self.masternode.dmn_operator_public_key = self.dmn_new_operator_pubkey if self.on_upd_success_callback: self.on_upd_success_callback(self.masternode) self.btnSendUpdateTx.setDisabled(True) self.edtPayoutAddress.setReadOnly(True) self.edtOperatorKey.setReadOnly(True) self.edtVotingKey.setReadOnly(True) self.btnGenerateOperatorKey.setDisabled(True) self.btnGenerateVotingKey.setDisabled(True) self.btnClose.show() url = self.app_config.get_block_explorer_tx() if url: url = url.replace('%TXID%', upd_tx_hash) upd_tx_hash = f'<a href="{url}">{upd_tx_hash}</a>' msg = 'The update_registrar transaction has been successfully sent. ' \ f'Tx hash: {upd_tx_hash}. <br><br>' \ f'The new values will be visible on the network after the transaction is confirmed, i.e. in ' \ f'about 2.5 minutes.' if changed: msg += '<br><br>The app configuration has been updated accordingly.' WndUtils.info_msg(msg) except Exception as e: if str(e).find('protx-dup') >= 0: WndUtils.error_msg( 'The previous protx transaction has not been confirmed yet. Wait until it is ' 'confirmed before sending a new transaction.') else: logging.error( 'Exception occurred while sending protx update_registrar.') WndUtils.error_msg(str(e))