java.lang.Object
net.i2p.crypto.YKGenerator

final class YKGeneratorextends Object
Precalculate the Y and K for ElGamal encryption operations.

This class precalcs a set of values on its own thread, using those transparently when a new instance is created. By default, the minimum threshold for creating new values for the pool is 50, and the max pool size is 200 (30 and 100 on a slow system); both scale up with heap size, to 400 and 1600. Whenever the pool has less than the minimum, it refills it above the minimum by however many values it saw consumed since the previous check, so an idle router does no speculative 2048-bit modular exponentiations. There is a delay after each precalculation so that the CPU isn't hosed during startup. These three parameters are controlled by java environmental variables and can be adjusted via: -Dcrypto.yk.precalc.min=40 -Dcrypto.yk.precalc.max=100 -Dcrypto.yk.precalc.delay=60000

(delay is milliseconds)

To disable precalculation, set min to 0

Tradeoff: the pool now normally sits near the minimum rather than near the maximum, so a sustained burst can drain it and cost a foreground modular exponentiation per message until the precalc thread catches up. Raise -Dcrypto.yk.precalc.min if that cost is noticeable.

  • Field Details

    • MIN_NUM_BUILDERS

      private final int MIN_NUM_BUILDERS
      Fewest builder threads allowed.
    • MAX_NUM_BUILDERS

      private final int MAX_NUM_BUILDERS
      Most builder threads allowed.
    • CALC_DELAY

      private final int CALC_DELAY
      Delay between the value calculations.
    • _values

      private final LinkedBlockingQueue<BigInteger[]> _values
      The precalculated Y values waiting for use.
    • _size

      private final AtomicInteger _size
      Pool occupancy, maintained alongside _values: sampling LinkedBlockingQueue.size() takes both the put and the take lock, so it contends with poll() on the encryption path.
    • _precalcThread

      private volatile Thread _precalcThread
      The precalc thread. Volatile so the encryption path can read it without taking the monitor that start() and shutdown() hold.
    • _pinged

      private final AtomicBoolean _pinged
      Whether the precalc thread has already been woken for the current idle period. A sustained burst misses on every message, and each miss would otherwise interrupt the precalc thread out of its check sleep and straight back into it.
    • ctx

      private final I2PAppContext ctx
      The app context.
    • _isRunning

      private volatile boolean _isRunning
      True while the generator runs.
    • PROP_YK_PRECALC_MIN

      public static final String PROP_YK_PRECALC_MIN
      Property: minimum pool threshold.
      See Also:
    • PROP_YK_PRECALC_MAX

      public static final String PROP_YK_PRECALC_MAX
      Property: maximum pool size.
      See Also:
    • PROP_YK_PRECALC_DELAY

      public static final String PROP_YK_PRECALC_DELAY
      Property: delay between precalc operations (ms).
      See Also:
    • DEFAULT_YK_PRECALC_MIN

      public static final int DEFAULT_YK_PRECALC_MIN
      Default minimum pool threshold.
    • DEFAULT_YK_PRECALC_MAX

      public static final int DEFAULT_YK_PRECALC_MAX
      Default maximum pool size.
    • DEFAULT_YK_PRECALC_DELAY

      public static final int DEFAULT_YK_PRECALC_DELAY
      Default delay between precalc operations (ms).
    • TWO

      private static final BigInteger TWO
      The big integer two.
  • Constructor Details

    • YKGenerator

      public YKGenerator(I2PAppContext context)
      Caller must also call start() to start the background precalc thread. Unit tests will still work without calling start().
      Parameters:
      context - application context, source of the precalc pool size and delay properties
  • Method Details

    • start

      public void start()
      Start the background precalc thread. Must be called for normal operation. If not called, all generation happens in the foreground. Not required for unit tests.
    • shutdown

      public void shutdown()
      Stop the background precalc thread. Can be restarted. Not required for unit tests.
    • addValues

      private final boolean addValues(BigInteger[] yk)
      Add a precomputed YK value to the buffer.
      Parameters:
      yk - the precomputed YK values to add
      Returns:
      true if successful, false if full
    • getNextYK

      public BigInteger[] getNextYK()
      Next precomputed YK value.
      Returns:
      rv[0] = Y; rv[1] = K
    • claimPing

      final boolean claimPing()
      Claim the one wake-up allowed for the current idle period, so a burst of misses interrupts the precalc thread once instead of per message. The precalc runner releases the claim when it goes back to sleep.
      Returns:
      true if this caller should interrupt the precalc thread
    • releasePing

      final void releasePing()
      Release the wake-up claim, called by the precalc runner as it goes back to sleep so the next drain of the pool can wake it again.
    • generateYK

      private final BigInteger[] generateYK()
      Generate a new YK pair.
      Returns:
      rv[0] = Y; rv[1] = K