From d6e3b11026d24513d6022ecd8a6faf2120831f57 Mon Sep 17 00:00:00 2001 From: Jack Robison Date: Tue, 28 Nov 2017 11:00:17 -0500 Subject: [PATCH 01/10] add claim_renew --- CHANGELOG.md | 1 + lbrynet/core/Wallet.py | 12 ++++++++++++ lbrynet/daemon/Daemon.py | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3f7022a7..9846019ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ at anytime. ### Added * Added `channel_import` and `channel_export` commands * Added `is_mine` field to `channel_list` results + * Added `claim_renew` command ### Removed * Removed claim related filter arguments `name`, `claim_id`, and `outpoint` from `file_list`, `file_delete`, `file_set_status`, and `file_reflect` diff --git a/lbrynet/core/Wallet.py b/lbrynet/core/Wallet.py index 5f2f20ac1..10908d0f8 100644 --- a/lbrynet/core/Wallet.py +++ b/lbrynet/core/Wallet.py @@ -1132,6 +1132,12 @@ class Wallet(object): def _get_values_for_uris(self, page, page_size, *uris): return defer.fail(NotImplementedError()) + def _claim_renew_all_before_expiration(self, height): + return defer.fail(NotImplementedError()) + + def _claim_renew(self, txid, nout): + return defer.fail(NotImplementedError()) + def send_claim_to_address(self, claim_id, destination, amount): return defer.fail(NotImplementedError()) @@ -1512,6 +1518,12 @@ class LBRYumWallet(Wallet): def get_certificates_for_signing(self): return self._run_cmd_as_defer_succeed('getcertificatesforsigning') + def _claim_renew_all_before_expiration(self, height): + return self._run_cmd_as_defer_succeed('renewclaimsbeforeexpiration', height) + + def _claim_renew(self, txid, nout): + return self._run_cmd_as_defer_succeed('listunspent') + # TODO: get rid of this function. lbryum should take care of it def _save_wallet(self, val=None): self.wallet.storage.write() diff --git a/lbrynet/daemon/Daemon.py b/lbrynet/daemon/Daemon.py index f01bb524c..55630c6ad 100644 --- a/lbrynet/daemon/Daemon.py +++ b/lbrynet/daemon/Daemon.py @@ -1993,6 +1993,40 @@ class Daemon(AuthJSONRPCServer): self.analytics_manager.send_claim_action('new_support') defer.returnValue(result) + @AuthJSONRPCServer.auth_required + @defer.inlineCallbacks + def jsonrpc_claim_renew(self, outpoint=None, height=None): + """ + Renew claim(s) or support(s) + + Usage: + claim_renew ( | --outpoint=) | ( | --height=) + + Return: + (dict) Dictionary containing result of the claim/support renewals + { + 'tx' : (str) hex encoded transaction + 'txid' : (str) txid of resulting claim + 'nout' : (int) nout of the resulting claim + 'fee' : (float) fee paid for the claim transaction + 'claim_id' : (str) claim ID of the resulting claim + } + """ + + if outpoint is None and height is None: + raise Exception("must provide an outpoint or a height") + elif outpoint is not None: + if len(outpoint.split(":")) == 2: + txid, nout = outpoint.split(":") + nout = int(nout) + else: + raise Exception("invalid outpoint") + result = yield self.session.wallet.claim_renew(txid, nout) + else: + height = int(height) + result = yield self.session.wallet.claim_renew_all_before_expiration(height) + defer.returnValue(result) + @AuthJSONRPCServer.auth_required @defer.inlineCallbacks def jsonrpc_claim_send_to_address(self, claim_id, address, amount=None): From 1ea8c1ad29cb6dee4a8efbea82d776cf3cb1be52 Mon Sep 17 00:00:00 2001 From: Kay Kurokawa Date: Tue, 28 Nov 2017 13:46:08 -0500 Subject: [PATCH 02/10] no underscore necessary (not a private function) --- lbrynet/core/Wallet.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lbrynet/core/Wallet.py b/lbrynet/core/Wallet.py index 10908d0f8..b8a3fd2b9 100644 --- a/lbrynet/core/Wallet.py +++ b/lbrynet/core/Wallet.py @@ -1132,10 +1132,10 @@ class Wallet(object): def _get_values_for_uris(self, page, page_size, *uris): return defer.fail(NotImplementedError()) - def _claim_renew_all_before_expiration(self, height): + def claim_renew_all_before_expiration(self, height): return defer.fail(NotImplementedError()) - def _claim_renew(self, txid, nout): + def claim_renew(self, txid, nout): return defer.fail(NotImplementedError()) def send_claim_to_address(self, claim_id, destination, amount): @@ -1518,10 +1518,10 @@ class LBRYumWallet(Wallet): def get_certificates_for_signing(self): return self._run_cmd_as_defer_succeed('getcertificatesforsigning') - def _claim_renew_all_before_expiration(self, height): + def claim_renew_all_before_expiration(self, height): return self._run_cmd_as_defer_succeed('renewclaimsbeforeexpiration', height) - def _claim_renew(self, txid, nout): + def claim_renew(self, txid, nout): return self._run_cmd_as_defer_succeed('listunspent') # TODO: get rid of this function. lbryum should take care of it From e4e60ebe9b40c0f311de99181806892707bff729 Mon Sep 17 00:00:00 2001 From: Kay Kurokawa Date: Tue, 28 Nov 2017 13:47:44 -0500 Subject: [PATCH 03/10] add auto_renew_claim_height_delta to configuration and auto renew after startup if necessary --- lbrynet/conf.py | 4 ++++ lbrynet/daemon/Daemon.py | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/lbrynet/conf.py b/lbrynet/conf.py index cc290a3bf..9c016a98c 100644 --- a/lbrynet/conf.py +++ b/lbrynet/conf.py @@ -242,6 +242,10 @@ ADJUSTABLE_SETTINGS = { # all of your credits. 'api_host': (str, 'localhost'), 'api_port': (int, 5279), + # claims set to expire within this many blocks will be + # automatically renewed after startup (if set to 0, renews + # will not be made automatically) + 'auto_renew_claim_height_delta': (int, 0), 'cache_time': (int, 150), 'data_dir': (str, default_data_dir), 'data_rate': (float, .0001), # points/megabyte diff --git a/lbrynet/daemon/Daemon.py b/lbrynet/daemon/Daemon.py index 55630c6ad..048065c71 100644 --- a/lbrynet/daemon/Daemon.py +++ b/lbrynet/daemon/Daemon.py @@ -188,6 +188,8 @@ class Daemon(AuthJSONRPCServer): self.reflector_port = conf.settings['reflector_port'] self.dht_node_port = conf.settings['dht_node_port'] self.use_upnp = conf.settings['use_upnp'] + self.auto_renew_claim_height_delta = conf.settings['auto_renew_claim_height_delta'] + self.startup_status = STARTUP_STAGES[0] self.connected_to_internet = True @@ -255,6 +257,7 @@ class Daemon(AuthJSONRPCServer): yield self._setup_server() log.info("Starting balance: " + str(self.session.wallet.get_balance())) yield _announce_startup() + self._auto_renew() def _get_platform(self): if self.platform is None: @@ -290,6 +293,23 @@ class Daemon(AuthJSONRPCServer): if not self.connected_to_internet: self.connection_status_code = CONNECTION_STATUS_NETWORK + @defer.inlineCallbacks + def _auto_renew(self): + # automatically renew claims + # auto renew is turned off if 0 or some negative number + if self.auto_renew_claim_height_delta < 1: + return + log.debug("Renewing claim") + h = self.session.wallet.network.get_local_height() + self.auto_renew_claim_height_delta + results = yield self.session.wallet.claim_renew_all_before_expiration(h) + for outpoint, result in results.iteritems(): + if result['success']: + log.info("Renewed claim at outpoint:%s claim ID:%s, paid fee:%s", + outpoint, result['claim_id'], result['fee']) + else: + log.info("Failed to renew claim at outpoint:%s, reason:%s", + outpoint, result['reason']) + def _start_server(self): if self.peer_port is not None: server_factory = ServerProtocolFactory(self.session.rate_limiter, From 36510a0a599a2c2647aabecf02ef7e5ea99543d7 Mon Sep 17 00:00:00 2001 From: Kay Kurokawa Date: Tue, 28 Nov 2017 13:48:17 -0500 Subject: [PATCH 04/10] make auto_renew_claim_height_delta settable in API commands settings_set --- lbrynet/daemon/Daemon.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lbrynet/daemon/Daemon.py b/lbrynet/daemon/Daemon.py index 048065c71..66f82605b 100644 --- a/lbrynet/daemon/Daemon.py +++ b/lbrynet/daemon/Daemon.py @@ -456,6 +456,7 @@ class Daemon(AuthJSONRPCServer): 'disable_max_key_fee': bool, 'peer_search_timeout': int, 'sd_download_timeout': int, + 'auto_renew_claim_height_delta': int } for key, setting_type in setting_types.iteritems(): @@ -1152,6 +1153,7 @@ class Daemon(AuthJSONRPCServer): [ | --share_usage_data=] [ | --peer_search_timeout=] [ | --sd_download_timeout=] + [ | --auto_renew_claim_height_delta=, --download_directory= : (str) @@ -1176,6 +1178,11 @@ class Daemon(AuthJSONRPCServer): , --share_usage_data= : (bool), True , --peer_search_timeout= : (int), 3 , --sd_download_timeout= : (int), 3 + , --auto_renew_claim_height_delta= : (int), 0 + claims set to expire within this many blocks will be + automatically renewed after startup (if set to 0, renews + will not be made automatically) + Returns: (dict) Updated dictionary of daemon settings From 8f05c1083f1766531072e0b5f2d498b6129ef18a Mon Sep 17 00:00:00 2001 From: Kay Kurokawa Date: Tue, 28 Nov 2017 23:00:22 -0500 Subject: [PATCH 05/10] pylint long lines --- lbrynet/daemon/Daemon.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lbrynet/daemon/Daemon.py b/lbrynet/daemon/Daemon.py index 66f82605b..f3d694244 100644 --- a/lbrynet/daemon/Daemon.py +++ b/lbrynet/daemon/Daemon.py @@ -1153,7 +1153,8 @@ class Daemon(AuthJSONRPCServer): [ | --share_usage_data=] [ | --peer_search_timeout=] [ | --sd_download_timeout=] - [ | --auto_renew_claim_height_delta= + | --auto_renew_claim_height_delta=, --download_directory= : (str) @@ -1178,7 +1179,8 @@ class Daemon(AuthJSONRPCServer): , --share_usage_data= : (bool), True , --peer_search_timeout= : (int), 3 , --sd_download_timeout= : (int), 3 - , --auto_renew_claim_height_delta= : (int), 0 + , + --auto_renew_claim_height_delta= : (int), 0 claims set to expire within this many blocks will be automatically renewed after startup (if set to 0, renews will not be made automatically) From bf29d28c4d15f2920f46feb3154a3e325f19e04c Mon Sep 17 00:00:00 2001 From: Kay Kurokawa Date: Wed, 29 Nov 2017 11:46:20 -0500 Subject: [PATCH 06/10] bug fix in claim_renew() --- lbrynet/core/Wallet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lbrynet/core/Wallet.py b/lbrynet/core/Wallet.py index b8a3fd2b9..e98d8d382 100644 --- a/lbrynet/core/Wallet.py +++ b/lbrynet/core/Wallet.py @@ -1522,7 +1522,7 @@ class LBRYumWallet(Wallet): return self._run_cmd_as_defer_succeed('renewclaimsbeforeexpiration', height) def claim_renew(self, txid, nout): - return self._run_cmd_as_defer_succeed('listunspent') + return self._run_cmd_as_defer_succeed('renewclaim', txid, nout) # TODO: get rid of this function. lbryum should take care of it def _save_wallet(self, val=None): From 707775214a4b79cb1a74a41347d37b3f2ae5609b Mon Sep 17 00:00:00 2001 From: Kay Kurokawa Date: Wed, 29 Nov 2017 12:16:51 -0500 Subject: [PATCH 07/10] update docstrings and make sure return value is consistent --- lbrynet/daemon/Daemon.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lbrynet/daemon/Daemon.py b/lbrynet/daemon/Daemon.py index f3d694244..9931d045b 100644 --- a/lbrynet/daemon/Daemon.py +++ b/lbrynet/daemon/Daemon.py @@ -2032,13 +2032,17 @@ class Daemon(AuthJSONRPCServer): claim_renew ( | --outpoint=) | ( | --height=) Return: - (dict) Dictionary containing result of the claim/support renewals + (dict) Dictionary where key is the the original claim's outpoint and + value is the result of the renewal { - 'tx' : (str) hex encoded transaction - 'txid' : (str) txid of resulting claim - 'nout' : (int) nout of the resulting claim - 'fee' : (float) fee paid for the claim transaction - 'claim_id' : (str) claim ID of the resulting claim + outpoint:{ + + 'tx' : (str) hex encoded transaction + 'txid' : (str) txid of resulting claim + 'nout' : (int) nout of the resulting claim + 'fee' : (float) fee paid for the claim transaction + 'claim_id' : (str) claim ID of the resulting claim + }, } """ @@ -2051,6 +2055,7 @@ class Daemon(AuthJSONRPCServer): else: raise Exception("invalid outpoint") result = yield self.session.wallet.claim_renew(txid, nout) + result = {outpoint:result} else: height = int(height) result = yield self.session.wallet.claim_renew_all_before_expiration(height) From bfbecd919657a458e4af9c75a5b6be3ffd6586ec Mon Sep 17 00:00:00 2001 From: Kay Kurokawa Date: Mon, 4 Dec 2017 16:01:19 -0500 Subject: [PATCH 08/10] fix use of return in inlinecallback, change to defer.returnValue(None) --- lbrynet/daemon/Daemon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lbrynet/daemon/Daemon.py b/lbrynet/daemon/Daemon.py index 9931d045b..ebd6fb94a 100644 --- a/lbrynet/daemon/Daemon.py +++ b/lbrynet/daemon/Daemon.py @@ -298,7 +298,7 @@ class Daemon(AuthJSONRPCServer): # automatically renew claims # auto renew is turned off if 0 or some negative number if self.auto_renew_claim_height_delta < 1: - return + defer.returnValue(None) log.debug("Renewing claim") h = self.session.wallet.network.get_local_height() + self.auto_renew_claim_height_delta results = yield self.session.wallet.claim_renew_all_before_expiration(h) From 7e93ea8d9771d0ebd435a89750c20f2b261c4b88 Mon Sep 17 00:00:00 2001 From: Kay Kurokawa Date: Mon, 4 Dec 2017 17:16:59 -0500 Subject: [PATCH 09/10] do a sanity check to see if we have remote height, use remote height instead of local height when auto renewing --- lbrynet/daemon/Daemon.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lbrynet/daemon/Daemon.py b/lbrynet/daemon/Daemon.py index ebd6fb94a..060fe9777 100644 --- a/lbrynet/daemon/Daemon.py +++ b/lbrynet/daemon/Daemon.py @@ -299,8 +299,11 @@ class Daemon(AuthJSONRPCServer): # auto renew is turned off if 0 or some negative number if self.auto_renew_claim_height_delta < 1: defer.returnValue(None) + if not self.session.wallet.network.get_remote_height(): + log.warning("Failed to get remote height, aborting auto renew") + defer.returnValue(None) log.debug("Renewing claim") - h = self.session.wallet.network.get_local_height() + self.auto_renew_claim_height_delta + h = self.session.wallet.network.get_remote_height() + self.auto_renew_claim_height_delta results = yield self.session.wallet.claim_renew_all_before_expiration(h) for outpoint, result in results.iteritems(): if result['success']: From 23b7c5448b1c6c84e7eda283e2cf49e25c0ddfc6 Mon Sep 17 00:00:00 2001 From: Jack Robison Date: Tue, 5 Dec 2017 09:42:44 -0500 Subject: [PATCH 10/10] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9846019ef..272a1dc71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ at anytime. * Added `channel_import` and `channel_export` commands * Added `is_mine` field to `channel_list` results * Added `claim_renew` command + * Added user configurable `auto_renew_claim_height_delta` setting, defaults to 0 (off) ### Removed * Removed claim related filter arguments `name`, `claim_id`, and `outpoint` from `file_list`, `file_delete`, `file_set_status`, and `file_reflect`