prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  HTTPS cert expired on LabelSync server
  The cert on https://sync.bytesized-hosting.com:9090/ has expired and the LabelSync plugin stopped working 
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `plugins/labels/labels.py`
  Content:
  ```
  1 import hashlib
  2 import requests
  3 import threading
  4 import json
  5 import sys
  6 import traceback
  7 
  8 import aes
  9 import base64
  10 
  11 import electrum
  12 from electrum.plugins import BasePlugin, hook
  13 from electrum.i18n import _
  14 
  15 
  16 
  17 
  18 class LabelsPlugin(BasePlugin):
  19 
  20     def __init__(self, parent, config, name):
  21         BasePlugin.__init__(self, parent, config, name)
  22         self.target_host = 'sync.bytesized-hosting.com:9090'
  23         self.wallets = {}
  24 
  25     def encode(self, wallet, msg):
  26         password, iv, wallet_id = self.wallets[wallet]
  27         encrypted = electrum.bitcoin.aes_encrypt_with_iv(password, iv,
  28                                                          msg.encode('utf8'))
  29         return base64.b64encode(encrypted)
  30 
  31     def decode(self, wallet, message):
  32         password, iv, wallet_id = self.wallets[wallet]
  33         decoded = base64.b64decode(message)
  34         decrypted = electrum.bitcoin.aes_decrypt_with_iv(password, iv, decoded)
  35         return decrypted.decode('utf8')
  36 
  37     def get_nonce(self, wallet):
  38         # nonce is the nonce to be used with the next change
  39         nonce = wallet.storage.get('wallet_nonce')
  40         if nonce is None:
  41             nonce = 1
  42             self.set_nonce(wallet, nonce)
  43         return nonce
  44 
  45     def set_nonce(self, wallet, nonce):
  46         self.print_error("set", wallet.basename(), "nonce to", nonce)
  47         wallet.storage.put("wallet_nonce", nonce)
  48 
  49     @hook
  50     def set_label(self, wallet, item, label):
  51         if not wallet in self.wallets:
  52             return
  53         nonce = self.get_nonce(wallet)
  54         wallet_id = self.wallets[wallet][2]
  55         bundle = {"walletId": wallet_id,
  56                   "walletNonce": nonce,
  57                   "externalId": self.encode(wallet, item),
  58                   "encryptedLabel": self.encode(wallet, label)}
  59         t = threading.Thread(target=self.do_request,
  60                              args=["POST", "/label", False, bundle])
  61         t.setDaemon(True)
  62         t.start()
  63         # Caller will write the wallet
  64         self.set_nonce(wallet, nonce + 1)
  65 
  66     def do_request(self, method, url = "/labels", is_batch=False, data=None):
  67         url = 'https://' + self.target_host + url
  68         kwargs = {'headers': {}}
  69         if method == 'GET' and data:
  70             kwargs['params'] = data
  71         elif method == 'POST' and data:
  72             kwargs['data'] = json.dumps(data)
  73             kwargs['headers']['Content-Type'] = 'application/json'
  74         response = requests.request(method, url, **kwargs)
  75         if response.status_code != 200:
  76             raise BaseException(response.status_code, response.text)
  77         response = response.json()
  78         if "error" in response:
  79             raise BaseException(response["error"])
  80         return response
  81 
  82     def push_thread(self, wallet):
  83         wallet_id = self.wallets[wallet][2]
  84         bundle = {"labels": [],
  85                   "walletId": wallet_id,
  86                   "walletNonce": self.get_nonce(wallet)}
  87         for key, value in wallet.labels.iteritems():
  88             try:
  89                 encoded_key = self.encode(wallet, key)
  90                 encoded_value = self.encode(wallet, value)
  91             except:
  92                 self.print_error('cannot encode', repr(key), repr(value))
  93                 continue
  94             bundle["labels"].append({'encryptedLabel': encoded_value,
  95                                      'externalId': encoded_key})
  96         self.do_request("POST", "/labels", True, bundle)
  97 
  98     def pull_thread(self, wallet, force):
  99         wallet_id = self.wallets[wallet][2]
  100         nonce = 1 if force else self.get_nonce(wallet) - 1
  101         self.print_error("asking for labels since nonce", nonce)
  102         try:
  103             response = self.do_request("GET", ("/labels/since/%d/for/%s" % (nonce, wallet_id) ))
  104             if response["labels"] is None:
  105                 self.print_error('no new labels')
  106                 return
  107             result = {}
  108             for label in response["labels"]:
  109                 try:
  110                     key = self.decode(wallet, label["externalId"])
  111                     value = self.decode(wallet, label["encryptedLabel"])
  112                 except:
  113                     continue
  114                 try:
  115                     json.dumps(key)
  116                     json.dumps(value)
  117                 except:
  118                     self.print_error('error: no json', key)
  119                     continue
  120                 result[key] = value
  121 
  122             for key, value in result.items():
  123                 if force or not wallet.labels.get(key):
  124                     wallet.labels[key] = value
  125 
  126             self.print_error("received %d labels" % len(response))
  127             # do not write to disk because we're in a daemon thread
  128             wallet.storage.put('labels', wallet.labels)
  129             self.set_nonce(wallet, response["nonce"] + 1)
  130             self.on_pulled(wallet)
  131 
  132         except Exception as e:
  133             traceback.print_exc(file=sys.stderr)
  134             self.print_error("could not retrieve labels")
  135 
  136     def start_wallet(self, wallet):
  137         nonce = self.get_nonce(wallet)
  138         self.print_error("wallet", wallet.basename(), "nonce is", nonce)
  139         mpk = wallet.get_fingerprint()
  140         if not mpk:
  141             return
  142         password = hashlib.sha1(mpk).digest().encode('hex')[:32]
  143         iv = hashlib.sha256(password).digest()[:16]
  144         wallet_id = hashlib.sha256(mpk).digest().encode('hex')
  145         self.wallets[wallet] = (password, iv, wallet_id)
  146         # If there is an auth token we can try to actually start syncing
  147         t = threading.Thread(target=self.pull_thread, args=(wallet, False))
  148         t.setDaemon(True)
  149         t.start()
  150 
  151     def stop_wallet(self, wallet):
  152         self.wallets.pop(wallet, None)
  153
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/plugins/labels/labels.py b/plugins/labels/labels.py
  --- a/plugins/labels/labels.py
  +++ b/plugins/labels/labels.py
  @@ -5,7 +5,6 @@
   import sys
   import traceback
   
  -import aes
   import base64
   
   import electrum
  @@ -19,7 +18,7 @@
   
       def __init__(self, parent, config, name):
           BasePlugin.__init__(self, parent, config, name)
  -        self.target_host = 'sync.bytesized-hosting.com:9090'
  +        self.target_host = 'labels.bauerj.eu'
           self.wallets = {}
   
       def encode(self, wallet, msg):
  
verification_info: {"golden_diff": "diff --git a/plugins/labels/labels.py b/plugins/labels/labels.py\n--- a/plugins/labels/labels.py\n+++ b/plugins/labels/labels.py\n@@ -5,7 +5,6 @@\n import sys\n import traceback\n \n-import aes\n import base64\n \n import electrum\n@@ -19,7 +18,7 @@\n \n     def __init__(self, parent, config, name):\n         BasePlugin.__init__(self, parent, config, name)\n-        self.target_host = 'sync.bytesized-hosting.com:9090'\n+        self.target_host = 'labels.bauerj.eu'\n         self.wallets = {}\n \n     def encode(self, wallet, msg):\n", "issue": "HTTPS cert expired on LabelSync server\nThe cert on https://sync.bytesized-hosting.com:9090/ has expired and the LabelSync plugin stopped working \n", "before_files": [{"content": "import hashlib\nimport requests\nimport threading\nimport json\nimport sys\nimport traceback\n\nimport aes\nimport base64\n\nimport electrum\nfrom electrum.plugins import BasePlugin, hook\nfrom electrum.i18n import _\n\n\n\n\nclass LabelsPlugin(BasePlugin):\n\n    def __init__(self, parent, config, name):\n        BasePlugin.__init__(self, parent, config, name)\n        self.target_host = 'sync.bytesized-hosting.com:9090'\n        self.wallets = {}\n\n    def encode(self, wallet, msg):\n        password, iv, wallet_id = self.wallets[wallet]\n        encrypted = electrum.bitcoin.aes_encrypt_with_iv(password, iv,\n                                                         msg.encode('utf8'))\n        return base64.b64encode(encrypted)\n\n    def decode(self, wallet, message):\n        password, iv, wallet_id = self.wallets[wallet]\n        decoded = base64.b64decode(message)\n        decrypted = electrum.bitcoin.aes_decrypt_with_iv(password, iv, decoded)\n        return decrypted.decode('utf8')\n\n    def get_nonce(self, wallet):\n        # nonce is the nonce to be used with the next change\n        nonce = wallet.storage.get('wallet_nonce')\n        if nonce is None:\n            nonce = 1\n            self.set_nonce(wallet, nonce)\n        return nonce\n\n    def set_nonce(self, wallet, nonce):\n        self.print_error(\"set\", wallet.basename(), \"nonce to\", nonce)\n        wallet.storage.put(\"wallet_nonce\", nonce)\n\n    @hook\n    def set_label(self, wallet, item, label):\n        if not wallet in self.wallets:\n            return\n        nonce = self.get_nonce(wallet)\n        wallet_id = self.wallets[wallet][2]\n        bundle = {\"walletId\": wallet_id,\n                  \"walletNonce\": nonce,\n                  \"externalId\": self.encode(wallet, item),\n                  \"encryptedLabel\": self.encode(wallet, label)}\n        t = threading.Thread(target=self.do_request,\n                             args=[\"POST\", \"/label\", False, bundle])\n        t.setDaemon(True)\n        t.start()\n        # Caller will write the wallet\n        self.set_nonce(wallet, nonce + 1)\n\n    def do_request(self, method, url = \"/labels\", is_batch=False, data=None):\n        url = 'https://' + self.target_host + url\n        kwargs = {'headers': {}}\n        if method == 'GET' and data:\n            kwargs['params'] = data\n        elif method == 'POST' and data:\n            kwargs['data'] = json.dumps(data)\n            kwargs['headers']['Content-Type'] = 'application/json'\n        response = requests.request(method, url, **kwargs)\n        if response.status_code != 200:\n            raise BaseException(response.status_code, response.text)\n        response = response.json()\n        if \"error\" in response:\n            raise BaseException(response[\"error\"])\n        return response\n\n    def push_thread(self, wallet):\n        wallet_id = self.wallets[wallet][2]\n        bundle = {\"labels\": [],\n                  \"walletId\": wallet_id,\n                  \"walletNonce\": self.get_nonce(wallet)}\n        for key, value in wallet.labels.iteritems():\n            try:\n                encoded_key = self.encode(wallet, key)\n                encoded_value = self.encode(wallet, value)\n            except:\n                self.print_error('cannot encode', repr(key), repr(value))\n                continue\n            bundle[\"labels\"].append({'encryptedLabel': encoded_value,\n                                     'externalId': encoded_key})\n        self.do_request(\"POST\", \"/labels\", True, bundle)\n\n    def pull_thread(self, wallet, force):\n        wallet_id = self.wallets[wallet][2]\n        nonce = 1 if force else self.get_nonce(wallet) - 1\n        self.print_error(\"asking for labels since nonce\", nonce)\n        try:\n            response = self.do_request(\"GET\", (\"/labels/since/%d/for/%s\" % (nonce, wallet_id) ))\n            if response[\"labels\"] is None:\n                self.print_error('no new labels')\n                return\n            result = {}\n            for label in response[\"labels\"]:\n                try:\n                    key = self.decode(wallet, label[\"externalId\"])\n                    value = self.decode(wallet, label[\"encryptedLabel\"])\n                except:\n                    continue\n                try:\n                    json.dumps(key)\n                    json.dumps(value)\n                except:\n                    self.print_error('error: no json', key)\n                    continue\n                result[key] = value\n\n            for key, value in result.items():\n                if force or not wallet.labels.get(key):\n                    wallet.labels[key] = value\n\n            self.print_error(\"received %d labels\" % len(response))\n            # do not write to disk because we're in a daemon thread\n            wallet.storage.put('labels', wallet.labels)\n            self.set_nonce(wallet, response[\"nonce\"] + 1)\n            self.on_pulled(wallet)\n\n        except Exception as e:\n            traceback.print_exc(file=sys.stderr)\n            self.print_error(\"could not retrieve labels\")\n\n    def start_wallet(self, wallet):\n        nonce = self.get_nonce(wallet)\n        self.print_error(\"wallet\", wallet.basename(), \"nonce is\", nonce)\n        mpk = wallet.get_fingerprint()\n        if not mpk:\n            return\n        password = hashlib.sha1(mpk).digest().encode('hex')[:32]\n        iv = hashlib.sha256(password).digest()[:16]\n        wallet_id = hashlib.sha256(mpk).digest().encode('hex')\n        self.wallets[wallet] = (password, iv, wallet_id)\n        # If there is an auth token we can try to actually start syncing\n        t = threading.Thread(target=self.pull_thread, args=(wallet, False))\n        t.setDaemon(True)\n        t.start()\n\n    def stop_wallet(self, wallet):\n        self.wallets.pop(wallet, None)\n", "path": "plugins/labels/labels.py"}], "after_files": [{"content": "import hashlib\nimport requests\nimport threading\nimport json\nimport sys\nimport traceback\n\nimport base64\n\nimport electrum\nfrom electrum.plugins import BasePlugin, hook\nfrom electrum.i18n import _\n\n\n\n\nclass LabelsPlugin(BasePlugin):\n\n    def __init__(self, parent, config, name):\n        BasePlugin.__init__(self, parent, config, name)\n        self.target_host = 'labels.bauerj.eu'\n        self.wallets = {}\n\n    def encode(self, wallet, msg):\n        password, iv, wallet_id = self.wallets[wallet]\n        encrypted = electrum.bitcoin.aes_encrypt_with_iv(password, iv,\n                                                         msg.encode('utf8'))\n        return base64.b64encode(encrypted)\n\n    def decode(self, wallet, message):\n        password, iv, wallet_id = self.wallets[wallet]\n        decoded = base64.b64decode(message)\n        decrypted = electrum.bitcoin.aes_decrypt_with_iv(password, iv, decoded)\n        return decrypted.decode('utf8')\n\n    def get_nonce(self, wallet):\n        # nonce is the nonce to be used with the next change\n        nonce = wallet.storage.get('wallet_nonce')\n        if nonce is None:\n            nonce = 1\n            self.set_nonce(wallet, nonce)\n        return nonce\n\n    def set_nonce(self, wallet, nonce):\n        self.print_error(\"set\", wallet.basename(), \"nonce to\", nonce)\n        wallet.storage.put(\"wallet_nonce\", nonce)\n\n    @hook\n    def set_label(self, wallet, item, label):\n        if not wallet in self.wallets:\n            return\n        nonce = self.get_nonce(wallet)\n        wallet_id = self.wallets[wallet][2]\n        bundle = {\"walletId\": wallet_id,\n                  \"walletNonce\": nonce,\n                  \"externalId\": self.encode(wallet, item),\n                  \"encryptedLabel\": self.encode(wallet, label)}\n        t = threading.Thread(target=self.do_request,\n                             args=[\"POST\", \"/label\", False, bundle])\n        t.setDaemon(True)\n        t.start()\n        # Caller will write the wallet\n        self.set_nonce(wallet, nonce + 1)\n\n    def do_request(self, method, url = \"/labels\", is_batch=False, data=None):\n        url = 'https://' + self.target_host + url\n        kwargs = {'headers': {}}\n        if method == 'GET' and data:\n            kwargs['params'] = data\n        elif method == 'POST' and data:\n            kwargs['data'] = json.dumps(data)\n            kwargs['headers']['Content-Type'] = 'application/json'\n        response = requests.request(method, url, **kwargs)\n        if response.status_code != 200:\n            raise BaseException(response.status_code, response.text)\n        response = response.json()\n        if \"error\" in response:\n            raise BaseException(response[\"error\"])\n        return response\n\n    def push_thread(self, wallet):\n        wallet_id = self.wallets[wallet][2]\n        bundle = {\"labels\": [],\n                  \"walletId\": wallet_id,\n                  \"walletNonce\": self.get_nonce(wallet)}\n        for key, value in wallet.labels.iteritems():\n            try:\n                encoded_key = self.encode(wallet, key)\n                encoded_value = self.encode(wallet, value)\n            except:\n                self.print_error('cannot encode', repr(key), repr(value))\n                continue\n            bundle[\"labels\"].append({'encryptedLabel': encoded_value,\n                                     'externalId': encoded_key})\n        self.do_request(\"POST\", \"/labels\", True, bundle)\n\n    def pull_thread(self, wallet, force):\n        wallet_id = self.wallets[wallet][2]\n        nonce = 1 if force else self.get_nonce(wallet) - 1\n        self.print_error(\"asking for labels since nonce\", nonce)\n        try:\n            response = self.do_request(\"GET\", (\"/labels/since/%d/for/%s\" % (nonce, wallet_id) ))\n            if response[\"labels\"] is None:\n                self.print_error('no new labels')\n                return\n            result = {}\n            for label in response[\"labels\"]:\n                try:\n                    key = self.decode(wallet, label[\"externalId\"])\n                    value = self.decode(wallet, label[\"encryptedLabel\"])\n                except:\n                    continue\n                try:\n                    json.dumps(key)\n                    json.dumps(value)\n                except:\n                    self.print_error('error: no json', key)\n                    continue\n                result[key] = value\n\n            for key, value in result.items():\n                if force or not wallet.labels.get(key):\n                    wallet.labels[key] = value\n\n            self.print_error(\"received %d labels\" % len(response))\n            # do not write to disk because we're in a daemon thread\n            wallet.storage.put('labels', wallet.labels)\n            self.set_nonce(wallet, response[\"nonce\"] + 1)\n            self.on_pulled(wallet)\n\n        except Exception as e:\n            traceback.print_exc(file=sys.stderr)\n            self.print_error(\"could not retrieve labels\")\n\n    def start_wallet(self, wallet):\n        nonce = self.get_nonce(wallet)\n        self.print_error(\"wallet\", wallet.basename(), \"nonce is\", nonce)\n        mpk = wallet.get_fingerprint()\n        if not mpk:\n            return\n        password = hashlib.sha1(mpk).digest().encode('hex')[:32]\n        iv = hashlib.sha256(password).digest()[:16]\n        wallet_id = hashlib.sha256(mpk).digest().encode('hex')\n        self.wallets[wallet] = (password, iv, wallet_id)\n        # If there is an auth token we can try to actually start syncing\n        t = threading.Thread(target=self.pull_thread, args=(wallet, False))\n        t.setDaemon(True)\n        t.start()\n\n    def stop_wallet(self, wallet):\n        self.wallets.pop(wallet, None)\n", "path": "plugins/labels/labels.py"}]}