combining /mint/melt and /mint/commit
This commit is contained in:
parent
07f18f1660
commit
c2c8646a83
@ -56,29 +56,24 @@
|
|||||||
#define TALER_SIGNATURE_WITHDRAW 4
|
#define TALER_SIGNATURE_WITHDRAW 4
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signature where the refresh session confirms
|
* Signature using a coin key confirming the melting of
|
||||||
* the list of melted coins and requested denominations.
|
* a coin.
|
||||||
*/
|
*/
|
||||||
#define TALER_SIGNATURE_REFRESH_MELT 5
|
#define TALER_SIGNATURE_REFRESH_MELT_COIN 5
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signature where the refresh session confirms
|
* Signature where the refresh session confirms
|
||||||
* the commits.
|
* the commits.
|
||||||
*/
|
*/
|
||||||
#define TALER_SIGNATURE_REFRESH_COMMIT 6
|
#define TALER_SIGNATURE_REFRESH_MELT 6
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signature where the mint (current signing key)
|
* Signature where the mint (current signing key)
|
||||||
* confirms the list of blind session keys.
|
* confirms the no-reveal index for cut-and-choose and
|
||||||
|
* the validity of the melted coins.
|
||||||
*/
|
*/
|
||||||
#define TALER_SIGNATURE_REFRESH_MELT_RESPONSE 7
|
#define TALER_SIGNATURE_REFRESH_MELT_RESPONSE 7
|
||||||
|
|
||||||
/**
|
|
||||||
* Signature where the mint (current signing key)
|
|
||||||
* confirms the no-reveal index for cut-and-choose.
|
|
||||||
*/
|
|
||||||
#define TALER_SIGNATURE_REFRESH_COMMIT_RESPONSE 8
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signature where coins confirm that they want
|
* Signature where coins confirm that they want
|
||||||
* to be melted into a certain session.
|
* to be melted into a certain session.
|
||||||
@ -234,17 +229,21 @@ struct TALER_DepositConfirmation
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format of the block signed by the Mint in response to
|
* Message signed by a coin to indicate that the coin should
|
||||||
* a successful "/refresh/melt" request. Hereby the mint
|
* be melted.
|
||||||
* affirms that all of the coins were successfully melted.
|
|
||||||
*/
|
*/
|
||||||
struct RefreshMeltResponseSignatureBody
|
struct RefreshMeltSignatureBody
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Purpose is #TALER_SIGNATURE_REFRESH_MELT_RESPONSE.
|
* Purpose is #TALER_SIGNATURE_REFRESH_MELT_COIN.
|
||||||
*/
|
*/
|
||||||
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
|
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Which melting operation should the coin become a part of.
|
||||||
|
*/
|
||||||
|
struct GNUNET_HashCode melt_hash;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signature of the client over the melt request (thereby
|
* Signature of the client over the melt request (thereby
|
||||||
* indirectly including all of the information the client
|
* indirectly including all of the information the client
|
||||||
@ -258,30 +257,6 @@ struct RefreshMeltResponseSignatureBody
|
|||||||
*/
|
*/
|
||||||
struct GNUNET_CRYPTO_EddsaPublicKey session_key;
|
struct GNUNET_CRYPTO_EddsaPublicKey session_key;
|
||||||
|
|
||||||
/**
|
|
||||||
* Security parameter requested for the commitments.
|
|
||||||
*/
|
|
||||||
uint32_t kappa GNUNET_PACKED;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Message signed by a coin to indicate that the coin should
|
|
||||||
* be melted.
|
|
||||||
*/
|
|
||||||
struct RefreshMeltSignatureBody
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Purpose is #TALER_SIGNATURE_REFRESH_MELT.
|
|
||||||
*/
|
|
||||||
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Which melting operation should the coin become a part of.
|
|
||||||
*/
|
|
||||||
struct GNUNET_HashCode melt_hash;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How much of the value of the coin should be melted?
|
* How much of the value of the coin should be melted?
|
||||||
* This amount includes the fees, so the final amount contributed
|
* This amount includes the fees, so the final amount contributed
|
||||||
@ -298,7 +273,7 @@ struct RefreshMeltSignatureBody
|
|||||||
struct RefreshCommitSignatureBody
|
struct RefreshCommitSignatureBody
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Purpose is #TALER_SIGNATURE_REFRESH_COMMIT.
|
* Purpose is #TALER_SIGNATURE_REFRESH_MELT.
|
||||||
*/
|
*/
|
||||||
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
|
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
|
||||||
|
|
||||||
@ -310,10 +285,12 @@ struct RefreshCommitSignatureBody
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message signed by the mint, committing it to a particular
|
* Format of the block signed by the Mint in response to a successful
|
||||||
* index to not be revealed during the refresh.
|
* "/refresh/melt" request. Hereby the mint affirms that all of the
|
||||||
|
* coins were successfully melted. This also commits the mint to a
|
||||||
|
* particular index to not be revealed during the refresh.
|
||||||
*/
|
*/
|
||||||
struct RefreshCommitResponseSignatureBody
|
struct RefreshMeltResponseSignatureBody
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Purpose is #TALER_SIGNATURE_REFRESH_MELT_RESPONSE.
|
* Purpose is #TALER_SIGNATURE_REFRESH_MELT_RESPONSE.
|
||||||
|
@ -1417,11 +1417,6 @@ TALER_MINT_DB_get_refresh_session (PGconn *db_conn,
|
|||||||
return GNUNET_SYSERR;
|
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_oldcoins = ntohs (session->num_oldcoins);
|
||||||
session->num_newcoins = ntohs (session->num_newcoins);
|
session->num_newcoins = ntohs (session->num_newcoins);
|
||||||
session->kappa = ntohs (session->kappa);
|
session->kappa = ntohs (session->kappa);
|
||||||
@ -1471,28 +1466,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.
|
* Store the given /refresh/melt request in the database.
|
||||||
*
|
*
|
||||||
|
@ -474,17 +474,10 @@ struct RefreshSession
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Index (smaller @e kappa) which the mint has chosen to not
|
* Index (smaller @e kappa) which the mint has chosen to not
|
||||||
* have revealed during cut and choose. Only valid if
|
* have revealed during cut and choose.
|
||||||
* @e has_commit_sig is set to #GNUNET_YES.
|
|
||||||
*/
|
*/
|
||||||
uint16_t noreveal_index;
|
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;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -519,24 +512,6 @@ TALER_MINT_DB_create_refresh_session (PGconn *db_conn,
|
|||||||
const struct RefreshSession *session);
|
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.
|
* Specification for coin in a /refresh/melt operation.
|
||||||
*/
|
*/
|
||||||
|
@ -152,12 +152,6 @@ handle_mhd_request (void *cls,
|
|||||||
{ "/refresh/melt", NULL, "text/plain",
|
{ "/refresh/melt", NULL, "text/plain",
|
||||||
"Only POST is allowed", 0,
|
"Only POST is allowed", 0,
|
||||||
&TALER_MINT_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
|
&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",
|
{ "/refresh/reveal", MHD_HTTP_METHOD_POST, "application/json",
|
||||||
NULL, 0,
|
NULL, 0,
|
||||||
&TALER_MINT_handler_refresh_melt, MHD_HTTP_OK },
|
&TALER_MINT_handler_refresh_melt, MHD_HTTP_OK },
|
||||||
|
@ -151,7 +151,7 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection,
|
|||||||
if (0 < TALER_amount_cmp (spent, value))
|
if (0 < TALER_amount_cmp (spent, value))
|
||||||
{
|
{
|
||||||
TALER_MINT_DB_rollback (db_conn);
|
TALER_MINT_DB_rollback (db_conn);
|
||||||
ret = TALER_MINT_reply_insufficient_funds (connection,
|
ret = TALER_MINT_reply_deposit_insufficient_funds (connection,
|
||||||
tl);
|
tl);
|
||||||
TALER_MINT_DB_free_coin_transaction_list (tl);
|
TALER_MINT_DB_free_coin_transaction_list (tl);
|
||||||
return ret;
|
return ret;
|
||||||
@ -435,8 +435,10 @@ refresh_accept_melts (struct MHD_Connection *connection,
|
|||||||
{
|
{
|
||||||
struct TALER_MINT_DenomKeyIssue *dki;
|
struct TALER_MINT_DenomKeyIssue *dki;
|
||||||
struct TALER_MINT_DB_TransactionList *tl;
|
struct TALER_MINT_DB_TransactionList *tl;
|
||||||
struct TALER_Amount coin_gain;
|
struct TALER_Amount coin_value;
|
||||||
|
struct TALER_Amount coin_residual;
|
||||||
struct RefreshMelt melt;
|
struct RefreshMelt melt;
|
||||||
|
int res;
|
||||||
|
|
||||||
dki = &TALER_MINT_get_denom_key (key_state,
|
dki = &TALER_MINT_get_denom_key (key_state,
|
||||||
coin_public_info->denom_pub)->issue;
|
coin_public_info->denom_pub)->issue;
|
||||||
@ -450,25 +452,30 @@ refresh_accept_melts (struct MHD_Connection *connection,
|
|||||||
"denom not found"))
|
"denom not found"))
|
||||||
? GNUNET_NO : GNUNET_SYSERR;
|
? 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,
|
tl = TALER_MINT_DB_get_coin_transactions (db_conn,
|
||||||
&coin_public_info->coin_pub);
|
&coin_public_info->coin_pub);
|
||||||
/* FIXME: #3636: compute how much value is left with this coin and
|
/* FIXME: #3636: compute how much value is left with this coin and
|
||||||
compare to `expected_value`! (subtract from "coin_gain") */
|
compare to `expected_value`! (subtract from "coin_value") */
|
||||||
TALER_MINT_DB_free_coin_transaction_list (tl);
|
coin_residual = coin_value;
|
||||||
|
|
||||||
/* Refuse to refresh when the coin does not have enough money left to
|
/* Refuse to refresh when the coin does not have enough money left to
|
||||||
* pay the refreshing fees of the coin. */
|
* pay the refreshing fees of the coin. */
|
||||||
|
|
||||||
if (TALER_amount_cmp (coin_gain,
|
if (TALER_amount_cmp (coin_residual,
|
||||||
coin_details->melt_amount) < 0)
|
coin_details->melt_amount) < 0)
|
||||||
return (MHD_YES ==
|
{
|
||||||
TALER_MINT_reply_json_pack (connection,
|
res = (MHD_YES ==
|
||||||
MHD_HTTP_NOT_FOUND,
|
TALER_MINT_reply_refresh_melt_insufficient_funds (connection,
|
||||||
"{s:s}",
|
&coin_public_info->coin_pub,
|
||||||
"error", "depleted")) ? GNUNET_NO : GNUNET_SYSERR;
|
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 = *coin_public_info;
|
||||||
melt.coin_sig = coin_details->melt_sig;
|
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
|
* required value left and if so, store that they have been
|
||||||
* melted and confirm the melting operation to the client.
|
* melted and confirm the melting operation to the client.
|
||||||
*
|
*
|
||||||
|
* FIXME: some arguments are redundant here...
|
||||||
|
*
|
||||||
* @param connection the MHD connection to handle
|
* @param connection the MHD connection to handle
|
||||||
* @param melt_hash hash code of the session the coins are melted into
|
* @param melt_hash hash code of the session the coins are melted into
|
||||||
* @param refresh_session_pub public key of the refresh session
|
* @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_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_public_infos information about the coins to melt
|
||||||
* @param coin_melt_details signatures and (residual) value of the respective coin should be melted
|
* @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
|
* @return MHD result code
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
@ -515,13 +533,20 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection,
|
|||||||
struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs,
|
struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs,
|
||||||
unsigned int coin_count,
|
unsigned int coin_count,
|
||||||
const struct TALER_CoinPublicInfo *coin_public_infos,
|
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 MintKeyState *key_state;
|
||||||
struct RefreshSession session;
|
struct RefreshSession session;
|
||||||
PGconn *db_conn;
|
PGconn *db_conn;
|
||||||
int res;
|
int res;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
unsigned int j;
|
||||||
|
|
||||||
if (NULL == (db_conn = TALER_MINT_DB_get_connection (GNUNET_NO)))
|
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)
|
if (GNUNET_YES == res)
|
||||||
{
|
{
|
||||||
TALER_MINT_DB_rollback (db_conn);
|
TALER_MINT_DB_rollback (db_conn);
|
||||||
return TALER_MINT_reply_refresh_melt_success (connection,
|
res = TALER_MINT_reply_refresh_melt_success (connection,
|
||||||
&session.melt_sig,
|
&session.session_hash,
|
||||||
refresh_session_pub,
|
session.noreveal_index);
|
||||||
session.kappa);
|
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
|
||||||
}
|
}
|
||||||
if (GNUNET_SYSERR == res)
|
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 (i = 0; i < kappa; i++)
|
||||||
{
|
{
|
||||||
for (j = 0; j < num_newcoins; j++)
|
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 !=
|
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_pub,
|
||||||
refresh_session.noreveal_index,
|
&session)))
|
||||||
commit_client_sig)))
|
|
||||||
{
|
{
|
||||||
TALER_MINT_DB_rollback (db_conn);
|
TALER_MINT_DB_rollback (db_conn);
|
||||||
return TALER_MINT_reply_internal_db_error (connection);
|
return TALER_MINT_reply_internal_db_error (connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
TALER_MINT_DB_commit (db_conn))
|
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_commit_error (connection);
|
||||||
}
|
}
|
||||||
|
return TALER_MINT_reply_refresh_melt_success (connection,
|
||||||
return TALER_MINT_reply_refresh_commit_success (connection,
|
&session.session_hash,
|
||||||
&refresh_session.session_hash,
|
session.noreveal_index);
|
||||||
refresh_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);
|
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 *
|
melts = GNUNET_malloc (refresh_session.num_oldcoins *
|
||||||
sizeof (struct RefreshMelt));
|
sizeof (struct RefreshMelt));
|
||||||
for (j=0;j<refresh_session.num_oldcoins;j++)
|
for (j=0;j<refresh_session.num_oldcoins;j++)
|
||||||
|
@ -107,6 +107,8 @@ struct MeltDetails
|
|||||||
* required value left and if so, store that they have been
|
* required value left and if so, store that they have been
|
||||||
* melted and confirm the melting operation to the client.
|
* melted and confirm the melting operation to the client.
|
||||||
*
|
*
|
||||||
|
* FIXME: some arguments are redundant here...
|
||||||
|
*
|
||||||
* @param connection the MHD connection to handle
|
* @param connection the MHD connection to handle
|
||||||
* @param melt_hash hash code of the session the coins are melted into
|
* @param melt_hash hash code of the session the coins are melted into
|
||||||
* @param refresh_session_pub public key of the refresh session
|
* @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_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_public_infos information about the coins to melt
|
||||||
* @param coin_melt_details signatures and (residual) value of the respective coin should be melted
|
* @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 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
|
||||||
@ -154,14 +132,21 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection,
|
|||||||
*/
|
*/
|
||||||
// FIXME: see #3635.
|
// FIXME: see #3635.
|
||||||
int
|
int
|
||||||
TALER_MINT_db_execute_refresh_commit (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_HashCode *melt_hash,
|
||||||
const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig,
|
const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub,
|
||||||
unsigned int kappa,
|
const struct GNUNET_CRYPTO_EddsaSignature *client_signature,
|
||||||
unsigned int num_oldcoins,
|
unsigned int num_new_denoms,
|
||||||
unsigned int num_newcoins,
|
struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs,
|
||||||
struct RefreshCommitCoin *const* commit_coin,
|
unsigned int coin_count,
|
||||||
struct RefreshCommitLink *const* commit_link);
|
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);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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_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 coin_melt_details array with @a coin_count entries with melting details
|
||||||
* @param melt_sig_json signature affirming the overall melt operation
|
* @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
|
* @return MHD result code
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@ -161,7 +170,14 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
|
|||||||
unsigned int coin_count,
|
unsigned int coin_count,
|
||||||
struct TALER_CoinPublicInfo *coin_public_infos,
|
struct TALER_CoinPublicInfo *coin_public_infos,
|
||||||
const struct MeltDetails *coin_melt_details,
|
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;
|
int res;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
@ -256,7 +272,13 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
|
|||||||
denom_pubs,
|
denom_pubs,
|
||||||
coin_count,
|
coin_count,
|
||||||
coin_public_infos,
|
coin_public_infos,
|
||||||
coin_melt_details);
|
coin_melt_details,
|
||||||
|
NULL /* FIXME: 3635! */,
|
||||||
|
kappa,
|
||||||
|
num_oldcoins,
|
||||||
|
num_newcoins,
|
||||||
|
commit_coin,
|
||||||
|
commit_link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -363,168 +385,6 @@ get_and_verify_coin_public_info (struct MHD_Connection *connection,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
* parses the JSON arrays and then passes processing on to
|
|
||||||
* #handle_refresh_melt_binary().
|
|
||||||
*
|
|
||||||
* @param connection the MHD connection to handle
|
|
||||||
* @param refresh_session_pub public key of the melt operation
|
|
||||||
* @param new_denoms array of denomination keys
|
|
||||||
* @param melt_coins array of coins to melt
|
|
||||||
* @param melt_sig_json signature affirming the melt operation
|
|
||||||
* @return MHD result code
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
unsigned int i;
|
|
||||||
unsigned int j;
|
|
||||||
struct GNUNET_CRYPTO_rsa_PublicKey **denom_pubs;
|
|
||||||
unsigned int num_new_denoms;
|
|
||||||
struct TALER_CoinPublicInfo *coin_public_infos;
|
|
||||||
struct MeltDetails *coin_melt_details;
|
|
||||||
unsigned int coin_count;
|
|
||||||
|
|
||||||
num_new_denoms = json_array_size (new_denoms);
|
|
||||||
denom_pubs = GNUNET_malloc (num_new_denoms *
|
|
||||||
sizeof (struct GNUNET_CRYPTO_rsa_PublicKey *));
|
|
||||||
for (i=0;i<num_new_denoms;i++)
|
|
||||||
{
|
|
||||||
res = GNUNET_MINT_parse_navigate_json (connection, new_denoms,
|
|
||||||
JNAV_INDEX, (int) i,
|
|
||||||
JNAV_RET_RSA_PUBLIC_KEY, &denom_pubs[i]);
|
|
||||||
if (GNUNET_OK != res)
|
|
||||||
{
|
|
||||||
for (j=0;j<i;j++)
|
|
||||||
GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j]);
|
|
||||||
GNUNET_free (denom_pubs);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
coin_count = json_array_size (melt_coins);
|
|
||||||
/* FIXME: make 'struct TALER_CoinPublicInfo' part of `struct MeltDetails`
|
|
||||||
and combine these two arrays/arguments! */
|
|
||||||
coin_public_infos = GNUNET_malloc (coin_count *
|
|
||||||
sizeof (struct TALER_CoinPublicInfo));
|
|
||||||
coin_melt_details = GNUNET_malloc (coin_count *
|
|
||||||
sizeof (struct MeltDetails));
|
|
||||||
for (i=0;i<coin_count;i++)
|
|
||||||
{
|
|
||||||
/* decode JSON data on coin to melt */
|
|
||||||
res = get_and_verify_coin_public_info (connection,
|
|
||||||
refresh_session_pub,
|
|
||||||
json_array_get (melt_coins, i),
|
|
||||||
&coin_public_infos[i],
|
|
||||||
&coin_melt_details[i]);
|
|
||||||
if (GNUNET_OK != res)
|
|
||||||
{
|
|
||||||
for (j=0;j<i;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 (GNUNET_NO == res) ? MHD_YES : MHD_NO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
* Release memory from the @a commit_coin array.
|
||||||
*
|
*
|
||||||
@ -577,14 +437,18 @@ free_commit_links (struct RefreshCommitLink **commit_link,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a "/refresh/commit" request. We have the individual JSON
|
* Handle a "/refresh/melt" request after the first parsing has happened.
|
||||||
* arrays, now we need to parse their contents and verify the
|
* We now need to validate the coins being melted and the session signature
|
||||||
* commit signature. Then we can commit the data to the database.
|
* and then hand things of to execute the melt operation. This function
|
||||||
|
* parses the JSON arrays and then passes processing on to
|
||||||
|
* #handle_refresh_melt_binary().
|
||||||
*
|
*
|
||||||
* @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 melt operation
|
||||||
|
* @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 commit_signature signature over the commit
|
||||||
* @param kappa security parameter for cut and choose
|
* @param kappa security parameter for cut and choose
|
||||||
* @param num_oldcoins number of coins that are being melted
|
* @param num_oldcoins number of coins that are being melted
|
||||||
@ -596,25 +460,83 @@ free_commit_links (struct RefreshCommitLink **commit_link,
|
|||||||
* @return MHD result code
|
* @return MHD result code
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
handle_refresh_commit_json (struct MHD_Connection *connection,
|
handle_refresh_melt_json (struct MHD_Connection *connection,
|
||||||
const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub,
|
const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub,
|
||||||
const json_t *commit_signature,
|
const json_t *new_denoms,
|
||||||
unsigned int kappa,
|
const json_t *melt_coins,
|
||||||
unsigned int num_oldcoins,
|
const json_t *melt_sig_json,
|
||||||
const json_t *transfer_pubs,
|
const json_t *commit_signature,
|
||||||
const json_t *secret_encs,
|
unsigned int kappa,
|
||||||
unsigned int num_newcoins,
|
unsigned int num_oldcoins,
|
||||||
const json_t *coin_evs,
|
const json_t *transfer_pubs,
|
||||||
const json_t *link_encs)
|
const json_t *secret_encs,
|
||||||
|
unsigned int num_newcoins,
|
||||||
|
const json_t *coin_evs,
|
||||||
|
const json_t *link_encs)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
int res;
|
||||||
|
unsigned int i;
|
||||||
|
unsigned int j;
|
||||||
|
struct GNUNET_CRYPTO_rsa_PublicKey **denom_pubs;
|
||||||
|
unsigned int num_new_denoms;
|
||||||
|
struct TALER_CoinPublicInfo *coin_public_infos;
|
||||||
|
struct MeltDetails *coin_melt_details;
|
||||||
|
unsigned int coin_count;
|
||||||
struct GNUNET_HashCode commit_hash;
|
struct GNUNET_HashCode commit_hash;
|
||||||
struct GNUNET_HashContext *hash_context;
|
struct GNUNET_HashContext *hash_context;
|
||||||
struct RefreshCommitSignatureBody body;
|
struct RefreshCommitSignatureBody body;
|
||||||
struct RefreshCommitCoin *commit_coin[kappa];
|
struct RefreshCommitCoin *commit_coin[kappa];
|
||||||
struct RefreshCommitLink *commit_link[kappa];
|
struct RefreshCommitLink *commit_link[kappa];
|
||||||
unsigned int i;
|
|
||||||
unsigned int j;
|
num_new_denoms = json_array_size (new_denoms);
|
||||||
int res;
|
denom_pubs = GNUNET_malloc (num_new_denoms *
|
||||||
|
sizeof (struct GNUNET_CRYPTO_rsa_PublicKey *));
|
||||||
|
for (i=0;i<num_new_denoms;i++)
|
||||||
|
{
|
||||||
|
res = GNUNET_MINT_parse_navigate_json (connection, new_denoms,
|
||||||
|
JNAV_INDEX, (int) i,
|
||||||
|
JNAV_RET_RSA_PUBLIC_KEY, &denom_pubs[i]);
|
||||||
|
if (GNUNET_OK != res)
|
||||||
|
{
|
||||||
|
for (j=0;j<i;j++)
|
||||||
|
GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j]);
|
||||||
|
GNUNET_free (denom_pubs);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
coin_count = json_array_size (melt_coins);
|
||||||
|
/* FIXME: make 'struct TALER_CoinPublicInfo' part of `struct MeltDetails`
|
||||||
|
and combine these two arrays/arguments! */
|
||||||
|
coin_public_infos = GNUNET_malloc (coin_count *
|
||||||
|
sizeof (struct TALER_CoinPublicInfo));
|
||||||
|
coin_melt_details = GNUNET_malloc (coin_count *
|
||||||
|
sizeof (struct MeltDetails));
|
||||||
|
for (i=0;i<coin_count;i++)
|
||||||
|
{
|
||||||
|
/* decode JSON data on coin to melt */
|
||||||
|
res = get_and_verify_coin_public_info (connection,
|
||||||
|
refresh_session_pub,
|
||||||
|
json_array_get (melt_coins, i),
|
||||||
|
&coin_public_infos[i],
|
||||||
|
&coin_melt_details[i]);
|
||||||
|
if (GNUNET_OK != res)
|
||||||
|
{
|
||||||
|
for (j=0;j<i;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 (GNUNET_NO == res) ? MHD_YES : MHD_NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* parse JSON arrays into 2d binary arrays and hash everything
|
/* parse JSON arrays into 2d binary arrays and hash everything
|
||||||
together for the signature check */
|
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);
|
GNUNET_CRYPTO_hash_context_finish (hash_context, &commit_hash);
|
||||||
|
|
||||||
/* verify commit signature */
|
/* 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.purpose.size = htonl (sizeof (struct RefreshCommitSignatureBody));
|
||||||
body.commit_hash = commit_hash;
|
body.commit_hash = commit_hash;
|
||||||
|
|
||||||
@ -738,29 +660,43 @@ handle_refresh_commit_json (struct MHD_Connection *connection,
|
|||||||
|
|
||||||
/* execute commit */
|
/* execute commit */
|
||||||
/* 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 = handle_refresh_melt_binary (connection,
|
||||||
refresh_session_pub,
|
refresh_session_pub,
|
||||||
NULL /* FIXME: 3635! */,
|
num_new_denoms,
|
||||||
kappa,
|
denom_pubs,
|
||||||
num_oldcoins,
|
coin_count,
|
||||||
num_newcoins,
|
coin_public_infos,
|
||||||
commit_coin,
|
coin_melt_details,
|
||||||
commit_link);
|
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_coins (commit_coin, kappa, num_newcoins);
|
||||||
free_commit_links (commit_link, kappa, num_oldcoins);
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a "/refresh/commit" request. Parses the top-level JSON to
|
* Handle a "/refresh/melt" request. Parses the request into the JSON
|
||||||
* determine the dimensions of the problem and then handles handing
|
* components and then hands things of to #handle_referesh_melt_json()
|
||||||
* off to #handle_refresh_commit_json() to parse the details of the
|
* to validate the melted coins, the signature and execute the melt
|
||||||
* JSON arguments. Once the signature has been verified, the
|
* using TALER_MINT_db_execute_refresh_melt().
|
||||||
* commit data is written to the database via
|
|
||||||
* #TALER_MINT_db_execute_refresh_commit() and the reveal parameter
|
|
||||||
* is then returned to the client.
|
|
||||||
*
|
*
|
||||||
* @param rh context of the handler
|
* @param rh context of the handler
|
||||||
* @param connection the MHD connection to handle
|
* @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 upload_data upload data
|
||||||
* @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
|
* @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
|
||||||
* @return MHD result code
|
* @return MHD result code
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
TALER_MINT_handler_refresh_commit (struct RequestHandler *rh,
|
TALER_MINT_handler_refresh_melt (struct RequestHandler *rh,
|
||||||
struct MHD_Connection *connection,
|
struct MHD_Connection *connection,
|
||||||
void **connection_cls,
|
void **connection_cls,
|
||||||
const char *upload_data,
|
const char *upload_data,
|
||||||
size_t *upload_data_size)
|
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 *root;
|
||||||
|
json_t *new_denoms;
|
||||||
|
json_t *melt_coins;
|
||||||
|
json_t *melt_sig_json;
|
||||||
json_t *coin_evs;
|
json_t *coin_evs;
|
||||||
json_t *link_encs;
|
json_t *link_encs;
|
||||||
json_t *transfer_pubs;
|
json_t *transfer_pubs;
|
||||||
json_t *secret_encs;
|
json_t *secret_encs;
|
||||||
json_t *coin_detail;
|
|
||||||
json_t *commit_sig_json;
|
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[] = {
|
struct GNUNET_MINT_ParseFieldSpec spec[] = {
|
||||||
TALER_MINT_PARSE_FIXED ("session_pub", &refresh_session_pub),
|
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 ("coin_evs", &coin_evs),
|
||||||
TALER_MINT_PARSE_ARRAY ("link_encs", &link_encs),
|
TALER_MINT_PARSE_ARRAY ("link_encs", &link_encs),
|
||||||
TALER_MINT_PARSE_ARRAY ("transfer_pubs", &transfer_pubs),
|
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;
|
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
|
||||||
}
|
}
|
||||||
num_oldcoins = json_array_size (coin_detail);
|
num_oldcoins = json_array_size (coin_detail);
|
||||||
res = handle_refresh_commit_json (connection,
|
|
||||||
&refresh_session_pub,
|
res = handle_refresh_melt_json (connection,
|
||||||
commit_sig_json,
|
&refresh_session_pub,
|
||||||
kappa,
|
new_denoms,
|
||||||
num_oldcoins,
|
melt_coins,
|
||||||
transfer_pubs,
|
melt_sig_json,
|
||||||
secret_encs,
|
commit_sig_json,
|
||||||
num_newcoins,
|
kappa,
|
||||||
coin_evs,
|
num_oldcoins,
|
||||||
link_encs);
|
transfer_pubs,
|
||||||
|
secret_encs,
|
||||||
|
num_newcoins,
|
||||||
|
coin_evs,
|
||||||
|
link_encs);
|
||||||
|
|
||||||
TALER_MINT_release_parsed_data (spec);
|
TALER_MINT_release_parsed_data (spec);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -931,7 +878,7 @@ handle_refresh_reveal_json (struct MHD_Connection *connection,
|
|||||||
/**
|
/**
|
||||||
* Handle a "/refresh/reveal" request. This time, the client reveals
|
* Handle a "/refresh/reveal" request. This time, the client reveals
|
||||||
* the private transfer keys except for the cut-and-choose value
|
* 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
|
* keys and secrets and ultimately passes everything to
|
||||||
* #TALER_MINT_db_execute_refresh_reveal() which will verify that the
|
* #TALER_MINT_db_execute_refresh_reveal() which will verify that the
|
||||||
* revealed information is valid then returns the signed refreshed
|
* revealed information is valid then returns the signed refreshed
|
||||||
|
@ -49,30 +49,6 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh,
|
|||||||
size_t *upload_data_size);
|
size_t *upload_data_size);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
* Handle a "/refresh/reveal" request. This time, the client reveals
|
||||||
* the private transfer keys except for the cut-and-choose value
|
* the private transfer keys except for the cut-and-choose value
|
||||||
|
@ -315,27 +315,20 @@ TALER_MINT_reply_deposit_success (struct MHD_Connection *connection,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send proof that a /deposit, /refresh/melt or /lock request is
|
* Compile the transaction history of a coin into a JSON object.
|
||||||
* 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 history to JSON-ify
|
||||||
* @param tl transaction list to use to build reply
|
* @return json representation of the @a rh
|
||||||
* @return MHD result code
|
|
||||||
*/
|
*/
|
||||||
int
|
static json_t *
|
||||||
TALER_MINT_reply_insufficient_funds (struct MHD_Connection *connection,
|
compile_transaction_history (const struct TALER_MINT_DB_TransactionList *tl)
|
||||||
const struct TALER_MINT_DB_TransactionList *tl)
|
|
||||||
{
|
{
|
||||||
const struct TALER_MINT_DB_TransactionList *pos;
|
|
||||||
int ret;
|
|
||||||
json_t *history;
|
|
||||||
json_t *transaction;
|
json_t *transaction;
|
||||||
const char *type;
|
const char *type;
|
||||||
struct TALER_Amount value;
|
struct TALER_Amount value;
|
||||||
|
json_t *history;
|
||||||
|
const struct TALER_MINT_DB_TransactionList *pos;
|
||||||
|
|
||||||
history = json_array ();
|
history = json_array ();
|
||||||
for (pos = tl; NULL != pos; pos = pos->next)
|
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),
|
"amount", TALER_JSON_from_amount (value),
|
||||||
"signature", transaction));
|
"signature", transaction));
|
||||||
}
|
}
|
||||||
|
return history;
|
||||||
|
}
|
||||||
|
|
||||||
ret = TALER_MINT_reply_json_pack (connection,
|
|
||||||
MHD_HTTP_FORBIDDEN,
|
/**
|
||||||
"{s:s, s:o}",
|
* Send proof that a /withdraw request is invalid to client. This
|
||||||
"error", "insufficient funds",
|
* function will create a message with all of the operations affecting
|
||||||
"history", history);
|
* the coin that demonstrate that the coin has insufficient value.
|
||||||
return ret;
|
*
|
||||||
|
* @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
|
* Send a response for a failed "/refresh/melt" request. The
|
||||||
* over the client's signature and public key, thereby
|
* transaction history of the given coin demonstrates that the
|
||||||
* demonstrating that we accepted all of the client's coins.
|
* @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 connection the connection to send the response to
|
||||||
* @param signature the client's signature over the melt request
|
* @param coin_pub public key of the coin
|
||||||
* @param session_pub the refresh session public key.
|
* @param coin_value original value of the coin
|
||||||
* @param kappa security parameter to use for cut and choose
|
* @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
|
* @return a MHD result code
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection,
|
TALER_MINT_reply_refresh_melt_insufficient_funds (struct MHD_Connection *connection,
|
||||||
const struct GNUNET_CRYPTO_EddsaSignature *signature,
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub,
|
||||||
const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
|
struct TALER_Amount coin_value,
|
||||||
unsigned int kappa)
|
struct TALER_MINT_DB_TransactionList *tl,
|
||||||
|
struct TALER_Amount requested,
|
||||||
|
struct TALER_Amount residual)
|
||||||
{
|
{
|
||||||
int ret;
|
json_t *history;
|
||||||
struct RefreshMeltResponseSignatureBody body;
|
|
||||||
struct GNUNET_CRYPTO_EddsaSignature sig;
|
|
||||||
json_t *sig_json;
|
|
||||||
|
|
||||||
body.purpose.size = htonl (sizeof (struct RefreshMeltResponseSignatureBody));
|
history = compile_transaction_history (tl);
|
||||||
body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_RESPONSE);
|
return TALER_MINT_reply_json_pack (connection,
|
||||||
body.melt_client_signature = *signature;
|
MHD_HTTP_NOT_FOUND,
|
||||||
body.session_key = *session_pub;
|
"{s:s, s:o, s:o, s:o, s:o, s:o}",
|
||||||
body.kappa = htonl (kappa);
|
"error", "insufficient funds",
|
||||||
TALER_MINT_keys_sign (&body.purpose,
|
"coin-pub", TALER_JSON_from_data (coin_pub,
|
||||||
&sig);
|
sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)),
|
||||||
sig_json = TALER_JSON_from_eddsa_sig (&body.purpose, &sig);
|
"original-value", TALER_JSON_from_amount (coin_value),
|
||||||
ret = TALER_MINT_reply_json_pack (connection,
|
"residual-value", TALER_JSON_from_amount (residual),
|
||||||
MHD_HTTP_OK,
|
"requested-value", TALER_JSON_from_amount (requested),
|
||||||
"{s:o, s:i}",
|
"history", history);
|
||||||
"signature", sig_json,
|
|
||||||
"kappa", (int) kappa);
|
|
||||||
json_decref (sig_json);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 connection the connection to send the response to
|
||||||
* @param session_hash hash of the refresh session
|
* @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
|
* @return a MHD status code
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
TALER_MINT_reply_refresh_commit_success (struct MHD_Connection *connection,
|
TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection,
|
||||||
const struct GNUNET_HashCode *session_hash,
|
const struct GNUNET_HashCode *session_hash,
|
||||||
uint16_t noreveal_index)
|
uint16_t noreveal_index)
|
||||||
{
|
{
|
||||||
struct RefreshCommitResponseSignatureBody body;
|
struct RefreshMeltResponseSignatureBody body;
|
||||||
struct GNUNET_CRYPTO_EddsaSignature sig;
|
struct GNUNET_CRYPTO_EddsaSignature sig;
|
||||||
json_t *sig_json;
|
json_t *sig_json;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
body.purpose.size = htonl (sizeof (struct RefreshCommitResponseSignatureBody));
|
body.purpose.size = htonl (sizeof (struct RefreshMeltResponseSignatureBody));
|
||||||
body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_COMMIT_RESPONSE);
|
body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_RESPONSE);
|
||||||
body.session_hash = *session_hash;
|
body.session_hash = *session_hash;
|
||||||
body.noreveal_index = htons (noreveal_index);
|
body.noreveal_index = htons (noreveal_index);
|
||||||
TALER_MINT_keys_sign (&body.purpose,
|
TALER_MINT_keys_sign (&body.purpose,
|
||||||
|
@ -194,18 +194,17 @@ TALER_MINT_reply_deposit_success (struct MHD_Connection *connection,
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send proof that a /deposit, /refresh/melt or /lock request is
|
* Send proof that a /deposit request is invalid to client. This
|
||||||
* invalid to client. This function will create a message with all of
|
* function will create a message with all of the operations affecting
|
||||||
* the operations affecting the coin that demonstrate that the coin
|
* the coin that demonstrate that the coin has insufficient value.
|
||||||
* has insufficient value.
|
|
||||||
*
|
*
|
||||||
* @param connection connection to the client
|
* @param connection connection to the client
|
||||||
* @param tl transaction list to use to build reply
|
* @param tl transaction list to use to build reply
|
||||||
* @return MHD result code
|
* @return MHD result code
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
TALER_MINT_reply_insufficient_funds (struct MHD_Connection *connection,
|
TALER_MINT_reply_deposit_insufficient_funds (struct MHD_Connection *connection,
|
||||||
const struct TALER_MINT_DB_TransactionList *tl);
|
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 connection the connection to send the response to
|
||||||
* @param session_hash hash of the refresh session
|
* @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
|
* @return a MHD status code
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
TALER_MINT_reply_refresh_commit_success (struct MHD_Connection *connection,
|
TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection,
|
||||||
const struct GNUNET_HashCode *session_hash,
|
const struct GNUNET_HashCode *session_hash,
|
||||||
uint16_t noreveal_index);
|
uint16_t noreveal_index);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a response for "/refresh/melt". Essentially we sign
|
* Send a response for a failed "/refresh/melt" request. The
|
||||||
* over the client's signature and public key, thereby
|
* transaction history of the given coin demonstrates that the
|
||||||
* demonstrating that we accepted all of the client's coins.
|
* @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 connection the connection to send the response to
|
||||||
* @param signature the client's signature over the melt request
|
* @param coin_pub public key of the coin
|
||||||
* @param session_pub the refresh session public key.
|
* @param coin_value original value of the coin
|
||||||
* @param kappa security parameter to use for cut and choose
|
* @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
|
* @return a MHD result code
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection,
|
TALER_MINT_reply_refresh_melt_insufficient_funds (struct MHD_Connection *connection,
|
||||||
const struct GNUNET_CRYPTO_EddsaSignature *signature,
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub,
|
||||||
const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
|
struct TALER_Amount coin_value,
|
||||||
unsigned int kappa);
|
struct TALER_MINT_DB_TransactionList *tl,
|
||||||
|
struct TALER_Amount requested,
|
||||||
|
struct TALER_Amount residual);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user