We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Fix backward compatibility in pickle_deserialize_old_knownnodes()
Hello!

#1662 is caused by changed package structure.

Here I've set up a minimal upgrade from v0.6.3 to reproduce the bug. Using v0.6.2 would be difficult, because it has no command line args.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/network/knownnodes.py`
Content:
```
1 """
2 Manipulations with knownNodes dictionary.
3 """
4 
5 import json
6 import logging
7 import os
8 import pickle
9 import threading
10 import time
11 try:
12     from collections.abc import Iterable
13 except ImportError:
14     from collections import Iterable
15 
16 import state
17 from bmconfigparser import BMConfigParser
18 from network.node import Peer
19 
20 knownNodesLock = threading.RLock()
21 """Thread lock for knownnodes modification"""
22 knownNodes = {stream: {} for stream in range(1, 4)}
23 """The dict of known nodes for each stream"""
24 
25 knownNodesTrimAmount = 2000
26 """trim stream knownnodes dict to this length"""
27 
28 knownNodesForgetRating = -0.5
29 """forget a node after rating is this low"""
30 
31 knownNodesActual = False
32 
33 logger = logging.getLogger('default')
34 
35 DEFAULT_NODES = (
36     Peer('5.45.99.75', 8444),
37     Peer('75.167.159.54', 8444),
38     Peer('95.165.168.168', 8444),
39     Peer('85.180.139.241', 8444),
40     Peer('158.222.217.190', 8080),
41     Peer('178.62.12.187', 8448),
42     Peer('24.188.198.204', 8111),
43     Peer('109.147.204.113', 1195),
44     Peer('178.11.46.221', 8444)
45 )
46 
47 
48 def json_serialize_knownnodes(output):
49     """
50     Reorganize knownnodes dict and write it as JSON to output
51     """
52     _serialized = []
53     for stream, peers in knownNodes.iteritems():
54         for peer, info in peers.iteritems():
55             info.update(rating=round(info.get('rating', 0), 2))
56             _serialized.append({
57                 'stream': stream, 'peer': peer._asdict(), 'info': info
58             })
59     json.dump(_serialized, output, indent=4)
60 
61 
62 def json_deserialize_knownnodes(source):
63     """
64     Read JSON from source and make knownnodes dict
65     """
66     global knownNodesActual  # pylint: disable=global-statement
67     for node in json.load(source):
68         peer = node['peer']
69         info = node['info']
70         peer = Peer(str(peer['host']), peer.get('port', 8444))
71         knownNodes[node['stream']][peer] = info
72         if not (knownNodesActual
73                 or info.get('self')) and peer not in DEFAULT_NODES:
74             knownNodesActual = True
75 
76 
77 def pickle_deserialize_old_knownnodes(source):
78     """
79     Unpickle source and reorganize knownnodes dict if it has old format
80     the old format was {Peer:lastseen, ...}
81     the new format is {Peer:{"lastseen":i, "rating":f}}
82     """
83     global knownNodes  # pylint: disable=global-statement
84     knownNodes = pickle.load(source)
85     for stream in knownNodes.keys():
86         for node, params in knownNodes[stream].iteritems():
87             if isinstance(params, (float, int)):
88                 addKnownNode(stream, node, params)
89 
90 
91 def saveKnownNodes(dirName=None):
92     """Save knownnodes to filesystem"""
93     if dirName is None:
94         dirName = state.appdata
95     with knownNodesLock:
96         with open(os.path.join(dirName, 'knownnodes.dat'), 'wb') as output:
97             json_serialize_knownnodes(output)
98 
99 
100 def addKnownNode(stream, peer, lastseen=None, is_self=False):
101     """
102     Add a new node to the dict or update lastseen if it already exists.
103     Do it for each stream number if *stream* is `Iterable`.
104     Returns True if added a new node.
105     """
106     # pylint: disable=too-many-branches
107     if isinstance(stream, Iterable):
108         with knownNodesLock:
109             for s in stream:
110                 addKnownNode(s, peer, lastseen, is_self)
111         return
112 
113     rating = 0.0
114     if not lastseen:
115         # FIXME: maybe about 28 days?
116         lastseen = int(time.time())
117     else:
118         lastseen = int(lastseen)
119         try:
120             info = knownNodes[stream].get(peer)
121             if lastseen > info['lastseen']:
122                 info['lastseen'] = lastseen
123         except (KeyError, TypeError):
124             pass
125         else:
126             return
127 
128     if not is_self:
129         if len(knownNodes[stream]) > BMConfigParser().safeGetInt(
130                 "knownnodes", "maxnodes"):
131             return
132 
133     knownNodes[stream][peer] = {
134         'lastseen': lastseen,
135         'rating': rating or 1 if is_self else 0,
136         'self': is_self,
137     }
138     return True
139 
140 
141 def createDefaultKnownNodes():
142     """Creating default Knownnodes"""
143     past = time.time() - 2418600  # 28 days - 10 min
144     for peer in DEFAULT_NODES:
145         addKnownNode(1, peer, past)
146     saveKnownNodes()
147 
148 
149 def readKnownNodes():
150     """Load knownnodes from filesystem"""
151     try:
152         with open(state.appdata + 'knownnodes.dat', 'rb') as source:
153             with knownNodesLock:
154                 try:
155                     json_deserialize_knownnodes(source)
156                 except ValueError:
157                     source.seek(0)
158                     pickle_deserialize_old_knownnodes(source)
159     except (IOError, OSError, KeyError, EOFError):
160         logger.debug(
161             'Failed to read nodes from knownnodes.dat', exc_info=True)
162         createDefaultKnownNodes()
163 
164     config = BMConfigParser()
165 
166     # your own onion address, if setup
167     onionhostname = config.safeGet('bitmessagesettings', 'onionhostname')
168     if onionhostname and ".onion" in onionhostname:
169         onionport = config.safeGetInt('bitmessagesettings', 'onionport')
170         if onionport:
171             self_peer = Peer(onionhostname, onionport)
172             addKnownNode(1, self_peer, is_self=True)
173             state.ownAddresses[self_peer] = True
174 
175 
176 def increaseRating(peer):
177     """Increase rating of a peer node"""
178     increaseAmount = 0.1
179     maxRating = 1
180     with knownNodesLock:
181         for stream in knownNodes.keys():
182             try:
183                 knownNodes[stream][peer]["rating"] = min(
184                     knownNodes[stream][peer]["rating"] + increaseAmount,
185                     maxRating
186                 )
187             except KeyError:
188                 pass
189 
190 
191 def decreaseRating(peer):
192     """Decrease rating of a peer node"""
193     decreaseAmount = 0.1
194     minRating = -1
195     with knownNodesLock:
196         for stream in knownNodes.keys():
197             try:
198                 knownNodes[stream][peer]["rating"] = max(
199                     knownNodes[stream][peer]["rating"] - decreaseAmount,
200                     minRating
201                 )
202             except KeyError:
203                 pass
204 
205 
206 def trimKnownNodes(recAddrStream=1):
207     """Triming Knownnodes"""
208     if len(knownNodes[recAddrStream]) < \
209             BMConfigParser().safeGetInt("knownnodes", "maxnodes"):
210         return
211     with knownNodesLock:
212         oldestList = sorted(
213             knownNodes[recAddrStream],
214             key=lambda x: x['lastseen']
215         )[:knownNodesTrimAmount]
216         for oldest in oldestList:
217             del knownNodes[recAddrStream][oldest]
218 
219 
220 def dns():
221     """Add DNS names to knownnodes"""
222     for port in [8080, 8444]:
223         addKnownNode(
224             1, Peer('bootstrap%s.bitmessage.org' % port, port))
225 
226 
227 def cleanupKnownNodes():
228     """
229     Cleanup knownnodes: remove old nodes and nodes with low rating
230     """
231     now = int(time.time())
232     needToWriteKnownNodesToDisk = False
233 
234     with knownNodesLock:
235         for stream in knownNodes:
236             if stream not in state.streamsInWhichIAmParticipating:
237                 continue
238             keys = knownNodes[stream].keys()
239             for node in keys:
240                 if len(knownNodes[stream]) <= 1:  # leave at least one node
241                     break
242                 try:
243                     age = now - knownNodes[stream][node]["lastseen"]
244                     # scrap old nodes (age > 28 days)
245                     if age > 2419200:
246                         needToWriteKnownNodesToDisk = True
247                         del knownNodes[stream][node]
248                         continue
249                     # scrap old nodes (age > 3 hours) with low rating
250                     if (age > 10800 and knownNodes[stream][node]["rating"]
251                             <= knownNodesForgetRating):
252                         needToWriteKnownNodesToDisk = True
253                         del knownNodes[stream][node]
254                         continue
255                 except TypeError:
256                     logger.warning('Error in %s', node)
257             keys = []
258 
259     # Let us write out the knowNodes to disk
260     # if there is anything new to write out.
261     if needToWriteKnownNodesToDisk:
262         saveKnownNodes()
263
```
--- 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()

```

diff --git a/src/network/knownnodes.py b/src/network/knownnodes.py
--- a/src/network/knownnodes.py
+++ b/src/network/knownnodes.py
@@ -17,6 +17,8 @@
 from bmconfigparser import BMConfigParser
 from network.node import Peer
 
+state.Peer = Peer
+
 knownNodesLock = threading.RLock()
 """Thread lock for knownnodes modification"""
 knownNodes = {stream: {} for stream in range(1, 4)}

{"golden_diff": "diff --git a/src/network/knownnodes.py b/src/network/knownnodes.py\n--- a/src/network/knownnodes.py\n+++ b/src/network/knownnodes.py\n@@ -17,6 +17,8 @@\n from bmconfigparser import BMConfigParser\n from network.node import Peer\n \n+state.Peer = Peer\n+\n knownNodesLock = threading.RLock()\n \"\"\"Thread lock for knownnodes modification\"\"\"\n knownNodes = {stream: {} for stream in range(1, 4)}\n", "issue": "Fix backward compatibility in pickle_deserialize_old_knownnodes()\nHello!\r\n\r\n#1662 is caused by changed package structure.\r\n\r\nHere I've set up a minimal upgrade from v0.6.3 to reproduce the bug. Using v0.6.2 would be difficult, because it has no command line args.\n", "before_files": [{"content": "\"\"\"\nManipulations with knownNodes dictionary.\n\"\"\"\n\nimport json\nimport logging\nimport os\nimport pickle\nimport threading\nimport time\ntry:\n    from collections.abc import Iterable\nexcept ImportError:\n    from collections import Iterable\n\nimport state\nfrom bmconfigparser import BMConfigParser\nfrom network.node import Peer\n\nknownNodesLock = threading.RLock()\n\"\"\"Thread lock for knownnodes modification\"\"\"\nknownNodes = {stream: {} for stream in range(1, 4)}\n\"\"\"The dict of known nodes for each stream\"\"\"\n\nknownNodesTrimAmount = 2000\n\"\"\"trim stream knownnodes dict to this length\"\"\"\n\nknownNodesForgetRating = -0.5\n\"\"\"forget a node after rating is this low\"\"\"\n\nknownNodesActual = False\n\nlogger = logging.getLogger('default')\n\nDEFAULT_NODES = (\n    Peer('5.45.99.75', 8444),\n    Peer('75.167.159.54', 8444),\n    Peer('95.165.168.168', 8444),\n    Peer('85.180.139.241', 8444),\n    Peer('158.222.217.190', 8080),\n    Peer('178.62.12.187', 8448),\n    Peer('24.188.198.204', 8111),\n    Peer('109.147.204.113', 1195),\n    Peer('178.11.46.221', 8444)\n)\n\n\ndef json_serialize_knownnodes(output):\n    \"\"\"\n    Reorganize knownnodes dict and write it as JSON to output\n    \"\"\"\n    _serialized = []\n    for stream, peers in knownNodes.iteritems():\n        for peer, info in peers.iteritems():\n            info.update(rating=round(info.get('rating', 0), 2))\n            _serialized.append({\n                'stream': stream, 'peer': peer._asdict(), 'info': info\n            })\n    json.dump(_serialized, output, indent=4)\n\n\ndef json_deserialize_knownnodes(source):\n    \"\"\"\n    Read JSON from source and make knownnodes dict\n    \"\"\"\n    global knownNodesActual  # pylint: disable=global-statement\n    for node in json.load(source):\n        peer = node['peer']\n        info = node['info']\n        peer = Peer(str(peer['host']), peer.get('port', 8444))\n        knownNodes[node['stream']][peer] = info\n        if not (knownNodesActual\n                or info.get('self')) and peer not in DEFAULT_NODES:\n            knownNodesActual = True\n\n\ndef pickle_deserialize_old_knownnodes(source):\n    \"\"\"\n    Unpickle source and reorganize knownnodes dict if it has old format\n    the old format was {Peer:lastseen, ...}\n    the new format is {Peer:{\"lastseen\":i, \"rating\":f}}\n    \"\"\"\n    global knownNodes  # pylint: disable=global-statement\n    knownNodes = pickle.load(source)\n    for stream in knownNodes.keys():\n        for node, params in knownNodes[stream].iteritems():\n            if isinstance(params, (float, int)):\n                addKnownNode(stream, node, params)\n\n\ndef saveKnownNodes(dirName=None):\n    \"\"\"Save knownnodes to filesystem\"\"\"\n    if dirName is None:\n        dirName = state.appdata\n    with knownNodesLock:\n        with open(os.path.join(dirName, 'knownnodes.dat'), 'wb') as output:\n            json_serialize_knownnodes(output)\n\n\ndef addKnownNode(stream, peer, lastseen=None, is_self=False):\n    \"\"\"\n    Add a new node to the dict or update lastseen if it already exists.\n    Do it for each stream number if *stream* is `Iterable`.\n    Returns True if added a new node.\n    \"\"\"\n    # pylint: disable=too-many-branches\n    if isinstance(stream, Iterable):\n        with knownNodesLock:\n            for s in stream:\n                addKnownNode(s, peer, lastseen, is_self)\n        return\n\n    rating = 0.0\n    if not lastseen:\n        # FIXME: maybe about 28 days?\n        lastseen = int(time.time())\n    else:\n        lastseen = int(lastseen)\n        try:\n            info = knownNodes[stream].get(peer)\n            if lastseen > info['lastseen']:\n                info['lastseen'] = lastseen\n        except (KeyError, TypeError):\n            pass\n        else:\n            return\n\n    if not is_self:\n        if len(knownNodes[stream]) > BMConfigParser().safeGetInt(\n                \"knownnodes\", \"maxnodes\"):\n            return\n\n    knownNodes[stream][peer] = {\n        'lastseen': lastseen,\n        'rating': rating or 1 if is_self else 0,\n        'self': is_self,\n    }\n    return True\n\n\ndef createDefaultKnownNodes():\n    \"\"\"Creating default Knownnodes\"\"\"\n    past = time.time() - 2418600  # 28 days - 10 min\n    for peer in DEFAULT_NODES:\n        addKnownNode(1, peer, past)\n    saveKnownNodes()\n\n\ndef readKnownNodes():\n    \"\"\"Load knownnodes from filesystem\"\"\"\n    try:\n        with open(state.appdata + 'knownnodes.dat', 'rb') as source:\n            with knownNodesLock:\n                try:\n                    json_deserialize_knownnodes(source)\n                except ValueError:\n                    source.seek(0)\n                    pickle_deserialize_old_knownnodes(source)\n    except (IOError, OSError, KeyError, EOFError):\n        logger.debug(\n            'Failed to read nodes from knownnodes.dat', exc_info=True)\n        createDefaultKnownNodes()\n\n    config = BMConfigParser()\n\n    # your own onion address, if setup\n    onionhostname = config.safeGet('bitmessagesettings', 'onionhostname')\n    if onionhostname and \".onion\" in onionhostname:\n        onionport = config.safeGetInt('bitmessagesettings', 'onionport')\n        if onionport:\n            self_peer = Peer(onionhostname, onionport)\n            addKnownNode(1, self_peer, is_self=True)\n            state.ownAddresses[self_peer] = True\n\n\ndef increaseRating(peer):\n    \"\"\"Increase rating of a peer node\"\"\"\n    increaseAmount = 0.1\n    maxRating = 1\n    with knownNodesLock:\n        for stream in knownNodes.keys():\n            try:\n                knownNodes[stream][peer][\"rating\"] = min(\n                    knownNodes[stream][peer][\"rating\"] + increaseAmount,\n                    maxRating\n                )\n            except KeyError:\n                pass\n\n\ndef decreaseRating(peer):\n    \"\"\"Decrease rating of a peer node\"\"\"\n    decreaseAmount = 0.1\n    minRating = -1\n    with knownNodesLock:\n        for stream in knownNodes.keys():\n            try:\n                knownNodes[stream][peer][\"rating\"] = max(\n                    knownNodes[stream][peer][\"rating\"] - decreaseAmount,\n                    minRating\n                )\n            except KeyError:\n                pass\n\n\ndef trimKnownNodes(recAddrStream=1):\n    \"\"\"Triming Knownnodes\"\"\"\n    if len(knownNodes[recAddrStream]) < \\\n            BMConfigParser().safeGetInt(\"knownnodes\", \"maxnodes\"):\n        return\n    with knownNodesLock:\n        oldestList = sorted(\n            knownNodes[recAddrStream],\n            key=lambda x: x['lastseen']\n        )[:knownNodesTrimAmount]\n        for oldest in oldestList:\n            del knownNodes[recAddrStream][oldest]\n\n\ndef dns():\n    \"\"\"Add DNS names to knownnodes\"\"\"\n    for port in [8080, 8444]:\n        addKnownNode(\n            1, Peer('bootstrap%s.bitmessage.org' % port, port))\n\n\ndef cleanupKnownNodes():\n    \"\"\"\n    Cleanup knownnodes: remove old nodes and nodes with low rating\n    \"\"\"\n    now = int(time.time())\n    needToWriteKnownNodesToDisk = False\n\n    with knownNodesLock:\n        for stream in knownNodes:\n            if stream not in state.streamsInWhichIAmParticipating:\n                continue\n            keys = knownNodes[stream].keys()\n            for node in keys:\n                if len(knownNodes[stream]) <= 1:  # leave at least one node\n                    break\n                try:\n                    age = now - knownNodes[stream][node][\"lastseen\"]\n                    # scrap old nodes (age > 28 days)\n                    if age > 2419200:\n                        needToWriteKnownNodesToDisk = True\n                        del knownNodes[stream][node]\n                        continue\n                    # scrap old nodes (age > 3 hours) with low rating\n                    if (age > 10800 and knownNodes[stream][node][\"rating\"]\n                            <= knownNodesForgetRating):\n                        needToWriteKnownNodesToDisk = True\n                        del knownNodes[stream][node]\n                        continue\n                except TypeError:\n                    logger.warning('Error in %s', node)\n            keys = []\n\n    # Let us write out the knowNodes to disk\n    # if there is anything new to write out.\n    if needToWriteKnownNodesToDisk:\n        saveKnownNodes()\n", "path": "src/network/knownnodes.py"}], "after_files": [{"content": "\"\"\"\nManipulations with knownNodes dictionary.\n\"\"\"\n\nimport json\nimport logging\nimport os\nimport pickle\nimport threading\nimport time\ntry:\n    from collections.abc import Iterable\nexcept ImportError:\n    from collections import Iterable\n\nimport state\nfrom bmconfigparser import BMConfigParser\nfrom network.node import Peer\n\nstate.Peer = Peer\n\nknownNodesLock = threading.RLock()\n\"\"\"Thread lock for knownnodes modification\"\"\"\nknownNodes = {stream: {} for stream in range(1, 4)}\n\"\"\"The dict of known nodes for each stream\"\"\"\n\nknownNodesTrimAmount = 2000\n\"\"\"trim stream knownnodes dict to this length\"\"\"\n\nknownNodesForgetRating = -0.5\n\"\"\"forget a node after rating is this low\"\"\"\n\nknownNodesActual = False\n\nlogger = logging.getLogger('default')\n\nDEFAULT_NODES = (\n    Peer('5.45.99.75', 8444),\n    Peer('75.167.159.54', 8444),\n    Peer('95.165.168.168', 8444),\n    Peer('85.180.139.241', 8444),\n    Peer('158.222.217.190', 8080),\n    Peer('178.62.12.187', 8448),\n    Peer('24.188.198.204', 8111),\n    Peer('109.147.204.113', 1195),\n    Peer('178.11.46.221', 8444)\n)\n\n\ndef json_serialize_knownnodes(output):\n    \"\"\"\n    Reorganize knownnodes dict and write it as JSON to output\n    \"\"\"\n    _serialized = []\n    for stream, peers in knownNodes.iteritems():\n        for peer, info in peers.iteritems():\n            info.update(rating=round(info.get('rating', 0), 2))\n            _serialized.append({\n                'stream': stream, 'peer': peer._asdict(), 'info': info\n            })\n    json.dump(_serialized, output, indent=4)\n\n\ndef json_deserialize_knownnodes(source):\n    \"\"\"\n    Read JSON from source and make knownnodes dict\n    \"\"\"\n    global knownNodesActual  # pylint: disable=global-statement\n    for node in json.load(source):\n        peer = node['peer']\n        info = node['info']\n        peer = Peer(str(peer['host']), peer.get('port', 8444))\n        knownNodes[node['stream']][peer] = info\n        if not (knownNodesActual\n                or info.get('self')) and peer not in DEFAULT_NODES:\n            knownNodesActual = True\n\n\ndef pickle_deserialize_old_knownnodes(source):\n    \"\"\"\n    Unpickle source and reorganize knownnodes dict if it has old format\n    the old format was {Peer:lastseen, ...}\n    the new format is {Peer:{\"lastseen\":i, \"rating\":f}}\n    \"\"\"\n    global knownNodes  # pylint: disable=global-statement\n    knownNodes = pickle.load(source)\n    for stream in knownNodes.keys():\n        for node, params in knownNodes[stream].iteritems():\n            if isinstance(params, (float, int)):\n                addKnownNode(stream, node, params)\n\n\ndef saveKnownNodes(dirName=None):\n    \"\"\"Save knownnodes to filesystem\"\"\"\n    if dirName is None:\n        dirName = state.appdata\n    with knownNodesLock:\n        with open(os.path.join(dirName, 'knownnodes.dat'), 'wb') as output:\n            json_serialize_knownnodes(output)\n\n\ndef addKnownNode(stream, peer, lastseen=None, is_self=False):\n    \"\"\"\n    Add a new node to the dict or update lastseen if it already exists.\n    Do it for each stream number if *stream* is `Iterable`.\n    Returns True if added a new node.\n    \"\"\"\n    # pylint: disable=too-many-branches\n    if isinstance(stream, Iterable):\n        with knownNodesLock:\n            for s in stream:\n                addKnownNode(s, peer, lastseen, is_self)\n        return\n\n    rating = 0.0\n    if not lastseen:\n        # FIXME: maybe about 28 days?\n        lastseen = int(time.time())\n    else:\n        lastseen = int(lastseen)\n        try:\n            info = knownNodes[stream].get(peer)\n            if lastseen > info['lastseen']:\n                info['lastseen'] = lastseen\n        except (KeyError, TypeError):\n            pass\n        else:\n            return\n\n    if not is_self:\n        if len(knownNodes[stream]) > BMConfigParser().safeGetInt(\n                \"knownnodes\", \"maxnodes\"):\n            return\n\n    knownNodes[stream][peer] = {\n        'lastseen': lastseen,\n        'rating': rating or 1 if is_self else 0,\n        'self': is_self,\n    }\n    return True\n\n\ndef createDefaultKnownNodes():\n    \"\"\"Creating default Knownnodes\"\"\"\n    past = time.time() - 2418600  # 28 days - 10 min\n    for peer in DEFAULT_NODES:\n        addKnownNode(1, peer, past)\n    saveKnownNodes()\n\n\ndef readKnownNodes():\n    \"\"\"Load knownnodes from filesystem\"\"\"\n    try:\n        with open(state.appdata + 'knownnodes.dat', 'rb') as source:\n            with knownNodesLock:\n                try:\n                    json_deserialize_knownnodes(source)\n                except ValueError:\n                    source.seek(0)\n                    pickle_deserialize_old_knownnodes(source)\n    except (IOError, OSError, KeyError, EOFError):\n        logger.debug(\n            'Failed to read nodes from knownnodes.dat', exc_info=True)\n        createDefaultKnownNodes()\n\n    config = BMConfigParser()\n\n    # your own onion address, if setup\n    onionhostname = config.safeGet('bitmessagesettings', 'onionhostname')\n    if onionhostname and \".onion\" in onionhostname:\n        onionport = config.safeGetInt('bitmessagesettings', 'onionport')\n        if onionport:\n            self_peer = Peer(onionhostname, onionport)\n            addKnownNode(1, self_peer, is_self=True)\n            state.ownAddresses[self_peer] = True\n\n\ndef increaseRating(peer):\n    \"\"\"Increase rating of a peer node\"\"\"\n    increaseAmount = 0.1\n    maxRating = 1\n    with knownNodesLock:\n        for stream in knownNodes.keys():\n            try:\n                knownNodes[stream][peer][\"rating\"] = min(\n                    knownNodes[stream][peer][\"rating\"] + increaseAmount,\n                    maxRating\n                )\n            except KeyError:\n                pass\n\n\ndef decreaseRating(peer):\n    \"\"\"Decrease rating of a peer node\"\"\"\n    decreaseAmount = 0.1\n    minRating = -1\n    with knownNodesLock:\n        for stream in knownNodes.keys():\n            try:\n                knownNodes[stream][peer][\"rating\"] = max(\n                    knownNodes[stream][peer][\"rating\"] - decreaseAmount,\n                    minRating\n                )\n            except KeyError:\n                pass\n\n\ndef trimKnownNodes(recAddrStream=1):\n    \"\"\"Triming Knownnodes\"\"\"\n    if len(knownNodes[recAddrStream]) < \\\n            BMConfigParser().safeGetInt(\"knownnodes\", \"maxnodes\"):\n        return\n    with knownNodesLock:\n        oldestList = sorted(\n            knownNodes[recAddrStream],\n            key=lambda x: x['lastseen']\n        )[:knownNodesTrimAmount]\n        for oldest in oldestList:\n            del knownNodes[recAddrStream][oldest]\n\n\ndef dns():\n    \"\"\"Add DNS names to knownnodes\"\"\"\n    for port in [8080, 8444]:\n        addKnownNode(\n            1, Peer('bootstrap%s.bitmessage.org' % port, port))\n\n\ndef cleanupKnownNodes():\n    \"\"\"\n    Cleanup knownnodes: remove old nodes and nodes with low rating\n    \"\"\"\n    now = int(time.time())\n    needToWriteKnownNodesToDisk = False\n\n    with knownNodesLock:\n        for stream in knownNodes:\n            if stream not in state.streamsInWhichIAmParticipating:\n                continue\n            keys = knownNodes[stream].keys()\n            for node in keys:\n                if len(knownNodes[stream]) <= 1:  # leave at least one node\n                    break\n                try:\n                    age = now - knownNodes[stream][node][\"lastseen\"]\n                    # scrap old nodes (age > 28 days)\n                    if age > 2419200:\n                        needToWriteKnownNodesToDisk = True\n                        del knownNodes[stream][node]\n                        continue\n                    # scrap old nodes (age > 3 hours) with low rating\n                    if (age > 10800 and knownNodes[stream][node][\"rating\"]\n                            <= knownNodesForgetRating):\n                        needToWriteKnownNodesToDisk = True\n                        del knownNodes[stream][node]\n                        continue\n                except TypeError:\n                    logger.warning('Error in %s', node)\n            keys = []\n\n    # Let us write out the knowNodes to disk\n    # if there is anything new to write out.\n    if needToWriteKnownNodesToDisk:\n        saveKnownNodes()\n", "path": "src/network/knownnodes.py"}]}