Dandelion updates

- expiration now uses poisson distribution just like in the bitcoin
version
This commit is contained in:
Peter Šurda 2018-02-06 22:28:56 +01:00
parent 6269e45a47
commit 3d1fa473fb
Signed by untrusted user: PeterSurda
GPG Key ID: 0C5F50C0B5F37D87
1 changed files with 18 additions and 7 deletions

View File

@ -1,5 +1,5 @@
from collections import namedtuple from collections import namedtuple
from random import choice, sample from random import choice, sample, expovariate
from threading import RLock from threading import RLock
from time import time from time import time
@ -12,8 +12,11 @@ import state
# randomise routes after 600 seconds # randomise routes after 600 seconds
REASSIGN_INTERVAL = 600 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 MAX_STEMS = 2
Stem = namedtuple('Stem', ['child', 'stream', 'timeout']) Stem = namedtuple('Stem', ['child', 'stream', 'timeout'])
@ -31,6 +34,14 @@ class Dandelion():
self.refresh = time() + REASSIGN_INTERVAL self.refresh = time() + REASSIGN_INTERVAL
self.lock = RLock() 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): def addHash(self, hashId, source=None, stream=1):
if not state.dandelion: if not state.dandelion:
return return
@ -38,7 +49,7 @@ class Dandelion():
self.hashMap[hashId] = Stem( self.hashMap[hashId] = Stem(
self.getNodeStem(source), self.getNodeStem(source),
stream, stream,
time() + FLUFF_TRIGGER_TIMEOUT) Dandelion.poissonTimeout())
def setHashStream(self, hashId, stream=1): def setHashStream(self, hashId, stream=1):
with self.lock: with self.lock:
@ -46,7 +57,7 @@ class Dandelion():
self.hashMap[hashId] = Stem( self.hashMap[hashId] = Stem(
self.hashMap[hashId].child, self.hashMap[hashId].child,
stream, stream,
time() + FLUFF_TRIGGER_TIMEOUT) Dandelion.poissonTimeout())
def removeHash(self, hashId, reason="no reason specified"): 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) 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): for k in (k for k, v in self.nodeMap.iteritems() if v is None):
self.nodeMap[k] = connection self.nodeMap[k] = connection
for k, v in {k: v for k, v in self.hashMap.iteritems() if v.child is None}.iteritems(): 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)) 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): for k in (k for k, v in self.nodeMap.iteritems() if v == connection):
self.nodeMap[k] = None self.nodeMap[k] = None
for k, v in {k: v for k, v in self.hashMap.iteritems() if v.child == connection}.iteritems(): 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): def pickStem(self, parent=None):
try: try: