Skip to content

Commit

Permalink
Support for update service
Browse files Browse the repository at this point in the history
Support for revoke operator
Ability of the explicit setting if the particular rpc will be rsa-encrypted
or not (given that the node supports it)
  • Loading branch information
Bertrand256 committed May 24, 2019
1 parent 3e4e3c3 commit 8d2e3fd
Show file tree
Hide file tree
Showing 19 changed files with 1,466 additions and 336 deletions.
22 changes: 19 additions & 3 deletions src/app_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ def __init__(self):
self._dash_blockchain_info = {}
self.feature_register_dmn_automatic = AppFeatueStatus(True, 0, '')
self.feature_update_registrar_automatic = AppFeatueStatus(True, 0, '')
self.feature_update_service_automatic = AppFeatueStatus(True, 0, '')
self.feature_revoke_operator_automatic = AppFeatueStatus(True, 0, '')

self.hw_type = None # TREZOR, KEEPKEY, LEDGERNANOS
self.hw_keepkey_psw_encoding = 'NFC' # Keepkey passphrase UTF8 chars encoding:
Expand Down Expand Up @@ -382,15 +384,27 @@ def close(self):

def save_cache_settings(self):
if self.feature_register_dmn_automatic.get_value() is not None:
app_cache.set_value('FEATURE_REGISTER_DMN_AUTOMATIC_' + self.dash_network, self.feature_register_dmn_automatic.get_value())
app_cache.set_value('FEATURE_REGISTER_DMN_AUTOMATIC_' + self.dash_network,
self.feature_register_dmn_automatic.get_value())
if self.feature_update_registrar_automatic.get_value() is not None:
app_cache.set_value('FEATURE_UPDATE_AUTOMATIC_REGISTRAR_' + self.dash_network, self.feature_update_registrar_automatic.get_value())
app_cache.set_value('FEATURE_UPDATE_REGISTRAR_AUTOMATIC_' + self.dash_network,
self.feature_update_registrar_automatic.get_value())
if self.feature_update_service_automatic.get_value() is not None:
app_cache.set_value('FEATURE_UPDATE_SERVICE_AUTOMATIC_' + self.dash_network,
self.feature_update_service_automatic.get_value())
if self.feature_revoke_operator_automatic.get_value() is not None:
app_cache.set_value('FEATURE_REVOKE_OPERATOR_AUTOMATIC_' + self.dash_network,
self.feature_revoke_operator_automatic.get_value())

def restore_cache_settings(self):
ena = app_cache.get_value('FEATURE_REGISTER_AUTOMATIC_DMN_' + self.dash_network, True, bool)
self.feature_register_dmn_automatic.set_value(ena, AppFeatueStatus.PRIORITY_APP_CACHE)
ena = app_cache.get_value('FEATURE_UPDATE_AUTOMATIC_REGISTRAR_' + self.dash_network, True, bool)
ena = app_cache.get_value('FEATURE_UPDATE_REGISTRAR_AUTOMATIC_' + self.dash_network, True, bool)
self.feature_update_registrar_automatic.set_value(ena, AppFeatueStatus.PRIORITY_APP_CACHE)
ena = app_cache.get_value('FEATURE_UPDATE_SERVICE_AUTOMATIC_' + self.dash_network, True, bool)
self.feature_update_service_automatic.set_value(ena, AppFeatueStatus.PRIORITY_APP_CACHE)
ena = app_cache.get_value('FEATURE_REVOKE_OPERATOR_AUTOMATIC_' + self.dash_network, True, bool)
self.feature_revoke_operator_automatic.set_value(ena, AppFeatueStatus.PRIORITY_APP_CACHE)

def copy_from(self, src_config):
self.dash_network = src_config.dash_network
Expand Down Expand Up @@ -1000,6 +1014,8 @@ def get_feature_config_remote(symbol) -> Tuple[Optional[bool], Optional[int], Op
if self._remote_app_params:
self.feature_register_dmn_automatic.set_value(*get_feature_config_remote('REGISTER_DMN_AUTOMATIC'))
self.feature_update_registrar_automatic.set_value(*get_feature_config_remote('UPDATE_REGISTRAR_AUTOMATIC'))
self.feature_update_service_automatic.set_value(*get_feature_config_remote('UPDATE_SERVICE_AUTOMATIC'))
self.feature_revoke_operator_automatic.set_value(*get_feature_config_remote('REVOKE_OPERATOR_AUTOMATIC'))

def read_dash_network_app_params(self, dashd_intf):
""" Read parameters having impact on the app's behavior (sporks/dips) from the Dash network. Called
Expand Down
2 changes: 1 addition & 1 deletion src/cmd_console_dlg.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ def set_log_format(self, format_string: str):

def rpc_command(self, command: str, *args):
if self.main_dlg.dashd_intf:
ret = self.main_dlg.dashd_intf.rpc_call(command, *args)
ret = self.main_dlg.dashd_intf.rpc_call(False, True, command, *args)
try:
if isinstance(ret, str):
ret = json.loads(ret)
Expand Down
6 changes: 5 additions & 1 deletion src/config_dlg.py
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,11 @@ def on_btnTestConnection_clicked(self):
try:
info = dashd_intf.getinfo(verify_node=True)
if info:
ret = dashd_intf.rpc_call_enc(True, "checkfeaturesupport", "enhanced_proxy")
try:
ret = dashd_intf.rpc_call(True, False, "checkfeaturesupport", "enhanced_proxy")
except Exception as e:
ret = None

if ret and type(ret) is dict:
self.infoMsg('Connection successful.\n\n'
'Additional info: this node supports message encryption.')
Expand Down
99 changes: 66 additions & 33 deletions src/dashd_intf.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ def __init__(self, parent_exception):
'Changing these parameters requires to execute dashd with "-reindex" option (linux: ./dashd -reindex)'


def control_rpc_call(_func=None, *, encrypt=False):
def control_rpc_call(_func=None, *, encrypt_rpc_arguments=False, allow_switching_conns=True):
"""
Decorator dedicated to functions related to RPC calls, taking care of switching an active connection if the
current one becomes faulty. It also performs argument encryption for configured RPC calls.
Expand All @@ -383,7 +383,7 @@ def catch_timeout_wrapper(*args, **kwargs):
for try_nr in range(1, 5):
try:
try:
if encrypt:
if encrypt_rpc_arguments:
if self.cur_conn_def:
pubkey = self.cur_conn_def.get_rpc_encryption_pubkey_object()
else:
Expand Down Expand Up @@ -436,11 +436,10 @@ def catch_timeout_wrapper(*args, **kwargs):
except JSONRPCException as e:
log.error('Error while calling of "' + str(func) + ' (2)". Details: ' + str(e))
err_message = e.error.get('message','').lower()
self.http_conn.close()
if e.code == -5 and e.message == 'No information available for address':
raise DashdIndexException(e)
elif err_message.find('403 forbidden') >= 0 or err_message.find('401 unauthorized') >= 0 or \
err_message.find('502 bad gateway') >= 0 or err_message.find('unknown error') >= 0:
self.http_conn.close()
elif err_message.find('502 bad gateway') >= 0 or err_message.find('unknown error') >= 0:
raise DashdConnectionError(e)
else:
raise
Expand All @@ -449,7 +448,7 @@ def catch_timeout_wrapper(*args, **kwargs):
# try another net config if possible
log.error('Error while calling of "' + str(func) + '" (4). Details: ' + str(e))

if not self.switch_to_next_config():
if not allow_switching_conns or not self.switch_to_next_config():
self.last_error_message = str(e.org_exception)
raise e.org_exception # couldn't use another conn config, raise last exception
else:
Expand Down Expand Up @@ -552,7 +551,6 @@ def __init__(self, window,
self.connections = []
self.cur_conn_index = 0
self.cur_conn_def: Optional['DashNetworkConnectionCfg'] = None
self.conf_switch_locked = False

# below is the connection with which particular RPC call has started; if connection is switched because of
# problems with some nodes, switching stops if we close round and return to the starting connection
Expand All @@ -574,6 +572,7 @@ def __init__(self, window,
self.on_connection_successful_callback = on_connection_successful_callback
self.on_connection_disconnected_callback = on_connection_disconnected_callback
self.last_error_message = None
self.mempool_txes:Dict[str, Dict] = {}
self.http_lock = threading.RLock()

def initialize(self, config: AppConfig, connection=None, for_testing_connections_only=False):
Expand Down Expand Up @@ -686,9 +685,6 @@ def switch_to_next_config(self):
with current connection config.
:return: True if successfully switched or False if there was no another config
"""
if self.conf_switch_locked:
return False

if self.cur_conn_def:
self.config.conn_cfg_failure(self.cur_conn_def) # mark connection as defective
if self.cur_conn_index < len(self.connections)-1:
Expand All @@ -710,12 +706,6 @@ def switch_to_next_config(self):
log.warning('Failed to connect: no another connection configurations.')
return False

def enable_conf_switching(self):
self.conf_switch_locked = True

def disable_conf_switching(self):
self.conf_switch_locked = False

def mark_cur_conn_cfg_is_ok(self):
if self.cur_conn_def:
self.config.conn_cfg_success(self.cur_conn_def)
Expand Down Expand Up @@ -909,12 +899,15 @@ def getinfo(self, verify_node: bool = True):
@control_rpc_call
def issynchronized(self):
if self.open():
# if connecting to HTTP(S) proxy do not check if dash daemon is synchronized
if self.cur_conn_def.is_http_proxy():
return True
else:
try:
syn = self.proxy.mnsync('status')
return syn.get('IsSynced')
except JSONRPCException as e:
if str(e).lower().find('403 forbidden') >= 0:
self.http_conn.close()
return True
else:
raise
else:
raise Exception('Not connected')

Expand Down Expand Up @@ -951,7 +944,8 @@ def read_protx_list(self):
'registered_height': s.get('registeredHeight'),
'pose_pelanlty': s.get('PoSePenalty'),
'pose_received_height': s.get('PoSeRevivedHeight'),
'pose_ban_height': s.get('PoSeBanHeight')
'pose_ban_height': s.get('PoSeBanHeight'),
'pose_revived_height': s.get('PoSeRevivedHeight', 0)
}
self.protx_by_mn_ident[ident] = p
return self.protx_by_mn_ident
Expand All @@ -964,10 +958,15 @@ def update_mn_queue_values(self):
payment_queue = []
for mn in self.masternodes:
if mn.status == 'ENABLED':
protx = self.protx_by_mn_ident.get(mn.ident)

if mn.lastpaidblock > 0:
mn.queue_position = mn.lastpaidblock
if protx:
pose_revived_height = protx.get('pose_revived_height', 0)
if pose_revived_height > 0:
mn.queue_position = pose_revived_height
else:
protx = self.protx_by_mn_ident.get(mn.ident)
if protx:
mn.queue_position = protx.get('registered_height')
else:
Expand Down Expand Up @@ -1140,6 +1139,23 @@ def getaddressmempool(self, addresses):
else:
raise Exception('Not connected')

@control_rpc_call
def getrawmempool(self):
if self.open():
cur_mempool_txes = self.proxy.getrawmempool()

txes_to_purge = []
for tx_hash in self.mempool_txes:
if tx_hash not in cur_mempool_txes:
txes_to_purge.append(tx_hash)

for tx_hash in txes_to_purge:
del self.mempool_txes[tx_hash]

return cur_mempool_txes
else:
raise Exception('Not connected')

@control_rpc_call
def getrawtransaction(self, txid, verbose, skip_cache=False):

Expand Down Expand Up @@ -1252,7 +1268,6 @@ def getaddresstxids(self, *args):
else:
raise Exception('Not connected')

@control_rpc_call(encrypt=True)
def protx(self, *args):
if self.open():
return self.proxy.protx(*args)
Expand All @@ -1266,21 +1281,15 @@ def spork(self, *args):
else:
raise Exception('Not connected')

@control_rpc_call
def rpc_call(self, command, *args):
if self.open():
c = self.proxy.__getattr__(command)
return c(*args)
else:
raise Exception('Not connected')

def rpc_call_enc(self, encrypt, command, *args):
def rpc_call(self, encrypt_rpc_arguments: bool, allow_switching_conns: bool, command: str, *args):
def call_command(self, *args):
c = self.proxy.__getattr__(command)
return c(*args)

if self.open():
fun = control_rpc_call(call_command, encrypt=encrypt)
call_command.__setattr__('__name__', command)
fun = control_rpc_call(call_command, encrypt_rpc_arguments=encrypt_rpc_arguments,
allow_switching_conns=allow_switching_conns)
c = fun(self, *args)
return c
else:
Expand All @@ -1307,4 +1316,28 @@ def checkfeaturesupport(self, feature_name: str, dmt_version: str, *args) -> Dic
else:
raise Exception('Not connected')

def is_protx_update_pending(self, proregtx_hash:str) -> bool:
"""
Check whether a protx transaction related to the proregtx passed as an argument exists in mempool.
:param protx_hash: Hash of the ProRegTx transaction
:return:
"""

try:
cur_mempool_txes = self.getrawmempool()
for tx_hash in cur_mempool_txes:
tx = self.mempool_txes.get(tx_hash)
if not tx:
tx = self.getrawtransaction(tx_hash, True, skip_cache=True)
self.mempool_txes[tx_hash] = tx
protx = tx.get('proUpRegTx')
if not protx:
protx = tx.get('proUpRevTx')
if not protx:
protx = tx.get('proUpServTx')
if protx and protx.get('proTxHash') == proregtx_hash:
return True
return False
except Exception as e:
return False

Loading

0 comments on commit 8d2e3fd

Please sign in to comment.