From d23d4c1d7396ac486d52b2f3bd609af4296d56a3 Mon Sep 17 00:00:00 2001
From: Jack Robison <jackrobison@lbry.io>
Date: Wed, 11 Oct 2017 23:23:07 -0400
Subject: [PATCH 1/3] fix lbryid length comparison

---
 lbrynet/dht/node.py | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/lbrynet/dht/node.py b/lbrynet/dht/node.py
index bf1436f16..2dfa71fea 100644
--- a/lbrynet/dht/node.py
+++ b/lbrynet/dht/node.py
@@ -484,8 +484,9 @@ class Node(object):
             raise TypeError, 'No port available'
 
         if 'lbryid' in value:
-            if len(value['lbryid']) > constants.key_bits:
-                raise ValueError, 'Invalid lbryid'
+            if len(value['lbryid']) != constants.key_bits / 8:
+                raise ValueError('Invalid lbryid (%i bytes): %s' % (len(value['lbryid']),
+                                                                    value['lbryid'].encode('hex')))
             else:
                 compact_address = compact_ip + compact_port + value['lbryid']
         else:

From 45adfc533b21299ae2a03ccdf78aac69073d8c37 Mon Sep 17 00:00:00 2001
From: Jack Robison <jackrobison@lbry.io>
Date: Sun, 22 Oct 2017 21:16:16 -0400
Subject: [PATCH 2/3] fix id of new contact replacing a dead contact

---
 lbrynet/dht/routingtable.py | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/lbrynet/dht/routingtable.py b/lbrynet/dht/routingtable.py
index 86af043dc..13d0bb802 100644
--- a/lbrynet/dht/routingtable.py
+++ b/lbrynet/dht/routingtable.py
@@ -11,7 +11,6 @@ from zope.interface import implements
 import constants
 import kbucket
 from interface import IRoutingTable
-from error import TimeoutError
 import logging
 
 log = logging.getLogger(__name__)
@@ -83,11 +82,16 @@ class TreeRoutingTable(object):
 
                     @type failure: twisted.python.failure.Failure
                     """
-                    failure.trap(TimeoutError)
-                    log.warning('==replacing contact==')
-                    # Remove the old contact...
-                    deadContactID = failure.getErrorMessage()
+                    # 'failure' is a Failure with an error message in the format:
+                    # "Timeout connecting to <node id hex>"
+                    error_message = failure.getErrorMessage()
+                    deadContactID = error_message[22:].decode('hex')
+
+                    if len(deadContactID) != constants.key_bits / 8:
+                        raise ValueError("invalid contact id")
+                    log.debug("Replacing dead contact: %s", deadContactID.encode('hex'))
                     try:
+                        # Remove the old contact...
                         self._buckets[bucketIndex].removeContact(deadContactID)
                     except ValueError:
                         # The contact has already been removed (probably due to a timeout)

From 8e94970b531634af6c54f0cb0ee88ba33769aab3 Mon Sep 17 00:00:00 2001
From: Jack Robison <jackrobison@lbry.io>
Date: Mon, 23 Oct 2017 01:25:13 -0400
Subject: [PATCH 3/3] changelog

---
 CHANGELOG.md | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ebffb776f..ec64216ba 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,9 @@ at anytime.
   * Fixed slow startup for nodes with many lbry files
   * Fixed setting the external ip on startup
   * Fixed session startup not blocking on joining the dht
+  * Fixed a bug that prevented replacing dht contacts
+  * Fixed lbryid length validation
+  * Fixed an old print statement that polluted logs
 
 ### Deprecated
   *