diff --git a/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java index b669f1447..712830f59 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java @@ -199,10 +199,10 @@ public class NetDbRenderer { FloodfillNetworkDatabaseFacade netdb = (FloodfillNetworkDatabaseFacade)_context.netDb(); buf.append("
Total Leasesets: ").append(leases.size()); buf.append("
Published (RAP) Leasesets: ").append(netdb.getKnownLeaseSets()); - buf.append("
Mod Data: \"").append(DataHelper.getUTF8(_context.routingKeyGenerator().getModData())) - .append("\" Last Changed: ").append(new Date(_context.routingKeyGenerator().getLastChanged())); - buf.append("
Next Mod Data: \"").append(DataHelper.getUTF8(_context.routingKeyGenerator().getNextModData())) - .append("\" Change in: ").append(DataHelper.formatDuration(_context.routingKeyGenerator().getTimeTillMidnight())); + buf.append("
Mod Data: \"").append(DataHelper.getUTF8(_context.routerKeyGenerator().getModData())) + .append("\" Last Changed: ").append(new Date(_context.routerKeyGenerator().getLastChanged())); + buf.append("
Next Mod Data: \"").append(DataHelper.getUTF8(_context.routerKeyGenerator().getNextModData())) + .append("\" Change in: ").append(DataHelper.formatDuration(_context.routerKeyGenerator().getTimeTillMidnight())); int ff = _context.peerManager().getPeersByCapability(FloodfillNetworkDatabaseFacade.CAPABILITY_FLOODFILL).size(); buf.append("
Known Floodfills: ").append(ff); buf.append("
Currently Floodfill? ");
diff --git a/core/java/src/net/i2p/I2PAppContext.java b/core/java/src/net/i2p/I2PAppContext.java
index 8357a485a..79c3108f7 100644
--- a/core/java/src/net/i2p/I2PAppContext.java
+++ b/core/java/src/net/i2p/I2PAppContext.java
@@ -86,7 +86,6 @@ public class I2PAppContext {
private SHA256Generator _sha;
protected Clock _clock; // overridden in RouterContext
private DSAEngine _dsa;
- private RoutingKeyGenerator _routingKeyGenerator;
private RandomSource _random;
private KeyGenerator _keyGenerator;
protected KeyRing _keyRing; // overridden in RouterContext
@@ -106,7 +105,6 @@ public class I2PAppContext {
private volatile boolean _shaInitialized;
protected volatile boolean _clockInitialized; // used in RouterContext
private volatile boolean _dsaInitialized;
- private volatile boolean _routingKeyGeneratorInitialized;
private volatile boolean _randomInitialized;
private volatile boolean _keyGeneratorInitialized;
protected volatile boolean _keyRingInitialized; // used in RouterContext
@@ -126,7 +124,7 @@ public class I2PAppContext {
private final Object _lock1 = new Object(), _lock2 = new Object(), _lock3 = new Object(), _lock4 = new Object(),
_lock5 = new Object(), _lock6 = new Object(), _lock7 = new Object(), _lock8 = new Object(),
_lock9 = new Object(), _lock10 = new Object(), _lock11 = new Object(), _lock12 = new Object(),
- _lock13 = new Object(), _lock14 = new Object(), _lock15 = new Object(), _lock16 = new Object(),
+ _lock13 = new Object(), _lock14 = new Object(), _lock16 = new Object(),
_lock17 = new Object(), _lock18 = new Object(), _lock19 = new Object(), _lock20 = new Object();
/**
@@ -851,19 +849,13 @@ public class I2PAppContext {
* may want to test out how things react when peers don't agree on
* how to skew.
*
+ * As of 0.9.16, returns null in I2PAppContext.
+ * You must be in RouterContext to get a generator.
+ *
+ * @return null always
*/
public RoutingKeyGenerator routingKeyGenerator() {
- if (!_routingKeyGeneratorInitialized)
- initializeRoutingKeyGenerator();
- return _routingKeyGenerator;
- }
-
- private void initializeRoutingKeyGenerator() {
- synchronized (_lock15) {
- if (_routingKeyGenerator == null)
- _routingKeyGenerator = new RoutingKeyGenerator(this);
- _routingKeyGeneratorInitialized = true;
- }
+ return null;
}
/**
diff --git a/core/java/src/net/i2p/data/DatabaseEntry.java b/core/java/src/net/i2p/data/DatabaseEntry.java
index 4b84ed106..2adc066bf 100644
--- a/core/java/src/net/i2p/data/DatabaseEntry.java
+++ b/core/java/src/net/i2p/data/DatabaseEntry.java
@@ -11,6 +11,7 @@ package net.i2p.data;
import java.util.Arrays;
+import net.i2p.I2PAppContext;
import net.i2p.crypto.DSAEngine;
/**
@@ -47,7 +48,7 @@ public abstract class DatabaseEntry extends DataStructureImpl {
protected volatile Signature _signature;
protected volatile Hash _currentRoutingKey;
- protected volatile byte[] _routingKeyGenMod;
+ protected volatile long _routingKeyGenMod;
/**
* A common interface to the timestamp of the two subclasses.
@@ -106,11 +107,15 @@ public abstract class DatabaseEntry extends DataStructureImpl {
* Get the routing key for the structure using the current modifier in the RoutingKeyGenerator.
* This only calculates a new one when necessary though (if the generator's key modifier changes)
*
+ * @throws IllegalStateException if not in RouterContext
*/
public Hash getRoutingKey() {
- RoutingKeyGenerator gen = RoutingKeyGenerator.getInstance();
- byte[] mod = gen.getModData();
- if (!Arrays.equals(mod, _routingKeyGenMod)) {
+ I2PAppContext ctx = I2PAppContext.getGlobalContext();
+ if (!ctx.isRouterContext())
+ throw new IllegalStateException("Not in router context");
+ RoutingKeyGenerator gen = ctx.routingKeyGenerator();
+ long mod = gen.getLastChanged();
+ if (mod != _routingKeyGenMod) {
_currentRoutingKey = gen.getRoutingKey(getHash());
_routingKeyGenMod = mod;
}
@@ -124,9 +129,16 @@ public abstract class DatabaseEntry extends DataStructureImpl {
_currentRoutingKey = key;
}
+ /**
+ * @throws IllegalStateException if not in RouterContext
+ */
public boolean validateRoutingKey() {
+ I2PAppContext ctx = I2PAppContext.getGlobalContext();
+ if (!ctx.isRouterContext())
+ throw new IllegalStateException("Not in router context");
+ RoutingKeyGenerator gen = ctx.routingKeyGenerator();
Hash destKey = getHash();
- Hash rk = RoutingKeyGenerator.getInstance().getRoutingKey(destKey);
+ Hash rk = gen.getRoutingKey(destKey);
return rk.equals(getRoutingKey());
}
diff --git a/core/java/src/net/i2p/data/RoutingKeyGenerator.java b/core/java/src/net/i2p/data/RoutingKeyGenerator.java
index 367089442..20e2218ee 100644
--- a/core/java/src/net/i2p/data/RoutingKeyGenerator.java
+++ b/core/java/src/net/i2p/data/RoutingKeyGenerator.java
@@ -9,215 +9,40 @@ package net.i2p.data;
*
*/
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Arrays;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-import java.util.TimeZone;
-
import net.i2p.I2PAppContext;
-import net.i2p.crypto.SHA256Generator;
-import net.i2p.util.HexDump;
-import net.i2p.util.Log;
/**
* Component to manage the munging of hashes into routing keys - given a hash,
* perform some consistent transformation against it and return the result.
* This transformation is fed by the current "mod data".
*
- * Right now the mod data is the current date (GMT) as a string: "yyyyMMdd",
- * and the transformation takes the original hash, appends the bytes of that mod data,
- * then returns the SHA256 of that concatenation.
- *
- * Do we want this to simply do the XOR of the SHA256 of the current mod data and
- * the key? does that provide the randomization we need? It'd save an SHA256 op.
- * Bah, too much effort to think about for so little gain. Other algorithms may come
- * into play layer on about making periodic updates to the routing key for data elements
- * to mess with Sybil. This may be good enough though.
- *
- * Also - the method generateDateBasedModData() should be called after midnight GMT
- * once per day to generate the correct routing keys!
- *
- * Warning - API subject to change. Not for use outside the router.
+ * As of 0.9.16, this is essentially just an interface.
+ * Implementation moved to net.i2p.data.router.RouterKeyGenerator.
+ * No generator is available in I2PAppContext; you must be in RouterContext.
*
*/
-public class RoutingKeyGenerator {
- private final Log _log;
- private final I2PAppContext _context;
-
- public RoutingKeyGenerator(I2PAppContext context) {
- _log = context.logManager().getLog(RoutingKeyGenerator.class);
- _context = context;
- // ensure non-null mod data
- generateDateBasedModData();
- }
+public abstract class RoutingKeyGenerator {
+ /**
+ * Get the generator for this context.
+ *
+ * @return null in I2PAppContext; non-null in RouterContext.
+ */
public static RoutingKeyGenerator getInstance() {
return I2PAppContext.getGlobalContext().routingKeyGenerator();
}
-
- private volatile byte _currentModData[];
- private volatile byte _nextModData[];
- private volatile long _nextMidnight;
- private volatile long _lastChanged;
-
- private final static Calendar _cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"));
- private static final String FORMAT = "yyyyMMdd";
- private static final int LENGTH = FORMAT.length();
- private final static SimpleDateFormat _fmt = new SimpleDateFormat(FORMAT, Locale.US);
- static {
- // make sure GMT is set, azi2phelper Vuze plugin is disabling static JVM TZ setting in Router.java
- _fmt.setCalendar(_cal);
- }
/**
- * The current (today's) mod data.
- * Warning - not a copy, do not corrupt.
- *
- * @return non-null, 8 bytes
+ * The version of the current (today's) mod data.
+ * Use to determine if the routing key should be regenerated.
*/
- public byte[] getModData() {
- return _currentModData;
- }
+ public abstract long getLastChanged();
/**
- * Tomorrow's mod data.
- * Warning - not a copy, do not corrupt.
- * For debugging use only.
- *
- * @return non-null, 8 bytes
- * @since 0.9.10
- */
- public byte[] getNextModData() {
- return _nextModData;
- }
-
- public long getLastChanged() {
- return _lastChanged;
- }
-
- /**
- * How long until midnight (ms)
- *
- * @return could be slightly negative
- * @since 0.9.10 moved from UpdateRoutingKeyModifierJob
- */
- public long getTimeTillMidnight() {
- return _nextMidnight - _context.clock().now();
- }
-
- /**
- * Set _cal to midnight for the time given.
- * Caller must synch.
- * @since 0.9.10
- */
- private void setCalToPreviousMidnight(long now) {
- _cal.setTime(new Date(now));
- _cal.set(Calendar.YEAR, _cal.get(Calendar.YEAR)); // gcj <= 4.0 workaround
- _cal.set(Calendar.DAY_OF_YEAR, _cal.get(Calendar.DAY_OF_YEAR)); // gcj <= 4.0 workaround
- _cal.set(Calendar.HOUR_OF_DAY, 0);
- _cal.set(Calendar.MINUTE, 0);
- _cal.set(Calendar.SECOND, 0);
- _cal.set(Calendar.MILLISECOND, 0);
- }
-
- /**
- * Generate mod data from _cal.
- * Caller must synch.
- * @since 0.9.10
- */
- private byte[] generateModDataFromCal() {
- Date today = _cal.getTime();
-
- String modVal = _fmt.format(today);
- if (modVal.length() != LENGTH)
- throw new IllegalStateException();
- byte[] mod = new byte[LENGTH];
- for (int i = 0; i < LENGTH; i++)
- mod[i] = (byte)(modVal.charAt(i) & 0xFF);
- return mod;
- }
-
- /**
- * Update the current modifier data with some bytes derived from the current
- * date (yyyyMMdd in GMT)
- *
- * @return true if changed
- */
- public synchronized boolean generateDateBasedModData() {
- long now = _context.clock().now();
- setCalToPreviousMidnight(now);
- byte[] mod = generateModDataFromCal();
- boolean changed = !Arrays.equals(_currentModData, mod);
- if (changed) {
- // add a day and store next midnight and mod data for convenience
- _cal.add(Calendar.DATE, 1);
- _nextMidnight = _cal.getTime().getTime();
- byte[] next = generateModDataFromCal();
- _currentModData = mod;
- _nextModData = next;
- _lastChanged = now;
- if (_log.shouldLog(Log.INFO))
- _log.info("Routing modifier generated: " + HexDump.dump(mod));
- }
- return changed;
- }
-
- /**
- * Generate a modified (yet consistent) hash from the origKey by generating the
- * SHA256 of the targetKey with the current modData appended to it
- *
- * This makes Sybil's job a lot harder, as she needs to essentially take over the
- * whole keyspace.
+ * Get the routing key for a key.
*
* @throws IllegalArgumentException if origKey is null
*/
- public Hash getRoutingKey(Hash origKey) {
- return getKey(origKey, _currentModData);
- }
-
- /**
- * Get the routing key using tomorrow's modData, not today's
- *
- * @since 0.9.10
- */
- public Hash getNextRoutingKey(Hash origKey) {
- return getKey(origKey, _nextModData);
- }
-
- /**
- * Generate a modified (yet consistent) hash from the origKey by generating the
- * SHA256 of the targetKey with the specified modData appended to it
- *
- * @throws IllegalArgumentException if origKey is null
- */
- private static Hash getKey(Hash origKey, byte[] modData) {
- if (origKey == null) throw new IllegalArgumentException("Original key is null");
- byte modVal[] = new byte[Hash.HASH_LENGTH + LENGTH];
- System.arraycopy(origKey.getData(), 0, modVal, 0, Hash.HASH_LENGTH);
- System.arraycopy(modData, 0, modVal, Hash.HASH_LENGTH, LENGTH);
- return SHA256Generator.getInstance().calculateHash(modVal);
- }
+ public abstract Hash getRoutingKey(Hash origKey);
-/****
- public static void main(String args[]) {
- Hash k1 = new Hash();
- byte k1d[] = new byte[Hash.HASH_LENGTH];
- RandomSource.getInstance().nextBytes(k1d);
- k1.setData(k1d);
-
- for (int i = 0; i < 10; i++) {
- System.out.println("K1: " + k1);
- Hash k1m = RoutingKeyGenerator.getInstance().getRoutingKey(k1);
- System.out.println("MOD: " + new String(RoutingKeyGenerator.getInstance().getModData()));
- System.out.println("K1M: " + k1m);
- }
- try {
- Thread.sleep(2000);
- } catch (Throwable t) { // nop
- }
- }
-****/
}
diff --git a/router/java/src/net/i2p/data/router/RouterKeyGenerator.java b/router/java/src/net/i2p/data/router/RouterKeyGenerator.java
new file mode 100644
index 000000000..69e6aacec
--- /dev/null
+++ b/router/java/src/net/i2p/data/router/RouterKeyGenerator.java
@@ -0,0 +1,224 @@
+package net.i2p.data.router;
+
+/*
+ * free (adj.): unencumbered; not under the control of others
+ * Written by jrandom in 2003 and released into the public domain
+ * with no warranty of any kind, either expressed or implied.
+ * It probably won't make your computer catch on fire, or eat
+ * your children, but it might. Use at your own risk.
+ *
+ */
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Arrays;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import net.i2p.I2PAppContext;
+import net.i2p.crypto.SHA256Generator;
+import net.i2p.data.Hash;
+import net.i2p.data.RoutingKeyGenerator;
+import net.i2p.util.HexDump;
+import net.i2p.util.Log;
+
+/**
+ * Component to manage the munging of hashes into routing keys - given a hash,
+ * perform some consistent transformation against it and return the result.
+ * This transformation is fed by the current "mod data".
+ *
+ * Right now the mod data is the current date (GMT) as a string: "yyyyMMdd",
+ * and the transformation takes the original hash, appends the bytes of that mod data,
+ * then returns the SHA256 of that concatenation.
+ *
+ * Do we want this to simply do the XOR of the SHA256 of the current mod data and
+ * the key? does that provide the randomization we need? It'd save an SHA256 op.
+ * Bah, too much effort to think about for so little gain. Other algorithms may come
+ * into play layer on about making periodic updates to the routing key for data elements
+ * to mess with Sybil. This may be good enough though.
+ *
+ * Also - the method generateDateBasedModData() should be called after midnight GMT
+ * once per day to generate the correct routing keys!
+ *
+ * @since 0.9.16 moved from net.i2p.data.RoutingKeyGenerator..
+ *
+ */
+public class RouterKeyGenerator extends RoutingKeyGenerator {
+ private final Log _log;
+ private final I2PAppContext _context;
+
+ public RouterKeyGenerator(I2PAppContext context) {
+ _log = context.logManager().getLog(RoutingKeyGenerator.class);
+ _context = context;
+ // ensure non-null mod data
+ generateDateBasedModData();
+ }
+
+ private volatile byte _currentModData[];
+ private volatile byte _nextModData[];
+ private volatile long _nextMidnight;
+ private volatile long _lastChanged;
+
+ private final static Calendar _cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"));
+ private static final String FORMAT = "yyyyMMdd";
+ private static final int LENGTH = FORMAT.length();
+ private final static SimpleDateFormat _fmt = new SimpleDateFormat(FORMAT, Locale.US);
+ static {
+ // make sure GMT is set, azi2phelper Vuze plugin is disabling static JVM TZ setting in Router.java
+ _fmt.setCalendar(_cal);
+ }
+
+ /**
+ * The current (today's) mod data.
+ * Warning - not a copy, do not corrupt.
+ *
+ * @return non-null, 8 bytes
+ */
+ public byte[] getModData() {
+ return _currentModData;
+ }
+
+ /**
+ * Tomorrow's mod data.
+ * Warning - not a copy, do not corrupt.
+ * For debugging use only.
+ *
+ * @return non-null, 8 bytes
+ * @since 0.9.10
+ */
+ public byte[] getNextModData() {
+ return _nextModData;
+ }
+
+ public long getLastChanged() {
+ return _lastChanged;
+ }
+
+ /**
+ * How long until midnight (ms)
+ *
+ * @return could be slightly negative
+ * @since 0.9.10 moved from UpdateRoutingKeyModifierJob
+ */
+ public long getTimeTillMidnight() {
+ return _nextMidnight - _context.clock().now();
+ }
+
+ /**
+ * Set _cal to midnight for the time given.
+ * Caller must synch.
+ * @since 0.9.10
+ */
+ private void setCalToPreviousMidnight(long now) {
+ _cal.setTime(new Date(now));
+ _cal.set(Calendar.YEAR, _cal.get(Calendar.YEAR)); // gcj <= 4.0 workaround
+ _cal.set(Calendar.DAY_OF_YEAR, _cal.get(Calendar.DAY_OF_YEAR)); // gcj <= 4.0 workaround
+ _cal.set(Calendar.HOUR_OF_DAY, 0);
+ _cal.set(Calendar.MINUTE, 0);
+ _cal.set(Calendar.SECOND, 0);
+ _cal.set(Calendar.MILLISECOND, 0);
+ }
+
+ /**
+ * Generate mod data from _cal.
+ * Caller must synch.
+ * @since 0.9.10
+ */
+ private byte[] generateModDataFromCal() {
+ Date today = _cal.getTime();
+
+ String modVal = _fmt.format(today);
+ if (modVal.length() != LENGTH)
+ throw new IllegalStateException();
+ byte[] mod = new byte[LENGTH];
+ for (int i = 0; i < LENGTH; i++)
+ mod[i] = (byte)(modVal.charAt(i) & 0xFF);
+ return mod;
+ }
+
+ /**
+ * Update the current modifier data with some bytes derived from the current
+ * date (yyyyMMdd in GMT)
+ *
+ * @return true if changed
+ */
+ public synchronized boolean generateDateBasedModData() {
+ long now = _context.clock().now();
+ setCalToPreviousMidnight(now);
+ byte[] mod = generateModDataFromCal();
+ boolean changed = !Arrays.equals(_currentModData, mod);
+ if (changed) {
+ // add a day and store next midnight and mod data for convenience
+ _cal.add(Calendar.DATE, 1);
+ _nextMidnight = _cal.getTime().getTime();
+ byte[] next = generateModDataFromCal();
+ _currentModData = mod;
+ _nextModData = next;
+ // ensure version is bumped
+ if (_lastChanged == now)
+ now++;
+ _lastChanged = now;
+ if (_log.shouldLog(Log.INFO))
+ _log.info("Routing modifier generated: " + HexDump.dump(mod));
+ }
+ return changed;
+ }
+
+ /**
+ * Generate a modified (yet consistent) hash from the origKey by generating the
+ * SHA256 of the targetKey with the current modData appended to it
+ *
+ * This makes Sybil's job a lot harder, as she needs to essentially take over the
+ * whole keyspace.
+ *
+ * @throws IllegalArgumentException if origKey is null
+ */
+ public Hash getRoutingKey(Hash origKey) {
+ return getKey(origKey, _currentModData);
+ }
+
+ /**
+ * Get the routing key using tomorrow's modData, not today's
+ *
+ * @since 0.9.10
+ */
+ public Hash getNextRoutingKey(Hash origKey) {
+ return getKey(origKey, _nextModData);
+ }
+
+ /**
+ * Generate a modified (yet consistent) hash from the origKey by generating the
+ * SHA256 of the targetKey with the specified modData appended to it
+ *
+ * @throws IllegalArgumentException if origKey is null
+ */
+ private static Hash getKey(Hash origKey, byte[] modData) {
+ if (origKey == null) throw new IllegalArgumentException("Original key is null");
+ byte modVal[] = new byte[Hash.HASH_LENGTH + LENGTH];
+ System.arraycopy(origKey.getData(), 0, modVal, 0, Hash.HASH_LENGTH);
+ System.arraycopy(modData, 0, modVal, Hash.HASH_LENGTH, LENGTH);
+ return SHA256Generator.getInstance().calculateHash(modVal);
+ }
+
+/****
+ public static void main(String args[]) {
+ Hash k1 = new Hash();
+ byte k1d[] = new byte[Hash.HASH_LENGTH];
+ RandomSource.getInstance().nextBytes(k1d);
+ k1.setData(k1d);
+
+ for (int i = 0; i < 10; i++) {
+ System.out.println("K1: " + k1);
+ Hash k1m = RoutingKeyGenerator.getInstance().getRoutingKey(k1);
+ System.out.println("MOD: " + new String(RoutingKeyGenerator.getInstance().getModData()));
+ System.out.println("K1M: " + k1m);
+ }
+ try {
+ Thread.sleep(2000);
+ } catch (Throwable t) { // nop
+ }
+ }
+****/
+}
diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java
index 3afd99de2..8fd08eb79 100644
--- a/router/java/src/net/i2p/router/Router.java
+++ b/router/java/src/net/i2p/router/Router.java
@@ -1070,7 +1070,7 @@ public class Router implements RouterClock.ClockShiftListener {
return;
_eventLog.addEvent(EventLog.CLOCK_SHIFT, Long.toString(delta));
// update the routing key modifier
- _context.routingKeyGenerator().generateDateBasedModData();
+ _context.routerKeyGenerator().generateDateBasedModData();
if (_context.commSystem().countActivePeers() <= 0)
return;
if (delta > 0)
diff --git a/router/java/src/net/i2p/router/RouterContext.java b/router/java/src/net/i2p/router/RouterContext.java
index 20b2fe9b7..fd5c65775 100644
--- a/router/java/src/net/i2p/router/RouterContext.java
+++ b/router/java/src/net/i2p/router/RouterContext.java
@@ -10,7 +10,9 @@ import java.util.concurrent.CopyOnWriteArrayList;
import net.i2p.I2PAppContext;
import net.i2p.app.ClientAppManager;
import net.i2p.data.Hash;
+import net.i2p.data.RoutingKeyGenerator;
import net.i2p.data.router.RouterInfo;
+import net.i2p.data.router.RouterKeyGenerator;
import net.i2p.internal.InternalClientManager;
import net.i2p.router.client.ClientManagerFacadeImpl;
import net.i2p.router.crypto.TransientSessionKeyManager;
@@ -65,6 +67,7 @@ public class RouterContext extends I2PAppContext {
//private MessageStateMonitor _messageStateMonitor;
private RouterThrottle _throttle;
private RouterAppManager _appManager;
+ private RouterKeyGenerator _routingKeyGenerator;
private final Set