diff options
| author | Christian Grothoff <christian@grothoff.org> | 2015-03-10 16:15:14 +0100 | 
|---|---|---|
| committer | Christian Grothoff <christian@grothoff.org> | 2015-03-10 16:15:14 +0100 | 
| commit | c2c8646a83c07662e1246f768c23e71c687ddcb0 (patch) | |
| tree | 3ea5a96e43fda20b9ecb10485bbc05b0749eff33 /src/mint | |
| parent | 07f18f16601cc4757c0c2658ad501497b07cebee (diff) | |
combining /mint/melt and /mint/commit
Diffstat (limited to 'src/mint')
| -rw-r--r-- | src/mint/mint_db.c | 27 | ||||
| -rw-r--r-- | src/mint/mint_db.h | 27 | ||||
| -rw-r--r-- | src/mint/taler-mint-httpd.c | 6 | ||||
| -rw-r--r-- | src/mint/taler-mint-httpd_db.c | 209 | ||||
| -rw-r--r-- | src/mint/taler-mint-httpd_db.h | 49 | ||||
| -rw-r--r-- | src/mint/taler-mint-httpd_refresh.c | 381 | ||||
| -rw-r--r-- | src/mint/taler-mint-httpd_refresh.h | 24 | ||||
| -rw-r--r-- | src/mint/taler-mint-httpd_responses.c | 122 | ||||
| -rw-r--r-- | src/mint/taler-mint-httpd_responses.h | 45 | 
9 files changed, 333 insertions, 557 deletions
| diff --git a/src/mint/mint_db.c b/src/mint/mint_db.c index 53d35b33..848f9e04 100644 --- a/src/mint/mint_db.c +++ b/src/mint/mint_db.c @@ -1417,11 +1417,6 @@ TALER_MINT_DB_get_refresh_session (PGconn *db_conn,      return GNUNET_SYSERR;    } -  if (TALER_DB_field_isnull (result, 0, "session_commit_sig")) -    session->has_commit_sig = GNUNET_NO; -  else -    session->has_commit_sig = GNUNET_YES; -    session->num_oldcoins = ntohs (session->num_oldcoins);    session->num_newcoins = ntohs (session->num_newcoins);    session->kappa = ntohs (session->kappa); @@ -1472,28 +1467,6 @@ TALER_MINT_DB_create_refresh_session (PGconn *db_conn,  /** - * Update new refresh session with the new state after the - * /refresh/commit operation. - * - * @param db_conn database handle to use - * @param refresh_session_pub public key to use to locate the session - * @param noreveal_index index chosen for the client to not reveal - * @param commit_client_sig signature of the client over its commitment - * @return #GNUNET_YES on success, - *         #GNUNET_SYSERR on DB failure - */ -int -TALER_MINT_DB_update_refresh_session (PGconn *db_conn, -                                      const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, -                                      uint16_t noreveal_index, -                                      const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig) -{ -  // FIXME: implement! -  return GNUNET_SYSERR; -} - - -/**   * Store the given /refresh/melt request in the database.   *   * @param db_conn database connection diff --git a/src/mint/mint_db.h b/src/mint/mint_db.h index 403e1f39..9818172a 100644 --- a/src/mint/mint_db.h +++ b/src/mint/mint_db.h @@ -474,17 +474,10 @@ struct RefreshSession    /**     * Index (smaller @e kappa) which the mint has chosen to not -   * have revealed during cut and choose.  Only valid if -   * @e has_commit_sig is set to #GNUNET_YES. +   * have revealed during cut and choose.     */    uint16_t noreveal_index; -  /** -   * #GNUNET_YES if we have accepted the /refresh/commit and -   * thus the @e commit_sig is valid. -   */ -  int has_commit_sig; -  }; @@ -520,24 +513,6 @@ TALER_MINT_DB_create_refresh_session (PGconn *db_conn,  /** - * Update new refresh session with the new state after the - * /refresh/commit operation. - * - * @param db_conn database handle to use - * @param refresh_session_pub public key to use to locate the session - * @param noreveal_index index chosen for the client to not reveal - * @param commit_client_sig signature of the client over its commitment - * @return #GNUNET_YES on success, - *         #GNUNET_SYSERR on DB failure - */ -int -TALER_MINT_DB_update_refresh_session (PGconn *db_conn, -                                      const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, -                                      uint16_t noreveal_index, -                                      const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig); - - -/**   * Specification for coin in a /refresh/melt operation.   */  struct RefreshMelt diff --git a/src/mint/taler-mint-httpd.c b/src/mint/taler-mint-httpd.c index 281f58f1..3b1512ff 100644 --- a/src/mint/taler-mint-httpd.c +++ b/src/mint/taler-mint-httpd.c @@ -152,12 +152,6 @@ handle_mhd_request (void *cls,        { "/refresh/melt", NULL, "text/plain",          "Only POST is allowed", 0,          &TALER_MINT_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, -      { "/refresh/commit", MHD_HTTP_METHOD_POST, "application/json", -        NULL, 0, -        &TALER_MINT_handler_refresh_commit, MHD_HTTP_OK }, -      { "/refresh/commit", NULL, "text/plain", -        "Only POST is allowed", 0, -        &TALER_MINT_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },        { "/refresh/reveal", MHD_HTTP_METHOD_POST, "application/json",          NULL, 0,          &TALER_MINT_handler_refresh_melt, MHD_HTTP_OK }, diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index d9a172a4..4423433b 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -151,7 +151,7 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection,    if (0 < TALER_amount_cmp (spent, value))    {      TALER_MINT_DB_rollback (db_conn); -    ret = TALER_MINT_reply_insufficient_funds (connection, +    ret = TALER_MINT_reply_deposit_insufficient_funds (connection,                                                 tl);      TALER_MINT_DB_free_coin_transaction_list (tl);      return ret; @@ -435,8 +435,10 @@ refresh_accept_melts (struct MHD_Connection *connection,  {    struct TALER_MINT_DenomKeyIssue *dki;    struct TALER_MINT_DB_TransactionList *tl; -  struct TALER_Amount coin_gain; +  struct TALER_Amount coin_value; +  struct TALER_Amount coin_residual;    struct RefreshMelt melt; +  int res;    dki = &TALER_MINT_get_denom_key (key_state,                                     coin_public_info->denom_pub)->issue; @@ -450,25 +452,30 @@ refresh_accept_melts (struct MHD_Connection *connection,                                          "denom not found"))        ? GNUNET_NO : GNUNET_SYSERR; -  coin_gain = TALER_amount_ntoh (dki->value); +  coin_value = TALER_amount_ntoh (dki->value);    tl = TALER_MINT_DB_get_coin_transactions (db_conn,                                              &coin_public_info->coin_pub);    /* FIXME: #3636: compute how much value is left with this coin and -     compare to `expected_value`! (subtract from "coin_gain") */ -  TALER_MINT_DB_free_coin_transaction_list (tl); - +     compare to `expected_value`! (subtract from "coin_value") */ +  coin_residual = coin_value;    /* Refuse to refresh when the coin does not have enough money left to     * pay the refreshing fees of the coin. */ -  if (TALER_amount_cmp (coin_gain, +  if (TALER_amount_cmp (coin_residual,                          coin_details->melt_amount) < 0) -    return (MHD_YES == -            TALER_MINT_reply_json_pack (connection, -                                        MHD_HTTP_NOT_FOUND, -                                        "{s:s}", -                                        "error", "depleted")) ? GNUNET_NO : GNUNET_SYSERR; - - +  { +    res = (MHD_YES == +           TALER_MINT_reply_refresh_melt_insufficient_funds (connection, +                                                             &coin_public_info->coin_pub, +                                                             coin_value, +                                                             tl, +                                                             coin_details->melt_amount, +                                                             coin_residual)) +      ? GNUNET_NO : GNUNET_SYSERR; +    TALER_MINT_DB_free_coin_transaction_list (tl); +    return res; +  } +  TALER_MINT_DB_free_coin_transaction_list (tl);    melt.coin = *coin_public_info;    melt.coin_sig = coin_details->melt_sig; @@ -494,6 +501,8 @@ refresh_accept_melts (struct MHD_Connection *connection,   * required value left and if so, store that they have been   * melted and confirm the melting operation to the client.   * + * FIXME: some arguments are redundant here... + *   * @param connection the MHD connection to handle   * @param melt_hash hash code of the session the coins are melted into   * @param refresh_session_pub public key of the refresh session @@ -504,6 +513,15 @@ refresh_accept_melts (struct MHD_Connection *connection,   * @param coin_count number of entries in @a coin_public_infos and @a coin_melt_details   * @param coin_public_infos information about the coins to melt   * @param coin_melt_details signatures and (residual) value of the respective coin should be melted + * @param commit_client_sig signature of the client over this commitment + * @param kappa size of x-dimension of @commit_coin and @commit_link arrays + * @param num_oldcoins size of y-dimension of @commit_link array + * @param num_newcoins size of y-dimension of @commit_coin array + * @param commit_coin 2d array of coin commitments (what the mint is to sign + *                    once the "/refres/reveal" of cut and choose is done) + * @param commit_link 2d array of coin link commitments (what the mint is + *                    to return via "/refresh/link" to enable linkage in the + *                    future)   * @return MHD result code   */  int @@ -515,13 +533,20 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection,                                      struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs,                                      unsigned int coin_count,                                      const struct TALER_CoinPublicInfo *coin_public_infos, -                                    const struct MeltDetails *coin_melt_details) +                                    const struct MeltDetails *coin_melt_details, +                                    const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, +                                    unsigned int kappa, +                                    unsigned int num_oldcoins, +                                    unsigned int num_newcoins, +                                    struct RefreshCommitCoin *const* commit_coin, +                                    struct RefreshCommitLink *const* commit_link)  {    struct MintKeyState *key_state;    struct RefreshSession session;    PGconn *db_conn;    int res;    unsigned int i; +  unsigned int j;    if (NULL == (db_conn = TALER_MINT_DB_get_connection (GNUNET_NO)))    { @@ -540,10 +565,10 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection,    if (GNUNET_YES == res)    {      TALER_MINT_DB_rollback (db_conn); -    return TALER_MINT_reply_refresh_melt_success (connection, -                                                  &session.melt_sig, -                                                  refresh_session_pub, -                                                  session.kappa); +    res = TALER_MINT_reply_refresh_melt_success (connection, +                                                 &session.session_hash, +                                                 session.noreveal_index); +    return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;    }    if (GNUNET_SYSERR == res)    { @@ -586,116 +611,6 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection,      }    } -  /* store 'global' session data */ -  session.melt_sig = *client_signature; -  session.session_hash = *melt_hash; -  session.num_oldcoins = coin_count; -  session.num_newcoins = num_new_denoms; -  session.kappa = KAPPA; -  session.noreveal_index = UINT16_MAX; -  session.has_commit_sig = GNUNET_NO; -  if (GNUNET_OK != -      (res = TALER_MINT_DB_create_refresh_session (db_conn, -                                                   refresh_session_pub, -                                                   &session))) -  { -    TALER_MINT_DB_rollback (db_conn); -    return TALER_MINT_reply_internal_db_error (connection); -  } - -  if (GNUNET_OK != -      TALER_MINT_DB_commit (db_conn)) -  { -    LOG_WARNING ("/refresh/melt transaction commit failed\n"); -    return TALER_MINT_reply_commit_error (connection); -  } -  return TALER_MINT_reply_refresh_melt_success (connection, -                                                client_signature, -                                                refresh_session_pub, -                                                session.kappa); -} - - -/** - * Execute a "/refresh/commit".  The client is committing to @a kappa - * sets of transfer keys, and linkage information for a refresh - * operation.  Confirm that the commit matches the melts of an - * existing @a refresh_session_pub, store the refresh session commit - * data and then return the client a challenge specifying which of the - * @a kappa sets of private transfer keys should not be revealed. - * - * @param connection the MHD connection to handle - * @param refresh_session public key of the session - * @param commit_client_sig signature of the client over this commitment - * @param kappa size of x-dimension of @commit_coin and @commit_link arrays - * @param num_oldcoins size of y-dimension of @commit_link array - * @param num_newcoins size of y-dimension of @commit_coin array - * @param commit_coin 2d array of coin commitments (what the mint is to sign - *                    once the "/refres/reveal" of cut and choose is done) - * @param commit_link 2d array of coin link commitments (what the mint is - *                    to return via "/refresh/link" to enable linkage in the - *                    future) - * @return MHD result code - */ -int -TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection, -                                      const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, -                                      const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, -                                      unsigned int kappa, -                                      unsigned int num_oldcoins, -                                      unsigned int num_newcoins, -                                      struct RefreshCommitCoin *const*commit_coin, -                                      struct RefreshCommitLink *const*commit_link) - -{ -  PGconn *db_conn; -  struct RefreshSession refresh_session; -  unsigned int i; -  unsigned int j; -  int res; - -  if (NULL == (db_conn = TALER_MINT_DB_get_connection (GNUNET_NO))) -  { -    GNUNET_break (0); -    return TALER_MINT_reply_internal_db_error (connection); -  } - -  if (GNUNET_OK != -      TALER_MINT_DB_transaction (db_conn)) -  { -    GNUNET_break (0); -    return TALER_MINT_reply_internal_db_error (connection); -  } -  res = TALER_MINT_DB_get_refresh_session (db_conn, -                                           refresh_session_pub, -                                           &refresh_session); -  if (GNUNET_SYSERR == res) -  { -    TALER_MINT_DB_rollback (db_conn); -    return TALER_MINT_reply_internal_db_error (connection); -  } -  if (GNUNET_NO == res) -  { -    TALER_MINT_DB_rollback (db_conn); -    return TALER_MINT_reply_arg_invalid (connection, -                                         "session_pub"); -  } -  if ( (refresh_session.kappa != kappa) || -       (refresh_session.num_newcoins != num_newcoins) || -       (refresh_session.num_oldcoins != num_oldcoins) ) -  { -    TALER_MINT_DB_rollback (db_conn); -    return TALER_MINT_reply_arg_invalid (connection, -                                         "dimensions"); -  } -  if (GNUNET_YES == refresh_session.has_commit_sig) -  { -    TALER_MINT_DB_rollback (db_conn); -    res = TALER_MINT_reply_refresh_commit_success (connection, -                                                   &refresh_session.session_hash, -                                                   refresh_session.noreveal_index); -    return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; -  }    for (i = 0; i < kappa; i++)    {      for (j = 0; j < num_newcoins; j++) @@ -729,31 +644,36 @@ TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection,      }    } -  refresh_session.noreveal_index -    = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, -                                refresh_session.kappa); +  /* store 'global' session data */ +  session.melt_sig = *client_signature; +  session.session_hash = *melt_hash; +  session.num_oldcoins = coin_count; +  session.num_newcoins = num_new_denoms; +  session.kappa = KAPPA; // FIXME... +  session.noreveal_index +    = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, +                                session.kappa);    if (GNUNET_OK != -      (res = TALER_MINT_DB_update_refresh_session (db_conn, +      (res = TALER_MINT_DB_create_refresh_session (db_conn,                                                     refresh_session_pub, -                                                   refresh_session.noreveal_index, -                                                   commit_client_sig))) +                                                   &session)))    {      TALER_MINT_DB_rollback (db_conn);      return TALER_MINT_reply_internal_db_error (connection);    } +    if (GNUNET_OK !=        TALER_MINT_DB_commit (db_conn))    { -    LOG_WARNING ("/refresh/commit transaction commit failed\n"); +    LOG_WARNING ("/refresh/melt transaction commit failed\n");      return TALER_MINT_reply_commit_error (connection);    } - -  return TALER_MINT_reply_refresh_commit_success (connection, -                                                  &refresh_session.session_hash, -                                                  refresh_session.noreveal_index); +  return TALER_MINT_reply_refresh_melt_success (connection, +                                                &session.session_hash, +                                                session.noreveal_index);  } @@ -1061,15 +981,6 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection,      return TALER_MINT_reply_internal_db_error (connection);    } -  if ( (refresh_session.noreveal_index >= refresh_session.kappa) || -       (GNUNET_NO == refresh_session.has_commit_sig) ) -  { -    GNUNET_break (UINT16_MAX == refresh_session.noreveal_index); -    GNUNET_break (GNUNET_NO == refresh_session.has_commit_sig); -    return TALER_MINT_reply_external_error (connection, -                                            "/refresh/commit must be executed first"); -  } -    melts = GNUNET_malloc (refresh_session.num_oldcoins *                           sizeof (struct RefreshMelt));    for (j=0;j<refresh_session.num_oldcoins;j++) diff --git a/src/mint/taler-mint-httpd_db.h b/src/mint/taler-mint-httpd_db.h index dcd5e6fa..2a26de9b 100644 --- a/src/mint/taler-mint-httpd_db.h +++ b/src/mint/taler-mint-httpd_db.h @@ -107,6 +107,8 @@ struct MeltDetails   * required value left and if so, store that they have been   * melted and confirm the melting operation to the client.   * + * FIXME: some arguments are redundant here... + *   * @param connection the MHD connection to handle   * @param melt_hash hash code of the session the coins are melted into   * @param refresh_session_pub public key of the refresh session @@ -117,30 +119,6 @@ struct MeltDetails   * @param coin_count number of entries in @a coin_public_infos and @ a coin_melt_details   * @param coin_public_infos information about the coins to melt   * @param coin_melt_details signatures and (residual) value of the respective coin should be melted - * @return MHD result code - */ -int -TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, -                                    const struct GNUNET_HashCode *melt_hash, -                                    const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, -                                    const struct GNUNET_CRYPTO_EddsaSignature *client_signature, -                                    unsigned int num_new_denoms, -                                    struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs, -                                    unsigned int coin_count, -                                    const struct TALER_CoinPublicInfo *coin_public_infos, -                                    const struct MeltDetails *coin_melt_details); - - -/** - * Execute a "/refresh/commit".  The client is committing to @a kappa - * sets of transfer keys, and linkage information for a refresh - * operation.  Confirm that the commit matches the melts of an - * existing @a refresh_session_pub, store the refresh session commit - * data and then return the client a challenge specifying which of the - * @a kappa sets of private transfer keys should not be revealed. - * - * @param connection the MHD connection to handle - * @param refresh_session public key of the session   * @param commit_client_sig signature of the client over this commitment   * @param kappa size of x-dimension of @commit_coin and @commit_link arrays   * @param num_oldcoins size of y-dimension of @commit_coin array @@ -154,14 +132,21 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection,   */  // FIXME: see #3635.  int -TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection, -                                      const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, -                                      const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, -                                      unsigned int kappa, -                                      unsigned int num_oldcoins, -                                      unsigned int num_newcoins, -                                      struct RefreshCommitCoin *const* commit_coin, -                                      struct RefreshCommitLink *const* commit_link); +TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, +                                    const struct GNUNET_HashCode *melt_hash, +                                    const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, +                                    const struct GNUNET_CRYPTO_EddsaSignature *client_signature, +                                    unsigned int num_new_denoms, +                                    struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs, +                                    unsigned int coin_count, +                                    const struct TALER_CoinPublicInfo *coin_public_infos, +                                    const struct MeltDetails *coin_melt_details, +                                    const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, +                                    unsigned int kappa, +                                    unsigned int num_oldcoins, +                                    unsigned int num_newcoins, +                                    struct RefreshCommitCoin *const* commit_coin, +                                    struct RefreshCommitLink *const* commit_link);  /** diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index cfb3ba0f..d7b67074 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c @@ -151,6 +151,15 @@ request_json_check_signature (struct MHD_Connection *connection,   * @param coin_public_infos array with @a coin_count entries about the coins   * @param coin_melt_details array with @a coin_count entries with melting details   * @param melt_sig_json signature affirming the overall melt operation + * @param commit_client_sig signature of the client over this commitment + * @param kappa size of x-dimension of @commit_coin and @commit_link arrays + * @param num_oldcoins size of y-dimension of @commit_coin array + * @param num_newcoins size of y-dimension of @commit_link array + * @param commit_coin 2d array of coin commitments (what the mint is to sign + *                    once the "/refres/reveal" of cut and choose is done) + * @param commit_link 2d array of coin link commitments (what the mint is + *                    to return via "/refresh/link" to enable linkage in the + *                    future)   * @return MHD result code   */  static int @@ -161,7 +170,14 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,                              unsigned int coin_count,                              struct TALER_CoinPublicInfo *coin_public_infos,                              const struct MeltDetails *coin_melt_details, -                            const json_t *melt_sig_json) +                            const json_t *melt_sig_json, +                            const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, +                            unsigned int kappa, +                            unsigned int num_oldcoins, +                            unsigned int num_newcoins, +                            struct RefreshCommitCoin *const* commit_coin, +                            struct RefreshCommitLink *const* commit_link) +  {    int res;    unsigned int i; @@ -256,7 +272,13 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,                                               denom_pubs,                                               coin_count,                                               coin_public_infos, -                                             coin_melt_details); +                                             coin_melt_details, +                                             NULL /* FIXME: 3635! */, +                                             kappa, +                                             num_oldcoins, +                                             num_newcoins, +                                             commit_coin, +                                             commit_link);  } @@ -364,6 +386,58 @@ get_and_verify_coin_public_info (struct MHD_Connection *connection,  /** + * Release memory from the @a commit_coin array. + * + * @param commit_coin array to release + * @param kappa size of 1st dimension + * @param num_new_coins size of 2nd dimension + */ +static void +free_commit_coins (struct RefreshCommitCoin **commit_coin, +                   unsigned int kappa, +                   unsigned int num_new_coins) +{ +  unsigned int i; +  unsigned int j; + +  for (i=0;i<kappa;i++) +  { +    if (NULL == commit_coin[i]) +      break; +    for (j=0;j<num_new_coins;j++) +    { +      GNUNET_free_non_null (commit_coin[i][j].coin_ev); +      GNUNET_free_non_null (commit_coin[i][j].refresh_link); +    } +    GNUNET_free (commit_coin[i]); +  } +} + + +/** + * Release memory from the @a commit_link array. + * + * @param commit_coin array to release + * @param kappa size of 1st dimension + * @param num_old_coins size of 2nd dimension + */ +static void +free_commit_links (struct RefreshCommitLink **commit_link, +                   unsigned int kappa, +                   unsigned int num_old_coins) +{ +  unsigned int i; + +  for (i=0;i<kappa;i++) +  { +    if (NULL == commit_link[i]) +      break; +    GNUNET_free (commit_link[i]); +  } +} + + +/**   * Handle a "/refresh/melt" request after the first parsing has happened.   * We now need to validate the coins being melted and the session signature   * and then hand things of to execute the melt operation.  This function @@ -375,6 +449,14 @@ get_and_verify_coin_public_info (struct MHD_Connection *connection,   * @param new_denoms array of denomination keys   * @param melt_coins array of coins to melt   * @param melt_sig_json signature affirming the melt operation + * @param commit_signature signature over the commit + * @param kappa security parameter for cut and choose + * @param num_oldcoins number of coins that are being melted + * @param transfer_pubs @a kappa-dimensional array of @a num_oldcoins transfer keys + * @param secret_encs @a kappa-dimensional array of @a num_oldcoins secrets + * @param num_newcoins number of coins that the refresh will generate + * @param coin_envs @a kappa-dimensional array of @a num_newcoins envelopes to sign + * @param link_encs @a kappa-dimensional array of @a num_newcoins encrypted links   * @return MHD result code   */  static int @@ -382,7 +464,16 @@ handle_refresh_melt_json (struct MHD_Connection *connection,                            const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub,                            const json_t *new_denoms,                            const json_t *melt_coins, -                          const json_t *melt_sig_json) +                          const json_t *melt_sig_json, +                          const json_t *commit_signature, +                          unsigned int kappa, +                          unsigned int num_oldcoins, +                          const json_t *transfer_pubs, +                          const json_t *secret_encs, +                          unsigned int num_newcoins, +                          const json_t *coin_evs, +                          const json_t *link_encs) +  {    int res;    unsigned int i; @@ -392,6 +483,11 @@ handle_refresh_melt_json (struct MHD_Connection *connection,    struct TALER_CoinPublicInfo *coin_public_infos;    struct MeltDetails *coin_melt_details;    unsigned int coin_count; +  struct GNUNET_HashCode commit_hash; +  struct GNUNET_HashContext *hash_context; +  struct RefreshCommitSignatureBody body; +  struct RefreshCommitCoin *commit_coin[kappa]; +  struct RefreshCommitLink *commit_link[kappa];    num_new_denoms = json_array_size (new_denoms);    denom_pubs = GNUNET_malloc (num_new_denoms * @@ -441,180 +537,6 @@ handle_refresh_melt_json (struct MHD_Connection *connection,      }    } -  res = handle_refresh_melt_binary (connection, -                                    refresh_session_pub, -                                    num_new_denoms, -                                    denom_pubs, -                                    coin_count, -                                    coin_public_infos, -                                    coin_melt_details, -                                    melt_sig_json); -  for (j=0;j<coin_count;j++) -  { -    GNUNET_CRYPTO_rsa_public_key_free (coin_public_infos[j].denom_pub); -    GNUNET_CRYPTO_rsa_signature_free (coin_public_infos[j].denom_sig); -  } -  GNUNET_free (coin_public_infos); -  for (j=0;j<num_new_denoms;j++) -  { -    GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j]); -  } -  GNUNET_free (coin_melt_details); -  GNUNET_free (denom_pubs); -  return res; -} - - -/** - * Handle a "/refresh/melt" request.  Parses the request into the JSON - * components and then hands things of to #handle_referesh_melt_json() - * to validate the melted coins, the signature and execute the melt - * using TALER_MINT_db_execute_refresh_melt(). - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[IN|OUT] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data - * @return MHD result code - */ -int -TALER_MINT_handler_refresh_melt (struct RequestHandler *rh, -                                 struct MHD_Connection *connection, -                                 void **connection_cls, -                                 const char *upload_data, -                                 size_t *upload_data_size) -{ -  json_t *root; -  json_t *new_denoms; -  json_t *melt_coins; -  json_t *melt_sig_json; -  struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub; -  int res; -  struct GNUNET_MINT_ParseFieldSpec spec[] = { -    TALER_MINT_PARSE_FIXED ("session_pub", &refresh_session_pub), -    TALER_MINT_PARSE_ARRAY ("new_denoms", &new_denoms), -    TALER_MINT_PARSE_ARRAY ("melt_coins", &melt_coins), -    TALER_MINT_PARSE_ARRAY ("melt_signature", &melt_sig_json), -    TALER_MINT_PARSE_END -  }; - -  res = TALER_MINT_parse_post_json (connection, -                                    connection_cls, -                                    upload_data, -                                    upload_data_size, -                                    &root); -  if (GNUNET_SYSERR == res) -    return MHD_NO; -  if ( (GNUNET_NO == res) || (NULL == root) ) -    return MHD_YES; - -  res = TALER_MINT_parse_json_data (connection, -                                    root, -                                    spec); -  json_decref (root); -  if (GNUNET_OK != res) -    return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; -  res = handle_refresh_melt_json (connection, -                                  &refresh_session_pub, -                                  new_denoms, -                                  melt_coins, -                                  melt_sig_json); -  TALER_MINT_release_parsed_data (spec); -  return res; -} - - -/** - * Release memory from the @a commit_coin array. - * - * @param commit_coin array to release - * @param kappa size of 1st dimension - * @param num_new_coins size of 2nd dimension - */ -static void -free_commit_coins (struct RefreshCommitCoin **commit_coin, -                   unsigned int kappa, -                   unsigned int num_new_coins) -{ -  unsigned int i; -  unsigned int j; - -  for (i=0;i<kappa;i++) -  { -    if (NULL == commit_coin[i]) -      break; -    for (j=0;j<num_new_coins;j++) -    { -      GNUNET_free_non_null (commit_coin[i][j].coin_ev); -      GNUNET_free_non_null (commit_coin[i][j].refresh_link); -    } -    GNUNET_free (commit_coin[i]); -  } -} - - -/** - * Release memory from the @a commit_link array. - * - * @param commit_coin array to release - * @param kappa size of 1st dimension - * @param num_old_coins size of 2nd dimension - */ -static void -free_commit_links (struct RefreshCommitLink **commit_link, -                   unsigned int kappa, -                   unsigned int num_old_coins) -{ -  unsigned int i; - -  for (i=0;i<kappa;i++) -  { -    if (NULL == commit_link[i]) -      break; -    GNUNET_free (commit_link[i]); -  } -} - - - -/** - * Handle a "/refresh/commit" request.  We have the individual JSON - * arrays, now we need to parse their contents and verify the - * commit signature.  Then we can commit the data to the database. - * - * @param connection the MHD connection to handle - * @param refresh_session_pub public key of the refresh session - * @param commit_signature signature over the commit - * @param kappa security parameter for cut and choose - * @param num_oldcoins number of coins that are being melted - * @param transfer_pubs @a kappa-dimensional array of @a num_oldcoins transfer keys - * @param secret_encs @a kappa-dimensional array of @a num_oldcoins secrets - * @param num_newcoins number of coins that the refresh will generate - * @param coin_envs @a kappa-dimensional array of @a num_newcoins envelopes to sign - * @param link_encs @a kappa-dimensional array of @a num_newcoins encrypted links - * @return MHD result code - */ -static int -handle_refresh_commit_json (struct MHD_Connection *connection, -                            const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, -                            const json_t *commit_signature, -                            unsigned int kappa, -                            unsigned int num_oldcoins, -                            const json_t *transfer_pubs, -                            const json_t *secret_encs, -                            unsigned int num_newcoins, -                            const json_t *coin_evs, -                            const json_t *link_encs) -{ -  struct GNUNET_HashCode commit_hash; -  struct GNUNET_HashContext *hash_context; -  struct RefreshCommitSignatureBody body; -  struct RefreshCommitCoin *commit_coin[kappa]; -  struct RefreshCommitLink *commit_link[kappa]; -  unsigned int i; -  unsigned int j; -  int res;    /* parse JSON arrays into 2d binary arrays and hash everything       together for the signature check */ @@ -721,7 +643,7 @@ handle_refresh_commit_json (struct MHD_Connection *connection,    GNUNET_CRYPTO_hash_context_finish (hash_context, &commit_hash);    /* verify commit signature */ -  body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_COMMIT); +  body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT);    body.purpose.size = htonl (sizeof (struct RefreshCommitSignatureBody));    body.commit_hash = commit_hash; @@ -738,29 +660,43 @@ handle_refresh_commit_json (struct MHD_Connection *connection,    /* execute commit */    /* FIXME: we must also store the signature! (#3635) */ -  res = TALER_MINT_db_execute_refresh_commit (connection, -                                              refresh_session_pub, -                                              NULL /* FIXME: 3635! */, -                                              kappa, -                                              num_oldcoins, -                                              num_newcoins, -                                              commit_coin, -                                              commit_link); +  res = handle_refresh_melt_binary (connection, +                                    refresh_session_pub, +                                    num_new_denoms, +                                    denom_pubs, +                                    coin_count, +                                    coin_public_infos, +                                    coin_melt_details, +                                    melt_sig_json, +                                    NULL /* FIXME: 3635! */, +                                    kappa, +                                    num_oldcoins, +                                    num_newcoins, +                                    commit_coin, +                                    commit_link);    free_commit_coins (commit_coin, kappa, num_newcoins);    free_commit_links (commit_link, kappa, num_oldcoins); - +  for (j=0;j<coin_count;j++) +  { +    GNUNET_CRYPTO_rsa_public_key_free (coin_public_infos[j].denom_pub); +    GNUNET_CRYPTO_rsa_signature_free (coin_public_infos[j].denom_sig); +  } +  GNUNET_free (coin_public_infos); +  for (j=0;j<num_new_denoms;j++) +  { +    GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j]); +  } +  GNUNET_free (coin_melt_details); +  GNUNET_free (denom_pubs);    return res;  }  /** - * Handle a "/refresh/commit" request.  Parses the top-level JSON to - * determine the dimensions of the problem and then handles handing - * off to #handle_refresh_commit_json() to parse the details of the - * JSON arguments.  Once the signature has been verified, the - * commit data is written to the database via - * #TALER_MINT_db_execute_refresh_commit() and the reveal parameter - * is then returned to the client. + * Handle a "/refresh/melt" request.  Parses the request into the JSON + * components and then hands things of to #handle_referesh_melt_json() + * to validate the melted coins, the signature and execute the melt + * using TALER_MINT_db_execute_refresh_melt().   *   * @param rh context of the handler   * @param connection the MHD connection to handle @@ -768,28 +704,34 @@ handle_refresh_commit_json (struct MHD_Connection *connection,   * @param upload_data upload data   * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data   * @return MHD result code -  */ + */  int -TALER_MINT_handler_refresh_commit (struct RequestHandler *rh, -                                   struct MHD_Connection *connection, -                                   void **connection_cls, -                                   const char *upload_data, -                                   size_t *upload_data_size) +TALER_MINT_handler_refresh_melt (struct RequestHandler *rh, +                                 struct MHD_Connection *connection, +                                 void **connection_cls, +                                 const char *upload_data, +                                 size_t *upload_data_size)  { -  struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub; -  int res; -  unsigned int kappa; -  unsigned int num_oldcoins; -  unsigned int num_newcoins;    json_t *root; +  json_t *new_denoms; +  json_t *melt_coins; +  json_t *melt_sig_json;    json_t *coin_evs;    json_t *link_encs;    json_t *transfer_pubs;    json_t *secret_encs; -  json_t *coin_detail;    json_t *commit_sig_json; +  unsigned int kappa; +  unsigned int num_oldcoins; +  unsigned int num_newcoins; +  json_t *coin_detail; +  struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub; +  int res;    struct GNUNET_MINT_ParseFieldSpec spec[] = {      TALER_MINT_PARSE_FIXED ("session_pub", &refresh_session_pub), +    TALER_MINT_PARSE_ARRAY ("new_denoms", &new_denoms), +    TALER_MINT_PARSE_ARRAY ("melt_coins", &melt_coins), +    TALER_MINT_PARSE_ARRAY ("melt_signature", &melt_sig_json),      TALER_MINT_PARSE_ARRAY ("coin_evs", &coin_evs),      TALER_MINT_PARSE_ARRAY ("link_encs", &link_encs),      TALER_MINT_PARSE_ARRAY ("transfer_pubs", &transfer_pubs), @@ -852,16 +794,21 @@ TALER_MINT_handler_refresh_commit (struct RequestHandler *rh,      return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;    }    num_oldcoins = json_array_size (coin_detail); -  res = handle_refresh_commit_json (connection, -                                    &refresh_session_pub, -                                    commit_sig_json, -                                    kappa, -                                    num_oldcoins, -                                    transfer_pubs, -                                    secret_encs, -                                    num_newcoins, -                                    coin_evs, -                                    link_encs); + +  res = handle_refresh_melt_json (connection, +                                  &refresh_session_pub, +                                  new_denoms, +                                  melt_coins, +                                  melt_sig_json, +                                  commit_sig_json, +                                  kappa, +                                  num_oldcoins, +                                  transfer_pubs, +                                  secret_encs, +                                  num_newcoins, +                                  coin_evs, +                                  link_encs); +    TALER_MINT_release_parsed_data (spec);    return res;  } @@ -931,7 +878,7 @@ handle_refresh_reveal_json (struct MHD_Connection *connection,  /**   * Handle a "/refresh/reveal" request. This time, the client reveals   * the private transfer keys except for the cut-and-choose value - * returned from "/refresh/commit".  This function parses the revealed + * returned from "/refresh/melt".  This function parses the revealed   * keys and secrets and ultimately passes everything to   * #TALER_MINT_db_execute_refresh_reveal() which will verify that the   * revealed information is valid then returns the signed refreshed diff --git a/src/mint/taler-mint-httpd_refresh.h b/src/mint/taler-mint-httpd_refresh.h index 80bad6c5..c1f69e1d 100644 --- a/src/mint/taler-mint-httpd_refresh.h +++ b/src/mint/taler-mint-httpd_refresh.h @@ -50,30 +50,6 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh,  /** - * Handle a "/refresh/commit" request.  Parses the top-level JSON to - * determine the dimensions of the problem and then handles handing - * off to #handle_refresh_commit_json() to parse the details of the - * JSON arguments.  Once the signature has been verified, the - * commit data is written to the database via - * #TALER_MINT_db_execute_refresh_commit() and the cut-and-choose value - * is then returned to the client. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[IN|OUT] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data - * @return MHD result code -  */ -int -TALER_MINT_handler_refresh_commit (struct RequestHandler *rh, -                                   struct MHD_Connection *connection, -                                   void **connection_cls, -                                   const char *upload_data, -                                   size_t *upload_data_size); - - -/**   * Handle a "/refresh/reveal" request.  This time, the client reveals   * the private transfer keys except for the cut-and-choose value   * returned from "/refresh/commit".  This function parses the revealed diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c index 21e20811..83c81e80 100644 --- a/src/mint/taler-mint-httpd_responses.c +++ b/src/mint/taler-mint-httpd_responses.c @@ -315,27 +315,20 @@ TALER_MINT_reply_deposit_success (struct MHD_Connection *connection,    return ret;  } -  /** - * Send proof that a /deposit, /refresh/melt or /lock request is - * invalid to client.  This function will create a message with all of - * the operations affecting the coin that demonstrate that the coin - * has insufficient value. + * Compile the transaction history of a coin into a JSON object.   * - * @param connection connection to the client - * @param tl transaction list to use to build reply - * @return MHD result code + * @param tl transaction history to JSON-ify + * @return json representation of the @a rh   */ -int -TALER_MINT_reply_insufficient_funds (struct MHD_Connection *connection, -                                     const struct TALER_MINT_DB_TransactionList *tl) +static json_t * +compile_transaction_history (const struct TALER_MINT_DB_TransactionList *tl)  { -  const struct TALER_MINT_DB_TransactionList *pos; -  int ret; -  json_t *history;    json_t *transaction;    const char *type;    struct TALER_Amount value; +  json_t *history; +  const struct TALER_MINT_DB_TransactionList *pos;    history = json_array ();    for (pos = tl; NULL != pos; pos = pos->next) @@ -392,13 +385,31 @@ TALER_MINT_reply_insufficient_funds (struct MHD_Connection *connection,                                        "amount", TALER_JSON_from_amount (value),                                        "signature", transaction));    } +  return history; +} -  ret = TALER_MINT_reply_json_pack (connection, -                                    MHD_HTTP_FORBIDDEN, -                                    "{s:s, s:o}", -                                    "error", "insufficient funds", -                                    "history", history); -  return ret; + +/** + * Send proof that a /withdraw request is invalid to client.  This + * function will create a message with all of the operations affecting + * the coin that demonstrate that the coin has insufficient value. + * + * @param connection connection to the client + * @param tl transaction list to use to build reply + * @return MHD result code + */ +int +TALER_MINT_reply_deposit_insufficient_funds (struct MHD_Connection *connection, +                                             const struct TALER_MINT_DB_TransactionList *tl) +{ +  json_t *history; + +  history = compile_transaction_history (tl); +  return TALER_MINT_reply_json_pack (connection, +                                     MHD_HTTP_FORBIDDEN, +                                     "{s:s, s:o}", +                                     "error", "insufficient funds", +                                     "history", history);  } @@ -589,47 +600,46 @@ TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection,  /** - * Send a response for "/refresh/melt".  Essentially we sign - * over the client's signature and public key, thereby - * demonstrating that we accepted all of the client's coins. + * Send a response for a failed "/refresh/melt" request.  The + * transaction history of the given coin demonstrates that the + * @a residual value of the coin is below the @a requested + * contribution of the coin for the melt.  Thus, the mint + * refuses the melt operation.   *   * @param connection the connection to send the response to - * @param signature the client's signature over the melt request - * @param session_pub the refresh session public key. - * @param kappa security parameter to use for cut and choose + * @param coin_pub public key of the coin + * @param coin_value original value of the coin + * @param tl transaction history for the coin + * @param requested how much this coin was supposed to contribute + * @param residual remaining value of the coin (after subtracting @a tl)   * @return a MHD result code   */  int -TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, -                                       const struct GNUNET_CRYPTO_EddsaSignature *signature, -                                       const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, -                                       unsigned int kappa) +TALER_MINT_reply_refresh_melt_insufficient_funds (struct MHD_Connection *connection, +                                                  const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, +                                                  struct TALER_Amount coin_value, +                                                  struct TALER_MINT_DB_TransactionList *tl, +                                                  struct TALER_Amount requested, +                                                  struct TALER_Amount residual)  { -  int ret; -  struct RefreshMeltResponseSignatureBody body; -  struct GNUNET_CRYPTO_EddsaSignature sig; -  json_t *sig_json; +  json_t *history; -  body.purpose.size = htonl (sizeof (struct RefreshMeltResponseSignatureBody)); -  body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_RESPONSE); -  body.melt_client_signature = *signature; -  body.session_key = *session_pub; -  body.kappa = htonl (kappa); -  TALER_MINT_keys_sign (&body.purpose, -                        &sig); -  sig_json = TALER_JSON_from_eddsa_sig (&body.purpose, &sig); -  ret = TALER_MINT_reply_json_pack (connection, -                                    MHD_HTTP_OK, -                                    "{s:o, s:i}", -                                    "signature", sig_json, -                                    "kappa", (int) kappa); -  json_decref (sig_json); -  return ret; +  history = compile_transaction_history (tl); +  return TALER_MINT_reply_json_pack (connection, +                                     MHD_HTTP_NOT_FOUND, +                                     "{s:s, s:o, s:o, s:o, s:o, s:o}", +                                     "error", "insufficient funds", +                                     "coin-pub", TALER_JSON_from_data (coin_pub, +                                                                       sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)), +                                     "original-value", TALER_JSON_from_amount (coin_value), +                                     "residual-value", TALER_JSON_from_amount (residual), +                                     "requested-value", TALER_JSON_from_amount (requested), +                                     "history", history);  }  /** - * Send a response to a "/refresh/commit" request. + * Send a response to a "/refresh/melt" request.   *   * @param connection the connection to send the response to   * @param session_hash hash of the refresh session @@ -637,17 +647,17 @@ TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection,   * @return a MHD status code   */  int -TALER_MINT_reply_refresh_commit_success (struct MHD_Connection *connection, -                                         const struct GNUNET_HashCode *session_hash, -                                         uint16_t noreveal_index) +TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, +                                       const struct GNUNET_HashCode *session_hash, +                                       uint16_t noreveal_index)  { -  struct RefreshCommitResponseSignatureBody body; +  struct RefreshMeltResponseSignatureBody body;    struct GNUNET_CRYPTO_EddsaSignature sig;    json_t *sig_json;    int ret; -  body.purpose.size = htonl (sizeof (struct RefreshCommitResponseSignatureBody)); -  body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_COMMIT_RESPONSE); +  body.purpose.size = htonl (sizeof (struct RefreshMeltResponseSignatureBody)); +  body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_RESPONSE);    body.session_hash = *session_hash;    body.noreveal_index = htons (noreveal_index);    TALER_MINT_keys_sign (&body.purpose, diff --git a/src/mint/taler-mint-httpd_responses.h b/src/mint/taler-mint-httpd_responses.h index abfb4318..7d0824c8 100644 --- a/src/mint/taler-mint-httpd_responses.h +++ b/src/mint/taler-mint-httpd_responses.h @@ -194,18 +194,17 @@ TALER_MINT_reply_deposit_success (struct MHD_Connection *connection,  /** - * Send proof that a /deposit, /refresh/melt or /lock request is - * invalid to client.  This function will create a message with all of - * the operations affecting the coin that demonstrate that the coin - * has insufficient value. + * Send proof that a /deposit request is invalid to client.  This + * function will create a message with all of the operations affecting + * the coin that demonstrate that the coin has insufficient value.   *   * @param connection connection to the client   * @param tl transaction list to use to build reply   * @return MHD result code   */  int -TALER_MINT_reply_insufficient_funds (struct MHD_Connection *connection, -                                     const struct TALER_MINT_DB_TransactionList *tl); +TALER_MINT_reply_deposit_insufficient_funds (struct MHD_Connection *connection, +                                             const struct TALER_MINT_DB_TransactionList *tl);  /** @@ -247,7 +246,7 @@ TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection,  /** - * Send a response to a "/refresh/commit" request. + * Send a confirmation response to a "/refresh/melt" request.   *   * @param connection the connection to send the response to   * @param session_hash hash of the refresh session @@ -255,27 +254,33 @@ TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection,   * @return a MHD status code   */  int -TALER_MINT_reply_refresh_commit_success (struct MHD_Connection *connection, -                                         const struct GNUNET_HashCode *session_hash, -                                         uint16_t noreveal_index); +TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, +                                       const struct GNUNET_HashCode *session_hash, +                                       uint16_t noreveal_index);  /** - * Send a response for "/refresh/melt". Essentially we sign - * over the client's signature and public key, thereby - * demonstrating that we accepted all of the client's coins. + * Send a response for a failed "/refresh/melt" request.  The + * transaction history of the given coin demonstrates that the + * @a residual value of the coin is below the @a requested + * contribution of the coin for the melt.  Thus, the mint + * refuses the melt operation.   *   * @param connection the connection to send the response to - * @param signature the client's signature over the melt request - * @param session_pub the refresh session public key. - * @param kappa security parameter to use for cut and choose + * @param coin_pub public key of the coin + * @param coin_value original value of the coin + * @param tl transaction history for the coin + * @param requested how much this coin was supposed to contribute + * @param residual remaining value of the coin (after subtracting @a tl)   * @return a MHD result code   */  int -TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, -                                       const struct GNUNET_CRYPTO_EddsaSignature *signature, -                                       const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, -                                       unsigned int kappa); +TALER_MINT_reply_refresh_melt_insufficient_funds (struct MHD_Connection *connection, +                                                  const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, +                                                  struct TALER_Amount coin_value, +                                                  struct TALER_MINT_DB_TransactionList *tl, +                                                  struct TALER_Amount requested, +                                                  struct TALER_Amount residual);  /** | 
