From 3d1fa473fb270339d8b326a31f2357f20fb71d9d Mon Sep 17 00:00:00 2001 From: Peter Surda Date: Tue, 6 Feb 2018 22:28:56 +0100 Subject: [PATCH] Dandelion updates - expiration now uses poisson distribution just like in the bitcoin version --- src/network/dandelion.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/network/dandelion.py b/src/network/dandelion.py index edd4fb5b..bee01d73 100644 --- a/src/network/dandelion.py +++ b/src/network/dandelion.py @@ -1,5 +1,5 @@ from collections import namedtuple -from random import choice, sample +from random import choice, sample, expovariate from threading import RLock from time import time @@ -12,8 +12,11 @@ import state # randomise routes after 600 seconds REASSIGN_INTERVAL = 600 -# trigger fluff due to expiration in 2 minutes -FLUFF_TRIGGER_TIMEOUT = 120 + +# trigger fluff due to expiration +FLUFF_TRIGGER_FIXED_DELAY = 10 +FLUFF_TRIGGER_MEAN_DELAY = 30 + MAX_STEMS = 2 Stem = namedtuple('Stem', ['child', 'stream', 'timeout']) @@ -31,6 +34,14 @@ class Dandelion(): self.refresh = time() + REASSIGN_INTERVAL self.lock = RLock() + @staticmethod + def poissonTimeout(start=None, average=0): + if start is None: + start = time() + if average == 0: + average = FLUFF_TRIGGER_MEAN_DELAY + return start + expovariate(1.0/average) + FLUFF_TRIGGER_FIXED_DELAY + def addHash(self, hashId, source=None, stream=1): if not state.dandelion: return @@ -38,7 +49,7 @@ class Dandelion(): self.hashMap[hashId] = Stem( self.getNodeStem(source), stream, - time() + FLUFF_TRIGGER_TIMEOUT) + Dandelion.poissonTimeout()) def setHashStream(self, hashId, stream=1): with self.lock: @@ -46,7 +57,7 @@ class Dandelion(): self.hashMap[hashId] = Stem( self.hashMap[hashId].child, stream, - time() + FLUFF_TRIGGER_TIMEOUT) + Dandelion.poissonTimeout()) def removeHash(self, hashId, reason="no reason specified"): logging.debug("%s entering fluff mode due to %s.", ''.join('%02x'%ord(i) for i in hashId), reason) @@ -70,7 +81,7 @@ class Dandelion(): for k in (k for k, v in self.nodeMap.iteritems() if v is None): self.nodeMap[k] = connection for k, v in {k: v for k, v in self.hashMap.iteritems() if v.child is None}.iteritems(): - self.hashMap[k] = Stem(connection, v.stream, time() + FLUFF_TRIGGER_TIMEOUT) + self.hashMap[k] = Stem(connection, v.stream, Dandelion.poissionTimeout()) invQueue.put((v.stream, k, v.child)) @@ -83,7 +94,7 @@ class Dandelion(): for k in (k for k, v in self.nodeMap.iteritems() if v == connection): self.nodeMap[k] = None for k, v in {k: v for k, v in self.hashMap.iteritems() if v.child == connection}.iteritems(): - self.hashMap[k] = Stem(None, v.stream, time() + FLUFF_TRIGGER_TIMEOUT) + self.hashMap[k] = Stem(None, v.stream, Dandelion.poissonTimeout()) def pickStem(self, parent=None): try: