gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r32181 - in gnunet-java: . bin src/main/java/org/gnunet/con


From: gnunet
Subject: [GNUnet-SVN] r32181 - in gnunet-java: . bin src/main/java/org/gnunet/consensus src/main/java/org/gnunet/consensus/messages src/main/java/org/gnunet/construct src/main/java/org/gnunet/core src/main/java/org/gnunet/gns src/main/java/org/gnunet/gns/messages src/main/java/org/gnunet/identity src/main/java/org/gnunet/peerinfo src/main/java/org/gnunet/testing src/main/java/org/gnunet/transport src/main/java/org/gnunet/transport/messages src/main/java/org/gnunet/util src/main/java/org/gnunet/util/crypto src/main/java/org/gnunet/voting src/main/resources/org/gnunet/construct src/test/java/org/gnunet/consensus src/test/java/org/gnunet/core src/test/java/org/gnunet/identity src/test/java/org/gnunet/transport src/test/java/org/gnunet/util
Date: Tue, 4 Feb 2014 00:03:52 +0100

Author: dold
Date: 2014-02-04 00:03:52 +0100 (Tue, 04 Feb 2014)
New Revision: 32181

Added:
   gnunet-java/bin/gnunet-gns
Modified:
   gnunet-java/ISSUES
   gnunet-java/build.gradle
   gnunet-java/src/main/java/org/gnunet/consensus/Consensus.java
   gnunet-java/src/main/java/org/gnunet/consensus/messages/ConcludeMessage.java
   gnunet-java/src/main/java/org/gnunet/consensus/messages/JoinMessage.java
   gnunet-java/src/main/java/org/gnunet/construct/MessageLoader.java
   gnunet-java/src/main/java/org/gnunet/core/Core.java
   gnunet-java/src/main/java/org/gnunet/core/SendMessage.java
   gnunet-java/src/main/java/org/gnunet/gns/GnsRecord.java
   gnunet-java/src/main/java/org/gnunet/gns/messages/ClientLookupMessage.java
   
gnunet-java/src/main/java/org/gnunet/gns/messages/ClientLookupResultMessage.java
   gnunet-java/src/main/java/org/gnunet/identity/Identity.java
   gnunet-java/src/main/java/org/gnunet/peerinfo/PeerInfo.java
   gnunet-java/src/main/java/org/gnunet/testing/TestingFixture.java
   gnunet-java/src/main/java/org/gnunet/transport/Transport.java
   gnunet-java/src/main/java/org/gnunet/transport/messages/StartMessage.java
   gnunet-java/src/main/java/org/gnunet/util/Connection.java
   gnunet-java/src/main/java/org/gnunet/util/MessageStreamTokenizer.java
   gnunet-java/src/main/java/org/gnunet/util/PeerIdentity.java
   gnunet-java/src/main/java/org/gnunet/util/RelativeTime.java
   gnunet-java/src/main/java/org/gnunet/util/Scheduler.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/DsaPrng.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EcdhePrivateKey.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPrivateKey.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPublicKey.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignature.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/Ed25519.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaPrivateKey.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaSignature.java
   gnunet-java/src/main/java/org/gnunet/voting/BallotTool.java
   gnunet-java/src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java
   gnunet-java/src/main/resources/org/gnunet/construct/MsgMap.txt
   gnunet-java/src/test/java/org/gnunet/consensus/ConsensusSingleTest.java
   gnunet-java/src/test/java/org/gnunet/consensus/ConsensusTestbedTest.java
   gnunet-java/src/test/java/org/gnunet/core/CoreTest.java
   gnunet-java/src/test/java/org/gnunet/identity/IdentityTest.java
   gnunet-java/src/test/java/org/gnunet/transport/TransportTest.java
   gnunet-java/src/test/java/org/gnunet/util/ClientServerTest.java
   gnunet-java/src/test/java/org/gnunet/util/EcdheTest.java
   gnunet-java/src/test/java/org/gnunet/util/EcdsaTest.java
   gnunet-java/src/test/java/org/gnunet/util/Ed25519Test.java
Log:
- scheduler-per-thread
- fixed ECDSA and crypto endianess
- Gns and GnsTool implemented
- updated consensus protocol 


Modified: gnunet-java/ISSUES
===================================================================
--- gnunet-java/ISSUES  2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/ISSUES  2014-02-03 23:03:52 UTC (rev 32181)
@@ -1,51 +1,35 @@
-secretsharing
- * plaintexts:
-  * due to the (sub-)group we chose, not every bit pattern is a valid
-    message
-  * => GNUNET_SECRETSHARING_message_generate (...)
+scheduler:
+ * scheduler-pre-thread implemented
 
-secretsharing working, both keygen and decryption
- * debugging was a pain ...
- * some mesh crashes appear randomly ...
+crypto:
+ * ECDSA now works correctly ... annoying to fix but entirely my fault
+ * => all the crypto is compatible now
 
-libgcrypt:
-The following code does not terminate.
+paillier:
+ * something broke paillier ... both cfuchs and me are not sure what ...
+ * had to bisect the repo ...
 
-  gcry_mpi_set_ui (x, 0);
-  gcry_mpi_sub_ui (x, x, 1);
-  gcry_mpi_set_ui (p, 17);
-  gcry_mpi_invm (x, x, p);
-
-... which was very "nice" to spot because
-    gcry_mpi_dump prints -1 as "01" ...
-
- * it's kind of hard to trust any gcry_mpi_* op that involves
-   any kind of negative value ....
-
- * it's not documented what powm does when the exponent is negative, but the 
inverse
-   does not exist!
-  * invm at least returns an error flag ...
-
-
 secretsharing:
- * problem with valgrind+testbed: slows stuff down, serialized due to testbed
-  * consensi get out of sync, but are started at the very beginning
-  * proposal: also specify start time for DKG,
-    crypto setup is done *before* start time (of consensus)
+ * key generation works with 'many' (16) peers
+  * sometimes, consensus seems to hang ... still trying to find the cause
+  * very large groups would have problems with element size
+ * distributed key generation still fails sometimes ... seems to be a
+   problem with the crypto implementation
 
-paillier is now in util!
+GNS:
+ * is pin the new FCFS? Why does is not seem to work?
+ * see the two bugs reported (namestore deletion, PKEY+others hangup)
+ * GNS in java:
+  * record types are implemented as Construct unions
+  * org.gnunet.gns.records.Record is the message union
+  * @UnionCase specifies the record number
+  * records must have a static recordTypeName, recordTypeId
+   * ... which is put in a table with reflection
+  * createFromString("A", "127.0.0.1") uses reflection
+  * recData.getRecordString instead of recData.toString, as toString should 
not return null
+  * => extensible via classpath
+  * gnunet-gns is also re-implemented in java now
 
-next: implement ZKPs
+Feb 02 19:23:20-300517 util-20283 DEBUG Connection transmitted 93/93 bytes to 
`/run/user/1000/gnunet-dold-runtime//gnunet-service-g' (0xcc4250)
 
-
-GNS:
- * rudimentary implementation in gnunet-java
- * why is record type in gns_api int, and not unsigned int?
- * gnsrecord: we're lost in java with the plugins
-  * call some helper bin for e.g. record type printing?
-  * use JNA (ctypes-style library for Java)
-  LookupMessage: string termination not documented
-   * fixed, but can't we agree on one way?
-  LookupResultMessage:
-  /* followed by rd_count GNUNET_GNSRECORD_Data structs*/
-  can't be true, as the struct contains a pointer ...
+The truncation is not very helpful

Added: gnunet-java/bin/gnunet-gns
===================================================================
--- gnunet-java/bin/gnunet-gns                          (rev 0)
+++ gnunet-java/bin/gnunet-gns  2014-02-03 23:03:52 UTC (rev 32181)
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+if [ "%GNJ_INSTALLED" = "true" ];
+then
+    export CLASSPATH="%INSTALL_PATH/share/java/*"
+else
+    DIR=`dirname $0`
+    # if we are in the development environment use class files directly 
instead of jar
+    export 
CLASSPATH="$DIR/../build-gradle/classes/main/:$DIR/../build-gradle/resources/main/:$DIR/../lib/*"
+fi
+
+java -ea org.gnunet.gns.GnsTool "$@"


Property changes on: gnunet-java/bin/gnunet-gns
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Modified: gnunet-java/build.gradle
===================================================================
--- gnunet-java/build.gradle    2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/build.gradle    2014-02-03 23:03:52 UTC (rev 32181)
@@ -4,16 +4,18 @@
 
 apply plugin: 'java'
 
-buildDir = "$projectDir/build-gradle"
+buildDir = "$projectDir/build-gradle"   
 
 sourceCompatibility = "1.6"
 targetCompatibility = "1.6"
 
 // specify where to get jars
 repositories {
+  // we either get them from the libs dir
   flatDir {
     dirs 'lib'
   }
+  // or from the maven central repository
   mavenCentral()
 }
 
@@ -109,6 +111,8 @@
   destinationDir = file("$buildDir/classes/main/")
 }
 
+// Define task and dependencies for creating an IZPack installer.
+
 project.ext.installerFile = "$projectDir/gnunet-java-installer.jar"
 
 task installer (type: Exec) {
@@ -131,13 +135,17 @@
 }
 
 
+// Which gradle version do we want to use
+// for the wrapper?
 task wrapper(type: Wrapper) {
-  gradleVersion = '1.7'
+    gradleVersion = '1.10'
 }
 
-if (hasProperty("xlint")) {
-  tasks.withType(Compile) {
-    options.compilerArgs << "-Xlint:unchecked"
-  }
+
+// Print test name, so that we can easily find out
+// which test does not terminate.
+test {
+    beforeTest{ descr ->
+        logger.warn("Starting Test ${descr.className} : ${descr.name}")    
+    }
 }
-

Modified: gnunet-java/src/main/java/org/gnunet/consensus/Consensus.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/consensus/Consensus.java       
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/consensus/Consensus.java       
2014-02-03 23:03:52 UTC (rev 32181)
@@ -69,6 +69,7 @@
 
         @Override
         public void handleError() {
+            System.out.println("Error receiving from consensus service.");
             consensusCallback.onElement(null);
         }
     }
@@ -81,8 +82,11 @@
      *              Inclusion of the local peer is optional.
      * @param sessionId session identifier
      *                   Allows a group of peers to have more than consensus 
session.
+     * @param startTime when should the consensus start?
+     * @param deadline when should we be done?
      */
-    public Consensus(Configuration cfg, PeerIdentity[] peers, HashCode 
sessionId) {
+    public Consensus(Configuration cfg, PeerIdentity[] peers, HashCode 
sessionId,
+                     AbsoluteTime startTime, AbsoluteTime deadline) {
         client = new Client("consensus", cfg);
         client.installReceiver(new ConsensusMessageReceiver());
 
@@ -90,6 +94,8 @@
         m.numPeers = peers.length;
         m.peers = peers;
         m.sessionId = sessionId;
+        m.startTime = startTime.asMessage();
+        m.deadline = deadline.asMessage();
         client.send(m);
     }
 
@@ -131,16 +137,13 @@
      * After conclude has been called, no further elements may be
      * inserted by the client.
      *
-     * @param concludeTimeout timeout for conclude, may never be forever
      * @param concludeCallback called when the consensus has concluded
      */
-    public void conclude(RelativeTime concludeTimeout, ConsensusCallback 
concludeCallback) {
+    public void conclude(ConsensusCallback concludeCallback) {
         Preconditions.checkNotNull(concludeCallback, "conclude with null 
callback");
         Preconditions.checkState(null == this.consensusCallback, "called 
conclude twice");
-        Preconditions.checkArgument(!concludeTimeout.isForever(), "conclude 
timeout may not be forever");
         this.consensusCallback = concludeCallback;
         ConcludeMessage m = new ConcludeMessage();
-        m.concludeTimeout = concludeTimeout.toNetwork();
         client.send(m);
     }
 

Modified: 
gnunet-java/src/main/java/org/gnunet/consensus/messages/ConcludeMessage.java
===================================================================
--- 
gnunet-java/src/main/java/org/gnunet/consensus/messages/ConcludeMessage.java    
    2014-02-03 23:00:30 UTC (rev 32180)
+++ 
gnunet-java/src/main/java/org/gnunet/consensus/messages/ConcludeMessage.java    
    2014-02-03 23:03:52 UTC (rev 32181)
@@ -21,10 +21,7 @@
 package org.gnunet.consensus.messages;
 
 import org.gnunet.construct.*;
-import org.gnunet.util.AbsoluteTime;
-import org.gnunet.util.GnunetMessage;
-import org.gnunet.util.RelativeTime;
-import org.gnunet.util.RelativeTimeMessage;
+import org.gnunet.util.*;
 
 /**
  * Notify the client of a new element.
@@ -35,6 +32,4 @@
  */
 @UnionCase(524)
 public class ConcludeMessage implements GnunetMessage.Body {
-    @NestedMessage
-    public RelativeTimeMessage concludeTimeout;
 }
\ No newline at end of file

Modified: 
gnunet-java/src/main/java/org/gnunet/consensus/messages/JoinMessage.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/consensus/messages/JoinMessage.java    
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/consensus/messages/JoinMessage.java    
2014-02-03 23:03:52 UTC (rev 32181)
@@ -24,6 +24,7 @@
 import org.gnunet.construct.UInt32;
 import org.gnunet.construct.UnionCase;
 import org.gnunet.construct.VariableSizeArray;
+import org.gnunet.util.AbsoluteTimeMessage;
 import org.gnunet.util.GnunetMessage;
 import org.gnunet.util.HashCode;
 import org.gnunet.util.PeerIdentity;
@@ -34,6 +35,9 @@
     public int numPeers;
     @NestedMessage
     public HashCode sessionId;
+    @NestedMessage
+    public AbsoluteTimeMessage startTime;
+    public AbsoluteTimeMessage deadline;
     @VariableSizeArray(lengthField = "numPeers")
     public PeerIdentity[] peers;
 }

Modified: gnunet-java/src/main/java/org/gnunet/construct/MessageLoader.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/construct/MessageLoader.java   
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/construct/MessageLoader.java   
2014-02-03 23:03:52 UTC (rev 32181)
@@ -197,6 +197,12 @@
         return map.get(unionCase);
     }
 
+    public static Class<? extends MessageUnion>[] getUnionCases(Class<? 
extends MessageUnion> unionInterface) {
+        Map<Class<? extends MessageUnion>, Integer> map = 
tagmap.get(unionInterface);
+        //noinspection unchecked
+        return (Class<? extends MessageUnion>[]) map.keySet().toArray(new 
Class[map.keySet().size()]);
+    }
+
     public static void registerUnionCase(Class<? extends MessageUnion> 
unionInterface,
                                          Class<? extends MessageUnion> 
unionCase, int tag) {
         if (!unionmap.containsKey(unionInterface)) {

Modified: gnunet-java/src/main/java/org/gnunet/core/Core.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/core/Core.java 2014-02-03 23:00:30 UTC 
(rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/core/Core.java 2014-02-03 23:03:52 UTC 
(rev 32181)
@@ -116,7 +116,8 @@
         final public MessageTransmitter transmitter;
         final public AbsoluteTime deadline;
 
-        public NotifyTransmitReadyRequest(int priority, int size, PeerIdentity 
target, RelativeTime timeout, MessageTransmitter transmitter) {
+        public NotifyTransmitReadyRequest(int priority, int size, PeerIdentity 
target,
+                                          RelativeTime timeout, 
MessageTransmitter transmitter) {
             this.deadline = timeout.toAbsolute();
             this.priority = priority;
             this.size = size;
@@ -197,6 +198,7 @@
         }
 
         public void visit(SendMessageReady m) {
+            logger.debug("got SendMessageReady");
             RequestIdentification rid = new RequestIdentification(m.smrId, 
m.peer);
             NotifyTransmitReadyRequest req = ntrRequests.getRequest(rid);
 
@@ -232,6 +234,7 @@
 
         @Override
         public void handleError() {
+            logger.warn("Error receiving from the transport service.");
             if (disconnectHandler != null) {
                 for (PeerIdentity e : connectedPeers.keySet()) {
                     disconnectHandler.onDisconnect(e);
@@ -285,7 +288,8 @@
         }
         int id = connectedPeers.get(target);
         connectedPeers.put(target, id+1);
-        NotifyTransmitReadyRequest notifyRequest = new 
NotifyTransmitReadyRequest(priority, size, target, maxdelay, transmitter);
+        NotifyTransmitReadyRequest notifyRequest = new 
NotifyTransmitReadyRequest(priority, size, target,
+                maxdelay, transmitter);
         notifyRequest.smrId = id;
         RequestIdentification rid = new 
RequestIdentification(notifyRequest.smrId, target);
         return ntrRequests.addRequest(rid, notifyRequest);

Modified: gnunet-java/src/main/java/org/gnunet/core/SendMessage.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/core/SendMessage.java  2014-02-03 
23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/core/SendMessage.java  2014-02-03 
23:03:52 UTC (rev 32181)
@@ -62,7 +62,7 @@
     /**
      * Always 0.
      */
-    @UInt64
+    @UInt32
     public int reserved;
 
     @NestedMessage(newFrame = true)

Modified: gnunet-java/src/main/java/org/gnunet/gns/GnsRecord.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/gns/GnsRecord.java     2014-02-03 
23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/gns/GnsRecord.java     2014-02-03 
23:03:52 UTC (rev 32181)
@@ -1,86 +1,129 @@
-/*
- This file is part of GNUnet.
-  (C) 2012, 2013 Christian Grothoff (and other contributing authors)
+package org.gnunet.gns;
 
-  GNUnet is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 3, or (at your
-  option) any later version.
 
-  GNUnet is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+import com.google.common.collect.Maps;
+import org.gnunet.construct.*;
+import org.gnunet.gns.records.RecordData;
+import org.gnunet.gns.records.UnknownRecordData;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-  You should have received a copy of the GNU General Public License
-  along with GNUnet; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-  Boston, MA 02111-1307, USA.
- */
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
 
-package org.gnunet.gns;
+public class GnsRecord implements Message {
+    private static final Logger logger = LoggerFactory
+            .getLogger(GnsRecord.class);
 
-import org.gnunet.construct.Message;
-import org.gnunet.construct.UInt32;
-import org.gnunet.construct.UInt64;
-import org.gnunet.construct.VariableSizeIntegerArray;
+    private static boolean registryInitialized;
 
-/**
- * A GNS record.
- */
-public class GnsRecord implements Message {
+    private static BiMap<String,Long> recordTypeMap = HashBiMap.create();
+    private static Map<Long,Class> recordClassMap = Maps.newHashMap();
+
     /**
-     * No special options.
+     * Expiration, either absolute or relative time depending on 'flags'.
      */
-    public static final int FLAG_NONE = 0;
-    /**
-     * No special options.
-     */
-    public static final int FLAG_PRIVATE = 2;
-    /**
-     * This record was added automatically by the system
-     * and is pending user confimation.
-     */
-    public static final int FLAG_PENDING = 4;
-    /**
-     * This expiration time of the record is a relative
-     * time (not an absolute time).
-     */
-    public static final int FLAG_RELATIVE_EXPIRATION = 8;
-    /**
-     * This record should not be used unless all (other) records with an 
absolute
-     * expiration time have expired.
-     */
-    public static final int FLAG_SHADOW_RECOD = 8;
-    /**
-     * Either absolute or relative expiration time,
-     * depending on 'flags'.
-     */
     @UInt64
-    public long expirationTime;
+    public long expiration;
 
     /**
-     * Size of the record data.
+     * Size of 'recordDataBytes'.
      */
     @UInt32
-    public int dataSize;
+    public long dataSize;
 
     /**
-     * Type of the record.
+     * Type ID of this record.
      */
     @UInt32
-    public int recordType;
+    public long recordType;
 
-    /**
-     * Flags for the record.
-     */
     @UInt32
-    int flags;
+    public long flags;
 
-    /**
-     * Binary value stored in the GNS record.
-     */
-    @VariableSizeIntegerArray(lengthField = "dataSize", bitSize = 8, signed = 
false)
-    byte[] data;
+    @VariableSizeIntegerArray(lengthField = "dataSize", signed = true, bitSize 
= 8)
+    public byte[] recordDataBytes;
 
+    public static void initializeRegistry() {
+        if (registryInitialized)
+            return;
+        Class<?>[] classes = MessageLoader.getUnionCases(RecordData.class);
+        for (Class<?> aClass : classes) {
+            String recordTypeString;
+            try {
+                Field field = aClass.getField("recordTypeString");
+                recordTypeString = (String) field.get(null);
+            } catch (NoSuchFieldException e) {
+                logger.warn("RecordData class {} has no recordTypeString 
field");
+                continue;
+            } catch (IllegalAccessException e) {
+                logger.warn("RecordData class {} can't access recordTypeString 
field");
+                continue;
+            }
+
+            long recordTypeId = MessageLoader.getUnionTag(RecordData.class, 
(Class<? extends MessageUnion>) aClass);
+            recordTypeMap.put(recordTypeString, recordTypeId);
+            recordClassMap.put(recordTypeId, aClass);
+        }
+        registryInitialized = true;
+    }
+
+    public RecordData getRecordData() {
+        initializeRegistry();
+        Class cls = recordClassMap.get(recordType);
+        if (null == cls) {
+            UnknownRecordData unknownRecordData = new UnknownRecordData();
+            unknownRecordData.data = recordDataBytes;
+        }
+        return (RecordData) Construct.parseAs(recordDataBytes, cls);
+    }
+
+    public static GnsRecord createFromString(String typeString, String 
content) {
+        long typeId = getIdFromString(typeString);
+        if (typeId < 0)
+            return null;
+        return createFromString(typeId, content);
+    }
+
+    public static GnsRecord createFromString(long typeId, String content) {
+        initializeRegistry();
+        Class cls = recordClassMap.get(typeId);
+        if (null == cls) {
+            return null;
+        }
+        Method mth;
+        try {
+            mth = cls.getMethod("createFromString", String.class);
+        } catch (NoSuchMethodException e) {
+            return null;
+        }
+        try {
+            return (GnsRecord) mth.invoke(null, content);
+        } catch (IllegalAccessException e) {
+            return null;
+        } catch (InvocationTargetException e) {
+            return null;
+        }
+    }
+
+    public static String getStringFromId(long typeId) {
+        initializeRegistry();
+        if (!recordTypeMap.inverse().containsKey(typeId)) {
+            return null;
+        }
+        return recordTypeMap.inverse().get(typeId);
+    }
+
+    public static long getIdFromString(String typeString) {
+        initializeRegistry();
+        if (!recordTypeMap.containsKey(typeString)) {
+            return -1;
+        }
+        return recordTypeMap.get(typeString);
+    }
 }

Modified: 
gnunet-java/src/main/java/org/gnunet/gns/messages/ClientLookupMessage.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/gns/messages/ClientLookupMessage.java  
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/gns/messages/ClientLookupMessage.java  
2014-02-03 23:03:52 UTC (rev 32181)
@@ -57,7 +57,7 @@
      * the type of record to look up
      */
     @Int32
-    public int type;
+    public long type;
 
     /**
      * The key for shorten, if haveKey is set

Modified: 
gnunet-java/src/main/java/org/gnunet/gns/messages/ClientLookupResultMessage.java
===================================================================
--- 
gnunet-java/src/main/java/org/gnunet/gns/messages/ClientLookupResultMessage.java
    2014-02-03 23:00:30 UTC (rev 32180)
+++ 
gnunet-java/src/main/java/org/gnunet/gns/messages/ClientLookupResultMessage.java
    2014-02-03 23:03:52 UTC (rev 32181)
@@ -43,8 +43,6 @@
 import org.gnunet.construct.*;
 import org.gnunet.gns.GnsRecord;
 import org.gnunet.util.GnunetMessage;
-import org.gnunet.util.crypto.EcdsaPrivateKey;
-import org.gnunet.util.crypto.EcdsaPublicKey;
 
 /**
  * Message GNS service to client as a response to a lookup request.
@@ -57,6 +55,9 @@
     @UInt32
     public long id;
 
+    /**
+     * Number of records.
+     */
     @UInt32
     public long recordCount;
 

Modified: gnunet-java/src/main/java/org/gnunet/identity/Identity.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/identity/Identity.java 2014-02-03 
23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/identity/Identity.java 2014-02-03 
23:03:52 UTC (rev 32181)
@@ -348,6 +348,7 @@
         @Override
         public void handleError() {
             logger.warn("identity service disconnected");
+            // FIXME: should have exp. backoff
             client.reconnect();
         }
 

Modified: gnunet-java/src/main/java/org/gnunet/peerinfo/PeerInfo.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/peerinfo/PeerInfo.java 2014-02-03 
23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/peerinfo/PeerInfo.java 2014-02-03 
23:03:52 UTC (rev 32181)
@@ -35,7 +35,7 @@
  */
 public class PeerInfo {
     private static final Logger logger = LoggerFactory
-            .getLogger(AbsoluteTime.class);
+            .getLogger(PeerInfo.class);
 
     /**
      * Client that connects to the peerinfo service.

Modified: gnunet-java/src/main/java/org/gnunet/testing/TestingFixture.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/testing/TestingFixture.java    
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/testing/TestingFixture.java    
2014-02-03 23:03:52 UTC (rev 32181)
@@ -3,12 +3,23 @@
 import org.gnunet.util.Scheduler;
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
+import org.junit.rules.Timeout;
 
 /**
  * Default JUnit4 fixture methods for gnunet-java tests.
  * Resets the scheduler properly.
  */
 public class TestingFixture {
+
+    /**
+     * All gnunet-java tests that inherit from the fixture
+     * have a 10-second default timeout.
+     * FIXME: for a longer timeout, which has precedence?
+     */
+    @Rule
+    public Timeout defaultTimeout = new Timeout(10000);
+
     @Before
     public void beginGNJTest() {
         Scheduler.forceReset();

Modified: gnunet-java/src/main/java/org/gnunet/transport/Transport.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/transport/Transport.java       
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/transport/Transport.java       
2014-02-03 23:03:52 UTC (rev 32181)
@@ -10,6 +10,8 @@
 import org.gnunet.transport.messages.RequestConnectMessage;
 import org.gnunet.transport.messages.StartMessage;
 import org.gnunet.util.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.LinkedList;
 import java.util.List;
@@ -20,7 +22,8 @@
  * @author Florian Dold
  */
 public class Transport {
-
+    private static final Logger logger = LoggerFactory
+            .getLogger(Transport.class);
     /**
      * Client that connects to the transport service,
      */
@@ -55,6 +58,8 @@
         }
         @Override
         public void handleError() {
+            logger.warn("Error receiving from the transport service, 
reconnecting.");
+            // FIXME: there is no backoff ...
             client.reconnect();
             sendStart();
         }
@@ -113,10 +118,7 @@
     /**
      * Obtain the HELLO message for this peer.
      *
-     * @param rec function to call with the HELLO, sender will be our peer
-     *            identity; message and sender will be NULL on timeout
-     *            (handshake with transport service pending/failed).
-     *            cost estimate will be 0.
+     * @param rec function to call with the HELLO
      * @return handle to cancel the operation
      */
     Cancelable getHello(final HelloUpdateCallback rec) {

Modified: 
gnunet-java/src/main/java/org/gnunet/transport/messages/StartMessage.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/transport/messages/StartMessage.java   
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/transport/messages/StartMessage.java   
2014-02-03 23:03:52 UTC (rev 32181)
@@ -1,3 +1,22 @@
+/*
+ This file is part of GNUnet.
+ (C) 2014 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING.  If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
 package org.gnunet.transport.messages;
 
 import org.gnunet.construct.NestedMessage;
@@ -7,7 +26,6 @@
 import org.gnunet.util.PeerIdentity;
 
 /**
- *
  * Message from the transport service to the library
  * asking to check if both processes agree about this
  * peers identity.

Modified: gnunet-java/src/main/java/org/gnunet/util/Connection.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/Connection.java   2014-02-03 
23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/util/Connection.java   2014-02-03 
23:03:52 UTC (rev 32181)
@@ -188,6 +188,7 @@
                 logger.debug("ready to receive");
                 try {
                     processedMessage = false;
+                    logger.debug("reading into mst ...");
                     int n = mst.readFrom(connectionChannel, true);
                     logger.debug("read {} bytes into mst", n);
                     if (processedMessage) {
@@ -263,7 +264,7 @@
                 throw new IOError(e);
             }
             if (transmitBuffer.remaining() == 0) {
-                //logger.debug("sent " + transmitBuffer.position() + "bytes 
complete message");
+                logger.debug("transmit buffer fully sent");
                 if (nextTransmitHelper == null) {
                     currentTransmitHelper = null;
                 } else {

Modified: gnunet-java/src/main/java/org/gnunet/util/MessageStreamTokenizer.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/MessageStreamTokenizer.java       
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/util/MessageStreamTokenizer.java       
2014-02-03 23:03:52 UTC (rev 32181)
@@ -125,6 +125,7 @@
      */
     public int readFrom(ReadableByteChannel source, boolean oneShot) throws 
IOException {
         int n;
+        logger.debug("reading in mst from channel");
         n = source.read(buffer);
         logger.debug("read {} bytes from channel", n);
         if (oneShot) {

Modified: gnunet-java/src/main/java/org/gnunet/util/PeerIdentity.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/PeerIdentity.java 2014-02-03 
23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/util/PeerIdentity.java 2014-02-03 
23:03:52 UTC (rev 32181)
@@ -28,31 +28,21 @@
 
 
 /**
- * Identity of a peer, stored as 512-bit public key.
+ * Identity of a peer.  Wrapper for an
+ * EdDSA key.
  */
 public class PeerIdentity implements Message {
 
-    @FixedSizeIntegerArray(length = 64, signed = false, bitSize = 8)
+    @FixedSizeIntegerArray(length = 32, signed = false, bitSize = 8)
     public byte[] data;
 
-    static final String HEXES = "0123456789ABCDEF";
-
     /**
      * Creates a zero-filled peer identity
      */
     public PeerIdentity() {
-        data = new byte[64];
+        data = new byte[32];
     }
 
-    public String getHex() {
-        final StringBuilder hex = new StringBuilder( 2 * data.length );
-        for (final byte b : data) {
-            hex.append(HEXES.charAt((b & 0xF0) >> 4))
-                    .append(HEXES.charAt((b & 0x0F)));
-        }
-        return hex.toString();
-    }
-
     public String toString() {
         return Strings.dataToString(data);
     }

Modified: gnunet-java/src/main/java/org/gnunet/util/RelativeTime.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/RelativeTime.java 2014-02-03 
23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/util/RelativeTime.java 2014-02-03 
23:03:52 UTC (rev 32181)
@@ -44,6 +44,8 @@
 
     public static final RelativeTime ZERO = new RelativeTime(0);
     public static final RelativeTime FOREVER = new 
RelativeTime(Long.MAX_VALUE);
+    public static final RelativeTime STD_BACKOFF = MILLISECOND;
+    public static final RelativeTime STD_BACKOFF_MAX = MINUTE.multiply(15);
 
     /**
      * Time offset in microseconds.
@@ -227,7 +229,11 @@
         }
     }
 
-    public Object getSeconds() {
+    public RelativeTime backoff() {
+        return RelativeTime.min(STD_BACKOFF_MAX, this.multiply(2));
+    }
+
+    public long getSeconds() {
         return rel_value_us / (1000 * 1000);
     }
 }

Modified: gnunet-java/src/main/java/org/gnunet/util/Scheduler.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/Scheduler.java    2014-02-03 
23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/util/Scheduler.java    2014-02-03 
23:03:52 UTC (rev 32181)
@@ -32,85 +32,352 @@
 
 /**
  * Schedule computations using continuation passing style.
- * <p/>
- * By design, it is not safe to scheduler tasks from different threads.
- * When threads can't be avoided, they should communicate with the scheduler by
- * a pipe.
  *
+ * All operations, per default, use the thread-local scheduler.
+ *
  * @author Florian Dold
  */
 public class Scheduler {
     private static final Logger logger = LoggerFactory
             .getLogger(Scheduler.class);
 
-    /**
-     * Task that we are currently executing, or null if no task is currently 
running.
-     */
-    private static TaskIdentifier activeTask = null;
 
-    /**
-     * Number of tasks in the ready lists, that is, number of tasks that is 
ready to run
-     * (all prerequisites are fulfilled).
-     */
-    private static volatile int readyCount = 0;
+    static ThreadLocal<SchedulerInstance> threadScheduler = new 
ThreadLocal<SchedulerInstance>() {
+        @Override
+        protected SchedulerInstance initialValue() {
+            return new SchedulerInstance();
+        }
+    };
 
-    /**
-     * Priority for Tasks, in order if ascending priority.
-     * When two tasks are ready, the one with the higher priority is executed 
first.
-     */
-    public enum Priority {
-        IDLE, BACKGROUND, DEFAULT, HIGH, UI, URGENT, SHUTDOWN;
 
+    private static class SchedulerInstance {
         /**
-         * how many different priorities do we have?
+         * Task that we are currently executing, or null if no task is 
currently running.
          */
-        private static final int numberOfPriorities = Priority.values().length;
-    }
+        TaskIdentifier activeTask = null;
 
-    /**
-     * For every priority, there is a list of tasks that is definitely ready 
to run.
-     */
-    @SuppressWarnings("unchecked")
-    final private static LinkedList<TaskIdentifier>[] readyLists = new 
LinkedList[Priority.numberOfPriorities];
+        /**
+         * Number of tasks in the ready lists, that is, number of tasks that 
is ready to run
+         * (all prerequisites are fulfilled).
+         */
+        int readyCount = 0;
 
-    static {
-        for (int i = 0; i < Priority.numberOfPriorities; ++i) {
-            readyLists[i] = new LinkedList<TaskIdentifier>();
+        /**
+         * Selector, used to check file descriptors for readiness.
+         */
+        Selector selector = null;
+
+        /**
+         * For every priority, there is a list of tasks that is definitely 
ready to run.
+         */
+        @SuppressWarnings("unchecked")
+        final LinkedList<TaskIdentifier>[] readyLists = new 
LinkedList[Priority.numberOfPriorities];
+
+        /**
+         * true iff the scheduler is currently running.
+         */
+        boolean schedulerRunning = false;
+
+
+        /**
+         * Pending tasks are waiting for an event. Each pending task has a 
(possibly infinitely long)
+         * deadline after which the task is executed regardless of the 
prerequisites.
+         */
+        final Queue<TaskIdentifier> pending = new 
PriorityQueue<TaskIdentifier>(5, new Comparator
+                <TaskIdentifier>() {
+            @Override
+            public int compare(TaskIdentifier a, TaskIdentifier b) {
+                return a.deadline.compareTo(b.deadline);
+            }
+        });
+
+
+        /**
+         * Check if the system is still life. Trigger disconnect if we have 
tasks, but
+         * none of them give us lifeness.
+         *
+         * @return true to continue the main loop, false to exit
+         */
+        private boolean checkLiveness() {
+            if (readyCount > 0) {
+                return true;
+            }
+            for (TaskIdentifier t : pending) {
+                if (t.lifeness) {
+                    return true;
+                }
+            }
+            // trigger shutdown if we still have pending tasks, but none of 
them has lifeness
+            if (!pending.isEmpty()) {
+                logger.debug("tasks pending but not alive -- disconnect");
+                shutdown();
+                return true;
+            }
+            return false;
         }
-    }
 
-    /**
-     * Selector, used to check file descriptors for readiness.
-     */
-    private static Selector selector = null;
+        /**
+         * Queue a Task for execution.
+         *
+         * @param tid TaskIdentifier of the ready task
+         */
+        private void queueReady(TaskIdentifier tid) {
+            int idx = tid.priority.ordinal();
+            readyLists[idx].add(tid);
+            readyCount++;
+            pending.remove(tid);
+        }
 
-    static {
-        try {
-            selector = SelectorProvider.provider().openSelector();
-        } catch (final IOException e) {
-            // what to do here?
-            logger.error("fatal: cannot create selector");
-            System.exit(-1);
+        void addContinuation(Task task, EnumSet<Reason> reasons) {
+            readyLists[Priority.DEFAULT.ordinal()].add(new 
TaskIdentifier(this, task, reasons));
+            readyCount += 1;
         }
+
+        /**
+         * Queue all tasks with expired timeout.
+         *
+         * @return the minimum time to wait until the next timeout expiry
+         */
+        private RelativeTime handleTimeouts() {
+            RelativeTime timeout = RelativeTime.FOREVER;
+
+            // check if any timeouts occurred
+            while (true) {
+                TaskIdentifier t = pending.peek();
+                if (t == null) {
+                    break;
+                }
+                RelativeTime remaining = t.deadline.getRemaining();
+                if (remaining.getMicroseconds() <= 0) {
+                    t.deregister();
+                    t.ctx.reasons = EnumSet.of(Reason.TIMEOUT);
+                    queueReady(t);
+                } else {
+                    timeout = remaining;
+                    break;
+                }
+            }
+            return timeout;
+        }
+
+
+        public SchedulerInstance() {
+            for (int i = 0; i < Priority.numberOfPriorities; ++i) {
+                readyLists[i] = new LinkedList<TaskIdentifier>();
+            }
+
+            try {
+                selector = SelectorProvider.provider().openSelector();
+            } catch (final IOException e) {
+                // what to do here?
+                logger.error("fatal: cannot create selector");
+                System.exit(-1);
+            }
+        }
+
+
+        /**
+         * Select on channels and queue tasks that become executable.
+         *
+         * @param timeout timeout for select
+         */
+        private void handleSelect(RelativeTime timeout) {
+            // gnunet-java uses microseconds, but the select api uses 
milliseconds
+            long timeout_ms = timeout.getMicroseconds() / 1000;
+            try {
+                // selector.select(0) would block indefinitely 
(counter-intuitive, java's fault)
+                if (timeout_ms == 0) {
+                    selector.selectNow();
+                } else if (timeout.isForever()) {
+                    // fixme: we should only do this if we are sure there are 
tasks that select on something
+                    logger.debug("selecting, timeout=forever");
+                    selector.select(0);
+                } else {
+                    selector.select(timeout_ms);
+                }
+            } catch (IOException e) {
+                throw new IOError(e);
+            }
+
+            logger.debug("select over");
+
+            // we use a set so that we don't execute any task twice
+            Collection<TaskIdentifier> executableTasks = new 
HashSet<TaskIdentifier>();
+            for (SelectionKey sk : selector.selectedKeys()) {
+                @SuppressWarnings("unchecked")
+                LinkedList<TaskInterestOps> subscribers = 
(LinkedList<TaskInterestOps>) sk.attachment();
+                for (TaskInterestOps ops : subscribers) {
+                    if ((sk.readyOps() & ops.interestOps) != 0) {
+                        executableTasks.add(ops.tid);
+                        addReasonsFromInterestOp(ops.tid.ctx.reasons, 
sk.readyOps() & ops.interestOps);
+                    }
+                }
+            }
+            for (TaskIdentifier tt : executableTasks) {
+                // cancel subscriptions to other events, we can execute now!
+                tt.deregister();
+                queueReady(tt);
+            }
+        }
+
+
+        /**
+         * Initialize and run scheduler. This function will return when all 
tasks
+         * have completed.
+         */
+        public void run() {
+            run(null);
+        }
+
+        /**
+         * Initialize and run scheduler. This function will return when all 
tasks
+         * have completed.
+         *
+         * @param initialTask the initial task to run immediately
+         */
+        public void run(Task initialTask) {
+            logger.debug("running scheduler");
+            if (schedulerRunning) {
+                throw new AssertionError("Scheduler already running");
+            }
+            schedulerRunning = true;
+            try {
+                runUnchecked(initialTask);
+            } finally {
+                logger.debug("cleaning up after scheduler ran");
+                // ensure that after run returns, the scheduler is in its 
initial state,
+                // even though there was an exception (e.g. after a test case 
that expects an exception)
+                forceReset();
+            }
+        }
+
+        /**
+         * Request the shutdown of the scheduler. Marks all currently pending 
tasks as
+         * ready because of disconnect. This will cause all tasks to run (as 
soon as
+         * possible, respecting priorities and prerequisite tasks). Note that 
tasks
+         * scheduled AFTER this call may still be delayed arbitrarily.
+         */
+        public void shutdown() {
+            // queueReady() while iterating would yield concurrent 
modification exn otherwise
+            for (TaskIdentifier tid : new ArrayList<TaskIdentifier>(pending)) {
+                tid.ctx.reasons.add(Reason.SHUTDOWN);
+                queueReady(tid);
+            }
+            pending.clear();
+        }
+
+        /**
+         * Reset the scheduler forcefully.
+         * Intended to be used internally in the Scheduler, as well as in test 
teardown.
+         */
+        public void forceReset() {
+            schedulerRunning = false;
+            readyCount = 0;
+            activeTask = null;
+            for (int i = 0; i < Priority.numberOfPriorities; ++i) {
+                readyLists[i] = Lists.newLinkedList();
+            }
+            pending.clear();
+        }
+
+
+        public boolean hasTasks() {
+            return readyCount != 0 || !pending.isEmpty();
+        }
+
+        /**
+         * Execute tasks until either
+         * <ul>
+         * <li>there are no ready tasks</li>
+         * <li>there is a pending task (which may be of higher priority)</li>
+         * </ul>
+         */
+        private void runReady() {
+            do {
+                if (readyCount == 0) {
+                    return;
+                }
+                // start executing from the highest priority down to 0
+                for (int p = Priority.numberOfPriorities - 1; p >= 0; p--) {
+                    // execute all tasks with priority p
+                    LinkedList<TaskIdentifier> queue = readyLists[p];
+                    while (!queue.isEmpty()) {
+                        TaskIdentifier tid = queue.removeFirst();
+                        readyCount--;
+                        tid.run();
+                    }
+                }
+            } while (pending.size() == 0);
+        }
+
+        /**
+         * Initialize and run scheduler. This function will return when all 
tasks
+         * have completed. Don't check if the scheduler is already running or 
not.
+         *
+         * @param initialTask the initial task to run immediately
+         */
+        private void runUnchecked(Task initialTask) {
+            if (initialTask != null) {
+                addContinuation(initialTask, EnumSet.of(Reason.STARTUP));
+            }
+
+            // the gnunet main loop
+            while (checkLiveness()) {
+                RelativeTime nextTimeout = handleTimeouts();
+                if (nextTimeout.getMicroseconds() < 0) {
+                    logger.warn("negative timeout for select");
+                }
+
+                // don't select if there are no tasks; we are done!
+                if (readyCount == 0 && pending.isEmpty()) {
+                    return;
+                }
+
+                // don't block in select if we have tasks ready to run!
+                if (readyCount > 0) {
+                    handleSelect(RelativeTime.ZERO);
+                } else {
+                    handleSelect(nextTimeout);
+                }
+                runReady();
+            }
+
+            if (readyCount != 0) {
+                throw new AssertionError("tasks ready after scheduler ran 
(count)");
+            }
+
+            for (List readyList : readyLists) {
+                if (!readyList.isEmpty()) {
+                    throw new AssertionError("tasks ready after scheduler ran 
(list)");
+                }
+            }
+
+            if (pending.size() != 0) {
+                throw new AssertionError("pending tasks after scheduler ran");
+            }
+
+            if (activeTask != null) {
+                throw new AssertionError("active task after scheduler ran");
+            }
+        }
+
     }
 
-    /**
-     * true iff the scheduler is currently running.
-     */
-    private static boolean schedulerRunning = false;
 
     /**
-     * Pending tasks are waiting for an event. Each pending task has a 
(possibly infinitely long)
-     * deadline after which the task is executed regardless of the 
prerequisites.
+     * Priority for Tasks, in order if ascending priority.
+     * When two tasks are ready, the one with the higher priority is executed 
first.
      */
-    final private static Queue<TaskIdentifier> pending = new 
PriorityQueue<TaskIdentifier>(5, new Comparator
-            <TaskIdentifier>() {
-        @Override
-        public int compare(TaskIdentifier a, TaskIdentifier b) {
-            return a.deadline.compareTo(b.deadline);
-        }
-    });
+    public enum Priority {
+        IDLE, BACKGROUND, DEFAULT, HIGH, UI, URGENT, SHUTDOWN;
 
+        /**
+         * how many different priorities do we have?
+         */
+        private static final int numberOfPriorities = Priority.values().length;
+    }
+
+
     /**
      * Reasons for executing a task.
      */
@@ -140,6 +407,11 @@
      * Manage subscriptions for selection events on channels.
      */
     private static class Subscriptions {
+        /**
+         * Selector to use for subscription operations.
+         */
+        private final Selector selector;
+
         private static class ChannelInterest {
             SelectableChannel channel;
             int interestOps;
@@ -211,6 +483,10 @@
                 key.interestOps(remainingInterestOps);
             }
         }
+
+        public Subscriptions(Selector selector) {
+            this.selector = selector;
+        }
     }
 
     /**
@@ -233,8 +509,10 @@
         private final Priority priority;
         private final AbsoluteTime deadline;
         private final Subscriptions subscriptions;
+        private SchedulerInstance scheduler;
 
-        public TaskIdentifier(Task task, EnumSet<Reason> reasons) {
+        public TaskIdentifier(SchedulerInstance scheduler, Task task, 
EnumSet<Reason> reasons) {
+            this.scheduler = scheduler;
             this.ctx.reasons = reasons;
             this.task = task;
             lifeness = true;
@@ -243,7 +521,8 @@
             subscriptions = null;
         }
 
-        public TaskIdentifier(TaskConfiguration tc) {
+        public TaskIdentifier(SchedulerInstance scheduler, TaskConfiguration 
tc) {
+            this.scheduler = scheduler;
             this.task = tc.task;
             this.subscriptions = tc.subscriptions;
             this.deadline = tc.deadline;
@@ -259,11 +538,11 @@
             if (isCanceled) {
                 return;
             }
-            TaskIdentifier old = activeTask;
-            activeTask = this;
+            TaskIdentifier old = scheduler.activeTask;
+            scheduler.activeTask = this;
             task.run(ctx);
             hasRun = true;
-            activeTask = old;
+            scheduler.activeTask = old;
         }
 
         @Override
@@ -275,7 +554,7 @@
                 throw new AssertionError("task canceled twice");
             }
             isCanceled = true;
-            pending.remove(this);
+            scheduler.pending.remove(this);
         }
 
         public void deregister() {
@@ -296,6 +575,8 @@
 
         private Subscriptions subscriptions;
 
+        private SchedulerInstance scheduler;
+
         /**
          * Create a TaskIdentifier.
          *
@@ -304,26 +585,34 @@
          *              (but only queued directly)
          * @param task  task to run with this TaskIdentifier
          */
-        TaskConfiguration(RelativeTime delay, Task task) {
+        TaskConfiguration(SchedulerInstance scheduler, RelativeTime delay, 
Task task) {
             if (delay == null)
                 throw new AssertionError("task delay may not be 'null'");
+            this.scheduler = scheduler;
             this.task = task;
             this.deadline = delay.toAbsolute();
         }
 
+        TaskConfiguration(RelativeTime delay, Task task) {
+            this(threadScheduler.get(), delay, task);
+        }
+
         public TaskIdentifier schedule() {
+            return schedule(Scheduler.threadScheduler.get());
+        }
 
+        public TaskIdentifier schedule(SchedulerInstance scheduler) {
             if (priority == null) {
-                if (activeTask != null) {
-                    priority = activeTask.priority;
+                if (scheduler.activeTask != null) {
+                    priority = scheduler.activeTask.priority;
                 } else {
                     priority = Priority.DEFAULT;
                 }
             }
-            TaskIdentifier tid = new TaskIdentifier(this);
+            TaskIdentifier tid = new TaskIdentifier(scheduler, this);
             if (subscriptions != null)
                 subscriptions.apply(tid);
-            pending.add(tid);
+            scheduler.pending.add(tid);
             return tid;
         }
 
@@ -332,7 +621,7 @@
                 throw new AssertionError("channel may not be null");
             }
             if (subscriptions == null)
-                subscriptions = new Subscriptions();
+                subscriptions = new Subscriptions(scheduler.selector);
             subscriptions.add(channel, event);
         }
     }
@@ -342,7 +631,7 @@
      * the same priority.
      */
     public static void addContinuation(Task task, EnumSet<Reason> reasons) {
-        queueReady(new TaskIdentifier(task, reasons));
+        threadScheduler.get().addContinuation(task, reasons);
     }
 
     /**
@@ -366,7 +655,7 @@
      */
     public static TaskIdentifier addDelayed(RelativeTime delay, Task task) {
         TaskConfiguration tid = new TaskConfiguration(delay, task);
-        return tid.schedule();
+        return tid.schedule(threadScheduler.get());
     }
 
     /**
@@ -382,10 +671,32 @@
                                          SelectableChannel chan, Task task) {
         TaskConfiguration tid = new TaskConfiguration(timeout, task);
         tid.addSelectEvent(chan, SelectionKey.OP_READ);
-        return tid.schedule();
+        return tid.schedule(threadScheduler.get());
     }
 
     /**
+     * Initialize and run scheduler. This function will return when all tasks
+     * have completed.
+     */
+    public static void run() {
+        threadScheduler.get().run();
+    }
+
+    /**
+     * Initialize and run scheduler. This function will return when all tasks
+     * have completed.
+     *
+     * @param initialTask the initial task to run immediately
+     */
+    public static void run(Task initialTask) {
+        threadScheduler.get().run(initialTask);
+    }
+
+    public static boolean hasTasks() {
+        return threadScheduler.get().hasTasks();
+    }
+
+    /**
      * Add a task to run after the specified delay, or after the given channel
      * is ready to write, whichever occurs first.
      *
@@ -398,73 +709,11 @@
                                           SelectableChannel chan, Task task) {
         TaskConfiguration tid = new TaskConfiguration(timeout, task);
         tid.addSelectEvent(chan, SelectionKey.OP_WRITE);
-        return tid.schedule();
+        return tid.schedule(threadScheduler.get());
     }
 
-    /**
-     * Check if the system is still life. Trigger disconnect if we have tasks, 
but
-     * none of them give us lifeness.
-     *
-     * @return true to continue the main loop, false to exit
-     */
-    private static boolean checkLiveness() {
-        if (readyCount > 0) {
-            return true;
-        }
-        for (TaskIdentifier t : pending) {
-            if (t.lifeness) {
-                return true;
-            }
-        }
-        // trigger shutdown if we still have pending tasks, but none of them 
has lifeness
-        if (!pending.isEmpty()) {
-            logger.debug("tasks pending but not alive -- disconnect");
-            shutdown();
-            return true;
-        }
-        return false;
-    }
 
-    /**
-     * Queue a Task for execution.
-     *
-     * @param tid TaskIdentifier of the ready task
-     */
-    private static void queueReady(TaskIdentifier tid) {
-        int idx = tid.priority.ordinal();
-        readyLists[idx].add(tid);
-        readyCount++;
-        pending.remove(tid);
-    }
 
-    /**
-     * Queue all tasks with expired timeout.
-     *
-     * @return the minimum time to wait until the next timeout expiry
-     */
-    private static RelativeTime handleTimeouts() {
-        RelativeTime timeout = RelativeTime.FOREVER;
-
-        // check if any timeouts occurred
-        while (true) {
-            TaskIdentifier t = pending.peek();
-            if (t == null) {
-                break;
-            }
-            RelativeTime remaining = t.deadline.getRemaining();
-            if (remaining.getMicroseconds() <= 0) {
-                t.deregister();
-                t.ctx.reasons = EnumSet.of(Reason.TIMEOUT);
-                queueReady(t);
-            } else {
-                timeout = remaining;
-                break;
-            }
-        }
-        return timeout;
-    }
-
-
     private static void addReasonsFromInterestOp(EnumSet<Reason> reasons, int 
interestOps) {
         if ((interestOps & SelectionKey.OP_READ) != 0)
             reasons.add(Reason.READ_READY);
@@ -476,194 +725,8 @@
             reasons.add(Reason.ACCEPT_READY);
     }
 
-    /**
-     * Select on channels and queue tasks that become executable.
-     *
-     * @param timeout timeout for select
-     */
-    private static void handleSelect(RelativeTime timeout) {
-        // gnunet-java uses microseconds, but the select api uses milliseconds
-        long timeout_ms = timeout.getMicroseconds() / 1000;
-        try {
-            // selector.select(0) would block indefinitely (counter-intuitive, 
java's fault)
-            if (timeout_ms == 0) {
-                selector.selectNow();
-            } else if (timeout.isForever()) {
-                // fixme: we should only do this if we are sure there are 
tasks that select on something
-                logger.debug("selecting, timeout=forever");
-                selector.select(0);
-            } else {
-                selector.select(timeout_ms);
-            }
-        } catch (IOException e) {
-            throw new IOError(e);
-        }
 
-        logger.debug("select over");
-
-        // we use a set so that we don't execute any task twice
-        Collection<TaskIdentifier> executableTasks = new 
HashSet<TaskIdentifier>();
-        for (SelectionKey sk : selector.selectedKeys()) {
-            @SuppressWarnings("unchecked")
-            LinkedList<TaskInterestOps> subscribers = 
(LinkedList<TaskInterestOps>) sk.attachment();
-            for (TaskInterestOps ops : subscribers) {
-                if ((sk.readyOps() & ops.interestOps) != 0) {
-                    executableTasks.add(ops.tid);
-                    addReasonsFromInterestOp(ops.tid.ctx.reasons, 
sk.readyOps() & ops.interestOps);
-                }
-            }
-        }
-        for (TaskIdentifier tt : executableTasks) {
-            // cancel subscriptions to other events, we can execute now!
-            tt.deregister();
-            queueReady(tt);
-        }
-    }
-
     /**
-     * Initialize and run scheduler. This function will return when all tasks
-     * have completed.
-     */
-    public static void run() {
-        run(null);
-    }
-
-    /**
-     * Initialize and run scheduler. This function will return when all tasks
-     * have completed.
-     *
-     * @param initialTask the initial task to run immediately
-     */
-    public static void run(Task initialTask) {
-        logger.debug("running scheduler");
-        if (schedulerRunning) {
-            throw new AssertionError("Scheduler already running");
-        }
-        schedulerRunning = true;
-        try {
-            run_unchecked(initialTask);
-        } finally {
-            logger.debug("cleaning up after scheduler ran");
-            // ensure that after run returns, the scheduler is in its initial 
state,
-            // even though there was an exception (e.g. after a test case that 
expects an exception)
-            forceReset();
-        }
-    }
-
-    /**
-     * Initialize and run scheduler. This function will return when all tasks
-     * have completed. Don't check if the scheduler is already running or not.
-     *
-     * @param initialTask the initial task to run immediately
-     */
-    private static void run_unchecked(Task initialTask) {
-        if (initialTask != null) {
-            addContinuation(initialTask, EnumSet.of(Reason.STARTUP));
-        }
-
-        // the gnunet main loop
-        while (checkLiveness()) {
-            RelativeTime nextTimeout = handleTimeouts();
-            if (nextTimeout.getMicroseconds() < 0) {
-                logger.warn("negative timeout for select");
-            }
-
-            // don't select if there are no tasks; we are done!
-            if (readyCount == 0 && pending.isEmpty()) {
-                return;
-            }
-
-            // don't block in select if we have tasks ready to run!
-            if (readyCount > 0) {
-                handleSelect(RelativeTime.ZERO);
-            } else {
-                handleSelect(nextTimeout);
-            }
-            runReady();
-        }
-
-        if (readyCount != 0) {
-            throw new AssertionError("tasks ready after scheduler ran 
(count)");
-        }
-
-        for (List readyList : Scheduler.readyLists) {
-            if (!readyList.isEmpty()) {
-                throw new AssertionError("tasks ready after scheduler ran 
(list)");
-            }
-        }
-
-        if (pending.size() != 0) {
-            throw new AssertionError("pending tasks after scheduler ran");
-        }
-
-        if (activeTask != null) {
-            throw new AssertionError("active task after scheduler ran");
-        }
-    }
-
-
-    /**
-     * Execute tasks until either
-     * <ul>
-     * <li>there are no ready tasks</li>
-     * <li>there is a pending task (which may be of higher priority)</li>
-     * </ul>
-     */
-    private static void runReady() {
-        do {
-            if (readyCount == 0) {
-                return;
-            }
-            // start executing from the highest priority down to 0
-            for (int p = Priority.numberOfPriorities - 1; p >= 0; p--) {
-                // execute all tasks with priority p
-                LinkedList<TaskIdentifier> queue = readyLists[p];
-                while (!queue.isEmpty()) {
-                    TaskIdentifier tid = queue.removeFirst();
-                    readyCount--;
-                    tid.run();
-                }
-            }
-        } while (pending.size() == 0);
-
-    }
-
-    /**
-     * Request the shutdown of the scheduler. Marks all currently pending 
tasks as
-     * ready because of disconnect. This will cause all tasks to run (as soon 
as
-     * possible, respecting priorities and prerequisite tasks). Note that tasks
-     * scheduled AFTER this call may still be delayed arbitrarily.
-     */
-    public static void shutdown() {
-        // queueReady() while iterating would yield concurrent modification 
exn otherwise
-        for (TaskIdentifier tid : new ArrayList<TaskIdentifier>(pending)) {
-            tid.ctx.reasons.add(Reason.SHUTDOWN);
-            queueReady(tid);
-        }
-        pending.clear();
-    }
-
-    /**
-     * Reset the scheduler forcefully.
-     * Intended to be used internally in the Scheduler, as well as in test 
teardown.
-     */
-    public static void forceReset() {
-        schedulerRunning = false;
-        readyCount = 0;
-        activeTask = null;
-        for (int i = 0; i < Priority.numberOfPriorities; ++i) {
-            readyLists[i] = Lists.newLinkedList();
-        }
-        pending.clear();
-    }
-
-
-    public static boolean hasTasks() {
-        return readyCount != 0 || !pending.isEmpty();
-    }
-
-
-    /**
      * A handle to a file system object that can be selected on.
      */
     public static class FilePipe {
@@ -676,7 +739,11 @@
         public Pipe.SourceChannel getSource() {
             return filePipeThread.pipe.source();
         }
+    }
 
+    public static void forceReset() {
+        // FIXME: this should reset all schedulers?
+        threadScheduler.get().forceReset();
     }
 
     /**

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/DsaPrng.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/DsaPrng.java       
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/DsaPrng.java       
2014-02-03 23:03:52 UTC (rev 32181)
@@ -41,7 +41,7 @@
     private static final int qlen = 32;
 
     /**
-     * Compute the HMAC of the fiven data with our current K-value.
+     * Compute the HMAC of the given data with our current K-value.
      *
      * @param args data
      * @return result of the hmac

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/EcdhePrivateKey.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EcdhePrivateKey.java       
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EcdhePrivateKey.java       
2014-02-03 23:03:52 UTC (rev 32181)
@@ -29,10 +29,12 @@
 
 /**
  * Private key for elliptic curve Diffie Hellman exchange.
+ * Note that (in contrast to NaCl) the key is encoded
+ * as big endian.
  */
 public class EcdhePrivateKey implements Message {
     /**
-     * Private key byte string, in little endian form.
+     * Private key byte string, in big endian form.
      */
     @FixedSizeIntegerArray(bitSize = 8, signed = false, length = 32)
     public byte[] d;
@@ -50,7 +52,7 @@
      * @return the public key for this private key
      */
     public EcdhePublicKey getPublicKey() {
-        BigInteger dCoeff = Ed25519.decodeScalar(d);
+        BigInteger dCoeff = this.asCoefficient();
         Ed25519 A = Ed25519.B.scalarmult(dCoeff);
         return new EcdhePublicKey(A);
     }
@@ -62,7 +64,7 @@
      * @return key material
      */
     public HashCode ecdh(EcdhePublicKey publicKey) {
-        BigInteger dCoeff = Ed25519.decodeScalar(d);
+        BigInteger dCoeff = this.asCoefficient();
         Ed25519 Q = publicKey.asPoint().scalarmult(dCoeff);
         // hash big endian representation of the x-coordinate.
         return HashCode.hash(Q.P0.toByteArray());
@@ -79,11 +81,18 @@
         privateKey.d = new byte[32];
         sr.nextBytes(privateKey.d);
         // clear bits so that d mod 8 = 0
-        privateKey.d[0] &= (byte) 248;
+        privateKey.d[31] &= (byte) 248;
         // make sure the key fits in 255 bits
-        privateKey.d[31] &= (byte) 127;
+        privateKey.d[0] &= (byte) 127;
         // make sure key does not have lots of leading zeros
-        privateKey.d[31] |= (byte) 64;
+        privateKey.d[0] |= (byte) 64;
         return privateKey;
     }
+
+    public BigInteger asCoefficient() {
+        /* We have a big endian value here ... */
+        return new BigInteger(1, d);
+    }
+
+
 }

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPrivateKey.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPrivateKey.java       
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPrivateKey.java       
2014-02-03 23:03:52 UTC (rev 32181)
@@ -32,7 +32,7 @@
  */
 public class EcdsaPrivateKey implements Message {
     /**
-     * Private key byte string, in little endian form.
+     * Private key byte string, in big endian form.
      */
     @FixedSizeIntegerArray(bitSize = 8, signed = false, length = 32)
     public byte[] d;
@@ -82,22 +82,23 @@
         EcdsaSignature signature = new EcdsaSignature();
         DsaPrng prng = new DsaPrng(d, data);
         HashCode h = HashCode.hash(data);
-        byte[] zData = new byte[32];
-        System.arraycopy(h.data, 0, zData, 0, 32);
-        BigInteger z = new BigInteger(1, zData);
-        BigInteger dCoeff = Ed25519.decodeScalar(d);
+        BigInteger z = new BigInteger(1, h.data);
+        BigInteger dCoeff = this.asCoefficient();
+
         while (true) {
             BigInteger k = prng.nextK();
             Ed25519 P = Ed25519.B.scalarmult(k);
-            BigInteger r = P.P0.mod(Ed25519.q);
+            BigInteger r = P.P0.mod(Ed25519.l);
             if (r.equals(BigInteger.ZERO))
                 continue;
-            BigInteger s = 
k.modInverse(Ed25519.q).multiply(z.add(r.multiply(dCoeff)));
-            if (!r.equals(BigInteger.ZERO)) {
-                signature.r = Ed25519.encodeScalar(r);
-                signature.s = Ed25519.encodeScalar(s);
-                return signature;
-            }
+            BigInteger kInv = k.modInverse(Ed25519.l);
+            BigInteger v = z.add(r.multiply(dCoeff));
+            BigInteger s = kInv.multiply(v).mod(Ed25519.l);
+            if (s.equals(BigInteger.ZERO))
+                continue;
+            signature.r = Ed25519.encodeScalar(r);
+            signature.s = Ed25519.encodeScalar(s);
+            return signature;
         }
     }
 
@@ -107,7 +108,7 @@
      * @return the public key for this private key
      */
     public EcdsaPublicKey getPublicKey() {
-        Ed25519 A = Ed25519.B.scalarmult(Ed25519.decodeScalar(d));
+        Ed25519 A = Ed25519.B.scalarmult(this.asCoefficient());
         return new EcdsaPublicKey(A);
     }
 
@@ -123,4 +124,19 @@
         sr.nextBytes(privateKey.d);
         return privateKey;
     }
+
+    public BigInteger asCoefficient() {
+        return new BigInteger(1, d);
+    }
+
+    /**
+     * Key that is set to all zeros.
+     *
+     * @return key that is set to all zeros
+     */
+    public static EcdsaPrivateKey zeroKey() {
+        EcdsaPrivateKey pk = new EcdsaPrivateKey();
+        pk.d = new byte[32];
+        return pk;
+    }
 }

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPublicKey.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPublicKey.java        
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPublicKey.java        
2014-02-03 23:03:52 UTC (rev 32181)
@@ -61,12 +61,13 @@
      * Load an ECDSA key from a string.
      *
      * @param s string with the key data
-     * @return a public key
+     * @return a public key, or NULL if 's' not a valid public key encoding
      */
     public static EcdsaPublicKey fromString(String s) {
         EcdsaPublicKey publicKey = new EcdsaPublicKey();
-        Strings.stringToData(s, publicKey.y);
-        return publicKey;
+        if (Strings.stringToData(s, publicKey.y))
+            return publicKey;
+        return null;
     }
 
     /**
@@ -105,4 +106,12 @@
         return result;
     }
 
+    /**
+     * Convert this public key to a point on the Ed25519 curve.
+     *
+     * @return a point corresponding to this key
+     */
+    public Ed25519 asPoint() {
+        return Ed25519.decode(y);
+    }
 }

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignature.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignature.java        
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignature.java        
2014-02-03 23:03:52 UTC (rev 32181)
@@ -62,17 +62,40 @@
      * @return whether the signature is valid
      */
     public boolean verify(byte[] m, int purpose, EcdsaPublicKey publicKey) {
+        if (publicKey.asPoint().isIdentity()) {
+            throw new AssertionError();
+        }
+
+        if (!publicKey.asPoint().isOnCurve()) {
+            throw new AssertionError();
+        }
+
+        if (!publicKey.asPoint().scalarmult(Ed25519.l).isIdentity()) {
+            throw new AssertionError("invalid public key");
+        }
+
         HashCode h = HashCode.hash(m);
-        byte[] zData = new byte[32];
-        System.arraycopy(h.data, 0, zData, 0, 32);
-        BigInteger z = new BigInteger(1, zData);
+        /*
+        byte[] zPart = new byte[32];
+        System.arraycopy(h.data, 0, zPart, 0, 32);
+        for (int i = 0; i < 16; i++) {
+            byte tmp = zPart[i];
+            zPart[i] = zPart[31-i];
+            zPart[31 - i] = tmp;
+        }
+        BigInteger z = new BigInteger(1, zPart);
+        */
+        BigInteger z = new BigInteger(1, h.data);
         BigInteger sCoeff = Ed25519.decodeScalar(s);
         BigInteger rCoeff = Ed25519.decodeScalar(r);
-        BigInteger w = sCoeff.modInverse(Ed25519.q);
-        BigInteger u1 = z.multiply(w).mod(Ed25519.q);
-        BigInteger u2 = rCoeff.multiply(w).mod(Ed25519.q);
-        Ed25519 P = Ed25519.B.scalarmult(u1).add(Ed25519.B.scalarmult(u2));
-        return P.P0.equals(rCoeff.mod(Ed25519.q));
+
+        // FIXME: check range of s and r
+        BigInteger w = sCoeff.modInverse(Ed25519.l);
+        BigInteger u1 = z.multiply(w).mod(Ed25519.l);
+        BigInteger u2 = rCoeff.multiply(w).mod(Ed25519.l);
+        // P = u1*B + u2*Q
+        Ed25519 P = 
Ed25519.B.scalarmult(u1).add(publicKey.asPoint().scalarmult(u2));
+        return P.P0.mod(Ed25519.l).equals(rCoeff);
     }
 
     /**

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/Ed25519.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/Ed25519.java       
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/Ed25519.java       
2014-02-03 23:03:52 UTC (rev 32181)
@@ -32,7 +32,7 @@
  */
 public class Ed25519 {
     /**
-     * curve parameter b
+     * The curve parameter b.
      */
     public static final int b = 256;
     /**
@@ -48,11 +48,11 @@
      */
     private static final BigInteger qp3 = q.add(BigInteger.valueOf(3));
     /**
-     * ???
+     * The l parameter (a prime, order of the base point B).
      */
-    static final BigInteger l = new 
BigInteger("7237005577332262213973186563042994240857116359379907606001950938285454250989");
+    public static final BigInteger l = new 
BigInteger("7237005577332262213973186563042994240857116359379907606001950938285454250989");
     /**
-     * ???
+     * The d parameter (a field element).
      */
     private static final BigInteger d = new 
BigInteger("-4513249062541557337682894930092624173785641285191125241628941591882900924598840740");
     /**
@@ -69,7 +69,7 @@
      */
     private static final BigInteger By = new 
BigInteger("46316835694926478169428394003475163141307993866256225615783033603165251855960");
     /**
-     * base point
+     * The chosen base point of order l.
      */
     public static final Ed25519 B = new Ed25519(Bx.mod(q),By.mod(q));
 
@@ -99,7 +99,9 @@
     }
 
     /**
-     * Create a curve point from its string representation
+     * Create a curve point from its string representation.
+     * Note that returned point is not necessarily a valid
+     * point.
      *
      * @param s the string representation
      * @return a curve point corresponsing to 's'
@@ -111,9 +113,6 @@
             x = q.subtract(x);
         }
         Ed25519 v = new Ed25519(x, y);
-        if (!v.isOnCurve()) {
-            throw new AssertionError("not on curve");
-        }
         return v;
     }
 
@@ -172,6 +171,10 @@
         return new Ed25519(x3.mod(q), y3.mod(q));
     }
 
+    public boolean isIdentity() {
+        return P0.mod(q).equals(BigInteger.ZERO) && 
P1.mod(q).equals(BigInteger.ONE);
+    }
+
     /**
      * Multiply this point by a scalar value.
      *
@@ -234,10 +237,7 @@
      */
     public byte[] encode() {
         byte[] out = encodeScalar(P1);
-        System.out.println("encodeScalar " + P1);
-        System.out.println("out1 " + Arrays.toString(out));
         out[out.length-1] |= (P0.testBit(0) ? (byte) 0x80 : 0);
-        System.out.println("out2 " + Arrays.toString(out));
         return out;
     }
 

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaPrivateKey.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaPrivateKey.java       
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaPrivateKey.java       
2014-02-03 23:03:52 UTC (rev 32181)
@@ -36,7 +36,6 @@
         return sign(getPublicKey(), purpose, m);
     }
 
-
     /**
      * Sign the given data with this private key.  Must include a purpose to 
mitigate
      * replay / copy and paste attacks.
@@ -124,15 +123,7 @@
     public EddsaPublicKey getPublicKey() {
         BigInteger a = computePublicKeyCoefficient();
         Ed25519 A = Ed25519.B.scalarmult(a);
-        if (!A.isOnCurve()) {
-            throw new AssertionError();
-        }
-        EddsaPublicKey publicKey = new EddsaPublicKey(A);
-
-        if (!A.equals(publicKey.asPoint())) {
-            throw new AssertionError();
-        }
-        return publicKey;
+        return new EddsaPublicKey(A);
     }
 
     /**

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaSignature.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaSignature.java        
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaSignature.java        
2014-02-03 23:03:52 UTC (rev 32181)
@@ -54,8 +54,18 @@
         this.s = Ed25519.encodeScalar(s);
     }
 
+    /**
+     * Verify the signature on a message with given purpose.
+     *
+     * @param m
+     * @param purpose
+     * @param publicKey
+     * @return
+     */
     public boolean verify(byte[] m, int purpose, EddsaPublicKey publicKey) {
         Ed25519 R = Ed25519.decode(r);
+        if (!R.isOnCurve())
+            return false;
         Ed25519 A = publicKey.asPoint();
         BigInteger S = Ed25519.decodeScalar(s);
         ByteBuffer Stemp = ByteBuffer.allocate(32 + 32 + m.length);

Modified: gnunet-java/src/main/java/org/gnunet/voting/BallotTool.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/voting/BallotTool.java 2014-02-03 
23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/voting/BallotTool.java 2014-02-03 
23:03:52 UTC (rev 32181)
@@ -332,7 +332,7 @@
             return;
         }
         ballotFilename = unprocessedArgs[0];
-        if (template) {
+        if (template)  {
             runTemplate();
             return;
         }

Modified: gnunet-java/src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java       
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java       
2014-02-03 23:03:52 UTC (rev 32181)
@@ -126,8 +126,7 @@
         }
         @Override
         public void run(Scheduler.RunContext ctx) {
-            
electionState.consensus.conclude(electionState.ballot.concludeTime.getRemaining(),
-                    new ElectionConsensusConclude(electionState));
+            electionState.consensus.conclude(new 
ElectionConsensusConclude(electionState));
         }
     }
 
@@ -207,7 +206,9 @@
             ids = b.getAuthorities().toArray(ids);
             electionState.consensus = new Consensus(getConfiguration(),
                     ids,
-                    b.getBallotGuid());
+                    b.getBallotGuid(),
+                    electionState.ballot.closingTime,
+                    electionState.ballot.concludeTime);
 
             ConsensusConcludeTask t = new ConsensusConcludeTask(electionState);
             if (b.concludeTime.isDue()) {

Modified: gnunet-java/src/main/resources/org/gnunet/construct/MsgMap.txt
===================================================================
--- gnunet-java/src/main/resources/org/gnunet/construct/MsgMap.txt      
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/main/resources/org/gnunet/construct/MsgMap.txt      
2014-02-03 23:03:52 UTC (rev 32181)
@@ -41,6 +41,10 @@
 
org.gnunet.util.GnunetMessage$Body|520=org.gnunet.consensus.messages.JoinMessage
 
org.gnunet.util.GnunetMessage$Body|521=org.gnunet.consensus.messages.InsertElementMessage
 
org.gnunet.util.GnunetMessage$Body|523=org.gnunet.consensus.messages.NewElementMessage
+org.gnunet.util.GnunetMessage$Body|782=org.gnunet.secretsharing.messages.DecryptDoneMessage
+org.gnunet.util.GnunetMessage$Body|783=org.gnunet.secretsharing.messages.SecretReadyMessage
+org.gnunet.util.GnunetMessage$Body|780=org.gnunet.secretsharing.messages.GenerateMessage
+org.gnunet.util.GnunetMessage$Body|781=org.gnunet.secretsharing.messages.ClientDecryptMessage
 org.gnunet.util.GnunetMessage$Body|68=org.gnunet.core.DisconnectNotifyMessage
 
org.gnunet.util.GnunetMessage$Body|70=org.gnunet.core.NotifyInboundTrafficMessage
 
org.gnunet.util.GnunetMessage$Body|476=org.gnunet.testbed.messages.PeerGetInformationMessage
@@ -81,6 +85,8 @@
 
org.gnunet.util.GnunetMessage$Body|369=org.gnunet.transport.messages.BlacklistInitMessage
 
org.gnunet.util.GnunetMessage$Body|371=org.gnunet.transport.messages.BlacklistReplyMessage
 
org.gnunet.util.GnunetMessage$Body|370=org.gnunet.transport.messages.BlacklistQueryMessage
+org.gnunet.util.GnunetMessage$Body|500=org.gnunet.gns.messages.ClientLookupMessage
+org.gnunet.util.GnunetMessage$Body|501=org.gnunet.gns.messages.ClientLookupResultMessage
 
org.gnunet.util.GnunetMessage$Body|380=org.gnunet.transport.messages.AddressIterateMessage
 
org.gnunet.util.GnunetMessage$Body|383=org.gnunet.transport.messages.AddressIterateResponseMessage
 
org.gnunet.util.GnunetMessage$Body|496=org.gnunet.testbed.messages.HelperReplyMessage
@@ -88,4 +94,6 @@
 
org.gnunet.util.GnunetMessage$Body|366=org.gnunet.transport.messages.SetQuotaMessage
 
org.gnunet.util.GnunetMessage$Body|360=org.gnunet.transport.messages.StartMessage
 
org.gnunet.util.GnunetMessage$Body|483=org.gnunet.testbed.messages.ManagePeerServiceMessage
-# generated 2013/10/22 01:57:19
+org.gnunet.gns.records.RecordData|65536=org.gnunet.gns.records.PkeyRecordData
+org.gnunet.gns.records.RecordData|1=org.gnunet.gns.records.ARecordData
+# generated 2014/02/03 23:33:43

Modified: 
gnunet-java/src/test/java/org/gnunet/consensus/ConsensusSingleTest.java
===================================================================
--- gnunet-java/src/test/java/org/gnunet/consensus/ConsensusSingleTest.java     
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/test/java/org/gnunet/consensus/ConsensusSingleTest.java     
2014-02-03 23:03:52 UTC (rev 32181)
@@ -20,6 +20,7 @@
 
 package org.gnunet.consensus;
 
+import org.gnunet.testing.TestingFixture;
 import org.gnunet.testing.TestingSubsystem;
 import org.gnunet.util.*;
 import org.junit.Assert;
@@ -31,7 +32,7 @@
 /**
  * Test consensus with only one peer.
  */
-public class ConsensusSingleTest {
+public class ConsensusSingleTest extends TestingFixture {
     @Test
     public void test_consensus_single() {
         Configuration armConf = new Configuration();
@@ -41,8 +42,12 @@
         TestingSubsystem ts = new TestingSubsystem("arm", 
armConf.writeTemp().getAbsolutePath());
         final Wrapper<Boolean> isDone = new Wrapper<Boolean>(false);
 
-        final Consensus consensus = new Consensus(ts.getConfiguration(), new 
PeerIdentity[0],
-                HashCode.random());
+        final Consensus consensus = new Consensus(
+                ts.getConfiguration(),
+                new PeerIdentity[0],
+                HashCode.random(),
+                AbsoluteTime.now(),
+                AbsoluteTime.now().add(RelativeTime.SECOND.multiply(10)));
 
         consensus.insertElement(new ConsensusElement("foo".getBytes(), 0));
         consensus.insertElement(new ConsensusElement("bar".getBytes(), 0));
@@ -50,7 +55,7 @@
 
         final List<String> received = new LinkedList<String>();
 
-        consensus.conclude(RelativeTime.SECOND, new ConsensusCallback() {
+        consensus.conclude(new ConsensusCallback() {
             @Override
             public void onElement(ConsensusElement element) {
                 Assert.assertNotNull(element);

Modified: 
gnunet-java/src/test/java/org/gnunet/consensus/ConsensusTestbedTest.java
===================================================================
--- gnunet-java/src/test/java/org/gnunet/consensus/ConsensusTestbedTest.java    
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/test/java/org/gnunet/consensus/ConsensusTestbedTest.java    
2014-02-03 23:03:52 UTC (rev 32181)
@@ -5,6 +5,7 @@
 import org.gnunet.testbed.Host;
 import org.gnunet.testbed.SimpleTestbed;
 import org.gnunet.testbed.callbacks.*;
+import org.gnunet.testing.TestingFixture;
 import org.gnunet.util.*;
 import org.junit.Assert;
 import org.junit.Test;
@@ -15,7 +16,7 @@
 /**
  * Test for consensus with multiple peers using testbed.
  */
-public class ConsensusTestbedTest {
+public class ConsensusTestbedTest extends TestingFixture {
     @Test
     public void test_consensus_testbed_2peers() {
         final Wrapper<Boolean> done = new Wrapper<Boolean>(false);
@@ -33,6 +34,8 @@
             int peersStarted;
             int peersConcludeDone;
             HashCode sessionId = HashCode.random();
+            AbsoluteTime start;
+            AbsoluteTime deadline;
 
             class MyConsensusCallback implements ConsensusCallback {
                 int n;
@@ -69,11 +72,11 @@
                 @Override
                 public void onConnect(Configuration cfg) {
                     System.out.println("connecting to consensus");
-                    consensi[n] = new Consensus(cfg, identities, sessionId);
+                    consensi[n] = new Consensus(cfg, identities, sessionId, 
start, deadline);
                     consensi[n].insertElement(new 
ConsensusElement("foo".getBytes(), 0));
                     consensi[n].insertElement(new 
ConsensusElement("bar".getBytes(), 0));
                     consensi[n].insertElement(new ConsensusElement(("num" + 
n).getBytes(), 0));
-                    consensi[n].conclude(RelativeTime.SECOND.multiply(10), new 
MyConsensusCallback(n));
+                    consensi[n].conclude(new MyConsensusCallback(n));
                 }
 
                 @Override
@@ -152,6 +155,8 @@
 
             @Override
             public void run() {
+                start = AbsoluteTime.now();
+                deadline = start.add(RelativeTime.SECOND.multiply(10));
                 // use local peer's config, does that really make sense?
                 h = new Host(null, null, getConfiguration(), 0);
                 cp = new ControllerProc();

Modified: gnunet-java/src/test/java/org/gnunet/core/CoreTest.java
===================================================================
--- gnunet-java/src/test/java/org/gnunet/core/CoreTest.java     2014-02-03 
23:00:30 UTC (rev 32180)
+++ gnunet-java/src/test/java/org/gnunet/core/CoreTest.java     2014-02-03 
23:03:52 UTC (rev 32181)
@@ -77,6 +77,7 @@
         final Core core = new Core(ts.getConfiguration());
         core.setMessageHandler(new Runabout() {
             public void visit(TestMessage t) {
+                System.out.println("got core response");
                 gotResponse.set(true);
                 core.disconnect();
             }
@@ -85,7 +86,8 @@
         core.init(new InitCallback() {
             @Override
             public void onInit(PeerIdentity myIdentity) {
-                System.out.println("in core init");
+                System.out.println("in core init, my identity is " + 
myIdentity);
+                // we want to send a 4-byte TestMessage
                 core.notifyTransmitReady(0, RelativeTime.FOREVER, myIdentity, 
4, new MessageTransmitter() {
                     @Override
                     public void transmit(Connection.MessageSink sink) {

Modified: gnunet-java/src/test/java/org/gnunet/identity/IdentityTest.java
===================================================================
--- gnunet-java/src/test/java/org/gnunet/identity/IdentityTest.java     
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/test/java/org/gnunet/identity/IdentityTest.java     
2014-02-03 23:03:52 UTC (rev 32181)
@@ -21,6 +21,7 @@
 package org.gnunet.identity;
 
 
+import org.gnunet.testing.TestingFixture;
 import org.gnunet.testing.TestingSubsystem;
 import org.gnunet.util.Program;
 import org.gnunet.util.Scheduler;
@@ -28,7 +29,7 @@
 import org.junit.Assert;
 import org.junit.Test;
 
-public class IdentityTest {
+public class IdentityTest extends TestingFixture {
     @Test
     public void test_identity_connect() {
         final Wrapper<Boolean> reachedEnd = new Wrapper<Boolean>(false);

Modified: gnunet-java/src/test/java/org/gnunet/transport/TransportTest.java
===================================================================
--- gnunet-java/src/test/java/org/gnunet/transport/TransportTest.java   
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/test/java/org/gnunet/transport/TransportTest.java   
2014-02-03 23:03:52 UTC (rev 32181)
@@ -23,6 +23,7 @@
 import org.gnunet.hello.HelloMessage;
 import org.gnunet.peerinfo.PeerInfo;
 import org.gnunet.peerinfo.PeerProcessor;
+import org.gnunet.testing.TestingFixture;
 import org.gnunet.testing.TestingSubsystem;
 import org.gnunet.transport.callbacks.HelloUpdateCallback;
 import org.gnunet.util.*;
@@ -30,8 +31,8 @@
 
 import static org.junit.Assert.assertTrue;
 
-public class TransportTest {
-    @Test
+public class TransportTest extends TestingFixture {
+    @Test(timeout = 5000)
     public void test_transport_get_hello() {
         Program.configureLogging("debug");
         final Wrapper<Boolean> ended = new Wrapper<Boolean>(false);

Modified: gnunet-java/src/test/java/org/gnunet/util/ClientServerTest.java
===================================================================
--- gnunet-java/src/test/java/org/gnunet/util/ClientServerTest.java     
2014-02-03 23:00:30 UTC (rev 32180)
+++ gnunet-java/src/test/java/org/gnunet/util/ClientServerTest.java     
2014-02-03 23:03:52 UTC (rev 32181)
@@ -3,6 +3,7 @@
 import com.google.common.collect.Lists;
 import org.gnunet.construct.UInt32;
 import org.gnunet.construct.UnionCase;
+import org.gnunet.testing.TestingFixture;
 import org.gnunet.testing.TestingServer;
 import org.gnunet.testing.TestingSetup;
 import org.junit.Assert;
@@ -20,7 +21,7 @@
  *
  * @author Florian Dold
  */
-public class ClientServerTest {
+public class ClientServerTest extends TestingFixture {
 
     @Test
     public void test_start_stop() {

Modified: gnunet-java/src/test/java/org/gnunet/util/EcdheTest.java
===================================================================
--- gnunet-java/src/test/java/org/gnunet/util/EcdheTest.java    2014-02-03 
23:00:30 UTC (rev 32180)
+++ gnunet-java/src/test/java/org/gnunet/util/EcdheTest.java    2014-02-03 
23:03:52 UTC (rev 32181)
@@ -74,13 +74,29 @@
         privKey1.d = new byte[32];
         EcdhePrivateKey privKey2 = new EcdhePrivateKey();
         privKey2.d = new byte[32];
-        
Strings.stringToData("FH7DONLOP82RMELK26NDEP8655HQFU9LUO36LNO1ENOJ5KOSRR00", 
privKey1.d);
-        
Strings.stringToData("LAJES5PBR68MJQP067I7DLJO3RUGG0EUHSOAVOFIDF24KBDE0SEG", 
privKey2.d);
+        
Strings.stringToData("A46TL3L8CF7R3BPPQDE8LJS999NQ58HD43DV11MPFI2B5JNJMM40", 
privKey1.d);
+        
Strings.stringToData("B60MFOBFKCVT0IVFDI800MH345FG372UJ4T7GEMNMO72O64G0D00", 
privKey2.d);
 
         EcdhePublicKey pubKey1 = privKey1.getPublicKey();
         EcdhePublicKey pubKey2 = privKey2.getPublicKey();
 
-        
Assert.assertEquals("VU5U4KNC3OH5RUL6M5T6BPH52BFBICEG5Q60A43V97HQV1VD3AG0", 
pubKey1.toString());
-        
Assert.assertEquals("8DSB6D0OKS1SD71BKRTVT8OK18Q73Q7MUALJ76V9DQJO6J0170RG", 
pubKey2.toString());
+        
Assert.assertEquals("JLU00RUGNB04APG6I9RKVT1CJLB16U8T7G130CC2IV4O3LJG5K40", 
pubKey1.toString());
+
+        
Assert.assertEquals("G9TDOQVP3CFA2K5Q7PSS8Q935FVEHAF3C08JPV1H3MPDK1ESLM6G", 
pubKey2.toString());
+
+        HashCode h1 = privKey1.ecdh(pubKey2);
+        HashCode h2 = privKey2.ecdh(pubKey1);
+
+        Assert.assertEquals(h1, h2);
+
+        byte[] gnunet_data = new byte[64];
+        boolean success = Strings.stringToData(
+                "R9A80A2VU4R0IL3NT4FBIMFRCGVP72DQODHTQQ1SGR65I4PMF1" +
+                "6C3ELIF2RSB9L8H0KLOUU795IM5L0CLCISI607B5P1QE8HRAPA56O",
+                gnunet_data);
+        Assert.assertTrue(success);
+
+        Assert.assertArrayEquals(gnunet_data, h1.data);
+
     }
 }

Modified: gnunet-java/src/test/java/org/gnunet/util/EcdsaTest.java
===================================================================
--- gnunet-java/src/test/java/org/gnunet/util/EcdsaTest.java    2014-02-03 
23:00:30 UTC (rev 32180)
+++ gnunet-java/src/test/java/org/gnunet/util/EcdsaTest.java    2014-02-03 
23:03:52 UTC (rev 32181)
@@ -24,13 +24,21 @@
 import org.junit.Assert;
 import org.junit.Test;
 
+import java.math.BigInteger;
+
 public class EcdsaTest {
     @Test
     public void test_sign_success() {
         byte[] data = "GNUnet".getBytes();
-        EcdsaPrivateKey privateKey = EcdsaPrivateKey.createRandom();
+        //EcdsaPrivateKey privateKey = EcdsaPrivateKey.createRandom();
+        EcdsaPrivateKey privateKey = new EcdsaPrivateKey();
+        privateKey.d = Ed25519.encodeScalar(new 
BigInteger("9751885127070397687372377515580876465521419304255864589795046632195735740054"));
         EcdsaPublicKey publicKey = privateKey.getPublicKey();
         EcdsaSignature signature = privateKey.sign(publicKey, 0, data);
+        System.out.println("private key: " + 
Ed25519.decodeScalar(privateKey.d));
+        System.out.println("public key: " + publicKey.asPoint());
+        System.out.println("signature r: " + 
Ed25519.decodeScalar(signature.r));
+        System.out.println("signature s: " + 
Ed25519.decodeScalar(signature.s));
         Assert.assertTrue(signature.verify(data, 0, publicKey));
     }
 

Modified: gnunet-java/src/test/java/org/gnunet/util/Ed25519Test.java
===================================================================
--- gnunet-java/src/test/java/org/gnunet/util/Ed25519Test.java  2014-02-03 
23:00:30 UTC (rev 32180)
+++ gnunet-java/src/test/java/org/gnunet/util/Ed25519Test.java  2014-02-03 
23:03:52 UTC (rev 32181)
@@ -46,7 +46,7 @@
     /**
      * Raw ECDH check.
      */
-    //@Test
+    @Test
     public void test_ecdh() {
         for (int i = 0; i < 5; ++i) {
             System.out.println("try " + i);
@@ -92,10 +92,10 @@
     /**
      * Test if decode is the inverse of encode.
      */
-    //@Test
+    @Test
     public void test_encode_inverse() {
         Random r = new Random();
-        for (int i = 0; i < 100; i++) {
+        for (int i = 0; i < 5; i++) {
             byte[] d1 = new byte[32];
             r.nextBytes(d1);
             d1[31] &= 127;
@@ -139,4 +139,11 @@
             Assert.assertArrayEquals(d1, d2);
         }
     }
+
+    @Test
+    public void test_order() {
+        Ed25519 P = Ed25519.B.scalarmult(Ed25519.l);
+        System.out.println("Point P: " + P);
+        Assert.assertTrue(P.isIdentity());
+    }
 }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]