gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated: add support for batch signing in


From: gnunet
Subject: [taler-exchange] branch master updated: add support for batch signing in RSA
Date: Sun, 13 Nov 2022 14:46:45 +0100

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new b93b9dd0 add support for batch signing in RSA
b93b9dd0 is described below

commit b93b9dd074cf347c978b7c58c3ce71d55aa669fd
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sun Nov 13 14:46:43 2022 +0100

    add support for batch signing in RSA
---
 src/util/crypto_helper_rsa.c | 304 ++++++++++++++++++++++---------------------
 src/util/test_helper_rsa.c   | 250 ++++++++++++++++++++++++++++++++++-
 2 files changed, 405 insertions(+), 149 deletions(-)

diff --git a/src/util/crypto_helper_rsa.c b/src/util/crypto_helper_rsa.c
index 811e5a03..58cc29a8 100644
--- a/src/util/crypto_helper_rsa.c
+++ b/src/util/crypto_helper_rsa.c
@@ -623,6 +623,7 @@ TALER_CRYPTO_helper_rsa_batch_sign (
               rsrs_length);
   rpos = 0;
   rend = 0;
+  wpos = 0;
   while (rpos < rsrs_length)
   {
     unsigned int mlen = sizeof (struct TALER_CRYPTO_BatchSignRequest);
@@ -639,15 +640,15 @@ TALER_CRYPTO_helper_rsa_batch_sign (
       char obuf[mlen] GNUNET_ALIGN;
       struct TALER_CRYPTO_BatchSignRequest *bsr
         = (struct TALER_CRYPTO_BatchSignRequest *) obuf;
-      void *wpos;
+      void *wbuf;
 
       bsr->header.type = htons (TALER_HELPER_RSA_MT_REQ_BATCH_SIGN);
       bsr->header.size = htons (mlen);
       bsr->batch_size = htonl (rend - rpos);
-      wpos = &bsr[1];
+      wbuf = &bsr[1];
       for (unsigned int i = rpos; i<rend; i++)
       {
-        struct TALER_CRYPTO_SignRequest *sr = wpos;
+        struct TALER_CRYPTO_SignRequest *sr = wbuf;
         const struct TALER_CRYPTO_RsaSignRequest *rsr = &rsrs[i];
 
         sr->header.type = htons (TALER_HELPER_RSA_MT_REQ_SIGN);
@@ -657,9 +658,13 @@ TALER_CRYPTO_helper_rsa_batch_sign (
         memcpy (&sr[1],
                 rsr->msg,
                 rsr->msg_size);
-        wpos += sizeof (*sr) + rsr->msg_size;
+        wbuf += sizeof (*sr) + rsr->msg_size;
       }
-      GNUNET_assert (wpos == &obuf[mlen]);
+      GNUNET_assert (wbuf == &obuf[mlen]);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Sending batch request [%u-%u)\n",
+                  rpos,
+                  rend);
       if (GNUNET_OK !=
           TALER_crypto_helper_send_all (dh->sock,
                                         obuf,
@@ -672,170 +677,175 @@ TALER_CRYPTO_helper_rsa_batch_sign (
       }
     }
     rpos = rend;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Awaiting reply\n");
-  wpos = 0;
-  {
-    char buf[UINT16_MAX];
-    size_t off = 0;
-    const struct GNUNET_MessageHeader *hdr
-      = (const struct GNUNET_MessageHeader *) buf;
-    bool finished = false;
-
-    while (1)
     {
-      uint16_t msize;
-      ssize_t ret;
+      char buf[UINT16_MAX];
+      size_t off = 0;
+      const struct GNUNET_MessageHeader *hdr
+        = (const struct GNUNET_MessageHeader *) buf;
+      bool finished = false;
 
-      ret = recv (dh->sock,
-                  &buf[off],
-                  sizeof (buf) - off,
-                  (finished && (0 == off))
+      while (1)
+      {
+        uint16_t msize;
+        ssize_t ret;
+
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "Awaiting reply at %u (up to %u)\n",
+                    wpos,
+                    rend);
+        ret = recv (dh->sock,
+                    &buf[off],
+                    sizeof (buf) - off,
+                    (finished && (0 == off))
                   ? MSG_DONTWAIT
                   : 0);
-      if (ret < 0)
-      {
-        if (EINTR == errno)
-          continue;
-        if (EAGAIN == errno)
-        {
-          GNUNET_assert (finished);
-          GNUNET_assert (0 == off);
-          return ec;
-        }
-        GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
-                             "recv");
-        do_disconnect (dh);
-        ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
-        break;
-      }
-      if (0 == ret)
-      {
-        GNUNET_break (0 == off);
-        if (! finished)
-          ec = TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
-        return ec;
-      }
-      off += ret;
-more:
-      if (off < sizeof (struct GNUNET_MessageHeader))
-        continue;
-      msize = ntohs (hdr->size);
-      if (off < msize)
-        continue;
-      switch (ntohs (hdr->type))
-      {
-      case TALER_HELPER_RSA_MT_RES_SIGNATURE:
-        if (msize < sizeof (struct TALER_CRYPTO_SignResponse))
+        if (ret < 0)
         {
-          GNUNET_break_op (0);
+          if (EINTR == errno)
+            continue;
+          if (EAGAIN == errno)
+          {
+            GNUNET_assert (finished);
+            GNUNET_assert (0 == off);
+            break;
+          }
+          GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+                               "recv");
           do_disconnect (dh);
-          ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
-          goto end;
+          ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
+          break;
         }
-        if (finished)
+        if (0 == ret)
         {
-          GNUNET_break_op (0);
-          do_disconnect (dh);
-          ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
-          goto end;
+          GNUNET_break (0 == off);
+          if (! finished)
+            ec = TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
+          if (TALER_EC_NONE == ec)
+            break;
+          return ec;
         }
+        off += ret;
+more:
+        if (off < sizeof (struct GNUNET_MessageHeader))
+          continue;
+        msize = ntohs (hdr->size);
+        if (off < msize)
+          continue;
+        switch (ntohs (hdr->type))
         {
-          const struct TALER_CRYPTO_SignResponse *sr =
-            (const struct TALER_CRYPTO_SignResponse *) buf;
-          struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
-
-          rsa_signature = GNUNET_CRYPTO_rsa_signature_decode (
-            &sr[1],
-            msize - sizeof (*sr));
-          if (NULL == rsa_signature)
+        case TALER_HELPER_RSA_MT_RES_SIGNATURE:
+          if (msize < sizeof (struct TALER_CRYPTO_SignResponse))
           {
             GNUNET_break_op (0);
             do_disconnect (dh);
-            ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
-            goto end;
+            return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+          }
+          if (finished)
+          {
+            GNUNET_break_op (0);
+            do_disconnect (dh);
+            return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+          }
+          {
+            const struct TALER_CRYPTO_SignResponse *sr =
+              (const struct TALER_CRYPTO_SignResponse *) buf;
+            struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
+
+            rsa_signature = GNUNET_CRYPTO_rsa_signature_decode (
+              &sr[1],
+              msize - sizeof (*sr));
+            if (NULL == rsa_signature)
+            {
+              GNUNET_break_op (0);
+              do_disconnect (dh);
+              return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+            }
+            GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                        "Received %u signature\n",
+                        wpos);
+            bss[wpos].cipher = TALER_DENOMINATION_RSA;
+            bss[wpos].details.blinded_rsa_signature = rsa_signature;
+            wpos++;
+            if (wpos == rend)
+            {
+              if (TALER_EC_INVALID == ec)
+                ec = TALER_EC_NONE;
+              finished = true;
+            }
+            break;
+          }
+        case TALER_HELPER_RSA_MT_RES_SIGN_FAILURE:
+          if (msize != sizeof (struct TALER_CRYPTO_SignFailure))
+          {
+            GNUNET_break_op (0);
+            do_disconnect (dh);
+            return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+          }
+          {
+            const struct TALER_CRYPTO_SignFailure *sf =
+              (const struct TALER_CRYPTO_SignFailure *) buf;
+
+            ec = (enum TALER_ErrorCode) ntohl (sf->ec);
+            GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                        "Signing failed with status %d!\n",
+                        ec);
+            wpos++;
+            if (wpos == rend)
+            {
+              finished = true;
+            }
+            break;
           }
+        case TALER_HELPER_RSA_MT_AVAIL:
           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                      "Received %u signature\n",
-                      wpos);
-          bss[wpos].cipher = TALER_DENOMINATION_RSA;
-          bss[wpos].details.blinded_rsa_signature = rsa_signature;
-          wpos++;
-          if (wpos == rsrs_length)
+                      "Received new key!\n");
+          if (GNUNET_OK !=
+              handle_mt_avail (dh,
+                               hdr))
           {
-            ec = TALER_EC_NONE;
-            finished = true;
+            GNUNET_break_op (0);
+            do_disconnect (dh);
+            return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
           }
-          break;
-        }
-      case TALER_HELPER_RSA_MT_RES_SIGN_FAILURE:
-        if (msize != sizeof (struct TALER_CRYPTO_SignFailure))
-        {
-          GNUNET_break_op (0);
-          do_disconnect (dh);
-          ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
-          goto end;
-        }
-        {
-          const struct TALER_CRYPTO_SignFailure *sf =
-            (const struct TALER_CRYPTO_SignFailure *) buf;
-
-          ec = (enum TALER_ErrorCode) ntohl (sf->ec);
+          break; /* while(1) loop ensures we recvfrom() again */
+        case TALER_HELPER_RSA_MT_PURGE:
           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                      "Signing failed!\n");
-          finished = true;
+                      "Received revocation!\n");
+          if (GNUNET_OK !=
+              handle_mt_purge (dh,
+                               hdr))
+          {
+            GNUNET_break_op (0);
+            do_disconnect (dh);
+            return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+          }
+          break; /* while(1) loop ensures we recvfrom() again */
+        case TALER_HELPER_RSA_SYNCED:
+          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      "Synchronized add odd time with RSA helper!\n");
+          dh->synced = true;
           break;
-        }
-      case TALER_HELPER_RSA_MT_AVAIL:
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "Received new key!\n");
-        if (GNUNET_OK !=
-            handle_mt_avail (dh,
-                             hdr))
-        {
+        default:
           GNUNET_break_op (0);
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                      "Received unexpected message of type %u\n",
+                      ntohs (hdr->type));
           do_disconnect (dh);
-          ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
-          goto end;
+          return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
         }
-        break; /* while(1) loop ensures we recvfrom() again */
-      case TALER_HELPER_RSA_MT_PURGE:
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "Received revocation!\n");
-        if (GNUNET_OK !=
-            handle_mt_purge (dh,
-                             hdr))
-        {
-          GNUNET_break_op (0);
-          do_disconnect (dh);
-          ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
-          goto end;
-        }
-        break; /* while(1) loop ensures we recvfrom() again */
-      case TALER_HELPER_RSA_SYNCED:
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    "Synchronized add odd time with RSA helper!\n");
-        dh->synced = true;
-        break;
-      default:
-        GNUNET_break_op (0);
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                    "Received unexpected message of type %u\n",
-                    ntohs (hdr->type));
-        do_disconnect (dh);
-        ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
-        goto end;
-      }
-      memmove (buf,
-               &buf[msize],
-               off - msize);
-      off -= msize;
-      goto more;
-    } /* while(1) */
-end:
-    return ec;
-  }
+        memmove (buf,
+                 &buf[msize],
+                 off - msize);
+        off -= msize;
+        goto more;
+      } /* while(1) */
+    } /* scope */
+  }   /* while (rpos < rsrs_length) */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Existing with %u signatures and status %d\n",
+              wpos,
+              ec);
+  return ec;
 }
 
 
diff --git a/src/util/test_helper_rsa.c b/src/util/test_helper_rsa.c
index 3f3eafdd..1b67607c 100644
--- a/src/util/test_helper_rsa.c
+++ b/src/util/test_helper_rsa.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2020, 2021 Taler Systems SA
+  (C) 2020, 2021, 2022 Taler Systems SA
 
   TALER 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
@@ -440,6 +440,223 @@ test_signing (struct TALER_CRYPTO_RsaDenominationHelper 
*dh)
 }
 
 
+/**
+ * Test batch signing logic.
+ *
+ * @param dh handle to the helper
+ * @param batch_size how large should the batch be
+ * @param check_sigs also check unknown key and signatures
+ * @return 0 on success
+ */
+static int
+test_batch_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh,
+                    unsigned int batch_size,
+                    bool check_sigs)
+{
+  struct TALER_BlindedDenominationSignature ds[batch_size];
+  enum TALER_ErrorCode ec;
+  bool success = false;
+  struct TALER_PlanchetMasterSecretP ps[batch_size];
+  struct TALER_ExchangeWithdrawValues alg_values[batch_size];
+  struct TALER_AgeCommitmentHash ach[batch_size];
+  struct TALER_CoinPubHashP c_hash[batch_size];
+  struct TALER_CoinSpendPrivateKeyP coin_priv[batch_size];
+  union TALER_DenominationBlindingKeyP bks[batch_size];
+
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
+                              &ps,
+                              sizeof (ps));
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+                              &ach,
+                              sizeof(ach));
+  for (unsigned int i = 0; i<batch_size; i++)
+  {
+    alg_values[i].cipher = TALER_DENOMINATION_RSA;
+    TALER_planchet_setup_coin_priv (&ps[i],
+                                    &alg_values[i],
+                                    &coin_priv[i]);
+    TALER_planchet_blinding_secret_create (&ps[i],
+                                           &alg_values[i],
+                                           &bks[i]);
+  }
+  for (unsigned int k = 0; k<MAX_KEYS; k++)
+  {
+    if (success && ! check_sigs)
+      break; /* only do one round */
+    if (! keys[k].valid)
+      continue;
+    if (TALER_DENOMINATION_RSA != keys[k].denom_pub.cipher)
+      continue;
+    {
+      struct TALER_PlanchetDetail pd[batch_size];
+      struct TALER_CRYPTO_RsaSignRequest rsr[batch_size];
+
+      for (unsigned int i = 0; i<batch_size; i++)
+      {
+        pd[i].blinded_planchet.cipher = TALER_DENOMINATION_RSA;
+        GNUNET_assert (GNUNET_YES ==
+                       TALER_planchet_prepare (&keys[k].denom_pub,
+                                               &alg_values[i],
+                                               &bks[i],
+                                               &coin_priv[i],
+                                               &ach[i],
+                                               &c_hash[i],
+                                               &pd[i]));
+        rsr[i].h_rsa
+          = &keys[k].h_rsa;
+        rsr[i].msg
+          = pd[i].blinded_planchet.details.rsa_blinded_planchet.blinded_msg;
+        rsr[i].msg_size
+          = 
pd[i].blinded_planchet.details.rsa_blinded_planchet.blinded_msg_size;
+      }
+      ec = TALER_CRYPTO_helper_rsa_batch_sign (dh,
+                                               rsr,
+                                               batch_size,
+                                               ds);
+      for (unsigned int i = 0; i<batch_size; i++)
+      {
+        if (TALER_EC_NONE == ec)
+          GNUNET_break (TALER_DENOMINATION_RSA ==
+                        ds[i].cipher);
+        TALER_blinded_planchet_free (&pd[i].blinded_planchet);
+      }
+    }
+    switch (ec)
+    {
+    case TALER_EC_NONE:
+      if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining (
+                                      keys[k].start_time.abs_time),
+                                    >,
+                                    GNUNET_TIME_UNIT_SECONDS))
+      {
+        /* key worked too early */
+        GNUNET_break (0);
+        return 4;
+      }
+      if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration (
+                                      keys[k].start_time.abs_time),
+                                    >,
+                                    keys[k].validity_duration))
+      {
+        /* key worked too later */
+        GNUNET_break (0);
+        return 5;
+      }
+      for (unsigned int i = 0; i<batch_size; i++)
+      {
+        struct TALER_DenominationSignature rs;
+
+        if (check_sigs)
+        {
+          if (GNUNET_OK !=
+              TALER_denom_sig_unblind (&rs,
+                                       &ds[i],
+                                       &bks[i],
+                                       &c_hash[i],
+                                       &alg_values[i],
+                                       &keys[k].denom_pub))
+          {
+            GNUNET_break (0);
+            return 6;
+          }
+        }
+        TALER_blinded_denom_sig_free (&ds[i]);
+        if (check_sigs)
+        {
+          if (GNUNET_OK !=
+              TALER_denom_pub_verify (&keys[k].denom_pub,
+                                      &rs,
+                                      &c_hash[i]))
+          {
+            /* signature invalid */
+            GNUNET_break (0);
+            TALER_denom_sig_free (&rs);
+            return 7;
+          }
+          TALER_denom_sig_free (&rs);
+        }
+      }
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "Received valid signature for key %s\n",
+                  GNUNET_h2s (&keys[k].h_rsa.hash));
+      success = true;
+      break;
+    case TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY:
+      /* This 'failure' is expected, we're testing also for the
+         error handling! */
+      for (unsigned int i = 0; i<batch_size; i++)
+        TALER_blinded_denom_sig_free (&ds[i]);
+      if ( (GNUNET_TIME_relative_is_zero (
+              GNUNET_TIME_absolute_get_remaining (
+                keys[k].start_time.abs_time))) &&
+           (GNUNET_TIME_relative_cmp (
+              GNUNET_TIME_absolute_get_duration (
+                keys[k].start_time.abs_time),
+              <,
+              keys[k].validity_duration)) )
+      {
+        /* key should have worked! */
+        GNUNET_break (0);
+        return 6;
+      }
+      break;
+    case TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN:
+      for (unsigned int i = 0; i<batch_size; i++)
+        TALER_blinded_denom_sig_free (&ds[i]);
+    default:
+      /* unexpected error */
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Unexpected error %d at %s:%u\n",
+                  ec,
+                  __FILE__,
+                  __LINE__);
+      for (unsigned int i = 0; i<batch_size; i++)
+        TALER_blinded_denom_sig_free (&ds[i]);
+      return 7;
+    }
+  }
+  if (! success)
+  {
+    /* no valid key for signing found, also bad */
+    GNUNET_break (0);
+    return 16;
+  }
+
+  /* check signing does not work if the key is unknown */
+  if (check_sigs)
+  {
+    struct TALER_RsaPubHashP rnd;
+    struct TALER_CRYPTO_RsaSignRequest rsr = {
+      .h_rsa = &rnd,
+      .msg = "Hello",
+      .msg_size = strlen ("Hello")
+    };
+
+    GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+                                &rnd,
+                                sizeof (rnd));
+    ec = TALER_CRYPTO_helper_rsa_batch_sign (dh,
+                                             &rsr,
+                                             1,
+                                             ds);
+    if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Signing with invalid key returned unexpected status %d\n",
+                  ec);
+      if (TALER_EC_NONE == ec)
+        TALER_blinded_denom_sig_free (ds);
+      GNUNET_break (0);
+      return 17;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Signing with invalid key %s failed as desired\n",
+                GNUNET_h2s (&rnd.hash));
+  }
+  return 0;
+}
+
+
 /**
  * Benchmark signing logic.
  *
@@ -614,7 +831,8 @@ run_test (void)
     return 77;
   }
 
-  fprintf (stderr, "Waiting for helper to start ... ");
+  fprintf (stderr,
+           "Waiting for helper to start ... ");
   for (unsigned int i = 0; i<100; i++)
   {
     nanosleep (&req,
@@ -649,6 +867,34 @@ run_test (void)
     ret = test_revocation (dh);
   if (0 == ret)
     ret = test_signing (dh);
+  if (0 == ret)
+    ret = test_batch_signing (dh,
+                              2,
+                              true);
+  if (0 == ret)
+    ret = test_batch_signing (dh,
+                              256,
+                              true);
+  for (unsigned int i = 0; i<5; i++)
+  {
+    static unsigned int batches[] = { 1, 4, 16, 64, 256 };
+    unsigned int batch_size = batches[i];
+    struct GNUNET_TIME_Absolute start;
+    struct GNUNET_TIME_Relative duration;
+
+    start = GNUNET_TIME_absolute_get ();
+    if (0 != ret)
+      break;
+    ret = test_batch_signing (dh,
+                              batch_size,
+                              false);
+    duration = GNUNET_TIME_absolute_get_duration (start);
+    fprintf (stderr,
+             "%4u (batch) signature operations took %s (total real time)\n",
+             (unsigned int) batch_size,
+             GNUNET_STRINGS_relative_time_to_string (duration,
+                                                     GNUNET_YES));
+  }
   if (0 == ret)
     ret = perf_signing (dh,
                         "sequential");

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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