working on cleaning up /refresh/melt logic

This commit is contained in:
Christian Grothoff 2015-01-29 20:00:21 +01:00
parent 8ca555500f
commit 090ddf170b
9 changed files with 374 additions and 276 deletions

View File

@ -233,6 +233,36 @@ struct TALER_DepositConfirmation
}; };
/**
* Format of the block signed by the Mint in response to
* a successful "/refresh/melt" request. Hereby the mint
* affirms that all of the coins were successfully melted.
*/
struct RefreshMeltResponseSignatureBody
{
/**
* Purpose is #TALER_SIGNATURE_REFRESH_MELT_RESPONSE.
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* Signature of the client over the melt request (thereby
* indirectly including all of the information the client
* sent).
*/
struct GNUNET_CRYPTO_EddsaSignature melt_client_signature;
/**
* Public key of the refresh session for which
* @e melt_client_signature must be a valid signature.
*/
struct GNUNET_CRYPTO_EddsaPublicKey session_key;
};
/** /**
* FIXME * FIXME
*/ */
@ -296,15 +326,6 @@ struct RefreshCommitResponseSignatureBody
}; };
/**
* FIXME
*/
struct RefreshMeltResponseSignatureBody
{
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
struct GNUNET_HashCode melt_response_hash;
};
/** /**
* FIXME * FIXME

View File

@ -36,54 +36,6 @@
/**
* Global information for a refreshing session.
*/
struct RefreshSession
{
/**
* Signature over the commitments by the client.
*/
struct GNUNET_CRYPTO_EddsaSignature commit_sig;
/**
* Public key of the refreshing session, used to sign
* the client's commit message.
*/
struct GNUNET_CRYPTO_EddsaPublicKey session_pub;
/**
* Number of coins we are melting.
*/
uint16_t num_oldcoins;
/**
* Number of new coins we are creating.
*/
uint16_t num_newcoins;
/**
* Number of parallel operations we perform for the cut and choose.
* (must be greater or equal to three for security).
*/
uint16_t kappa;
/**
* Index (smaller @e kappa) which the mint has chosen to not
* have revealed during cut and choose.
*/
uint16_t noreveal_index;
/**
* FIXME.
*/
int has_commit_sig;
/**
* FIXME.
*/
uint8_t reveal_ok;
};

View File

@ -581,76 +581,6 @@ TALER_MINT_DB_insert_refresh_order (PGconn *db_conn,
} }
int
TALER_MINT_DB_get_refresh_session (PGconn *db_conn,
const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub,
struct RefreshSession *session)
{
int res;
struct TALER_DB_QueryParam params[] = {
TALER_DB_QUERY_PARAM_PTR(refresh_session_pub),
TALER_DB_QUERY_PARAM_END
};
PGresult *result = TALER_DB_exec_prepared (db_conn, "get_refresh_session", params);
if (PGRES_TUPLES_OK != PQresultStatus (result))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Query failed: %s\n",
PQresultErrorMessage (result));
PQclear (result);
return GNUNET_SYSERR;
}
if (0 == PQntuples (result))
return GNUNET_NO;
GNUNET_assert (1 == PQntuples (result));
/* We're done if the caller is only interested in
* whether the session exists or not */
if (NULL == session)
return GNUNET_YES;
memset (session, 0, sizeof (struct RefreshSession));
session->session_pub = *refresh_session_pub;
struct TALER_DB_ResultSpec rs[] = {
TALER_DB_RESULT_SPEC("num_oldcoins", &session->num_oldcoins),
TALER_DB_RESULT_SPEC("num_newcoins", &session->num_newcoins),
TALER_DB_RESULT_SPEC("kappa", &session->kappa),
TALER_DB_RESULT_SPEC("noreveal_index", &session->noreveal_index),
TALER_DB_RESULT_SPEC("reveal_ok", &session->reveal_ok),
TALER_DB_RESULT_SPEC_END
};
res = TALER_DB_extract_result (result, rs, 0);
if (GNUNET_OK != res)
{
GNUNET_break (0);
PQclear (result);
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);
session->noreveal_index = ntohs (session->noreveal_index);
PQclear (result);
return GNUNET_YES;
}
int int
TALER_MINT_DB_get_known_coin (PGconn *db_conn, TALER_MINT_DB_get_known_coin (PGconn *db_conn,
const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub,
@ -743,34 +673,6 @@ TALER_MINT_DB_get_known_coin (PGconn *db_conn,
} }
int
TALER_MINT_DB_create_refresh_session (PGconn *db_conn,
const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub)
{
uint16_t noreveal_index;
struct TALER_DB_QueryParam params[] = {
TALER_DB_QUERY_PARAM_PTR(session_pub),
TALER_DB_QUERY_PARAM_PTR(&noreveal_index),
TALER_DB_QUERY_PARAM_END
};
noreveal_index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1<<15);
noreveal_index = htonl (noreveal_index);
PGresult *result = TALER_DB_exec_prepared (db_conn, "insert_refresh_session", params);
if (PGRES_COMMAND_OK != PQresultStatus (result))
{
break_db_err (result);
PQclear (result);
return GNUNET_SYSERR;
}
PQclear (result);
return GNUNET_OK;
}
int int
TALER_MINT_DB_set_commit_signature (PGconn *db_conn, TALER_MINT_DB_set_commit_signature (PGconn *db_conn,
const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
@ -1881,6 +1783,145 @@ TALER_MINT_DB_insert_deposit (PGconn *db_conn,
} }
/**
* Lookup refresh session data under the given public key.
*
* @param db_conn database handle to use
* @param refresh_session_pub public key to use for the lookup
* @param session[OUT] where to store the result
* @return #GNUNET_YES on success,
* #GNUNET_NO if not found,
* #GNUNET_SYSERR on DB failure
*/
int
TALER_MINT_DB_get_refresh_session (PGconn *db_conn,
const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub,
struct RefreshSession *session)
{
// FIXME: check logic!
int res;
struct TALER_DB_QueryParam params[] = {
TALER_DB_QUERY_PARAM_PTR(refresh_session_pub),
TALER_DB_QUERY_PARAM_END
};
PGresult *result = TALER_DB_exec_prepared (db_conn, "get_refresh_session", params);
if (PGRES_TUPLES_OK != PQresultStatus (result))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Query failed: %s\n",
PQresultErrorMessage (result));
PQclear (result);
return GNUNET_SYSERR;
}
if (0 == PQntuples (result))
return GNUNET_NO;
GNUNET_assert (1 == PQntuples (result));
/* We're done if the caller is only interested in
* whether the session exists or not */
if (NULL == session)
return GNUNET_YES;
memset (session, 0, sizeof (struct RefreshSession));
struct TALER_DB_ResultSpec rs[] = {
TALER_DB_RESULT_SPEC("num_oldcoins", &session->num_oldcoins),
TALER_DB_RESULT_SPEC("num_newcoins", &session->num_newcoins),
TALER_DB_RESULT_SPEC("kappa", &session->kappa),
TALER_DB_RESULT_SPEC("noreveal_index", &session->noreveal_index),
TALER_DB_RESULT_SPEC_END
};
res = TALER_DB_extract_result (result, rs, 0);
if (GNUNET_OK != res)
{
GNUNET_break (0);
PQclear (result);
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);
session->noreveal_index = ntohs (session->noreveal_index);
PQclear (result);
return GNUNET_YES;
}
/**
* Store new refresh session data under the given public key.
*
* @param db_conn database handle to use
* @param refresh_session_pub public key to use to locate the session
* @param session session data to store
* @return #GNUNET_YES on success,
* #GNUNET_SYSERR on DB failure
*/
int
TALER_MINT_DB_create_refresh_session (PGconn *db_conn,
const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
const struct RefreshSession *session)
{
// FIXME: actually store session data!
uint16_t noreveal_index;
struct TALER_DB_QueryParam params[] = {
TALER_DB_QUERY_PARAM_PTR(session_pub),
TALER_DB_QUERY_PARAM_PTR(&noreveal_index),
TALER_DB_QUERY_PARAM_END
};
noreveal_index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1<<15);
noreveal_index = htonl (noreveal_index);
PGresult *result = TALER_DB_exec_prepared (db_conn, "insert_refresh_session", params);
if (PGRES_COMMAND_OK != PQresultStatus (result))
{
break_db_err (result);
PQclear (result);
return GNUNET_SYSERR;
}
PQclear (result);
return GNUNET_OK;
}
/**
* 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;
}
/** /**
* Test if the given /refresh/melt request is known to us. * Test if the given /refresh/melt request is known to us.
* *

View File

@ -44,10 +44,9 @@ TALER_MINT_DB_insert_refresh_order (PGconn *db_conn,
const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub); const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub);
int
TALER_MINT_DB_get_refresh_session (PGconn *db_conn,
const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub,
struct RefreshSession *r_session);
/** /**
@ -86,10 +85,6 @@ TALER_MINT_DB_insert_known_coin (PGconn *db_conn,
const struct KnownCoin *known_coin); const struct KnownCoin *known_coin);
int
TALER_MINT_DB_create_refresh_session (PGconn *db_conn,
const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub);
/** /**
* Store the commitment to the given (encrypted) refresh link data * Store the commitment to the given (encrypted) refresh link data
@ -521,10 +516,111 @@ TALER_MINT_DB_insert_deposit (PGconn *db_conn,
const struct Deposit *deposit); const struct Deposit *deposit);
/** /**
* Specification for a /refresh/melt operation. * Global information for a refreshing session. Includes
* dimensions of the operation, security parameters and
* client signatures from "/refresh/melt" and "/refresh/commit".
*/ */
struct RefreshMelt struct RefreshSession
{
/**
* Signature over the commitments by the client,
* only valid if @e has_commit_sig is set.
*/
struct GNUNET_CRYPTO_EddsaSignature commit_sig;
/**
* Signature over the melt by the client.
*/
struct GNUNET_CRYPTO_EddsaSignature melt_sig;
/**
* Number of coins we are melting.
*/
uint16_t num_oldcoins;
/**
* Number of new coins we are creating.
*/
uint16_t num_newcoins;
/**
* Number of parallel operations we perform for the cut and choose.
* (must be greater or equal to three for security). 0 if not yet
* known.
*/
uint16_t kappa;
/**
* 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.
*/
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;
};
/**
* Lookup refresh session data under the given public key.
*
* @param db_conn database handle to use
* @param refresh_session_pub public key to use for the lookup
* @param session[OUT] where to store the result
* @return #GNUNET_YES on success,
* #GNUNET_NO if not found,
* #GNUNET_SYSERR on DB failure
*/
int
TALER_MINT_DB_get_refresh_session (PGconn *db_conn,
const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub,
struct RefreshSession *session);
/**
* Store new refresh session data under the given public key.
*
* @param db_conn database handle to use
* @param refresh_session_pub public key to use to locate the session
* @param session session data to store
* @return #GNUNET_YES on success,
* #GNUNET_SYSERR on DB failure
*/
int
TALER_MINT_DB_create_refresh_session (PGconn *db_conn,
const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
const struct RefreshSession *session);
/**
* 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 /* FIXME: name to make it clearer this is about ONE coin! */
{ {
/** /**
* Information about the coin that is being melted. * Information about the coin that is being melted.

View File

@ -602,6 +602,8 @@ refresh_accept_melts (struct MHD_Connection *connection,
* *
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param refresh_session_pub public key of the refresh session * @param refresh_session_pub public key of the refresh session
* @param client_signature signature of the client (matching @a refresh_session_pub)
* over the melting request
* @param num_new_denoms number of entries in @a denom_pubs * @param num_new_denoms number of entries in @a denom_pubs
* @param denum_pubs public keys of the coins we want to withdraw in the end * @param denum_pubs public keys of the coins we want to withdraw in the end
* @param coin_count number of entries in @a coin_public_infos * @param coin_count number of entries in @a coin_public_infos
@ -611,6 +613,7 @@ refresh_accept_melts (struct MHD_Connection *connection,
int int
TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection,
const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub,
const struct GNUNET_CRYPTO_EddsaSignature *client_signature,
unsigned int num_new_denoms, unsigned int num_new_denoms,
struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs, struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs,
unsigned int coin_count, unsigned int coin_count,
@ -622,57 +625,48 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection,
PGconn *db_conn; PGconn *db_conn;
int res; int res;
/* We incrementally update the db with other parameters in a transaction.
* The transaction is aborted if some parameter does not validate. */
/* Send response immediately if we already know the session.
* Do _not_ care about fields other than session_pub in this case. */
if (NULL == (db_conn = TALER_MINT_DB_get_connection ())) if (NULL == (db_conn = TALER_MINT_DB_get_connection ()))
{ {
GNUNET_break (0); GNUNET_break (0);
return TALER_MINT_reply_internal_db_error (connection); return TALER_MINT_reply_internal_db_error (connection);
} }
res = TALER_MINT_DB_get_refresh_session (db_conn,
refresh_session_pub,
NULL);
if (GNUNET_YES == res)
{
if (GNUNET_OK !=
(res = TALER_MINT_DB_get_refresh_session (db_conn,
refresh_session_pub,
&session)))
{
// FIXME: send internal error
GNUNET_break (0);
return MHD_NO;
}
return TALER_MINT_reply_refresh_melt_success (connection,
&session,
refresh_session_pub);
}
if (GNUNET_SYSERR == res)
{
// FIXME: return 'internal error'?
GNUNET_break (0);
return MHD_NO;
}
if (GNUNET_OK != if (GNUNET_OK !=
TALER_MINT_DB_transaction (db_conn)) TALER_MINT_DB_transaction (db_conn))
{ {
GNUNET_break (0); GNUNET_break (0);
return TALER_MINT_reply_internal_db_error (connection); return TALER_MINT_reply_internal_db_error (connection);
} }
res = TALER_MINT_DB_get_refresh_session (db_conn,
if (GNUNET_OK != TALER_MINT_DB_create_refresh_session (db_conn, refresh_session_pub,
refresh_session_pub)) &session);
if (GNUNET_YES == res)
{ {
// FIXME: return 'internal error'?
GNUNET_break (0);
TALER_MINT_DB_rollback (db_conn); TALER_MINT_DB_rollback (db_conn);
return MHD_NO; return TALER_MINT_reply_refresh_melt_success (connection,
&session.melt_sig,
refresh_session_pub);
}
if (GNUNET_SYSERR == res)
{
TALER_MINT_DB_rollback (db_conn);
return TALER_MINT_reply_internal_db_error (connection);
}
session.melt_sig = *client_signature;
session.num_oldcoins = coin_count;
session.num_newcoins = num_new_denoms;
session.kappa = 0; /* FIXME: should be chosen by mint per config! */
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);
} }
/* The next two operations must see the same key state, /* The next two operations must see the same key state,
@ -725,7 +719,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection,
return MHD_NO; return MHD_NO;
} }
return TALER_MINT_reply_refresh_melt_success (connection, return TALER_MINT_reply_refresh_melt_success (connection,
&session, client_signature,
refresh_session_pub); refresh_session_pub);
@ -741,6 +735,8 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection,
* @a kappa sets of private transfer keys should not be revealed. * @a kappa sets of private transfer keys should not be revealed.
* *
* @param connection the MHD connection to handle * @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 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_oldcoins size of y-dimension of @commit_link array
* @param num_newcoins size of y-dimension of @commit_coin array * @param num_newcoins size of y-dimension of @commit_coin array
@ -754,6 +750,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection,
int int
TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection, TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection,
const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub,
const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig,
unsigned int kappa, unsigned int kappa,
unsigned int num_oldcoins, unsigned int num_oldcoins,
unsigned int num_newcoins, unsigned int num_newcoins,
@ -773,12 +770,35 @@ TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection,
return TALER_MINT_reply_internal_db_error (connection); return TALER_MINT_reply_internal_db_error (connection);
} }
/* Send response immediately if we already know the session. if (GNUNET_OK !=
* Do _not_ care about fields other than session_pub in this case. */ 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, res = TALER_MINT_DB_get_refresh_session (db_conn,
refresh_session_pub, refresh_session_pub,
&refresh_session); &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 (GNUNET_YES == refresh_session.has_commit_sig)
{
TALER_MINT_DB_rollback (db_conn);
res = TALER_MINT_reply_refresh_commit_success (connection,
&refresh_session);
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
}
// FIXME: this should check that kappa and num_newcoins match // FIXME: this should check that kappa and num_newcoins match
// our expectations from refresh_session! // our expectations from refresh_session!
@ -814,47 +834,20 @@ 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);
if ( (GNUNET_YES == res) &&
(GNUNET_YES == refresh_session.has_commit_sig) )
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"sending cached commit response\n");
res = TALER_MINT_reply_refresh_commit_success (connection,
&refresh_session);
GNUNET_break (res != GNUNET_SYSERR);
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
}
if (GNUNET_SYSERR == res)
{
// FIXME: return 'internal error'?
GNUNET_break (0);
return MHD_NO;
}
if (GNUNET_OK != if (GNUNET_OK !=
TALER_MINT_DB_transaction (db_conn)) (res = TALER_MINT_DB_update_refresh_session (db_conn,
refresh_session_pub,
refresh_session.noreveal_index,
commit_client_sig)))
{ {
GNUNET_break (0); TALER_MINT_DB_rollback (db_conn);
return TALER_MINT_reply_internal_db_error (connection); return TALER_MINT_reply_internal_db_error (connection);
} }
/* Re-fetch the session information from the database,
* in case a concurrent transaction modified it. */
res = TALER_MINT_DB_get_refresh_session (db_conn,
refresh_session_pub,
&refresh_session);
if (GNUNET_OK != res)
{
// FIXME: return 'internal error'?
GNUNET_break (GNUNET_SYSERR != res);
TALER_MINT_DB_rollback (db_conn);
return MHD_NO;
}
if (GNUNET_OK != if (GNUNET_OK !=
TALER_MINT_DB_commit (db_conn)) TALER_MINT_DB_commit (db_conn))
@ -943,24 +936,14 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection,
return TALER_MINT_reply_internal_db_error (connection); return TALER_MINT_reply_internal_db_error (connection);
} }
/* Send response immediately if we already know the session,
* and the session commited already.
* Do _not_ care about fields other than session_pub in this case. */
res = TALER_MINT_DB_get_refresh_session (db_conn, res = TALER_MINT_DB_get_refresh_session (db_conn,
refresh_session_pub, refresh_session_pub,
&refresh_session); &refresh_session);
if (GNUNET_YES == res && 0 != refresh_session.reveal_ok) if (GNUNET_NO == res)
return helper_refresh_reveal_send_response (connection, return TALER_MINT_reply_arg_invalid (connection,
db_conn, "session_pub");
&refresh_session,
refresh_session_pub);
if (GNUNET_SYSERR == res) if (GNUNET_SYSERR == res)
{ return TALER_MINT_reply_internal_db_error (connection);
GNUNET_break (0);
// FIXME: return 'internal error'?
return MHD_NO;
}
/* Check that the transfer private keys match their commitments. /* Check that the transfer private keys match their commitments.
* Then derive the shared secret for each kappa, and check that they match. */ * Then derive the shared secret for each kappa, and check that they match. */

View File

@ -91,6 +91,8 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection,
* *
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param refresh_session_pub public key of the refresh session * @param refresh_session_pub public key of the refresh session
* @param client_signature signature of the client (matching @a refresh_session_pub)
* over the melting request
* @param num_new_denoms number of entries in @a denom_pubs * @param num_new_denoms number of entries in @a denom_pubs
* @param denum_pubs array of public denomination keys for the refresh (?) * @param denum_pubs array of public denomination keys for the refresh (?)
* @param coin_count number of entries in @a coin_public_infos * @param coin_count number of entries in @a coin_public_infos
@ -100,6 +102,7 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection,
int int
TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection,
const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub,
const struct GNUNET_CRYPTO_EddsaSignature *client_signature,
unsigned int num_new_denoms, unsigned int num_new_denoms,
struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs, struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs,
unsigned int coin_count, unsigned int coin_count,
@ -115,6 +118,8 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection,
* @a kappa sets of private transfer keys should not be revealed. * @a kappa sets of private transfer keys should not be revealed.
* *
* @param connection the MHD connection to handle * @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 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_oldcoins size of y-dimension of @commit_coin array
* @param num_newcoins size of y-dimension of @commit_link array * @param num_newcoins size of y-dimension of @commit_link array
@ -129,6 +134,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection,
int int
TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection, TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection,
const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub,
const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig,
unsigned int kappa, unsigned int kappa,
unsigned int num_oldcoins, unsigned int num_oldcoins,
unsigned int num_newcoins, unsigned int num_newcoins,

View File

@ -242,8 +242,10 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
"error", "value mismatch"); "error", "value mismatch");
} }
/* FIXME: we must also store the signature over the melt! (#3635) */
return TALER_MINT_db_execute_refresh_melt (connection, return TALER_MINT_db_execute_refresh_melt (connection,
refresh_session_pub, refresh_session_pub,
NULL, /* FIXME: #3635! */
num_new_denoms, num_new_denoms,
denom_pubs, denom_pubs,
coin_count, coin_count,
@ -715,6 +717,7 @@ handle_refresh_commit_json (struct MHD_Connection *connection,
/* FIXME: we must also store the signature! (#3635) */ /* FIXME: we must also store the signature! (#3635) */
res = TALER_MINT_db_execute_refresh_commit (connection, res = TALER_MINT_db_execute_refresh_commit (connection,
refresh_session_pub, refresh_session_pub,
NULL /* FIXME: 3635! */,
kappa, kappa,
num_oldcoins, num_oldcoins,
num_newcoins, num_newcoins,

View File

@ -518,43 +518,37 @@ TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection,
/** /**
* Send a response for "/refresh/melt". * 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.
* *
* @param connection the connection to send the response to * @param connection the connection to send the response to
* @param db_conn the database connection to fetch values from * @param signature the client's signature over the melt request
* @param session_pub the refresh session public key. * @param session_pub the refresh session public key.
* @return a MHD result code * @return a MHD result code
*/ */
int int
TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection,
const struct RefreshSession *session, const struct GNUNET_CRYPTO_EddsaSignature *signature,
const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub) const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub)
{ {
int ret; int ret;
json_t *list;
struct GNUNET_HashContext *hash_context;
struct RefreshMeltResponseSignatureBody body; struct RefreshMeltResponseSignatureBody body;
struct GNUNET_CRYPTO_EddsaSignature sig; struct GNUNET_CRYPTO_EddsaSignature sig;
json_t *sig_json; json_t *sig_json;
list = json_array ();
hash_context = GNUNET_CRYPTO_hash_context_start ();
body.purpose.size = htonl (sizeof (struct RefreshMeltResponseSignatureBody)); body.purpose.size = htonl (sizeof (struct RefreshMeltResponseSignatureBody));
body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_RESPONSE); body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_RESPONSE);
/* FIXME: should we not add something to the hash_context in the meantime? */ body.melt_client_signature = *signature;
GNUNET_CRYPTO_hash_context_finish (hash_context, body.session_key = *session_pub;
&body.melt_response_hash);
TALER_MINT_keys_sign (&body.purpose, TALER_MINT_keys_sign (&body.purpose,
&sig); &sig);
sig_json = TALER_JSON_from_sig (&body.purpose, &sig); sig_json = TALER_JSON_from_sig (&body.purpose, &sig);
GNUNET_assert (NULL != sig_json);
ret = TALER_MINT_reply_json_pack (connection, ret = TALER_MINT_reply_json_pack (connection,
MHD_HTTP_OK, MHD_HTTP_OK,
"{s:o, s:o}", "{s:o}",
"signature", sig_json, "signature", sig_json);
"blind_session_pubs", list);
json_decref (sig_json); json_decref (sig_json);
json_decref (list);
return ret; return ret;
} }
@ -570,7 +564,7 @@ TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection,
*/ */
int int
TALER_MINT_reply_refresh_commit_success (struct MHD_Connection *connection, TALER_MINT_reply_refresh_commit_success (struct MHD_Connection *connection,
struct RefreshSession *refresh_session) const struct RefreshSession *refresh_session)
{ {
struct RefreshCommitResponseSignatureBody body; struct RefreshCommitResponseSignatureBody body;
struct GNUNET_CRYPTO_EddsaSignature sig; struct GNUNET_CRYPTO_EddsaSignature sig;

View File

@ -245,20 +245,22 @@ TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection,
*/ */
int int
TALER_MINT_reply_refresh_commit_success (struct MHD_Connection *connection, TALER_MINT_reply_refresh_commit_success (struct MHD_Connection *connection,
struct RefreshSession *refresh_session); const struct RefreshSession *refresh_session);
/** /**
* Send a response for "/refresh/melt". * 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.
* *
* @param connection the connection to send the response to * @param connection the connection to send the response to
* @param session session data to generate reply from * @param signature the client's signature over the melt request
* @param session_pub the refresh session public key. * @param session_pub the refresh session public key.
* @return a MHD result code * @return a MHD result code
*/ */
int int
TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection,
const struct RefreshSession *session, const struct GNUNET_CRYPTO_EddsaSignature *signature,
const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub); const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub);