gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r32833 - in gnunet-java: . ivy-repo ivy-repo/org.gnunet ivy


From: gnunet
Subject: [GNUnet-SVN] r32833 - in gnunet-java: . ivy-repo ivy-repo/org.gnunet ivy-repo/org.gnunet/gnunet-java ivy-repo/org.gnunet/gnunet-java/0.2 src/main/java/org/gnunet/construct/parsers src/main/java/org/gnunet/core src/main/java/org/gnunet/mesh src/main/java/org/gnunet/mq src/main/java/org/gnunet/secretsharing src/main/java/org/gnunet/statistics src/main/java/org/gnunet/util src/main/java/org/gnunet/util/crypto src/main/java/org/gnunet/voting src/main/java/org/gnunet/voting/messages src/main/java/org/gnunet/voting/simulation src/main/resources/org/gnunet/construct src/main/resources/org/gnunet/voting src/test/java/org/gnunet/mesh src/test/java/org/gnunet/util src/test/java/org/gnunet/voting src/test/python
Date: Sun, 30 Mar 2014 23:41:58 +0200

Author: dold
Date: 2014-03-30 23:41:58 +0200 (Sun, 30 Mar 2014)
New Revision: 32833

Added:
   gnunet-java/ivy-repo/
   gnunet-java/ivy-repo/org.gnunet/
   gnunet-java/ivy-repo/org.gnunet/gnunet-java/
   gnunet-java/ivy-repo/org.gnunet/gnunet-java/0.2/
   gnunet-java/ivy-repo/org.gnunet/gnunet-java/0.2/gnunet-java-0.2.jar
   gnunet-java/ivy-repo/org.gnunet/gnunet-java/0.2/gnunet-java-0.2.jar.sha1
   gnunet-java/ivy-repo/org.gnunet/gnunet-java/0.2/ivy-0.2.xml
   gnunet-java/ivy-repo/org.gnunet/gnunet-java/0.2/ivy-0.2.xml.sha1
   gnunet-java/src/main/java/org/gnunet/mesh/InboundChannelHandler.java
   
gnunet-java/src/main/java/org/gnunet/util/crypto/ContentWithPurposeMessage.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaSignedMessage.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/SignedContentMessage.java
   gnunet-java/src/main/java/org/gnunet/voting/ChaumPedersenZkp.java
   gnunet-java/src/main/java/org/gnunet/voting/DisjunctionZkp.java
   gnunet-java/src/main/java/org/gnunet/voting/SignedEncryptedVote.java
   gnunet-java/src/test/java/org/gnunet/util/HighLevelCryptoTest.java
Removed:
   gnunet-java/src/main/java/org/gnunet/mesh/DisconnectHandler.java
   gnunet-java/src/main/java/org/gnunet/mesh/InboundTunnelHandler.java
   gnunet-java/src/main/java/org/gnunet/mesh/TunnelNotificationMessage.java
   gnunet-java/src/main/java/org/gnunet/statistics/SetRequest.java
Modified:
   gnunet-java/ISSUES
   gnunet-java/src/main/java/org/gnunet/construct/parsers/IntegerUtil.java
   gnunet-java/src/main/java/org/gnunet/core/Core.java
   gnunet-java/src/main/java/org/gnunet/mesh/ConnectHandler.java
   gnunet-java/src/main/java/org/gnunet/mesh/Mesh.java
   gnunet-java/src/main/java/org/gnunet/mesh/MeshRunabout.java
   gnunet-java/src/main/java/org/gnunet/mesh/TunnelEndHandler.java
   gnunet-java/src/main/java/org/gnunet/mesh/package-info.java
   gnunet-java/src/main/java/org/gnunet/mq/MessageQueue.java
   gnunet-java/src/main/java/org/gnunet/secretsharing/Ciphertext.java
   gnunet-java/src/main/java/org/gnunet/secretsharing/Parameters.java
   gnunet-java/src/main/java/org/gnunet/secretsharing/Plaintext.java
   gnunet-java/src/main/java/org/gnunet/util/BigIntegers.java
   gnunet-java/src/main/java/org/gnunet/util/Connection.java
   gnunet-java/src/main/java/org/gnunet/util/Strings.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPrivateKey.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignature.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignedMessage.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaPrivateKey.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaPublicKey.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaSignature.java
   gnunet-java/src/main/java/org/gnunet/voting/Ballot.java
   gnunet-java/src/main/java/org/gnunet/voting/BallotTool.java
   gnunet-java/src/main/java/org/gnunet/voting/EncryptedVote.java
   gnunet-java/src/main/java/org/gnunet/voting/GroupCert.java
   gnunet-java/src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java
   gnunet-java/src/main/java/org/gnunet/voting/messages/SubmitMessage.java
   gnunet-java/src/main/java/org/gnunet/voting/simulation/Ballot.java
   gnunet-java/src/main/java/org/gnunet/voting/simulation/VotingParameters.java
   gnunet-java/src/main/resources/org/gnunet/construct/MsgMap.txt
   gnunet-java/src/main/resources/org/gnunet/voting/ballot-template.espec
   gnunet-java/src/test/java/org/gnunet/mesh/MeshTest.java
   gnunet-java/src/test/java/org/gnunet/util/EcdsaTest.java
   gnunet-java/src/test/java/org/gnunet/util/EddsaTest.java
   gnunet-java/src/test/java/org/gnunet/util/StringsTest.java
   gnunet-java/src/test/java/org/gnunet/voting/TestVotingCrypto.java
   gnunet-java/src/test/python/test_voting_single.py
Log:
- fix election crypto
- multi-way elections
- high-level signature containers
- fix bug in mesh test case
- fix bug in Strings.java
- ivy repo


Modified: gnunet-java/ISSUES
===================================================================
--- gnunet-java/ISSUES  2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/ISSUES  2014-03-30 21:41:58 UTC (rev 32833)
@@ -1,38 +1,23 @@
-coverage:
-gradle now has built-in support for JaCoCo => no cobertura, smaller build 
file, smaller repo
-(gradle downloads jacoco on demand)
 
-dependencies and packaging:
- * svn does not have any dependencies anymore, use gradle to fetch them (as 
discussed)
- * 'gradle publish' creates an ivy repository, containing
-  * the gnunet-java-<version>.jar
-  * transitive dependency information
- * we might want to host the repo directly on gnunet.org (via http)
+While waiting for mesh fixes, I looked again at
+multi-way elections, and implemented them (suprisingly they even work ;)
+ * zero knowledge proof turned out to be tricky but easier than I anticipated
+    Basic Idea:
+     * The chaum pedersen proof can prove equality of logs
+     * The Cramer-Damgard-Schoenmakers construction transforms any ZKP (with 
the required properties)
+       into disjunction (or more complicated access structures) proofs
+ * currently there's no fancy algorithm for the dlog,
+   just very crude brute force
 
-gnunet-java-ext:
- * build.gradle simply specifies the ivy repository
-  * choices: user must edit, https on gnunet.org, $GNUNET_JAVA_IVY
 
-gnunet-java shell wrappers and dependencies:
- * as deps of gnunet-java.jar are stored _somewhere_,
-   wrappers are problematic
- * proposal 1 (what most large java apps do):
-  * require that bin/ is always relative to lib/
-  * advantage: no dependency hell, easy
-  * disadvantage: more/redundant jars
- * proposal 2:
-  * template wrapper
-  * gradle script generates one wrapper for the
-    developer (with deps from the local gradle repo),
-    and one for the end user, relative to installation $PREFIX
+ * signing in gnunet-java now works like in GNUnet (correct usage of purpose 
header)
+  * as discussed, implemented with construct message unions
 
+ * voting crypto works
+ * simple voting test case works
+  * suggestions for test cases?
+   * no double voting, edge cases etc.
+ * Fixed the annoying java mesh api bug, that was actually a bug in the test 
case
 
-I'm working on a more powerful machine now -- a LOT of stuff goes wrong with 
mesh now that I can
-run larger testbeds
-(and Sree demonstrated to me that playing around with which transport plugin 
to use can have interesting effects)
-also, mesh constantly changes => new bugs
+Main problem right now: mesh is really unstable, consensus or secretsharing 
crash it all the time
 
-voting in java has some problems with crypto right now ... brute-forcing the 
tally does not find a result.
-(however, local tests work.  Printing ciphertexts, there does not seem to be a 
problem transmitting them,
-I'm still figuring out where that behavior might come from)
-

Added: gnunet-java/ivy-repo/org.gnunet/gnunet-java/0.2/gnunet-java-0.2.jar
===================================================================
(Binary files differ)

Index: gnunet-java/ivy-repo/org.gnunet/gnunet-java/0.2/gnunet-java-0.2.jar
===================================================================
--- gnunet-java/ivy-repo/org.gnunet/gnunet-java/0.2/gnunet-java-0.2.jar 
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/ivy-repo/org.gnunet/gnunet-java/0.2/gnunet-java-0.2.jar 
2014-03-30 21:41:58 UTC (rev 32833)

Property changes on: 
gnunet-java/ivy-repo/org.gnunet/gnunet-java/0.2/gnunet-java-0.2.jar
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Added: gnunet-java/ivy-repo/org.gnunet/gnunet-java/0.2/gnunet-java-0.2.jar.sha1
===================================================================
--- gnunet-java/ivy-repo/org.gnunet/gnunet-java/0.2/gnunet-java-0.2.jar.sha1    
                        (rev 0)
+++ gnunet-java/ivy-repo/org.gnunet/gnunet-java/0.2/gnunet-java-0.2.jar.sha1    
2014-03-30 21:41:58 UTC (rev 32833)
@@ -0,0 +1 @@
+7fda01a7189b9003f4567462c5778d6949a8474c
\ No newline at end of file

Added: gnunet-java/ivy-repo/org.gnunet/gnunet-java/0.2/ivy-0.2.xml
===================================================================
--- gnunet-java/ivy-repo/org.gnunet/gnunet-java/0.2/ivy-0.2.xml                 
        (rev 0)
+++ gnunet-java/ivy-repo/org.gnunet/gnunet-java/0.2/ivy-0.2.xml 2014-03-30 
21:41:58 UTC (rev 32833)
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ivy-module version="2.0">
+  <info organisation="org.gnunet" module="gnunet-java" revision="0.2" 
status="integration" publication="20140330202945"/>
+  <configurations>
+    <conf name="default" visibility="public" extends="runtime"/>
+    <conf name="runtime" visibility="public"/>
+  </configurations>
+  <publications>
+    <artifact name="gnunet-java" type="jar" ext="jar" conf="runtime"/>
+  </publications>
+  <dependencies>
+    <dependency org="com.google.guava" name="guava" rev="16.0.1" 
conf="runtime-&gt;default"/>
+    <dependency org="junit" name="junit" rev="4.11" 
conf="runtime-&gt;default"/>
+    <dependency org="log4j" name="log4j" rev="1.2.16" 
conf="runtime-&gt;default"/>
+    <dependency org="org.slf4j" name="slf4j-api" rev="1.6.4" 
conf="runtime-&gt;default"/>
+    <dependency org="org.slf4j" name="slf4j-log4j12" rev="1.6.4" 
conf="runtime-&gt;default"/>
+  </dependencies>
+</ivy-module>

Added: gnunet-java/ivy-repo/org.gnunet/gnunet-java/0.2/ivy-0.2.xml.sha1
===================================================================
--- gnunet-java/ivy-repo/org.gnunet/gnunet-java/0.2/ivy-0.2.xml.sha1            
                (rev 0)
+++ gnunet-java/ivy-repo/org.gnunet/gnunet-java/0.2/ivy-0.2.xml.sha1    
2014-03-30 21:41:58 UTC (rev 32833)
@@ -0,0 +1 @@
+0ce753b50f68508ccfece4ec1df60129e66ff6fc
\ No newline at end of file

Modified: 
gnunet-java/src/main/java/org/gnunet/construct/parsers/IntegerUtil.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/construct/parsers/IntegerUtil.java     
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/construct/parsers/IntegerUtil.java     
2014-03-30 21:41:58 UTC (rev 32833)
@@ -47,7 +47,7 @@
         val |= s;
 
         if (isSigned) {
-            // explicitly OR sign bit to the right place if the source buffer 
is
+            // explicitly OR signRaw bit to the right place if the source 
buffer is
             // too large
             long sign = (srcBuf.get(first) & 0x80);
             val |= (sign << 7);
@@ -69,9 +69,9 @@
         }
 
         if (isSigned) {
-            // a long has 8 bytes, shift by 7 bytes (non-arithmetically) to 
get the sign
+            // a long has 8 bytes, shift by 7 bytes (non-arithmetically) to 
get the signRaw
             byte sign = (byte) ((val >>> (7*8)) & 0x80);
-            // remove the sign bit from the buffer
+            // remove the signRaw bit from the buffer
             dstBuf.put(dstBuf.position() + byteSize - 1, (byte) 
(dstBuf.get(dstBuf.position() + byteSize - 1) & ~sign));
             // ... and put it in the right place (lowest byte)
             dstBuf.put(dstBuf.position(), (byte) 
(dstBuf.get(dstBuf.position()) | sign));

Modified: gnunet-java/src/main/java/org/gnunet/core/Core.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/core/Core.java 2014-03-30 13:42:47 UTC 
(rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/core/Core.java 2014-03-30 21:41:58 UTC 
(rev 32833)
@@ -267,7 +267,7 @@
         for (int i : interested) {
             logger.debug("we are interested in " + i);
         }
-        client.sendPrefered(initMessage);
+        client.sendPreferred(initMessage);
     }
 
     /**

Modified: gnunet-java/src/main/java/org/gnunet/mesh/ConnectHandler.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/mesh/ConnectHandler.java       
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/mesh/ConnectHandler.java       
2014-03-30 21:41:58 UTC (rev 32833)
@@ -8,5 +8,5 @@
  * @author Florian Dold
  */
 public interface ConnectHandler {
-    public void onConnect(Mesh.Tunnel tunnel, PeerIdentity peer);
+    public void onConnect(Mesh.Channel channel, PeerIdentity peer);
 }

Deleted: gnunet-java/src/main/java/org/gnunet/mesh/DisconnectHandler.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/mesh/DisconnectHandler.java    
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/mesh/DisconnectHandler.java    
2014-03-30 21:41:58 UTC (rev 32833)
@@ -1,12 +0,0 @@
-package org.gnunet.mesh;
-
-import org.gnunet.util.PeerIdentity;
-
-/**
- * ...
- *
- * @author Florian Dold
- */
-public interface DisconnectHandler {
-    void onDisconnect(PeerIdentity peer);
-}

Copied: gnunet-java/src/main/java/org/gnunet/mesh/InboundChannelHandler.java 
(from rev 32831, 
gnunet-java/src/main/java/org/gnunet/mesh/InboundTunnelHandler.java)
===================================================================
--- gnunet-java/src/main/java/org/gnunet/mesh/InboundChannelHandler.java        
                        (rev 0)
+++ gnunet-java/src/main/java/org/gnunet/mesh/InboundChannelHandler.java        
2014-03-30 21:41:58 UTC (rev 32833)
@@ -0,0 +1,12 @@
+package org.gnunet.mesh;
+
+import org.gnunet.util.PeerIdentity;
+
+/**
+ * ...
+ *
+ * @author Florian Dold
+ */
+public interface InboundChannelHandler {
+    void onInboundTunnel(Mesh.Channel channel, PeerIdentity initiator);
+}

Deleted: gnunet-java/src/main/java/org/gnunet/mesh/InboundTunnelHandler.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/mesh/InboundTunnelHandler.java 
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/mesh/InboundTunnelHandler.java 
2014-03-30 21:41:58 UTC (rev 32833)
@@ -1,12 +0,0 @@
-package org.gnunet.mesh;
-
-import org.gnunet.util.PeerIdentity;
-
-/**
- * ...
- *
- * @author Florian Dold
- */
-public interface InboundTunnelHandler {
-    void onInboundTunnel(Mesh.Tunnel tunnel, PeerIdentity initiator);
-}

Modified: gnunet-java/src/main/java/org/gnunet/mesh/Mesh.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/mesh/Mesh.java 2014-03-30 13:42:47 UTC 
(rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/mesh/Mesh.java 2014-03-30 21:41:58 UTC 
(rev 32833)
@@ -50,7 +50,7 @@
     private static final long TUNNEL_ID_CLI = 0x80000000L;
 
     /**
-     * For tunnels created by the server, the bit in this
+     * For tunnels created by the service, the bit in this
      * mask is always set.
      */
     private static final long TUNNEL_ID_SERV = 0xB0000000L;
@@ -91,12 +91,12 @@
     /**
      * Handler for inbound tunnels.
      */
-    private InboundTunnelHandler inboundTunnelHandler;
+    private InboundChannelHandler inboundChannelHandler;
 
     /**
      * Mapping from the tunnel's ID to the tunnel object.
      */
-    private Map<Long,Tunnel> tunnelMap = new HashMap<Long,Tunnel>();
+    private Map<Long,Channel> tunnelMap = new HashMap<Long,Channel>();
 
     /**
      * Counter for generating fresh tunnel ID's
@@ -108,7 +108,7 @@
      * A tunnel to a remote peer.
      * @param <T> type of context data for the tunnel
      */
-    public class Tunnel<T> extends MessageQueue {
+    public class Channel<T> extends MessageQueue {
         private T context;
         private final int opt;
         final PeerIdentity peer;
@@ -133,7 +133,7 @@
          * @param nobuffer Flag for disabling buffering on relay nodes.
          * @param reliable Flag for end-to-end reliability.
          */
-        public Tunnel(PeerIdentity peer, int port, boolean nobuffer, boolean 
reliable, T context) {
+        public Channel(PeerIdentity peer, int port, boolean nobuffer, boolean 
reliable, T context) {
             this(peer, 0, port, nobuffer, reliable);
             TunnelCreateMessage tcm = new TunnelCreateMessage();
             tcm.otherEnd = peer;
@@ -154,7 +154,7 @@
          * @param nobuffer
          * @param reliable
          */
-        public Tunnel(PeerIdentity peer, long tunnelId, int port, boolean 
nobuffer, boolean reliable) {
+        public Channel(PeerIdentity peer, long tunnelId, int port, boolean 
nobuffer, boolean reliable) {
             int myOpt = 0;
             if (reliable)
                 myOpt |= OPTION_RELIABLE;
@@ -242,16 +242,16 @@
 
     private class MeshMessageReceiver extends RunaboutMessageReceiver {
         public void visit(TunnelCreateMessage m) {
-            Tunnel t = new Tunnel(m.otherEnd, m.tunnelId, m.port,
+            Channel t = new Channel(m.otherEnd, m.tunnelId, m.port,
                     (m.opt & OPTION_NOBUFFER) != 0, (m.opt & OPTION_NOBUFFER) 
!= 0);
             logger.debug("inbound tunnel {}", m.tunnelId);
-            if (inboundTunnelHandler != null) {
-                inboundTunnelHandler.onInboundTunnel(t, m.otherEnd);
+            if (inboundChannelHandler != null) {
+                inboundChannelHandler.onInboundTunnel(t, m.otherEnd);
             }
         }
 
         public void visit(DataMessage m) {
-            Tunnel t = tunnelMap.get(m.tid);
+            Channel t = tunnelMap.get(m.tid);
             if (t != null)
             {
                 if (t.receiveDoneExpected)
@@ -268,7 +268,7 @@
 
         public void visit(LocalAckMessage m) {
             logger.debug("got LocalAckMessage for {}", m.tid);
-            Tunnel t = tunnelMap.get(m.tid);
+            Channel t = tunnelMap.get(m.tid);
             if (t != null) {
                 t.handleAck();
             } else {
@@ -277,38 +277,36 @@
         }
 
         public void visit(TunnelDestroyMessage m) {
-            Tunnel t = tunnelMap.get(m.tunnelId);
+            Channel t = tunnelMap.get(m.tunnelId);
             if (null == t) {
                 logger.warn("server got confused with tunnel IDs on destroy, 
ignoring message");
                 return;
             }
             t.destroyedByService = true;
+            logger.debug("tunnel destroyed by service");
             t.destroy();
-            if (null != tunnelEndHandler) {
-                tunnelEndHandler.onTunnelEnd(t);
-            }
+            tunnelEndHandler.onChannelEnd(t);
         }
 
         public void visit(RejectMessage m) {
             // FIXME: C code indicates that the nack/reject message might 
change ...
-            Tunnel t = tunnelMap.get(m.tunnelId);
+            Channel t = tunnelMap.get(m.tunnelId);
             if (null == t) {
                 logger.warn("server got confused with tunnel IDs on destroy, 
ignoring message");
                 return;
             }
             t.destroyedByService = true;
+            logger.debug("tunnel destroyed by service (nack/reject)");
             t.destroy();
-            if (null != tunnelEndHandler) {
-                tunnelEndHandler.onTunnelEnd(t);
-            }
+            tunnelEndHandler.onChannelEnd(t);
         }
 
         @Override
         public void handleError() {
             logger.warn("lost connection to mesh service, reconnecting");
             if (null != tunnelEndHandler) {
-                for (Tunnel t : tunnelMap.values()) {
-                    tunnelEndHandler.onTunnelEnd(t);
+                for (Channel t : tunnelMap.values()) {
+                    tunnelEndHandler.onChannelEnd(t);
                 }
             }
             tunnelMap.clear();
@@ -322,21 +320,22 @@
     /**
      * Connect to the mesh service, listening to the given ports.
      *
-     * @param cfg                  configuration to use
-     * @param inboundTunnelHandler function called when an *inbound* tunnel is 
created
-     * @param tunnelEndHandler     function called when an *inbound* tunnel is 
destroyed by the
-     *                             remote peer, it is *not* called if 
Tunnel.destroy
-     *                             is called on the tunnel
+     * @param cfg configuration to use
+     * @param inboundChannelHandler called when an inbound channel is 
established
+     * @param tunnelEndHandler called when a tunnel is destroyed (either by 
the client calling Tunnel.destroy(),
+     *                         or by the service)
      * @param messageReceiver runabout for messages we are interested in
      * @param ports ports to listen on
      */
-    public Mesh(Configuration cfg, InboundTunnelHandler inboundTunnelHandler,
+    public Mesh(Configuration cfg, InboundChannelHandler inboundChannelHandler,
                 TunnelEndHandler tunnelEndHandler, MeshRunabout 
messageReceiver, int... ports) {
+        if (null == tunnelEndHandler) {
+            throw new AssertionError("tunnel end handler may not be null");
+        }
         this.tunnelEndHandler = tunnelEndHandler;
         this.messageReceiver = messageReceiver;
         this.ports = ports;
-        this.inboundTunnelHandler = inboundTunnelHandler;
-
+        this.inboundChannelHandler = inboundChannelHandler;
         client = new Client("mesh", cfg);
         client.installReceiver(new MeshMessageReceiver());
         ClientConnectMessage ccm = new ClientConnectMessage();
@@ -351,24 +350,35 @@
     }
 
     /**
-     * Connect to the mesh service.
+     * Connect to the mesh service. Use this constructor if you are not 
interested in inbound tunnels.
      *
-     * @param cfg                  configuration to use
-     * @param tunnelEndHandler     function called when an *inbound* tunnel is 
destroyed by the
-     *                             remote peer, it is *not* called if 
Tunnel.destroy
-     *                             is called on the tunnel
+     * @param cfg configuration to use
+     * @param tunnelEndHandler called when a tunnel is destroyed (either by 
the client calling Tunnel.destroy(),
+     *                         or by the service)
      */
     public Mesh(Configuration cfg, TunnelEndHandler tunnelEndHandler, 
MeshRunabout messageReceiver) {
         this(cfg, null, tunnelEndHandler, messageReceiver);
     }
 
-    public <T> Tunnel<T> createTunnel(PeerIdentity peer, int port, boolean 
nobuffer, boolean reliable, T initialContext) {
-        return new Tunnel<T>(peer, port, nobuffer, reliable, initialContext);
+    /**
+     * Connect to the mesh service. Use this constructor if you are not 
interested in inbound tunnels
+     * and don't want to receive messages.
+     *
+     * @param cfg configuration to use
+     * @param tunnelEndHandler called when a tunnel is destroyed (either by 
the client calling Tunnel.destroy(),
+     *                         or by the service)
+     */
+    public Mesh(Configuration cfg, TunnelEndHandler tunnelEndHandler) {
+        this(cfg, null, tunnelEndHandler, null);
     }
 
-    public <T> Tunnel<T> createTunnel(PeerIdentity peer, int port, boolean 
nobuffer, boolean reliable) {
+    public <T> Channel<T> createTunnel(PeerIdentity peer, int port, boolean 
nobuffer, boolean reliable, T initialContext) {
+        return new Channel<T>(peer, port, nobuffer, reliable, initialContext);
+    }
+
+    public <T> Channel<T> createTunnel(PeerIdentity peer, int port, boolean 
nobuffer, boolean reliable) {
         logger.debug("creating tunnel to peer {} over port {}", 
peer.toString(), port);
-        return new Tunnel<T>(peer, port, nobuffer, reliable, null);
+        return new Channel<T>(peer, port, nobuffer, reliable, null);
     }
 
     /**

Modified: gnunet-java/src/main/java/org/gnunet/mesh/MeshRunabout.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/mesh/MeshRunabout.java 2014-03-30 
13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/mesh/MeshRunabout.java 2014-03-30 
21:41:58 UTC (rev 32833)
@@ -8,11 +8,11 @@
  * @author Florian Dold
  */
 public class MeshRunabout extends Runabout {
-    private Mesh.Tunnel sender;
-    /* package private */ void setSender(Mesh.Tunnel sender) {
+    private Mesh.Channel sender;
+    /* package private */ void setSender(Mesh.Channel sender) {
         this.sender = sender;
     }
-    public Mesh.Tunnel getSender() {
+    public Mesh.Channel getSender() {
         return sender;
     }
 }

Modified: gnunet-java/src/main/java/org/gnunet/mesh/TunnelEndHandler.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/mesh/TunnelEndHandler.java     
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/mesh/TunnelEndHandler.java     
2014-03-30 21:41:58 UTC (rev 32833)
@@ -7,11 +7,11 @@
  */
 public interface TunnelEndHandler {
     /**
-     * Called once a tunnel has been destroyed.
-     * The given tunnel can not be used anymore, and is only provided
-     * to identify the tunnel that has been destroyed.
+     * Called once a channel has been destroyed.
+     * The given channel can not be used anymore, and is only provided
+     * to identify the channel that has been destroyed.
      *
-     * @param tunnel tunnel that has been destroyed
+     * @param channel channel that has been destroyed
      */
-    void onTunnelEnd(Mesh.Tunnel tunnel);
+    void onChannelEnd(Mesh.Channel channel);
 }

Deleted: 
gnunet-java/src/main/java/org/gnunet/mesh/TunnelNotificationMessage.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/mesh/TunnelNotificationMessage.java    
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/mesh/TunnelNotificationMessage.java    
2014-03-30 21:41:58 UTC (rev 32833)
@@ -1,22 +0,0 @@
-package org.gnunet.mesh;
-
-import org.gnunet.construct.NestedMessage;
-import org.gnunet.construct.UInt32;
-import org.gnunet.util.GnunetMessage;
-import org.gnunet.util.PeerIdentity;
-
-/**
- * ...
- *
- * @author Florian Dold
- */
-public class TunnelNotificationMessage implements GnunetMessage.Body {
-    @UInt32
-    public int tunnelId;
-    /**
-     * Peer at the other end, if any
-     * TODO: ask bart what 'if any' means here
-     */
-    @NestedMessage
-    public PeerIdentity peer;
-}

Modified: gnunet-java/src/main/java/org/gnunet/mesh/package-info.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/mesh/package-info.java 2014-03-30 
13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/mesh/package-info.java 2014-03-30 
21:41:58 UTC (rev 32833)
@@ -20,6 +20,6 @@
 
 
 /**
- * Create tunnels for packet-based communication to distant peers.
+ * Create channels for packet-based communication to distant peers.
  */
 package org.gnunet.mesh;

Modified: gnunet-java/src/main/java/org/gnunet/mq/MessageQueue.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/mq/MessageQueue.java   2014-03-30 
13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/mq/MessageQueue.java   2014-03-30 
21:41:58 UTC (rev 32833)
@@ -2,6 +2,8 @@
 
 
 import org.gnunet.util.GnunetMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.LinkedList;
 
@@ -9,9 +11,31 @@
  * General-purpose message queue
  */
 public abstract class MessageQueue {
+    /**
+     * Class logger.
+     */
+    private static final Logger logger = LoggerFactory
+            .getLogger(MessageQueue.class);
+    /**
+     * Envelopes queued for sending.
+     */
     private LinkedList<Envelope> queuedEnvelopes = new LinkedList<Envelope>();
-    private LinkedList<Envelope> preferedQueuedEnvelopes = new 
LinkedList<Envelope>();
+    /**
+     * Envelopes queued for sending.  The preferred envelopes will always be 
sent before
+     * the envelopes in 'queuedEnvelopes'.
+     */
+    private LinkedList<Envelope> preferredQueuedEnvelopes = new 
LinkedList<Envelope>();
+    /**
+     * Envelope we are currently in the process of submitting.
+     * While the 'currentEnvelope' is not null, no other envelope
+     * can be transmitted.
+     */
     protected Envelope currentEnvelope;
+
+    /**
+     * Are we ready to submit messages, or should we wait and queue further 
submit
+     * requests?
+     */
     private boolean readyForSubmit;
 
     /**
@@ -30,23 +54,25 @@
         send(new Envelope(body));
     }
 
-    public void sendPrefered(GnunetMessage.Body body) {
-        sendPrefered(new Envelope(body));
+    public void sendPreferred(GnunetMessage.Body body) {
+        sendPreferred(new Envelope(body));
     }
 
     public void send(Envelope ev) {
+        logger.debug("message queue {}: queueing message", 
this.getClass().getName());
         queuedEnvelopes.addLast(ev);
         trySubmitNext();
     }
 
-    public void sendPrefered(Envelope ev) {
-        preferedQueuedEnvelopes.addLast(ev);
+    public void sendPreferred(Envelope ev) {
+        logger.debug("message queue {}: queueing preferred message", 
this.getClass().getName());
+        preferredQueuedEnvelopes.addLast(ev);
         trySubmitNext();
     }
 
     private Envelope pollNextEnvelope() {
-        if (!preferedQueuedEnvelopes.isEmpty())
-            return preferedQueuedEnvelopes.removeFirst();
+        if (!preferredQueuedEnvelopes.isEmpty())
+            return preferredQueuedEnvelopes.removeFirst();
         if (!queuedEnvelopes.isEmpty())
             return queuedEnvelopes.removeFirst();
         return null;
@@ -54,10 +80,12 @@
 
     protected void trySubmitNext() {
         if (currentEnvelope != null || !readyForSubmit) {
+            logger.debug("message queue {}: not submitting (not ready)", 
this.getClass().getName());
             return;
         }
         Envelope ev = pollNextEnvelope();
         if (ev == null) {
+            logger.debug("message queue {}: not submitting (nothing to send)", 
this.getClass().getName());
             return;
         }
         currentEnvelope = ev;
@@ -69,6 +97,7 @@
         if (readyForSubmit) {
             throw new AssertionError("message queue reported 'ready for 
submit' twice");
         }
+        logger.debug("message queue {} ready for submit", 
this.getClass().getName());
         readyForSubmit = true;
         trySubmitNext();
     }
@@ -90,15 +119,13 @@
      *
      * @param ev the envelope to onCancel
      */
-    /* pkg-private */ void cancelEnvelope(Envelope ev) {
-        if (null == currentEnvelope)
-            throw new AssertionError();
+    void cancelEnvelope(Envelope ev) {
         if (ev == currentEnvelope) {
             retract();
             trySubmitNext();
         } else {
             queuedEnvelopes.remove(ev);
-            preferedQueuedEnvelopes.remove(ev);
+            preferredQueuedEnvelopes.remove(ev);
         }
     }
 }

Modified: gnunet-java/src/main/java/org/gnunet/secretsharing/Ciphertext.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/secretsharing/Ciphertext.java  
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/secretsharing/Ciphertext.java  
2014-03-30 21:41:58 UTC (rev 32833)
@@ -26,6 +26,7 @@
 import org.gnunet.util.Strings;
 
 import java.math.BigInteger;
+import java.util.Arrays;
 
 /**
  * ElGamal ciphertext.
@@ -37,6 +38,26 @@
     @FixedSizeIntegerArray(signed = true, bitSize = 8, length = 
Parameters.elgamalBits / 8)
     public byte[] c_2;
 
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Ciphertext that = (Ciphertext) o;
+
+        if (!Arrays.equals(c_1, that.c_1)) return false;
+        if (!Arrays.equals(c_2, that.c_2)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = c_1 != null ? Arrays.hashCode(c_1) : 0;
+        result = 31 * result + (c_2 != null ? Arrays.hashCode(c_2) : 0);
+        return result;
+    }
+
     /**
      * Allocate the ciphertext with zeros.
      */

Modified: gnunet-java/src/main/java/org/gnunet/secretsharing/Parameters.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/secretsharing/Parameters.java  
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/secretsharing/Parameters.java  
2014-03-30 21:41:58 UTC (rev 32833)
@@ -20,12 +20,15 @@
 
 package org.gnunet.secretsharing;
 
+import org.gnunet.voting.simulation.VotingParameters;
+
 import java.math.BigInteger;
+import java.security.SecureRandom;
 
 /**
  * Constants used by the crypto of the secretsharing API.
  */
-public interface Parameters {
+public abstract class Parameters {
     /**
      * Size of the key.
      */
@@ -66,4 +69,26 @@
             "9cfd9f953674fab5d511e1c078fc72d72b34086f" +
             "c82b4b951989eb85325cb203ff98df76bc366bba" +
             "1d7024c3650f60d0da", 16);
+
+    public static BigInteger randomQ() {
+        SecureRandom r = new SecureRandom();
+        BigInteger y;
+        do {
+            y = new BigInteger(Parameters.elgamalBits - 1, r);
+        } while (y.compareTo(BigInteger.ONE) == 0 || 
y.compareTo(Parameters.elgamalQ) >= 0);
+        return y;
+    }
+
+    public static BigInteger modPowG(BigInteger exp) {
+        return elgamalG.modPow(exp, elgamalP);
+    }
+
+    public static BigInteger[] generateGenerators(int i) {
+        BigInteger[] generators = new BigInteger[i];
+        for (int j = 0; j < i; j++) {
+            // FIXME: this violates proper layering of the modules
+            generators[j] = VotingParameters.selectSubgroupGenerator(elgamalP, 
elgamalQ);
+        }
+        return generators;
+    }
 }

Modified: gnunet-java/src/main/java/org/gnunet/secretsharing/Plaintext.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/secretsharing/Plaintext.java   
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/secretsharing/Plaintext.java   
2014-03-30 21:41:58 UTC (rev 32833)
@@ -26,6 +26,7 @@
 
 import java.math.BigInteger;
 import java.security.SecureRandom;
+import java.util.Arrays;
 
 public class Plaintext implements Message {
     @FixedSizeIntegerArray(signed = true, bitSize = 8, length = 
Parameters.elgamalBits / 8)
@@ -39,17 +40,55 @@
         return plaintext;
     }
 
-    public long bruteForceDiscreteLog(final long l) {
+    /**
+     * Try all products of length l of the given generators.
+     *
+     * @param l number of factors
+     * @param generators different factors to chose from
+     * @return null if no solution was found, or an array of coefficients
+     */
+    public long[] bruteForceDiscreteLog(final long l, BigInteger[] generators) 
{
         BigInteger needle = new BigInteger(1, bits);
-        for (long i = -l; i <= l; i++) {
-            BigInteger val;
-            val = Parameters.elgamalG.modPow(BigInteger.valueOf(l), 
Parameters.elgamalP);
-            if (val.equals(needle))
-                return i;
+        if (l == 0) {
+            if (needle.equals(BigInteger.ONE))
+                return new long[0];
+            return null;
         }
-        throw new ArithmeticException(String.format("discrete log has no 
solution in range [%s, %s]", -l, l));
+        long[] combo = new long[generators.length];
+        boolean success = bruteForceDiscreteLog(l, combo, needle, 
BigInteger.ONE, generators, 0);
+        if (success) {
+            return combo;
+        }
+        return null;
     }
 
+    private static boolean bruteForceDiscreteLog(final long l, long[] combo,
+                                                final BigInteger needle, final 
BigInteger haystack,
+                                                BigInteger[] generators, final 
int genIdx) {
+        if (l == 0) {
+            combo[genIdx] = 0;
+            return haystack.equals(needle);
+        }
+        if (genIdx == generators.length - 1) {
+            combo[genIdx] = l;
+            BigInteger myHay = 
haystack.multiply(generators[genIdx].modPow(BigInteger.valueOf(l), 
Parameters.elgamalP)).mod(Parameters.elgamalP);
+            return myHay.equals(needle);
+        } else {
+            BigInteger myHay = haystack;
+            for (int i = 0; i <= l; i++) {
+                combo[genIdx] = i;
+                boolean success = bruteForceDiscreteLog(l - i, combo, needle, 
myHay, generators, genIdx + 1);
+                if (success) {
+                    return true;
+                }
+                myHay = 
myHay.multiply(generators[genIdx]).mod(Parameters.elgamalP);
+            }
+        }
+        return false;
+    }
+
+
+
     public Ciphertext encrypt(ThresholdPublicKey publicKey) {
         SecureRandom secureRandom = new SecureRandom();
         BigInteger c_1;
@@ -74,4 +113,11 @@
 
         return ciphertext;
     }
+
+    @Override
+    public String toString() {
+        return "Plaintext{" +
+                "bits=" + Arrays.toString(bits) +
+                '}';
+    }
 }

Deleted: gnunet-java/src/main/java/org/gnunet/statistics/SetRequest.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/statistics/SetRequest.java     
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/statistics/SetRequest.java     
2014-03-30 21:41:58 UTC (rev 32833)
@@ -1,50 +0,0 @@
-package org.gnunet.statistics;
-
-import org.gnunet.mq.Envelope;
-import org.gnunet.mq.MessageQueue;
-import org.gnunet.requests.Request;
-import org.gnunet.requests.RequestContainer;
-import org.gnunet.statistics.messages.SetMessage;
-import org.gnunet.util.RelativeTime;
-
-
-public class SetRequest extends Request {
-    /**
-     * Time after we give up on setting values in statistics
-     */
-    private static final RelativeTime SET_TIMEOUT = 
RelativeTime.SECOND.multiply(10);
-
-    private final static int SETFLAG_RELATIVE = 1;
-    private final static int SETFLAG_PERSIST = 2;
-    private final String subsystem;
-    private final String name;
-    private final boolean persist;
-    private final long value;
-    private final boolean relative;
-
-    public SetRequest(String subsystem, String name, long value, boolean 
relative, boolean persist) {
-        this.subsystem = subsystem;
-        this.name = name;
-        this.persist = persist;
-        this.value = value;
-        this.relative = relative;
-
-    }
-
-    @Override
-    public Envelope assembleRequest() {
-        SetMessage m = new SetMessage();
-        m.statisticName = name;
-        m.subsystemName = subsystem;
-        m.value = value;
-        if (relative)
-            m.flags |= SETFLAG_RELATIVE;
-        if (persist)
-            m.flags |= SETFLAG_PERSIST;
-        return new Envelope(m);
-    }
-
-    public void cancel() {
-        //To change body of implemented methods use File | Settings | File 
Templates.
-    }
-}

Modified: gnunet-java/src/main/java/org/gnunet/util/BigIntegers.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/BigIntegers.java  2014-03-30 
13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/util/BigIntegers.java  2014-03-30 
21:41:58 UTC (rev 32833)
@@ -31,18 +31,18 @@
 
     /**
      * Serialize a BigInteger, but do not add an extra bit for a
-     * sign.
+     * signRaw.
      *
      * @param bigInteger big integer to serialize
      * @param bits how many bits should the binary representation have?
      *             rounded up to the next multiple of 8.
-     * @return big endian representation of the given BigInteger, without a 
sign bit
+     * @return big endian representation of the given BigInteger, without a 
signRaw bit
      */
     public static byte[] serializeUnsigned(BigInteger bigInteger, int bits) {
         byte[] bytes = bigInteger.toByteArray();
         int start;
         Preconditions.checkArgument(bigInteger.bitCount() <= bits);
-        // skip byte that was only added to fit the sign
+        // skip byte that was only added to fit the signRaw
         if (bytes[0] == 0) {
             start = 1;
         } else {

Modified: gnunet-java/src/main/java/org/gnunet/util/Connection.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/Connection.java   2014-03-30 
13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/util/Connection.java   2014-03-30 
21:41:58 UTC (rev 32833)
@@ -200,6 +200,7 @@
                         return;
                     }
                 } catch (IOException e) {
+                    logger.debug("got IOException ({}, {})", 
e.getClass().getName(), e.getMessage());
                     error();
                     return;
                 }

Modified: gnunet-java/src/main/java/org/gnunet/util/Strings.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/Strings.java      2014-03-30 
13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/util/Strings.java      2014-03-30 
21:41:58 UTC (rev 32833)
@@ -48,7 +48,7 @@
         while ((rpos < size) || (vbit > 0)) {
             if ((rpos < size) && (vbit < 5)) {
                 byte b = data[(int) rpos++];
-                // convert (possibly negative) byte to int without sign 
extension
+                // convert (possibly negative) byte to int without signRaw 
extension
                 int s = b >= 0 ? b : (256 + b);
                 // eat 8 more bits
                 bits = (bits << 8) | s;
@@ -62,6 +62,8 @@
             sb.append(encTable.charAt((int) (bits >>> (vbit - 5)) & 31));
             vbit -= 5;
         }
+        if (sb.length() != getEncodedStringLength(data.length))
+            throw new AssertionError();
         return sb.toString();
     }
 
@@ -74,34 +76,44 @@
      * @return was the encoding successful?
      */
     public static boolean stringToData(String string, byte[] outData) {
-        long rpos;
-        long wpos;
-        long bits;
+        long rpos; // read position
+        long wpos; // write position
+        long bits; // bits to write next
         long vbit;
         long ret;
         long shift;
         int enclen = string.length();
         int encodedLen = outData.length * 8;
+
+        if (0 == enclen) {
+            if (0 == outData.length)
+                return true;
+            return false;
+        }
+
+        wpos = outData.length;
+        rpos = enclen;
+
         if (encodedLen % 5 > 0) {
             // padding!
             vbit = encodedLen % 5;
             shift = 5 - vbit;
+            bits = (ret = getValue(string.charAt((int) (--rpos)))) >>> (5 - 
(encodedLen % 5));
         } else {
-            vbit = 0;
+            vbit = 5;
             shift = 0;
+            bits = (ret = getValue(string.charAt((int) (--rpos))));
         }
         if ((encodedLen + shift) / 5 != enclen) {
             return false;
         }
-
-        wpos = outData.length;
-        rpos = enclen;
-        bits = (ret = getValue(string.charAt((int) (--rpos)))) >> (5 - 
encodedLen % 5);
         if (-1 == ret) {
             return false;
         }
         while (wpos > 0) {
-            assert rpos > 0;
+            if (0 == rpos) {
+                throw new AssertionError("rpos=0, but wpos " + wpos);
+            }
             bits = ((ret = getValue(string.charAt((int) (--rpos)))) << vbit) | 
bits;
             if (-1 == ret) {
                 return false;
@@ -109,12 +121,13 @@
             vbit += 5;
             if (vbit >= 8) {
                 outData[(int)--wpos] = (byte)((char) bits);
-                bits >>= 8;
+                bits >>>= 8;
                 vbit -= 8;
             }
         }
-        assert(rpos == 0);
-        assert(vbit == 0);
+        if (rpos != 0 || vbit != 0) {
+            return false;
+        }
         return true;
     }
 
@@ -165,4 +178,8 @@
         }
         return -1;
     }
+
+    public static byte[] stringToData(String s) {
+        return stringToData(s, getDecodedDataLength(s.length()));
+    }
 }

Added: 
gnunet-java/src/main/java/org/gnunet/util/crypto/ContentWithPurposeMessage.java
===================================================================
--- 
gnunet-java/src/main/java/org/gnunet/util/crypto/ContentWithPurposeMessage.java 
                            (rev 0)
+++ 
gnunet-java/src/main/java/org/gnunet/util/crypto/ContentWithPurposeMessage.java 
    2014-03-30 21:41:58 UTC (rev 32833)
@@ -0,0 +1,17 @@
+package org.gnunet.util.crypto;
+
+import org.gnunet.construct.Message;
+import org.gnunet.construct.UInt32;
+import org.gnunet.construct.Union;
+
+/**
+ * Purpose header fields, together with content union.
+ */
+public class ContentWithPurposeMessage<M extends SignedContentMessage> 
implements Message {
+    @UInt32
+    public int size;
+    @UInt32
+    public int purpose;
+    @Union(tag = "purpose")
+    public M m;
+}

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPrivateKey.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPrivateKey.java       
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPrivateKey.java       
2014-03-30 21:41:58 UTC (rev 32833)
@@ -24,6 +24,10 @@
 import org.gnunet.construct.Message;
 import org.gnunet.util.HashCode;
 
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOError;
+import java.io.IOException;
 import java.math.BigInteger;
 import java.security.SecureRandom;
 
@@ -56,29 +60,42 @@
         return privateKey;
     }
 
+    public EcdsaSignature sign(byte[] data, int purpose) {
+        return sign(data, purpose, getPublicKey());
+    }
+
+    public EcdsaSignature sign(byte[] data, int purpose, EcdsaPublicKey 
publicKey) {
+        ByteArrayOutputStream os = new ByteArrayOutputStream(data.length + 8);
+        DataOutputStream dos = new DataOutputStream(os);
+        try {
+            dos.writeInt(data.length);
+            dos.writeInt(purpose);
+            dos.write(data);
+        } catch (IOException e) {
+            throw new IOError(e);
+        }
+        return signRaw(publicKey, os.toByteArray());
+    }
+
     /**
-     * Sign the given data with this private key.  Must include a purpose to 
mitigate
-     * replay / copy and paste attacks.
+     * Sign the given data with this private key.
      *
-     * @param purpose purpose for the signature
-     * @param data data to sign
+     * @param data data to signRaw
      * @return the signature over both the data and the purpose
      */
-    public EcdsaSignature sign(int purpose, byte[] data) {
-        return sign(getPublicKey(), purpose, data);
+    public EcdsaSignature signRaw(byte[] data) {
+        return signRaw(getPublicKey(), data);
     }
 
     /**
-     * Sign the given data with this private key.  Must include a purpose to 
mitigate
-     * replay / copy and paste attacks.
+     * Sign the given data with this private key.
      *
      * @param publicKey public key corresponding to this private key, 
supplying this parameter
      *                  leads to better performance as the public key does not 
have to be derived
-     * @param purpose purpose for the signature
-     * @param data data to sign
+     * @param data data to signRaw
      * @return the signature over both the data and the purpose
      */
-    public EcdsaSignature sign(EcdsaPublicKey publicKey, int purpose, byte[] 
data) {
+    public EcdsaSignature signRaw(EcdsaPublicKey publicKey, byte[] data) {
         EcdsaSignature signature = new EcdsaSignature();
         DsaPrng prng = new DsaPrng(d, data);
         HashCode h = HashCode.hash(data);

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignature.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignature.java        
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignature.java        
2014-03-30 21:41:58 UTC (rev 32833)
@@ -26,6 +26,10 @@
 import org.gnunet.util.HashCode;
 import org.gnunet.util.Strings;
 
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOError;
+import java.io.IOException;
 import java.math.BigInteger;
 import java.security.SecureRandom;
 
@@ -57,11 +61,10 @@
      * given data and purpose.
      *
      * @param m message that was signed
-     * @param purpose purpose of the signature
      * @param publicKey public key to check for
      * @return whether the signature is valid
      */
-    public boolean verify(byte[] m, int purpose, EcdsaPublicKey publicKey) {
+    public boolean verifyRaw(byte[] m, EcdsaPublicKey publicKey) {
         if (publicKey.asPoint().isIdentity()) {
             throw new AssertionError();
         }
@@ -75,16 +78,6 @@
         }
 
         HashCode h = HashCode.hash(m);
-        /*
-        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);
@@ -98,6 +91,19 @@
         return P.P0.mod(Ed25519.l).equals(rCoeff);
     }
 
+    public boolean verify(byte[] data, int purpose, EcdsaPublicKey publicKey) {
+        ByteArrayOutputStream os = new ByteArrayOutputStream(data.length + 8);
+        DataOutputStream dos = new DataOutputStream(os);
+        try {
+            dos.writeInt(data.length);
+            dos.writeInt(purpose);
+            dos.write(data);
+        } catch (IOException e) {
+            throw new IOError(e);
+        }
+        return verifyRaw(os.toByteArray(), publicKey);
+    }
+
     /**
      * Load a signature from a string.
      *

Modified: 
gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignedMessage.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignedMessage.java    
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignedMessage.java    
2014-03-30 21:41:58 UTC (rev 32833)
@@ -20,41 +20,48 @@
 
 package org.gnunet.util.crypto;
 
-import org.gnunet.construct.Construct;
-import org.gnunet.construct.Message;
-import org.gnunet.construct.NestedMessage;
-import org.gnunet.construct.UInt32;
+import org.gnunet.construct.*;
 
 /**
  * A message together with a signature on the message and its purpose.
  */
-public class EcdsaSignedMessage<M extends Message> implements Message {
+public class EcdsaSignedMessage<M extends SignedContentMessage> implements 
Message {
     @NestedMessage
     public EcdsaSignature signature;
-    @UInt32
-    public int purpose;
-    @NestedMessage
-    public M innerMessage;
 
+    @NestedMessage(newFrame = true)
+    public ContentWithPurposeMessage<M> cpm;
+
+
     public EcdsaSignedMessage() {
         // empty constructor required by org.gnunet.construct
     }
 
-    public boolean verify(EcdsaPublicKey signerPublicKey) {
-        return signature.verify(Construct.toBinary(innerMessage), purpose, 
signerPublicKey);
+    public boolean verify(EcdsaPublicKey signerPublicKey, Class<? extends 
SignedContentMessage> expectedClass) {
+        if (!expectedClass.isInstance(cpm.m)) {
+            return false;
+        }
+        System.out.println("right class");
+        byte[] data = Construct.toBinary(cpm);
+        return signature.verifyRaw(data, signerPublicKey);
     }
 
-    public static <T extends Message> EcdsaSignedMessage<T> signMessage(T 
innerMessage, int purpose,
-                                             EcdsaPrivateKey privateKey, 
EcdsaPublicKey publicKey) {
-        EcdsaSignedMessage<T> esm = new EcdsaSignedMessage<T>();
-        esm.purpose = purpose;
-        esm.innerMessage = innerMessage;
-        esm.signature = privateKey.sign(purpose, 
Construct.toBinary(innerMessage));
-        return esm;
+    public EcdsaSignedMessage(M message, EcdsaPrivateKey privateKey,
+                              EcdsaPublicKey publicKey) {
+        cpm = new ContentWithPurposeMessage();
+        cpm.m = message;
+        Construct.patch(cpm);
+        byte[] data = Construct.toBinary(cpm);
+        signature = privateKey.signRaw(publicKey, data);
     }
 
-    public static <T extends Message> EcdsaSignedMessage<T> signMessage(T 
innerMessage, int purpose,
-                                             EcdsaPrivateKey privateKey) {
-        return signMessage(innerMessage, purpose, privateKey, 
privateKey.getPublicKey());
+    public EcdsaSignedMessage(M message, EcdsaPrivateKey privateKey) {
+        this(message, privateKey, privateKey.getPublicKey());
     }
+
+    public M get() {
+        return cpm.m;
+    }
+
 }
+

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaPrivateKey.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaPrivateKey.java       
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaPrivateKey.java       
2014-03-30 21:41:58 UTC (rev 32833)
@@ -22,6 +22,10 @@
 import org.gnunet.construct.FixedSizeIntegerArray;
 import org.gnunet.construct.Message;
 
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOError;
+import java.io.IOException;
 import java.math.BigInteger;
 import java.nio.ByteBuffer;
 import java.security.MessageDigest;
@@ -32,8 +36,8 @@
     @FixedSizeIntegerArray(bitSize = 8, signed = false, length = 32)
     public byte[] d;
 
-    public EddsaSignature sign(int purpose, byte[] m) {
-        return sign(getPublicKey(), purpose, m);
+    public EddsaSignature signRaw(byte[] m) {
+        return signRaw(getPublicKey(), m);
     }
 
     /**
@@ -42,11 +46,10 @@
      *
      * @param publicKey public key corresponding to this private key, 
supplying this parameter
      *                  leads to better performance as the public key does not 
have to be derived
-     * @param purpose purpose for the signature
-     * @param m data to sign
+     * @param m data to signRaw
      * @return the signature over both the data and the purpose
      */
-    public EddsaSignature sign(EddsaPublicKey publicKey, int purpose, byte[] 
m) {
+    public EddsaSignature signRaw(EddsaPublicKey publicKey, byte[] m) {
         if (!publicKey.asPoint().isOnCurve()) {
             throw new AssertionError();
         }
@@ -115,6 +118,24 @@
         return a;
     }
 
+    public EddsaSignature sign(byte[] data, int purpose) {
+        return sign(data, purpose, getPublicKey());
+    }
+
+    public EddsaSignature sign(byte[] data, int purpose, EddsaPublicKey 
publicKey) {
+        ByteArrayOutputStream os = new ByteArrayOutputStream(data.length + 8);
+        DataOutputStream dos = new DataOutputStream(os);
+        try {
+            dos.writeInt(data.length);
+            dos.writeInt(purpose);
+            dos.write(data);
+        } catch (IOException e) {
+            throw new IOError(e);
+        }
+        return signRaw(publicKey, os.toByteArray());
+    }
+
+
     /**
      * Get the public key for this private key.
      *

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaPublicKey.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaPublicKey.java        
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaPublicKey.java        
2014-03-30 21:41:58 UTC (rev 32833)
@@ -24,6 +24,10 @@
 import org.gnunet.construct.Message;
 import org.gnunet.util.Strings;
 
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOError;
+import java.io.IOException;
 import java.security.SecureRandom;
 import java.util.Arrays;
 

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaSignature.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaSignature.java        
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaSignature.java        
2014-03-30 21:41:58 UTC (rev 32833)
@@ -25,6 +25,10 @@
 import org.gnunet.construct.Message;
 import org.gnunet.util.Strings;
 
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOError;
+import java.io.IOException;
 import java.math.BigInteger;
 import java.nio.ByteBuffer;
 import java.security.SecureRandom;
@@ -58,11 +62,10 @@
      * 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) {
+    public boolean verifyRaw(byte[] m, EddsaPublicKey publicKey) {
         Ed25519 R = Ed25519.decode(r);
         if (!R.isOnCurve())
             return false;
@@ -99,6 +102,20 @@
         return sig;
     }
 
+
+    public boolean verify(byte[] data, int purpose, EddsaPublicKey publicKey) {
+        ByteArrayOutputStream os = new ByteArrayOutputStream(data.length + 8);
+        DataOutputStream dos = new DataOutputStream(os);
+        try {
+            dos.writeInt(data.length);
+            dos.writeInt(purpose);
+            dos.write(data);
+        } catch (IOException e) {
+            throw new IOError(e);
+        }
+        return verifyRaw(os.toByteArray(), publicKey);
+    }
+
     /**
      * Return a signature that is invalid with very, very high probability.
      *

Copied: 
gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaSignedMessage.java (from 
rev 32831, 
gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignedMessage.java)
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaSignedMessage.java    
                        (rev 0)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaSignedMessage.java    
2014-03-30 21:41:58 UTC (rev 32833)
@@ -0,0 +1,63 @@
+/*
+ This file is part of GNUnet.
+  (C) 2012, 2013 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.util.crypto;
+
+import org.gnunet.construct.Construct;
+import org.gnunet.construct.Message;
+import org.gnunet.construct.NestedMessage;
+
+/**
+ * A message together with a signature on the message and its purpose.
+ */
+public class EddsaSignedMessage implements Message {
+    @NestedMessage
+    public EddsaSignature signature;
+
+    @NestedMessage(newFrame = true)
+    public ContentWithPurposeMessage cpm;
+
+
+    public EddsaSignedMessage() {
+        // empty constructor required by org.gnunet.construct
+    }
+
+    public boolean verify(EddsaPublicKey signerPublicKey, Class<? extends 
SignedContentMessage> expectedClass) {
+        if (!expectedClass.isInstance(cpm.m)) {
+            return false;
+        }
+        byte[] data = Construct.toBinary(cpm);
+        return signature.verifyRaw(data, signerPublicKey);
+    }
+
+    public EddsaSignedMessage(SignedContentMessage message, EddsaPrivateKey 
privateKey,
+                              EddsaPublicKey publicKey) {
+        cpm = new ContentWithPurposeMessage();
+        cpm.m = message;
+        Construct.patch(cpm);
+        byte[] data = Construct.toBinary(cpm);
+        signature = privateKey.signRaw(publicKey, data);
+    }
+
+    public EddsaSignedMessage(SignedContentMessage message, EddsaPrivateKey 
privateKey) {
+        this(message, privateKey, privateKey.getPublicKey());
+    }
+
+}

Added: 
gnunet-java/src/main/java/org/gnunet/util/crypto/SignedContentMessage.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/SignedContentMessage.java  
                        (rev 0)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/SignedContentMessage.java  
2014-03-30 21:41:58 UTC (rev 32833)
@@ -0,0 +1,8 @@
+package org.gnunet.util.crypto;
+
+
+import org.gnunet.construct.MessageUnion;
+
+public interface SignedContentMessage extends MessageUnion {
+    // empty, this is a tag interface
+}

Modified: gnunet-java/src/main/java/org/gnunet/voting/Ballot.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/voting/Ballot.java     2014-03-30 
13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/voting/Ballot.java     2014-03-30 
21:41:58 UTC (rev 32833)
@@ -27,6 +27,7 @@
 import com.google.common.collect.HashBiMap;
 import com.google.common.collect.Maps;
 import com.google.common.primitives.Longs;
+import org.gnunet.secretsharing.Parameters;
 import org.gnunet.secretsharing.ThresholdPublicKey;
 import org.gnunet.util.AbsoluteTime;
 import org.gnunet.util.Configuration;
@@ -37,7 +38,10 @@
 import org.gnunet.util.crypto.EcdsaSignature;
 import org.gnunet.util.crypto.EddsaSignature;
 import org.gnunet.voting.messages.KeyQueryResponseMessage;
+import org.gnunet.voting.simulation.VotingParameters;
+import org.omg.CORBA.DynAnyPackage.Invalid;
 
+import java.math.BigInteger;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.*;
@@ -129,6 +133,11 @@
     SortedMap<String,KeyQueryResponseMessage> thresholdPublicKeys;
 
     /**
+     * Generators, one for each choice.
+     */
+    BigInteger generators[];
+
+    /**
      * Threshold for the election.
      */
     public int threshold;
@@ -310,6 +319,19 @@
             m.signedGuidKey.publicKey = 
ThresholdPublicKey.fromString(e.getValue());
             thresholdPublicKeys.put(alias, m);
         }
+        // If there's one generator, the others have to be there, too.
+        if (cfg.haveValue("generators", "g0")) {
+            generators = new BigInteger[choices.size()];
+            for (int i = 0; i < choices.size(); i++) {
+                Optional<String> optG = cfg.getValueString("generators", 
"g"+i);
+                if (!optG.isPresent()) {
+                    throw new InvalidBallotException(
+                            String.format("Generator %s is missing.  Please 
issue the ballot correctlly", i));
+                }
+                generators[i] = new BigInteger(optG.get(), 16);
+            }
+        }
+
     }
 
     /**
@@ -387,6 +409,9 @@
      */
     public void encodeChoice(String choice, ThresholdPublicKey 
thresholdPublicKey,
                              EcdsaPrivateKey voterPrivateKey) {
+        if (null == generators || generators.length != choices.size()) {
+            throw new InvalidBallotException("Can't encrypt vote without valid 
generators.");
+        }
         int choiceId = -1;
         int i = 0;
         for (String possibleChoice : choices) {
@@ -396,7 +421,8 @@
             i++;
         }
         voterPub = voterPrivateKey.getPublicKey();
-        encryptedVote = EncryptedVote.fromChoice(choiceId, thresholdPublicKey, 
voterPrivateKey, voterPub);
+        encryptedVote = EncryptedVote.fromChoice(choiceId, thresholdPublicKey, 
voterPrivateKey, voterPub,
+                generators);
         System.out.println("voter encrypted vote, ciphertext: " + 
encryptedVote.v.toString());
         System.out.println("threshold key (of voter): " + 
thresholdPublicKey.toString());
     }
@@ -452,6 +478,11 @@
             cfg.setValueString("threshold-pubkey-sigs", e.getKey(),
                     e.getValue().signature.toString());
         }
+        if (generators != null) {
+            for (int i = 0; i < generators.length; i++) {
+                cfg.setValueString("generators", "g"+i, 
generators[i].toString(16));
+            }
+        }
         return cfg;
     }
 
@@ -606,13 +637,18 @@
 
     /**
      * Add the issuer to the ballot, and sign the election information in the 
ballot.
+     * Also selects the generators for every choice.
      *
      * @param privateKey private key of the issuer
      */
     public void issue(EcdsaPrivateKey privateKey) {
+        generators = new BigInteger[choices.size()];
+        for (int i = 0; i < choices.size(); i++) {
+            generators[i] = 
VotingParameters.selectSubgroupGenerator(Parameters.elgamalP, 
Parameters.elgamalQ);
+        }
         issuerPub = privateKey.getPublicKey();
         // FIXME: purpose
-        issuerSig = privateKey.sign(0, getBallotGuid().data);
+        issuerSig = privateKey.sign(getBallotGuid().data, 0);
     }
 
     /**

Modified: gnunet-java/src/main/java/org/gnunet/voting/BallotTool.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/voting/BallotTool.java 2014-03-30 
13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/voting/BallotTool.java 2014-03-30 
21:41:58 UTC (rev 32833)
@@ -146,9 +146,9 @@
     private Mesh mesh;
 
     /**
-     * A tunnel to 'currentAuthority' or null.
+     * A channel to 'currentAuthority' or null.
      */
-    private Mesh.Tunnel tunnel;
+    private Mesh.Channel channel;
 
     /**
      * The authority we are currently communicating with.
@@ -156,7 +156,7 @@
     private PeerIdentity currentAuthority;
 
     /**
-     * Are we finished with communicating over the mesh tunnel and don't need 
to worry about
+     * Are we finished with communicating over the mesh channel and don't need 
to worry about
      * disconnection?
      */
     private boolean tunnelCommunicationFinished;
@@ -165,11 +165,11 @@
 
     public class BallotTunnelEndHandler implements TunnelEndHandler {
         @Override
-        public void onTunnelEnd(final Mesh.Tunnel tunnel) {
+        public void onChannelEnd(final Mesh.Channel channel) {
             // FIXME: just re-running 'doCommands' is a bit of a hack
-            BallotTool.this.tunnel = null;
+            BallotTool.this.channel = null;
             if (!tunnelCommunicationFinished) {
-                logger.warn("mesh tunnel disconnected, but operation not 
finished");
+                logger.warn("mesh channel disconnected, but operation not 
finished");
                 Scheduler.addDelayed(tunnelReconnectBackoff, new 
Scheduler.Task() {
                     @Override
                     public void run(Scheduler.RunContext ctx) {
@@ -182,14 +182,14 @@
     }
 
     /**
-     * Destroy the tunnel to the authority as well
+     * Destroy the channel to the authority as well
      * as the mesh handle.
      */
     private void endMesh() {
         tunnelCommunicationFinished = true;
-        if (null != tunnel) {
-            tunnel.destroy();
-            tunnel = null;
+        if (null != channel) {
+            channel.destroy();
+            channel = null;
         }
         if (null != mesh) {
             mesh.destroy();
@@ -260,7 +260,7 @@
         public void visit(SubmitFailureMessage m) {
             System.out.println("vote not submitted: " + m.reason);
             if (m.signedAuthorityTime != null) {
-                // FIXME: verify
+                // FIXME: verifyRaw
                 System.out.println("authority time: " +
                         
AbsoluteTime.fromNetwork(m.signedAuthorityTime.time).toFancyString());
             }
@@ -323,11 +323,11 @@
             currentAuthority = 
remainingAuthorities.get(r.nextInt(remainingAuthorities.size()));
             System.out.println("registering ballot with authority " + 
currentAuthority.toString());
             mesh = new Mesh(getConfiguration(), new BallotTunnelEndHandler(), 
new BallotRegisterReceiver());
-            tunnel = mesh.createTunnel(currentAuthority, 
TallyAuthorityDaemon.MESH_PORT, true, true);
+            channel = mesh.createTunnel(currentAuthority, 
TallyAuthorityDaemon.MESH_PORT, true, true);
             BallotRegisterRequestMessage m = new 
BallotRegisterRequestMessage();
             CompressedConfig ccfg = new 
CompressedConfig(ballot.toConfiguration());
             m.compressedBallotConfig = ccfg.compressedData;
-            tunnel.send(m);
+            channel.send(m);
             return;
         }
         if (issue) {
@@ -368,7 +368,7 @@
             System.out.println("submitting to authority " + 
authority.toString());
             currentAuthority = authority;
             mesh = new Mesh(cfg, new BallotTunnelEndHandler(), new 
SubmitReceiver());
-            tunnel = mesh.createTunnel(authority, 
TallyAuthorityDaemon.MESH_PORT, true, true, null);
+            channel = mesh.createTunnel(authority, 
TallyAuthorityDaemon.MESH_PORT, true, true, null);
             SubmitMessage m = new SubmitMessage();
             if (ballot.voterPub == null) {
                 throw new InvalidBallotException("no voter in ballot");
@@ -384,7 +384,7 @@
                 throw new InvalidBallotException("no encrypted vote in 
ballot");
             }
             m.encryptedVote = ballot.encryptedVote;
-            tunnel.send(m);
+            channel.send(m);
             return;
         }
         if (verify) {
@@ -402,10 +402,10 @@
             currentAuthority = 
remainingAuthorities.get(r.nextInt(remainingAuthorities.size()));
             System.out.println("querying authority " + 
currentAuthority.toString());
             mesh = new Mesh(cfg, new BallotTunnelEndHandler(), new 
QueryReceiver());
-            tunnel = mesh.createTunnel(currentAuthority, 
TallyAuthorityDaemon.MESH_PORT, true, true, null);
+            channel = mesh.createTunnel(currentAuthority, 
TallyAuthorityDaemon.MESH_PORT, true, true, null);
             ResultQueryMessage m = new ResultQueryMessage();
             m.ballotGuid = ballot.getBallotGuid();
-            tunnel.send(m);
+            channel.send(m);
             return;
         }
         if (requestKey) {
@@ -418,10 +418,10 @@
             currentAuthority = 
remainingAuthorities.get(r.nextInt(remainingAuthorities.size()));
             System.out.println("asking authority for key " + 
currentAuthority.toString());
             mesh = new Mesh(cfg, new BallotTunnelEndHandler(), new 
PublicKeyReceiver());
-            tunnel = mesh.createTunnel(currentAuthority, 
TallyAuthorityDaemon.MESH_PORT, true, true, null);
+            channel = mesh.createTunnel(currentAuthority, 
TallyAuthorityDaemon.MESH_PORT, true, true, null);
             KeyQueryMessage m = new KeyQueryMessage();
             m.ballotGuid = ballot.getBallotGuid();
-            tunnel.send(m);
+            channel.send(m);
             return;
         }
         setReturnValue(1);

Added: gnunet-java/src/main/java/org/gnunet/voting/ChaumPedersenZkp.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/voting/ChaumPedersenZkp.java           
                (rev 0)
+++ gnunet-java/src/main/java/org/gnunet/voting/ChaumPedersenZkp.java   
2014-03-30 21:41:58 UTC (rev 32833)
@@ -0,0 +1,75 @@
+/*
+ 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.voting;
+
+import org.gnunet.construct.FixedSizeIntegerArray;
+import org.gnunet.construct.Message;
+import org.gnunet.secretsharing.Parameters;
+
+import java.math.BigInteger;
+
+/**
+ * Proof in zero knowledge of dlog equality.
+ * Proves log_g(x) = log_h(y) = alpha
+ * FIXME: get the details right, the Cramers voting paper uses a proof that is 
a
+ * FIXME: bit different from the plain chaum pedersen proof
+ */
+public class ChaumPedersenZkp implements Message {
+    @FixedSizeIntegerArray(signed = true, bitSize = 8, length = 
Parameters.elgamalBits / 8)
+    public byte[] commit_a;
+    @FixedSizeIntegerArray(signed = true, bitSize = 8, length = 
Parameters.elgamalBits / 8)
+    public byte[] commit_b;
+
+    @FixedSizeIntegerArray(signed = true, bitSize = 8, length = 
Parameters.elgamalBits / 8)
+    public byte[] challenge_d;
+
+    @FixedSizeIntegerArray(signed = true, bitSize = 8, length = 
Parameters.elgamalBits / 8)
+    public byte[] response_r;
+
+
+    /**
+     * Verify the simulated proof.  That is, don't check
+     * if the challenge was actually computed correctly from the commits.
+     */
+    public boolean verifySim(BigInteger x, BigInteger y, BigInteger coeffG, 
BigInteger h) {
+        BigInteger a = new BigInteger(1, commit_a);
+        BigInteger b = new BigInteger(1, commit_b);
+        BigInteger d = new BigInteger(1, challenge_d);
+        BigInteger r = new BigInteger(1, response_r);
+        BigInteger g = Parameters.elgamalG;
+        BigInteger p = Parameters.elgamalP;
+
+        if (!b.equals(h.modPow(r, 
p).multiply(y.multiply(coeffG.modInverse(p)).modPow(d, p)).mod(p))) {
+            System.out.println("b not equal");
+            return false;
+        }
+
+        if (!a.equals(g.modPow(r, p).multiply(x.modPow(d, p)).mod(p))) {
+            System.out.println("a not equal");
+            return false;
+        }
+
+
+        return true;
+    }
+}
+
+

Added: gnunet-java/src/main/java/org/gnunet/voting/DisjunctionZkp.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/voting/DisjunctionZkp.java             
                (rev 0)
+++ gnunet-java/src/main/java/org/gnunet/voting/DisjunctionZkp.java     
2014-03-30 21:41:58 UTC (rev 32833)
@@ -0,0 +1,64 @@
+/*
+ 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.voting;
+
+import org.gnunet.construct.*;
+import org.gnunet.secretsharing.Parameters;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * Disjunction of Chaum Pedersen ZKPs.
+ */
+public class DisjunctionZkp implements Message {
+    @UInt64
+    public int numProofs;
+    @FixedSizeIntegerArray(signed = true, bitSize = 8, length = 
Parameters.elgamalBits / 8)
+    public byte[] challenge_c;
+    @VariableSizeArray(lengthField = "numProofs")
+    public ChaumPedersenZkp[] chaumPedersenZkps;
+
+    public boolean verifyChallenge() {
+        BigInteger c_actual = new BigInteger(1, challenge_c);
+        BigInteger c_expected = BigInteger.ZERO;
+        for (ChaumPedersenZkp chaumPedersenZkp : chaumPedersenZkps) {
+            BigInteger d = new BigInteger(1, chaumPedersenZkp.challenge_d);
+            c_expected = c_expected.add(d).mod(Parameters.elgamalQ);
+        }
+        return c_actual.equals(c_expected) && 
computeChallengeFromCommits().equals(c_actual);
+    }
+
+    public BigInteger computeChallengeFromCommits() {
+        MessageDigest digest;
+        try {
+            digest = MessageDigest.getInstance("SHA-512");
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException("crypto algorithm 'SHA-512' required 
but not provided");
+        }
+        for (ChaumPedersenZkp chaumPedersenZkp : chaumPedersenZkps) {
+            digest.update(chaumPedersenZkp.commit_a);
+            digest.update(chaumPedersenZkp.commit_b);
+        }
+        return (new BigInteger(digest.digest())).mod(Parameters.elgamalQ);
+    }
+}

Modified: gnunet-java/src/main/java/org/gnunet/voting/EncryptedVote.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/voting/EncryptedVote.java      
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/voting/EncryptedVote.java      
2014-03-30 21:41:58 UTC (rev 32833)
@@ -22,49 +22,33 @@
 
 
 import com.google.common.base.Optional;
+import org.gnunet.construct.Construct;
 import org.gnunet.construct.Message;
 import org.gnunet.construct.NestedMessage;
 import org.gnunet.secretsharing.Ciphertext;
-import org.gnunet.secretsharing.Plaintext;
+import org.gnunet.secretsharing.Parameters;
 import org.gnunet.secretsharing.ThresholdPublicKey;
+import org.gnunet.util.BigIntegers;
 import org.gnunet.util.Configuration;
+import org.gnunet.util.Strings;
 import org.gnunet.util.crypto.EcdsaPrivateKey;
 import org.gnunet.util.crypto.EcdsaPublicKey;
-import org.gnunet.voting.simulation.Voter;
-import org.omg.CORBA.DynAnyPackage.Invalid;
+import org.gnunet.util.crypto.SignedContentMessage;
+import org.gnunet.voting.simulation.CryptoUtil;
 
 import java.math.BigInteger;
+import java.util.Arrays;
 
-public class EncryptedVote implements Message {
+public class EncryptedVote implements Message, SignedContentMessage {
     @NestedMessage
     public Ciphertext v;
 
+    @NestedMessage
+    public DisjunctionZkp disjunctionZkp;
 
     @NestedMessage
     public EcdsaPublicKey voterPublicKey;
 
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        EncryptedVote that = (EncryptedVote) o;
-
-        if (v != null ? !v.equals(that.v) : that.v != null) return false;
-        if (voterPublicKey != null ? 
!voterPublicKey.equals(that.voterPublicKey) : that.voterPublicKey != null)
-            return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = v != null ? v.hashCode() : 0;
-        result = 31 * result + (voterPublicKey != null ? 
voterPublicKey.hashCode() : 0);
-        return result;
-    }
-
-
     /**
      * Construct an EncryptedVote by parsing it from the configuration.
      * The voter public key must be passed separately.
@@ -78,30 +62,127 @@
         if (!optVal.isPresent()) {
             return null;
         }
+        Optional<String> optZkp = cfg.getValueString("vote", "ZKP");
+        if (!optZkp.isPresent()) {
+            return null;
+        }
         EncryptedVote encryptedVote = new EncryptedVote();
         encryptedVote.voterPublicKey = voterPublicKey;
         encryptedVote.v = Ciphertext.fromString(optVal.get());
+        System.out.println("reading, string size " + optZkp.get().length());
+        byte[] zkpData = Strings.stringToData(optZkp.get());
+        if (null == zkpData) {
+            throw new InvalidBallotException("could not read ZKP from ballot");
+        }
+        encryptedVote.disjunctionZkp = Construct.parseAs(zkpData, 
DisjunctionZkp.class);
         return encryptedVote;
     }
-    // TODO: zero knowledge proof
-    // TODO: signature
 
-    public static EncryptedVote fromChoice(int choiceId, ThresholdPublicKey 
thresholdPublicKey,
-                                           EcdsaPrivateKey voterPrivateKey, 
EcdsaPublicKey voterPublicKey) {
-        // for now, we only support one choice!
-        if (choiceId < 0 || choiceId > 1) {
-            throw new InvalidBallotException(String.format("choice '%s' not 
valid", choiceId));
-        }
-        int choiceExp = (choiceId == 1) ? 1 : -1;
-        // FIXME: can we use 'g', or should we use another generator?
-        Plaintext p = Plaintext.generate(BigInteger.valueOf(choiceExp));
+    public static EncryptedVote fromChoice(int choiceId, ThresholdPublicKey 
thresholdPublicKey, EcdsaPublicKey voterPublicKey,
+                                           BigInteger[] generators) {
+
         EncryptedVote encryptedVote = new EncryptedVote();
-        encryptedVote.v = p.encrypt(thresholdPublicKey);
+        encryptedVote.v = new Ciphertext();
         encryptedVote.voterPublicKey = voterPublicKey;
+        encryptedVote.disjunctionZkp = new DisjunctionZkp();
+
+        encryptedVote.disjunctionZkp.chaumPedersenZkps = new 
ChaumPedersenZkp[generators.length];
+        encryptedVote.disjunctionZkp.numProofs = generators.length;
+
+        // the discrete logarithm
+        BigInteger alpha = Parameters.randomQ();
+        // the secret for the ZKP
+        BigInteger w = Parameters.randomQ();
+
+        BigInteger h = new BigInteger(1, thresholdPublicKey.bits);
+        BigInteger g = Parameters.elgamalG;
+        BigInteger p = Parameters.elgamalP;
+        BigInteger q = Parameters.elgamalQ;
+
+        BigInteger x = Parameters.modPowG(alpha);
+        BigInteger y = h.modPow(alpha, 
p).multiply(generators[choiceId]).mod(p);
+
+        encryptedVote.v.c_1 = BigIntegers.serializeUnsigned(x, 
Parameters.elgamalBits);
+        encryptedVote.v.c_2 = BigIntegers.serializeUnsigned(y, 
Parameters.elgamalBits);
+
+        // sum of all the simulation challenges
+        BigInteger d_sim_sum = BigInteger.ZERO;
+
+        // generate simulated proofs
+        for (int i = 0; i < generators.length; i++) {
+            if (i == choiceId) {
+                continue;
+            }
+            BigInteger r = Parameters.randomQ();
+            BigInteger d = Parameters.randomQ();
+            BigInteger a = g.modPow(r, p).multiply(x.modPow(d, p)).mod(p);
+            BigInteger b = h.modPow(r, 
p).multiply(y.multiply(generators[i].modInverse(p)).modPow(d, p)).mod(p);
+
+            d_sim_sum = d_sim_sum.add(d);
+
+            ChaumPedersenZkp zkp = new ChaumPedersenZkp();
+            zkp.challenge_d = BigIntegers.serializeUnsigned(d, 
Parameters.elgamalBits);
+            zkp.response_r = BigIntegers.serializeUnsigned(r, 
Parameters.elgamalBits);
+            zkp.commit_a = BigIntegers.serializeUnsigned(a, 
Parameters.elgamalBits);
+            zkp.commit_b = BigIntegers.serializeUnsigned(b, 
Parameters.elgamalBits);
+
+            if (!zkp.verifySim(x, y, generators[i], h)) {
+                throw new AssertionError("crypto not working");
+            }
+
+            encryptedVote.disjunctionZkp.chaumPedersenZkps[i] = zkp;
+        }
+
+        ChaumPedersenZkp zkp = new ChaumPedersenZkp();
+        encryptedVote.disjunctionZkp.chaumPedersenZkps[choiceId] = zkp;
+        BigInteger a = g.modPow(w, p);
+        BigInteger b = h.modPow(w, p);
+        zkp.commit_a = BigIntegers.serializeUnsigned(a, 
Parameters.elgamalBits);
+        zkp.commit_b = BigIntegers.serializeUnsigned(b, 
Parameters.elgamalBits);
+
+
+        BigInteger c = 
encryptedVote.disjunctionZkp.computeChallengeFromCommits();
+
+        BigInteger d = c.subtract(d_sim_sum).mod(q);
+        BigInteger r = w.subtract(alpha.multiply(d)).mod(q);
+
+
+        zkp.challenge_d = BigIntegers.serializeUnsigned(d, 
Parameters.elgamalBits);
+        zkp.response_r = BigIntegers.serializeUnsigned(r, 
Parameters.elgamalBits);
+
+
+        if (!zkp.verifySim(x,y,generators[choiceId], h)) {
+            throw new AssertionError("crypto (2) not working");
+        }
+
+        encryptedVote.disjunctionZkp.challenge_c = 
BigIntegers.serializeUnsigned(c, Parameters.elgamalBits);
+
+        if (!encryptedVote.disjunctionZkp.verifyChallenge()) {
+            throw new AssertionError("crypto not working (3)");
+        }
+
         return encryptedVote;
     }
 
     public void writeToConfiguration(Configuration cfg) {
         cfg.setValueString("vote", "ENCRYPTED_VOTE_VAL", v.toString());
+        byte[] zkpData = Construct.toBinary(disjunctionZkp);
+        String zkpString = Strings.dataToString(zkpData);
+        if (zkpString.length() != 
Strings.getEncodedStringLength(zkpData.length))
+            throw new AssertionError("fail");
+        if (zkpData.length != Strings.getDecodedDataLength(zkpString.length()))
+            throw new AssertionError("fail, got " + zkpData.length + " 
expected " +
+                    Strings.getDecodedDataLength(zkpString.length()) + "for 
string length" + zkpString.length());
+        System.out.println("everyting ok, size binary size" + zkpData.length 
+" str size " + zkpString.length());
+        byte[] zkpData2 = Strings.stringToData(zkpString);
+        if (!Arrays.equals(zkpData, zkpData2)) {
+            throw new AssertionError("something wrong");
+        }
+        System.out.println("everyting ok, size binary size" + zkpData.length 
+" str size " + zkpString.length());
+        cfg.setValueString("vote", "ZKP", zkpString);
     }
+
+    public boolean verify() {
+        return false;
+    }
 }

Modified: gnunet-java/src/main/java/org/gnunet/voting/GroupCert.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/voting/GroupCert.java  2014-03-30 
13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/voting/GroupCert.java  2014-03-30 
21:41:58 UTC (rev 32833)
@@ -60,7 +60,7 @@
         signData += expiration.getSeconds();
         signData += group;
         signData += signerPublicKey;
-        groupCert.signature = signerPrivateKey.sign(0 /*FIXME*/, 
signData.getBytes());
+        groupCert.signature = signerPrivateKey.sign(signData.getBytes(), 0);
         return groupCert;
 
     }

Added: gnunet-java/src/main/java/org/gnunet/voting/SignedEncryptedVote.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/voting/SignedEncryptedVote.java        
                        (rev 0)
+++ gnunet-java/src/main/java/org/gnunet/voting/SignedEncryptedVote.java        
2014-03-30 21:41:58 UTC (rev 32833)
@@ -0,0 +1,8 @@
+package org.gnunet.voting;
+
+import org.gnunet.construct.Message;
+import org.gnunet.util.crypto.EcdsaSignedMessage;
+
+public class SignedEncryptedVote implements Message {
+    EcdsaSignedMessage<EncryptedVote> signedMessage;
+}

Modified: gnunet-java/src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java       
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java       
2014-03-30 21:41:58 UTC (rev 32833)
@@ -27,6 +27,7 @@
 import org.gnunet.construct.Construct;
 import org.gnunet.mesh.Mesh;
 import org.gnunet.mesh.MeshRunabout;
+import org.gnunet.mesh.TunnelEndHandler;
 import org.gnunet.secretsharing.*;
 import org.gnunet.secretsharing.callbacks.DecryptCallback;
 import org.gnunet.secretsharing.callbacks.SecretReadyCallback;
@@ -173,11 +174,13 @@
                         public void onResult(Plaintext plaintext) {
                             logger.info("got decypt result");
                             long l = electionState.countedVoters.size();
-                            long t = plaintext.bruteForceDiscreteLog(l);
-                            logger.info("brute-forced result");
-                            electionState.tally = new long[2];
-                            electionState.tally[0] = (l - t) / 2;
-                            electionState.tally[1] = l - 
electionState.tally[0];
+                            long t[] = plaintext.bruteForceDiscreteLog(l, 
electionState.ballot.generators);
+                            if (null == t) {
+                                logger.warn("could not brute-force result");
+                            } else {
+                                logger.info("brute-forced result");
+                                electionState.tally = t;
+                            }
                         }
                     });
         }
@@ -217,8 +220,7 @@
         // FIXME!
         tm.purpose = 0;
         tm.time = AbsoluteTime.now().asMessage();
-        tm.signature = authorityPrivateKey.sign(authorityPublicKey, tm.purpose,
-                Construct.toBinary(tm.time));
+        tm.signature = authorityPrivateKey.sign(Construct.toBinary(tm.time), 
tm.purpose,authorityPublicKey);
         return tm;
     }
 
@@ -371,8 +373,8 @@
             rm.signedGuidKey = ballotPublicKey;
             // FIXME!
             rm.purpose = 0;
-            rm.signature = authorityPrivateKey.sign(authorityPublicKey, 
rm.purpose,
-                    Construct.toBinary(rm.signedGuidKey));
+            rm.signature = 
authorityPrivateKey.sign(Construct.toBinary(rm.signedGuidKey),
+                    rm.purpose, authorityPublicKey);
             getSender().send(rm);
         }
     }
@@ -391,7 +393,12 @@
     @Override
     public void run() {
         logger.info("running tally daemon");
-        mesh = new Mesh(getConfiguration(), null, null, new 
TallyMeshReceiver(), MESH_PORT);
+        mesh = new Mesh(getConfiguration(), null, new TunnelEndHandler() {
+            @Override
+            public void onChannelEnd(Mesh.Channel channel) {
+                logger.warn("on channel end");
+            }
+        }, new TallyMeshReceiver(), MESH_PORT);
 
         Scheduler.addDelayed(RelativeTime.FOREVER, new Scheduler.Task() {
             @Override

Modified: 
gnunet-java/src/main/java/org/gnunet/voting/messages/SubmitMessage.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/voting/messages/SubmitMessage.java     
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/voting/messages/SubmitMessage.java     
2014-03-30 21:41:58 UTC (rev 32833)
@@ -38,7 +38,6 @@
     /**
      * The encrypted vote, including zero knowledge proofs
      * for correctness.
-     * FIXME: wrap in a signature container
      */
     @NestedMessage
     public EncryptedVote encryptedVote;

Modified: gnunet-java/src/main/java/org/gnunet/voting/simulation/Ballot.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/voting/simulation/Ballot.java  
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/java/org/gnunet/voting/simulation/Ballot.java  
2014-03-30 21:41:58 UTC (rev 32833)
@@ -76,7 +76,6 @@
         BigInteger h = groupPublicKey.getKey();
         // verifier
 
-
         if (!c.equals(CryptoUtil.hash(voterId, x, y, a_1, b_1, a_2, 
b_2).mod(parameters.q))) {
             throw new AssertionError();
         }
@@ -99,7 +98,5 @@
         if (!b_1.equals(h.modPow(r_1, p).multiply(y.multiply(g).modPow(d_1, 
p)).mod(p))) {
             throw new AssertionError();
         }
-
-
     }
 }

Modified: 
gnunet-java/src/main/java/org/gnunet/voting/simulation/VotingParameters.java
===================================================================
--- 
gnunet-java/src/main/java/org/gnunet/voting/simulation/VotingParameters.java    
    2014-03-30 13:42:47 UTC (rev 32832)
+++ 
gnunet-java/src/main/java/org/gnunet/voting/simulation/VotingParameters.java    
    2014-03-30 21:41:58 UTC (rev 32833)
@@ -46,8 +46,7 @@
         BigInteger[] safePrimes = generateSafePrimes(p_bitlen, certainty);
         BigInteger p = safePrimes[0];
         BigInteger q = safePrimes[1];
-        BigInteger alpha = selectGenerator(p, q);
-        BigInteger g = selectSubgroupHigherOrderElement(alpha, p, q);
+        BigInteger g = selectSubgroupGenerator(p, q);
         if (!g.modPow(q, p).equals(BigInteger.ONE)) {
             throw new AssertionError();
         }
@@ -82,22 +81,7 @@
         return new BigInteger[]{p, q};
     }
 
-    /*
-    * Select a high order element of the multiplicative group Zn*
-    */
-    private static BigInteger selectHighOrderElement(BigInteger n, 
SecureRandom random) {
-        BigInteger g;
-        final BigInteger nMinusTwo = n.subtract(BigInteger.valueOf(2));
-        do {
-            BigInteger h = 
CryptoUtil.createRandomInRange(BigInteger.valueOf(2), nMinusTwo);
 
-            g = h.modPow(BigInteger.valueOf(2), n);
-        }
-        while (g.equals(BigInteger.valueOf(1)));
-
-        return g;
-    }
-
     /**
      * Returns a higher-order-element of Gq, the subgroup of Zp*,
      * with order q where alpha is a generator of Zp*
@@ -135,15 +119,9 @@
         return q;
     }
 
-    public BigInteger generateGq() {
-        BigInteger r;
-        while (true) {
-            r = CryptoUtil.createRandomInRange(BigInteger.ZERO, this.p);
-            if (r.modPow(q, p).equals(BigInteger.ONE)) {
-                break;
-            }
-        }
-        return r;
+    public static BigInteger selectSubgroupGenerator(BigInteger p, BigInteger 
q) {
+        BigInteger alpha = selectGenerator(p, q);
+        return selectSubgroupHigherOrderElement(alpha, p, q);
     }
 
     /**

Modified: gnunet-java/src/main/resources/org/gnunet/construct/MsgMap.txt
===================================================================
--- gnunet-java/src/main/resources/org/gnunet/construct/MsgMap.txt      
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/resources/org/gnunet/construct/MsgMap.txt      
2014-03-30 21:41:58 UTC (rev 32833)
@@ -100,4 +100,4 @@
 
org.gnunet.util.GnunetMessage$Body|483=org.gnunet.testbed.messages.ManagePeerServiceMessage
 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/25 01:43:32
+# generated 2014/03/30 01:11:14

Modified: gnunet-java/src/main/resources/org/gnunet/voting/ballot-template.espec
===================================================================
--- gnunet-java/src/main/resources/org/gnunet/voting/ballot-template.espec      
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/main/resources/org/gnunet/voting/ballot-template.espec      
2014-03-30 21:41:58 UTC (rev 32833)
@@ -40,6 +40,13 @@
 # deanonymize a voter?
 THRESHOLD =
 
+
+[generators]
+# Generators, one for every choice.  Determined by the issuer.
+# g0 = <gen_0>
+# ...
+# g<n> = <gen_n>
+
 [authorities]
 # specified as <authority-alias> = <peer-identity>, one entry for each 
authority; e.g.
 # awesome_authority_one = 123abc

Modified: gnunet-java/src/test/java/org/gnunet/mesh/MeshTest.java
===================================================================
--- gnunet-java/src/test/java/org/gnunet/mesh/MeshTest.java     2014-03-30 
13:42:47 UTC (rev 32832)
+++ gnunet-java/src/test/java/org/gnunet/mesh/MeshTest.java     2014-03-30 
21:41:58 UTC (rev 32833)
@@ -22,6 +22,20 @@
             m2.destroy();
         }
     }
+
+    public static class MyTunnelEndHandler implements TunnelEndHandler {
+        Mesh mesh1;
+        PeerIdentity peerIdentity;
+        @Override
+        public void onChannelEnd(Mesh.Channel channel) {
+            Mesh.Channel<Void> myChannel = mesh1.createTunnel(peerIdentity, 
42, false, true, null);
+            myChannel.send(new TestMessage());
+        }
+    }
+
+    /**
+     * Send a message locally, to our own peer.
+     */
     @Test (timeout = 5000)
     public void test_mesh_send() {
         Program.configureLogging("DEBUG");
@@ -35,22 +49,28 @@
             @Override
             public void cont(PeerIdentity peerIdentity) {
                 System.out.println("got peer identity from core");
-                final Mesh mesh1 = new Mesh(cfg, null, null, null);
-                final Mesh mesh2 = new Mesh(cfg, new InboundTunnelHandler() {
+                //
+                MyTunnelEndHandler teh = new MyTunnelEndHandler();
+                // first mesh handle, used to send the message
+                final Mesh mesh1 = new Mesh(cfg, teh);
+                teh.mesh1 = mesh1;
+                teh.peerIdentity = peerIdentity;
+                // second mesh handle, used to receive the message
+                final Mesh mesh2 = new Mesh(cfg, new InboundChannelHandler() {
                     @Override
-                    public void onInboundTunnel(Mesh.Tunnel tunnel, 
PeerIdentity initiator) {
-                        System.out.println("got inbound tunnel " + initiator);
+                    public void onInboundTunnel(Mesh.Channel tunnel, 
PeerIdentity initiator) {
+                        System.out.println("got inbound channel " + initiator);
                     }
                 }, new TunnelEndHandler() {
                     @Override
-                    public void onTunnelEnd(Mesh.Tunnel tunnel) {
-                        System.out.println("tunnel end handler called");
+                    public void onChannelEnd(Mesh.Channel tunnel) {
+                        System.out.println("channel end handler called");
                     }
                 }, mh, 42);
                 mh.m1 = mesh1;
                 mh.m2 = mesh2;
-                Mesh.Tunnel<Void> tunnel = mesh1.createTunnel(peerIdentity, 
42, false, true, null);
-                tunnel.send(new TestMessage());
+                Mesh.Channel<Void> channel = mesh1.createTunnel(peerIdentity, 
42, false, true, null);
+                channel.send(new TestMessage());
             }
         });
         Scheduler.run();

Modified: gnunet-java/src/test/java/org/gnunet/util/EcdsaTest.java
===================================================================
--- gnunet-java/src/test/java/org/gnunet/util/EcdsaTest.java    2014-03-30 
13:42:47 UTC (rev 32832)
+++ gnunet-java/src/test/java/org/gnunet/util/EcdsaTest.java    2014-03-30 
21:41:58 UTC (rev 32833)
@@ -37,7 +37,7 @@
         EcdsaPrivateKey privateKey = new EcdsaPrivateKey();
         privateKey.d = Ed25519.encodeScalar(new 
BigInteger("9751885127070397687372377515580876465521419304255864589795046632195735740054"));
         EcdsaPublicKey publicKey = privateKey.getPublicKey();
-        EcdsaSignature signature = privateKey.sign(publicKey, 0, data);
+        EcdsaSignature signature = privateKey.sign(data, 0, publicKey);
         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));

Modified: gnunet-java/src/test/java/org/gnunet/util/EddsaTest.java
===================================================================
--- gnunet-java/src/test/java/org/gnunet/util/EddsaTest.java    2014-03-30 
13:42:47 UTC (rev 32832)
+++ gnunet-java/src/test/java/org/gnunet/util/EddsaTest.java    2014-03-30 
21:41:58 UTC (rev 32833)
@@ -33,7 +33,7 @@
         byte[] data = "GNUnet".getBytes();
         EddsaPrivateKey privateKey = EddsaPrivateKey.createRandom();
         EddsaPublicKey publicKey = privateKey.getPublicKey();
-        EddsaSignature signature = privateKey.sign(publicKey, 0, data);
+        EddsaSignature signature = privateKey.sign(data, 0, publicKey);
         Assert.assertTrue(signature.verify(data, 0, publicKey));
     }
 

Added: gnunet-java/src/test/java/org/gnunet/util/HighLevelCryptoTest.java
===================================================================
--- gnunet-java/src/test/java/org/gnunet/util/HighLevelCryptoTest.java          
                (rev 0)
+++ gnunet-java/src/test/java/org/gnunet/util/HighLevelCryptoTest.java  
2014-03-30 21:41:58 UTC (rev 32833)
@@ -0,0 +1,83 @@
+package org.gnunet.util;
+
+
+import org.gnunet.construct.MessageLoader;
+import org.gnunet.construct.UInt32;
+import org.gnunet.construct.UnionCase;
+import org.gnunet.construct.ZeroTerminatedString;
+import org.gnunet.util.crypto.*;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class HighLevelCryptoTest {
+
+    public static class MySecretContent implements SignedContentMessage {
+        @ZeroTerminatedString
+        public String foo;
+        @UInt32
+        public int bar;
+    }
+
+    public static class MyFakeContent implements SignedContentMessage {
+
+    }
+
+    public void setupMessageMap() {
+        MessageLoader.registerUnionCase(SignedContentMessage.class, 
MySecretContent.class, 1);
+        MessageLoader.registerUnionCase(SignedContentMessage.class, 
MyFakeContent.class, 2);
+    }
+
+    @Test
+    public void test_hl_ecdsa() {
+        setupMessageMap();
+        MySecretContent c = new MySecretContent();
+        c.bar = 42;
+        c.foo = "quux";
+        EcdsaPrivateKey privateKey = EcdsaPrivateKey.createRandom();
+        EcdsaPublicKey publicKey = privateKey.getPublicKey();
+        EcdsaSignedMessage m = new EcdsaSignedMessage(c, privateKey, 
publicKey);
+
+        Assert.assertTrue(m.verify(publicKey, MySecretContent.class));
+    }
+
+    @Test
+    public void test_hl_ecdsa_purpose() {
+        setupMessageMap();
+        MySecretContent c = new MySecretContent();
+        c.bar = 42;
+        c.foo = "quux";
+        EcdsaPrivateKey privateKey = EcdsaPrivateKey.createRandom();
+        EcdsaPublicKey publicKey = privateKey.getPublicKey();
+        EcdsaSignedMessage m = new EcdsaSignedMessage(c, privateKey, 
publicKey);
+
+        Assert.assertFalse(m.verify(publicKey, MyFakeContent.class));
+    }
+
+
+    @Test
+    public void test_hl_eddsa() {
+        setupMessageMap();
+        MySecretContent c = new MySecretContent();
+        c.bar = 42;
+        c.foo = "quux";
+        EddsaPrivateKey privateKey = EddsaPrivateKey.createRandom();
+        EddsaPublicKey publicKey = privateKey.getPublicKey();
+        EddsaSignedMessage m = new EddsaSignedMessage(c, privateKey, 
publicKey);
+
+        Assert.assertTrue(m.verify(publicKey, MySecretContent.class));
+    }
+
+    @Test
+    public void test_hl_eddsa_purpose() {
+        setupMessageMap();
+        MySecretContent c = new MySecretContent();
+        c.bar = 42;
+        c.foo = "quux";
+        EddsaPrivateKey privateKey = EddsaPrivateKey.createRandom();
+        EddsaPublicKey publicKey = privateKey.getPublicKey();
+        EddsaSignedMessage m = new EddsaSignedMessage(c, privateKey, 
publicKey);
+
+        Assert.assertFalse(m.verify(publicKey, MyFakeContent.class));
+    }
+
+}

Modified: gnunet-java/src/test/java/org/gnunet/util/StringsTest.java
===================================================================
--- gnunet-java/src/test/java/org/gnunet/util/StringsTest.java  2014-03-30 
13:42:47 UTC (rev 32832)
+++ gnunet-java/src/test/java/org/gnunet/util/StringsTest.java  2014-03-30 
21:41:58 UTC (rev 32833)
@@ -3,6 +3,8 @@
 import org.junit.Assert;
 import org.junit.Test;
 
+import java.util.Random;
+
 /**
  * ...
  *
@@ -16,5 +18,12 @@
         byte[] data2 = Strings.stringToData(str, data.length);
         Assert.assertArrayEquals(data, data2);
     }
+
+    @Test
+    public void test_regression() {
+        String str = "00000000";
+        byte[] data = new byte[5];
+        Assert.assertTrue(Strings.stringToData(str, data));
+    }
 }
 

Modified: gnunet-java/src/test/java/org/gnunet/voting/TestVotingCrypto.java
===================================================================
--- gnunet-java/src/test/java/org/gnunet/voting/TestVotingCrypto.java   
2014-03-30 13:42:47 UTC (rev 32832)
+++ gnunet-java/src/test/java/org/gnunet/voting/TestVotingCrypto.java   
2014-03-30 21:41:58 UTC (rev 32833)
@@ -20,6 +20,7 @@
 
 package org.gnunet.voting;
 
+import org.gnunet.construct.Construct;
 import org.gnunet.secretsharing.*;
 import org.gnunet.secretsharing.callbacks.DecryptCallback;
 import org.gnunet.secretsharing.callbacks.SecretReadyCallback;
@@ -30,13 +31,62 @@
 import org.gnunet.util.crypto.EcdsaPrivateKey;
 import org.gnunet.util.crypto.EcdsaPublicKey;
 import org.junit.Assert;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
+import java.math.BigInteger;
+import java.util.Arrays;
+
 public class TestVotingCrypto extends TestingFixture {
+
+    static BigInteger[] generators2;
+
+    @BeforeClass
+    public static void generateGenerators() {
+        generators2 = Parameters.generateGenerators(2);
+    }
+
     @Test
+    public void testEmptyTally() {
+        final Wrapper<Boolean> success = new Wrapper<Boolean>();
+        Configuration armConf = new Configuration();
+        armConf.setValueString("arm", "DEFAULTSERVICES", "consensus set 
secretsharing");
+        Program.configureLogging("DEBUG");
+        // for testing, we vote with the same voter identity multiple times,
+        // does not matter here ...
+        final EcdsaPrivateKey privateKey = EcdsaPrivateKey.createRandom();
+        final EcdsaPublicKey publicKey = privateKey.getPublicKey();
+        final TestingSubsystem ts = new TestingSubsystem("arm", 
armConf.writeTemp().getAbsolutePath());
+        KeyGeneration kg = new KeyGeneration(ts.getConfiguration(), new 
PeerIdentity[0],
+                HashCode.random(), AbsoluteTime.now(), 
AbsoluteTime.now().add(RelativeTime.fromSeconds(5)),
+                1, new SecretReadyCallback() {
+            @Override
+            public void onSecretReady(Share share) {
+                Assert.assertNotNull(share);
+                Ciphertext sum = Ciphertext.identity();
+                Decryption decryption = new Decryption(ts.getConfiguration(), 
share, sum,
+                        AbsoluteTime.now(), 
AbsoluteTime.now().add(RelativeTime.fromSeconds(5)), new DecryptCallback() {
+                    @Override
+                    public void onResult(Plaintext plaintext) {
+                        Assert.assertNotNull(plaintext);
+                        System.out.println("Plaintext: " + plaintext);
+                        long x[] = plaintext.bruteForceDiscreteLog(0, new 
BigInteger[0]);
+                        Assert.assertNotNull(x);
+                        success.set(true);
+                    }
+                });
+            }
+        });
+        Scheduler.run();
+        Assert.assertTrue(success.get());
+    }
+
+
+    @Test
     public void testVoteTally() {
+        final Wrapper<Boolean> success = new Wrapper<Boolean>();
         Configuration armConf = new Configuration();
-        armConf.setValueString("arm", "DEFAULTSERVICES", "consensus set");
+        armConf.setValueString("arm", "DEFAULTSERVICES", "consensus set 
secretsharing");
         Program.configureLogging("DEBUG");
         // for testing, we vote with the same voter identity multiple times,
         // does not matter here ...
@@ -49,9 +99,9 @@
             @Override
             public void onSecretReady(Share share) {
                 Assert.assertNotNull(share);
-                EncryptedVote encryptedVote1 = EncryptedVote.fromChoice(1, 
share.publicKey, privateKey, publicKey);
-                EncryptedVote encryptedVote2 = EncryptedVote.fromChoice(0, 
share.publicKey, privateKey, publicKey);
-                EncryptedVote encryptedVote3 = EncryptedVote.fromChoice(0, 
share.publicKey, privateKey, publicKey);
+                EncryptedVote encryptedVote1 = EncryptedVote.fromChoice(1, 
share.publicKey, privateKey, publicKey, generators2);
+                EncryptedVote encryptedVote2 = EncryptedVote.fromChoice(0, 
share.publicKey, privateKey, publicKey, generators2);
+                EncryptedVote encryptedVote3 = EncryptedVote.fromChoice(0, 
share.publicKey, privateKey, publicKey, generators2);
 
                 Ciphertext sum = 
Ciphertext.identity().multiply(encryptedVote1.v.multiply(encryptedVote2.v).multiply(encryptedVote3.v));
 
@@ -61,37 +111,55 @@
                     @Override
                     public void onResult(Plaintext plaintext) {
                         Assert.assertNotNull(plaintext);
-                        long x = plaintext.bruteForceDiscreteLog(3);
-                        // one yes, two no
-                        Assert.assertEquals(-1, x);
+                        long[] t = plaintext.bruteForceDiscreteLog(3, 
generators2);
+                        Assert.assertNotNull(t);
+                        Assert.assertEquals(t[0], 2);
+                        Assert.assertEquals(t[1], 1);
+                        success.set(true);
                     }
                 });
             }
         });
+        Scheduler.run();
+        Assert.assertTrue(success.get());
     }
 
+
     @Test
     public void testSerialization() {
+        final Wrapper<Boolean> success = new Wrapper<Boolean>();
         Configuration armConf = new Configuration();
-        armConf.setValueString("arm", "DEFAULTSERVICES", "consensus set");
+        armConf.setValueString("arm", "DEFAULTSERVICES", "consensus set 
secretsharing");
         Program.configureLogging("DEBUG");
         final TestingSubsystem ts = new TestingSubsystem("arm", 
armConf.writeTemp().getAbsolutePath());
         final EcdsaPrivateKey privateKey = EcdsaPrivateKey.createRandom();
         final EcdsaPublicKey publicKey = privateKey.getPublicKey();
-        KeyGeneration kg = new KeyGeneration(ts.getConfiguration(), new 
PeerIdentity[0],
+        final KeyGeneration kg = new KeyGeneration(ts.getConfiguration(), new 
PeerIdentity[0],
                 HashCode.random(), AbsoluteTime.now(), 
AbsoluteTime.now().add(RelativeTime.fromSeconds(5)),
                 1, new SecretReadyCallback() {
             @Override
             public void onSecretReady(Share share) {
                 Assert.assertNotNull(share);
-                EncryptedVote encryptedVote1 = EncryptedVote.fromChoice(1, 
share.publicKey, privateKey, publicKey);
+                EncryptedVote encryptedVote1 = EncryptedVote.fromChoice(1, 
share.publicKey, privateKey, publicKey, generators2);
+                
Assert.assertTrue(encryptedVote1.disjunctionZkp.verifyChallenge());
                 Configuration c = new Configuration();
                 encryptedVote1.writeToConfiguration(c);
+                System.out.println("Challenge:");
+                
System.out.println(Arrays.toString(encryptedVote1.disjunctionZkp.challenge_c));
+                System.out.println("ZKP:");
+                
System.out.println(Arrays.toString(Construct.toBinary(encryptedVote1.disjunctionZkp)));
+                System.out.println("configuration: ");
+                System.out.println(c.serialize());
                 EncryptedVote encryptedVote2 = 
EncryptedVote.parseFromConfiguration(c, publicKey);
-                Assert.assertEquals(encryptedVote1, encryptedVote2);
+                
Assert.assertTrue(encryptedVote1.disjunctionZkp.verifyChallenge());
+                Assert.assertEquals(encryptedVote1.v, encryptedVote2.v);
+                success.set(true);
             }
 
         });
+        Scheduler.run();
+        Assert.assertTrue(success.get());
     }
+
 }
 

Modified: gnunet-java/src/test/python/test_voting_single.py
===================================================================
--- gnunet-java/src/test/python/test_voting_single.py   2014-03-30 13:42:47 UTC 
(rev 32832)
+++ gnunet-java/src/test/python/test_voting_single.py   2014-03-30 21:41:58 UTC 
(rev 32833)
@@ -4,10 +4,12 @@
 import os
 import subprocess
 import time
+import random
+import shutil
 
 
 NUM_AUTHORITIES = 1
-NUM_VOTERS = 1
+NUM_VOTERS = 5
 
 
 def wait_for_after(ts):
@@ -15,6 +17,8 @@
   if now < ts:
     print "waiting", ts - now, "seconds"
     time.sleep(ts - now)
+  else:
+    print "not waiting"
 
 def get_config(section, option, filename=None, expand=False):
   args = ["gnunet-config"]
@@ -75,7 +79,9 @@
 
 print "public key", public_key
 
-create_identity("voter0", conf[0])
+for vi in range(NUM_VOTERS):
+  create_identity("voter"+str(vi), conf[0])
+
 create_identity("issuer", conf[0])
 create_identity("groupca", conf[0])
 
@@ -89,15 +95,15 @@
 TS_START = now + 15
 TS_CLOSING = now + 20
 TS_CONCLUDE = now + 25
-TS_QUERY = now + 30
-TS_END = now + 35
+TS_QUERY = now + 35
+TS_END = now + 40
 
 ballot.write("[authorities]\n")
 ballot.write("auth0 = %s\n" % public_key)
 ballot.write("[election]\n")
 ballot.write("TOPIC = mytopic\n")
 ballot.write("THRESHOLD = 1\n")
-ballot.write("CHOICES = yes//no\n")
+ballot.write("CHOICES = yes//no//maybe\n")
 ballot.write("GROUP = mygroup\n")
 ballot.write("CA_PUB = %s\n" % get_identity_pubkey("groupca", conf[0]))
 ballot.write("TIMESTAMP_KEYGEN_START = %s\n" % TS_KEYGEN_START)
@@ -110,15 +116,17 @@
 
 ballot.close()
 
-groupcert_filename = os.path.join(testdir, "v0-cert")
-groupcert_file = open(groupcert_filename, "w")
+# create group certs for all voters
+for vi in range(NUM_VOTERS):
+  groupcert_filename = os.path.join(testdir, "v"+str(vi)+"-cert")
+  groupcert_file = open(groupcert_filename, "w")
 
-v0_pub = get_identity_pubkey("voter0", conf[0])
+  v_pub = get_identity_pubkey("voter"+str(vi), conf[0])
 
-subprocess.check_call(["gnunet-ballot-group-certify", "-c", conf[0],
-  "-g", "mygroup", "-e", "groupca", "-m", v0_pub], stdout=groupcert_file)
+  subprocess.check_call(["gnunet-ballot-group-certify", "-c", conf[0],
+    "-g", "mygroup", "-e", "groupca", "-m", v_pub], stdout=groupcert_file)
 
-groupcert_file.close()
+  groupcert_file.close()
 
 # register the ballot with authorities
 subprocess.check_call(["gnunet-ballot", "-LINFO", "-i", ballot_filename, "-e", 
"issuer", "-c", conf[0]])
@@ -135,18 +143,25 @@
 
 print "threshold public key retrieved"
 
-exit()
+# actually vote
+for vi in range(NUM_VOTERS):
+  voter_ballot_filename = os.path.join(testdir, "v"+str(vi)+"-ballot")
+  shutil.copy(ballot_filename, voter_ballot_filename)
+  groupcert_filename = os.path.join(testdir, "v"+str(vi)+"-cert")
+  # add voter's group information
+  subprocess.check_call(["gnunet-ballot", "-g", groupcert_filename, 
voter_ballot_filename, "-c", conf[0]])
 
-# add voter's group information
-subprocess.check_call(["gnunet-ballot", "-g", groupcert_filename, 
ballot_filename, "-c", conf[0]])
+  ch = random.choice(["yes", "no", "maybe"])
 
-# actually vote ...
-subprocess.check_call(["gnunet-ballot", "-x", "yes", ballot_filename, "-e", 
"voter0", "-c", conf[0]])
+  # actually vote ...
+  subprocess.check_call(["gnunet-ballot", "-x", ch, voter_ballot_filename, 
"-e", "voter"+str(vi), "-c", conf[0]])
 
 wait_for_after(TS_START)
 
-# submit the ballot with the vote
-subprocess.check_call(["gnunet-ballot", "-s", ballot_filename, "-c", conf[0]])
+for vi in range(NUM_VOTERS):
+  voter_ballot_filename = os.path.join(testdir, "v"+str(vi)+"-ballot")
+  # submit the ballot with the vote
+  subprocess.check_call(["gnunet-ballot", "-s", voter_ballot_filename, "-c", 
conf[0]])
 
 wait_for_after(TS_QUERY)
 




reply via email to

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