-minor merge conflict resolves

This commit is contained in:
Özgür Kesim 2022-02-18 00:44:55 +01:00
commit f4f502d037
Signed by: oec
GPG Key ID: 3D76A56D79EDD9D7
59 changed files with 1721 additions and 1060 deletions

View File

@ -169,12 +169,14 @@ The denomination key was chosen because it has the recopu protocol in place that
\\ & & b := \text{HKDF}(1,n_w || d_s, \text{"b"})
\\ & & s \leftarrow \text{GetWithdraw}(n_w, D_p)
\\ & & \textbf{if } s = \bot
\\ & & \textbf{check !} \text{NonceReuse} (n_w, D_p)
\\ & & r_b := \text{HKDF}(256,n_w || d_s, \text{"r}b\text{"})
% sign coin
\\ & & s := r_b + c_b d_s \mod p
% the following db operations are atomic
\\ & & \text{decrease balance if sufficient and}
\\ & & \text{persist } \langle n_w, D_p, s \rangle
\\ & & \text{persist NonceUse } \langle n_w, D_p, s \rangle
\\ & & \text{persist } \langle D_p, s \rangle
\\ & & \textbf{endif}
\\ & \xleftarrow[\rule{2.5cm}{0pt}]{b,s} &
% verify signature
@ -187,7 +189,6 @@ The denomination key was chosen because it has the recopu protocol in place that
\\ \textbf{check if } s'G = R'_b + c'_b D_p & &
\\ \sigma_C := \langle R'_b, s' \rangle & &
\\ \text{resulting coin: } c_s, C_p, \sigma_C, D_p & &
\end{array}$
}
\end{equation*}
@ -287,9 +288,9 @@ In the reveal phase, the RSA signing and unblinding is exchanged with Schnorr's
\\ h_T := H(T_1, \dots, T_k)
\\ h_{\overline{c_0}} := H(\overline{c_{0_1}},\dots, \overline{c}_{0_k})
\\ h_{\overline{c_1}} := H(\overline{c_{1_1}},\dots, \overline{c}_{1_k})
\\ h_{\overline{c}} := H(h_{\overline{c_0}}, h_{\overline{c_1}})
\\ h_{\overline{c}} := H(h_{\overline{c_0}}, h_{\overline{c_1}}, n_r)
\\ h_C := H(h_T, h_{\overline{c}})
\\ \rho_{RC} := \langle h_C, D_p, \text{ } D_{p(0)}, C_p^{(0)}, \sigma_C^{(0)} \rangle
\\ \rho_{RC} := \langle h_C, D_p, \text{ } D_{p(0)}, C_p^{(0)}, \sigma_C^{(0)} \rangle
\\ \sigma_{RC} := \text{Ed25519.Sign}(c_s^{(0)}, \rho_{RC})
\\ \text{Persist refresh-request}
\\ \langle \omega, R_0, R_1, \rho_{RC}, \sigma_{RC} \rangle
@ -311,7 +312,7 @@ In the reveal phase, the RSA signing and unblinding is exchanged with Schnorr's
\\ & \textit{Continuation of}
\\ & \textit{figure \ref{fig:refresh-commit-part1}}
\\
\\ & \xrightarrow[\rule{2cm}{0pt}]{\rho_{RC}, \sigma_{RC}} &
\\ & \xrightarrow[\rule{2cm}{0pt}]{\rho_{RC}, \sigma_{RC}, n_r} &
% Exchange checks refresh request
\\ & & \langle h_C, D_p, D_{p(0)}, C_p^{(0)}, \sigma_C^{(0)} \rangle := \rho_{RC}
\\ & & \textbf{check} \text{ Ed25519.Verify}(C_p^{(0)}, \sigma_{RC}, \rho_{RC})
@ -323,10 +324,12 @@ In the reveal phase, the RSA signing and unblinding is exchanged with Schnorr's
\\ & & v := \text{Denomination}(D_p)
\\ & & \textbf{check } \text{IsOverspending}(C_p^{(0)}, D_ {p(0)}, v)
\\ & & \text{verify if } D_p \text{ is valid}
\\ & & \textbf{check !} \text{NonceReuse} (n_r, D_p)
\\ & & \textbf{check } \text{Schnorr.Verify}(D_{p(0)}, C_p^{(0)}, \sigma_C^{(0)})
\\ & & \text{MarkFractionalSpend}(C_p^{(0)}, v)
\\ & & \gamma \leftarrow \{1, \dots, \kappa\}
\\ & & \text{Persist refresh-record } \langle \rho_{RC},\gamma \rangle
\\ & & \text{persist NonceUse } \langle n_r, D_p, \rho_{RC} \rangle
\\ & & \text{persist refresh-record } \langle \rho_{RC},\gamma \rangle
\\ & \xleftarrow[\rule{2cm}{0pt}]{\gamma} &
% Check challenge and send challenge response (reveal not selected msgs)
\\ \textbf{check } \text{IsConsistentChallenge}(\rho_{RC}, \gamma)
@ -334,7 +337,7 @@ In the reveal phase, the RSA signing and unblinding is exchanged with Schnorr's
\\
\\ \text{Persist refresh-challenge} \langle \rho_{RC}, \gamma \rangle
\\ S := \langle t_1, \dots, t_{\gamma-1}, t_{\gamma+1}, \dots,t_\kappa \rangle % all seeds without the gamma seed
\\ \rho_L := \langle C_p^{(0)}, D_p, T_{\gamma}, \overline{c_0}_\gamma, \overline{c_1}_\gamma, n_r \rangle
\\ \rho_L := \langle C_p^{(0)}, D_p, T_{\gamma}, \overline{c_0}_\gamma, \overline{c_1}_\gamma \rangle
\\ \rho_{RR} := \langle \rho_L, S \rangle
\\ \sigma_{L} := \text{Ed25519.Sign}(c_s^{(0)}, \rho_{L})
\\ & \xrightarrow[\rule{2.5cm}{0pt}]{\rho_{RR},\rho_L, \sigma_{L}} &
@ -359,7 +362,7 @@ In the reveal phase, the RSA signing and unblinding is exchanged with Schnorr's
\\
\\ & \xrightarrow[\rule{2.5cm}{0pt}]{\rho_{RR},\rho_L, \sigma_{L}} &
% check revealed msgs and sign coin
\\ & & \langle C_p^{(0)}, D_p, T_{\gamma}, \overline{c_0}_\gamma, \overline{c_1}_\gamma, n_r \rangle := \rho_L
\\ & & \langle C_p^{(0)}, D_p, T_{\gamma}, \overline{c_0}_\gamma, \overline{c_1}_\gamma \rangle := \rho_L
\\ & & \langle T'_\gamma, \overline{c_0}_\gamma, \overline{c_1}_\gamma, S \rangle := \rho_{RR}
\\ & & \langle t_1,\dots,t_{\gamma-1},t_{\gamma+1},\dots,t_\kappa \rangle := S
\\ & & \textbf{check } \text{Ed25519.Verify}(C_p^{(0)}, \sigma_L, \rho_L)
@ -371,7 +374,7 @@ In the reveal phase, the RSA signing and unblinding is exchanged with Schnorr's
\\ & & h_T' = H(T_1,\dots,T_{\gamma-1},T'_{\gamma},T_{\gamma+1},\dots,T_\kappa)
\\ & & h_{\overline{c_0}}' := H(\overline{c_{0_1}},\dots, \overline{c}_{0_k})
\\ & & h_{\overline{c_1}}' := H(\overline{c_{1_1}},\dots, \overline{c}_{1_k})
\\ & & h_{\overline{c}}' := H(h_{\overline{c_0}}, h_{\overline{c_1}})
\\ & & h_{\overline{c}}' := H(h_{\overline{c_0}}, h_{\overline{c_1}}, n_r)
\\ & & h_C' = H(h_T', h_{\overline{c}}')
\\ & & \textbf{check } h_C = h_C'
\\ & & r_b := \text{HKDF}(256,n_r || d_s, \text{"r}b\text{"})

View File

@ -141,7 +141,7 @@ add_denomination (
GNUNET_h2s (&issue->denom_hash.hash),
TALER_amount2s (&value));
TALER_amount_ntoh (&value,
&issue->fee_withdraw);
&issue->fees.withdraw);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Withdraw fee is %s\n",
TALER_amount2s (&value));

View File

@ -471,7 +471,7 @@ check_transaction_history_for_deposit (
/* Fee according to denomination data of auditor */
TALER_amount_ntoh (&fee_expected,
&issue->fee_deposit);
&issue->fees.deposit);
if (0 !=
TALER_amount_cmp (&fee_expected,
fee_claimed))
@ -496,7 +496,7 @@ check_transaction_history_for_deposit (
struct TALER_Amount fee_expected;
TALER_amount_ntoh (&fee_expected,
&issue->fee_refresh);
&issue->fees.refresh);
if (0 !=
TALER_amount_cmp (&fee_expected,
fee_claimed))
@ -540,7 +540,7 @@ check_transaction_history_for_deposit (
struct TALER_Amount fee_expected;
TALER_amount_ntoh (&fee_expected,
&issue->fee_refund);
&issue->fees.refund);
if (0 !=
TALER_amount_cmp (&fee_expected,
fee_claimed))

View File

@ -1281,7 +1281,7 @@ refresh_session_cb (void *cls,
TALER_denom_pub_hash (denom_pub,
&h_denom_pub);
TALER_amount_ntoh (&fee_refresh,
&issue->fee_refresh);
&issue->fees.refresh);
if (GNUNET_OK !=
TALER_wallet_melt_verify (amount_with_fee,
&fee_refresh,
@ -1375,7 +1375,7 @@ refresh_session_cb (void *cls,
struct TALER_Amount value;
TALER_amount_ntoh (&fee,
&reveal_ctx.new_issues[i]->fee_withdraw);
&reveal_ctx.new_issues[i]->fees.withdraw);
TALER_amount_ntoh (&value,
&reveal_ctx.new_issues[i]->value);
TALER_ARL_amount_add (&refresh_cost,
@ -1391,7 +1391,7 @@ refresh_session_cb (void *cls,
struct TALER_Amount melt_fee;
TALER_amount_ntoh (&melt_fee,
&issue->fee_refresh);
&issue->fees.refresh);
if (TALER_ARL_SR_POSITIVE !=
TALER_ARL_amount_subtract_neg (&amount_without_fee,
amount_with_fee,
@ -1528,7 +1528,7 @@ refresh_session_cb (void *cls,
struct TALER_Amount rfee;
TALER_amount_ntoh (&rfee,
&issue->fee_refresh);
&issue->fees.refresh);
TALER_ARL_amount_add (&total_melt_fee_income,
&total_melt_fee_income,
&rfee);
@ -1621,7 +1621,7 @@ deposit_cb (void *cls,
&deposit->wire_salt,
&h_wire);
TALER_amount_ntoh (&deposit_fee,
&issue->fee_deposit);
&issue->fees.deposit);
/* NOTE: This is one of the operations we might eventually
want to do in parallel in the background to improve
auditor performance! */
@ -1726,7 +1726,7 @@ deposit_cb (void *cls,
struct TALER_Amount dfee;
TALER_amount_ntoh (&dfee,
&issue->fee_deposit);
&issue->fees.deposit);
TALER_ARL_amount_add (&total_deposit_fee_income,
&total_deposit_fee_income,
&dfee);
@ -1821,7 +1821,7 @@ refund_cb (void *cls,
}
TALER_amount_ntoh (&refund_fee,
&issue->fee_refund);
&issue->fees.refund);
if (TALER_ARL_SR_INVALID_NEGATIVE ==
TALER_ARL_amount_subtract_neg (&amount_without_fee,
amount_with_fee,
@ -2178,10 +2178,7 @@ check_denomination (
enum GNUNET_DB_QueryStatus qs;
struct TALER_AuditorSignatureP auditor_sig;
struct TALER_Amount coin_value;
struct TALER_Amount fee_withdraw;
struct TALER_Amount fee_deposit;
struct TALER_Amount fee_refresh;
struct TALER_Amount fee_refund;
struct TALER_DenomFeeSet fees;
struct GNUNET_TIME_Timestamp start;
struct GNUNET_TIME_Timestamp end;
@ -2189,14 +2186,8 @@ check_denomination (
(void) denom_pub;
TALER_amount_ntoh (&coin_value,
&issue->value);
TALER_amount_ntoh (&fee_withdraw,
&issue->fee_withdraw);
TALER_amount_ntoh (&fee_deposit,
&issue->fee_deposit);
TALER_amount_ntoh (&fee_refresh,
&issue->fee_refresh);
TALER_amount_ntoh (&fee_refund,
&issue->fee_refund);
TALER_denom_fee_set_ntoh (&fees,
&issue->fees);
start = GNUNET_TIME_timestamp_ntoh (issue->start);
end = GNUNET_TIME_timestamp_ntoh (issue->expire_legal);
qs = TALER_ARL_edb->select_auditor_denom_sig (TALER_ARL_edb->cls,
@ -2224,10 +2215,7 @@ check_denomination (
GNUNET_TIME_timestamp_ntoh (issue->expire_deposit),
end,
&coin_value,
&fee_withdraw,
&fee_deposit,
&fee_refresh,
&fee_refund,
&fees,
&TALER_ARL_auditor_pub,
&auditor_sig))
{

View File

@ -594,7 +594,7 @@ handle_reserve_out (void *cls,
}
TALER_amount_ntoh (&withdraw_fee,
&issue->fee_withdraw);
&issue->fees.withdraw);
TALER_amount_ntoh (&auditor_value,
&issue->value);
TALER_ARL_amount_add (&auditor_amount_with_fee,

View File

@ -505,10 +505,10 @@ run (void *cls,
TALER_denom_pub_hash (&denom_pub,
&h_denom_pub);
make_amountN (2, 0, &issue.properties.value);
make_amountN (0, 5, &issue.properties.fee_withdraw);
make_amountN (0, 5, &issue.properties.fee_deposit);
make_amountN (0, 5, &issue.properties.fee_refresh);
make_amountN (0, 5, &issue.properties.fee_refund);
make_amountN (0, 5, &issue.properties.fees.withdraw);
make_amountN (0, 5, &issue.properties.fees.deposit);
make_amountN (0, 5, &issue.properties.fees.refresh);
make_amountN (0, 5, &issue.properties.fees.refund);
issue.properties.denom_hash = h_denom_pub;
if (0 >=
plugin->insert_denomination_info (plugin->cls,

View File

@ -757,10 +757,7 @@ show_denomkeys (const json_t *denomkeys)
struct GNUNET_TIME_Timestamp stamp_expire_deposit;
struct GNUNET_TIME_Timestamp stamp_expire_legal;
struct TALER_Amount coin_value;
struct TALER_Amount fee_withdraw;
struct TALER_Amount fee_deposit;
struct TALER_Amount fee_refresh;
struct TALER_Amount fee_refund;
struct TALER_DenomFeeSet fees;
struct TALER_MasterSignatureP master_sig;
struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_denom_pub ("denom_pub",
@ -768,18 +765,9 @@ show_denomkeys (const json_t *denomkeys)
TALER_JSON_spec_amount ("value",
currency,
&coin_value),
TALER_JSON_spec_amount ("fee_withdraw",
currency,
&fee_withdraw),
TALER_JSON_spec_amount ("fee_deposit",
currency,
&fee_deposit),
TALER_JSON_spec_amount ("fee_refresh",
currency,
&fee_refresh),
TALER_JSON_spec_amount ("fee_refund",
currency,
&fee_refund),
TALER_JSON_SPEC_DENOM_FEES ("fee",
currency,
&fees),
GNUNET_JSON_spec_timestamp ("stamp_start",
&stamp_start),
GNUNET_JSON_spec_timestamp ("stamp_expire_withdraw",
@ -824,10 +812,7 @@ show_denomkeys (const json_t *denomkeys)
stamp_expire_deposit,
stamp_expire_legal,
&coin_value,
&fee_withdraw,
&fee_deposit,
&fee_refresh,
&fee_refund,
&fees,
&master_pub,
&master_sig))
{
@ -847,10 +832,10 @@ show_denomkeys (const json_t *denomkeys)
char *deposit_s;
char *legal_s;
withdraw_fee_s = TALER_amount_to_string (&fee_withdraw);
deposit_fee_s = TALER_amount_to_string (&fee_deposit);
refresh_fee_s = TALER_amount_to_string (&fee_refresh);
refund_fee_s = TALER_amount_to_string (&fee_refund);
withdraw_fee_s = TALER_amount_to_string (&fees.withdraw);
deposit_fee_s = TALER_amount_to_string (&fees.deposit);
refresh_fee_s = TALER_amount_to_string (&fees.refresh);
refund_fee_s = TALER_amount_to_string (&fees.refund);
deposit_s = GNUNET_strdup (
GNUNET_TIME_timestamp2s (stamp_expire_deposit));
legal_s = GNUNET_strdup (
@ -1058,10 +1043,7 @@ sign_denomkeys (const json_t *denomkeys)
struct GNUNET_TIME_Timestamp stamp_expire_deposit;
struct GNUNET_TIME_Timestamp stamp_expire_legal;
struct TALER_Amount coin_value;
struct TALER_Amount fee_withdraw;
struct TALER_Amount fee_deposit;
struct TALER_Amount fee_refresh;
struct TALER_Amount fee_refund;
struct TALER_DenomFeeSet fees;
struct TALER_MasterSignatureP master_sig;
struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_denom_pub ("denom_pub",
@ -1069,18 +1051,9 @@ sign_denomkeys (const json_t *denomkeys)
TALER_JSON_spec_amount ("value",
currency,
&coin_value),
TALER_JSON_spec_amount ("fee_withdraw",
currency,
&fee_withdraw),
TALER_JSON_spec_amount ("fee_deposit",
currency,
&fee_deposit),
TALER_JSON_spec_amount ("fee_refresh",
currency,
&fee_refresh),
TALER_JSON_spec_amount ("fee_refund",
currency,
&fee_refund),
TALER_JSON_SPEC_DENOM_FEES ("fee",
currency,
&fees),
GNUNET_JSON_spec_timestamp ("stamp_start",
&stamp_start),
GNUNET_JSON_spec_timestamp ("stamp_expire_withdraw",
@ -1121,10 +1094,7 @@ sign_denomkeys (const json_t *denomkeys)
stamp_expire_deposit,
stamp_expire_legal,
&coin_value,
&fee_withdraw,
&fee_deposit,
&fee_refresh,
&fee_refund,
&fees,
&master_pub,
&master_sig))
{
@ -1147,10 +1117,7 @@ sign_denomkeys (const json_t *denomkeys)
stamp_expire_deposit,
stamp_expire_legal,
&coin_value,
&fee_withdraw,
&fee_deposit,
&fee_refresh,
&fee_refund,
&fees,
&auditor_priv,
&auditor_sig);
output_operation (OP_SIGN_DENOMINATION,

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2020, 2021 Taler Systems SA
Copyright (C) 2020, 2021, 2022 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@ -2831,10 +2831,7 @@ show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
struct GNUNET_TIME_Timestamp stamp_expire_deposit;
struct GNUNET_TIME_Timestamp stamp_expire_legal;
struct TALER_Amount coin_value;
struct TALER_Amount fee_withdraw;
struct TALER_Amount fee_deposit;
struct TALER_Amount fee_refresh;
struct TALER_Amount fee_refund;
struct TALER_DenomFeeSet fees;
struct TALER_SecurityModuleSignatureP secm_sig;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("section_name",
@ -2844,18 +2841,9 @@ show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
TALER_JSON_spec_amount ("value",
currency,
&coin_value),
TALER_JSON_spec_amount ("fee_withdraw",
currency,
&fee_withdraw),
TALER_JSON_spec_amount ("fee_deposit",
currency,
&fee_deposit),
TALER_JSON_spec_amount ("fee_refresh",
currency,
&fee_refresh),
TALER_JSON_spec_amount ("fee_refund",
currency,
&fee_refund),
TALER_JSON_SPEC_DENOM_FEES ("fee",
currency,
&fees),
GNUNET_JSON_spec_timestamp ("stamp_start",
&stamp_start),
GNUNET_JSON_spec_timestamp ("stamp_expire_withdraw",
@ -2949,10 +2937,10 @@ show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
char *deposit_s;
char *legal_s;
withdraw_fee_s = TALER_amount_to_string (&fee_withdraw);
deposit_fee_s = TALER_amount_to_string (&fee_deposit);
refresh_fee_s = TALER_amount_to_string (&fee_refresh);
refund_fee_s = TALER_amount_to_string (&fee_refund);
withdraw_fee_s = TALER_amount_to_string (&fees.withdraw);
deposit_fee_s = TALER_amount_to_string (&fees.deposit);
refresh_fee_s = TALER_amount_to_string (&fees.refresh);
refund_fee_s = TALER_amount_to_string (&fees.refund);
deposit_s = GNUNET_strdup (
GNUNET_TIME_timestamp2s (stamp_expire_deposit));
legal_s = GNUNET_strdup (
@ -3324,10 +3312,7 @@ sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
struct GNUNET_TIME_Timestamp stamp_expire_deposit;
struct GNUNET_TIME_Timestamp stamp_expire_legal;
struct TALER_Amount coin_value;
struct TALER_Amount fee_withdraw;
struct TALER_Amount fee_deposit;
struct TALER_Amount fee_refresh;
struct TALER_Amount fee_refund;
struct TALER_DenomFeeSet fees;
struct TALER_SecurityModuleSignatureP secm_sig;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("section_name",
@ -3337,18 +3322,9 @@ sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
TALER_JSON_spec_amount ("value",
currency,
&coin_value),
TALER_JSON_spec_amount ("fee_withdraw",
currency,
&fee_withdraw),
TALER_JSON_spec_amount ("fee_deposit",
currency,
&fee_deposit),
TALER_JSON_spec_amount ("fee_refresh",
currency,
&fee_refresh),
TALER_JSON_spec_amount ("fee_refund",
currency,
&fee_refund),
TALER_JSON_SPEC_DENOM_FEES ("fee",
currency,
&fees),
GNUNET_JSON_spec_timestamp ("stamp_start",
&stamp_start),
GNUNET_JSON_spec_timestamp ("stamp_expire_withdraw",
@ -3458,10 +3434,7 @@ sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
stamp_expire_deposit,
stamp_expire_legal,
&coin_value,
&fee_withdraw,
&fee_deposit,
&fee_refresh,
&fee_refund,
&fees,
&master_priv,
&master_sig);
GNUNET_assert (0 ==

View File

@ -925,9 +925,15 @@ handle_mhd_request (void *cls,
},
/* request R, used in clause schnorr withdraw and refresh */
{
.url = "csr",
.url = "csr-melt",
.method = MHD_HTTP_METHOD_POST,
.handler.post = &TEH_handler_csr,
.handler.post = &TEH_handler_csr_melt,
.nargs = 0
},
{
.url = "csr-withdraw",
.method = MHD_HTTP_METHOD_POST,
.handler.post = &TEH_handler_csr_withdraw,
.nargs = 0
},
/* Withdrawing coins / interaction with reserves */

View File

@ -150,10 +150,7 @@ add_auditor_denom_sig (void *cls,
meta.expire_deposit,
meta.expire_legal,
&meta.value,
&meta.fee_withdraw,
&meta.fee_deposit,
&meta.fee_refresh,
&meta.fee_refund,
&meta.fees,
awc->auditor_pub,
&awc->auditor_sig))
{

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014-2021 Taler Systems SA
Copyright (C) 2014-2022 Taler Systems SA
TALER is free software; you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
@ -33,15 +33,16 @@
MHD_RESULT
TEH_handler_csr (struct TEH_RequestContext *rc,
const json_t *root,
const char *const args[])
TEH_handler_csr_melt (struct TEH_RequestContext *rc,
const json_t *root,
const char *const args[])
{
struct TALER_RefreshMasterSecretP rms;
unsigned int csr_requests_num;
json_t *csr_requests;
json_t *csr_response_ewvs;
json_t *csr_response;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("rms",
&rms),
GNUNET_JSON_spec_json ("nks",
&csr_requests),
GNUNET_JSON_spec_end ()
@ -50,8 +51,7 @@ TEH_handler_csr (struct TEH_RequestContext *rc,
struct TEH_DenominationKey *dk;
(void) args;
// parse input
/* parse input */
{
enum GNUNET_GenericReturnValue res;
@ -62,7 +62,8 @@ TEH_handler_csr (struct TEH_RequestContext *rc,
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
}
csr_requests_num = json_array_size (csr_requests);
if (TALER_MAX_FRESH_COINS <= csr_requests_num)
if ( (TALER_MAX_FRESH_COINS <= csr_requests_num) ||
(0 == csr_requests_num) )
{
GNUNET_JSON_parse_free (spec);
return TALER_MHD_reply_with_error (
@ -71,109 +72,253 @@ TEH_handler_csr (struct TEH_RequestContext *rc,
TALER_EC_EXCHANGE_GENERIC_NEW_DENOMS_ARRAY_SIZE_EXCESSIVE,
NULL);
}
struct TALER_CsNonce nonces[GNUNET_NZL (csr_requests_num)];
struct TALER_DenominationHash denom_pub_hashes[GNUNET_NZL (csr_requests_num)];
for (unsigned int i = 0; i < csr_requests_num; i++)
{
struct TALER_CsNonce *nonce = &nonces[i];
struct TALER_DenominationHash *denom_pub_hash = &denom_pub_hashes[i];
struct GNUNET_JSON_Specification csr_spec[] = {
GNUNET_JSON_spec_fixed ("nonce",
nonce,
sizeof (struct TALER_CsNonce)),
GNUNET_JSON_spec_fixed ("denom_pub_hash",
denom_pub_hash,
sizeof (struct TALER_DenominationHash)),
GNUNET_JSON_spec_end ()
};
enum GNUNET_GenericReturnValue res;
res = TALER_MHD_parse_json_array (rc->connection,
csr_requests,
csr_spec,
i,
-1);
if (GNUNET_OK != res)
{
struct TALER_ExchangeWithdrawValues ewvs[csr_requests_num];
{
struct TALER_CsNonce nonces[csr_requests_num];
struct TALER_DenominationHash denom_pub_hashes[csr_requests_num];
for (unsigned int i = 0; i < csr_requests_num; i++)
{
uint32_t coin_off;
struct TALER_DenominationHash *denom_pub_hash = &denom_pub_hashes[i];
struct GNUNET_JSON_Specification csr_spec[] = {
GNUNET_JSON_spec_uint32 ("coin_offset",
&coin_off),
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
denom_pub_hash),
GNUNET_JSON_spec_end ()
};
enum GNUNET_GenericReturnValue res;
res = TALER_MHD_parse_json_array (rc->connection,
csr_requests,
csr_spec,
i,
-1);
if (GNUNET_OK != res)
{
GNUNET_JSON_parse_free (spec);
return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
}
TALER_cs_refresh_nonce_derive (&rms,
coin_off,
&nonces[i]);
}
GNUNET_JSON_parse_free (spec);
return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
for (unsigned int i = 0; i < csr_requests_num; i++)
{
const struct TALER_CsNonce *nonce = &nonces[i];
const struct TALER_DenominationHash *denom_pub_hash =
&denom_pub_hashes[i];
struct TALER_DenominationCSPublicRPairP *r_pub
= &ewvs[i].details.cs_values;
ewvs[i].cipher = TALER_DENOMINATION_CS;
/* check denomination referenced by denom_pub_hash */
{
struct TEH_KeyStateHandle *ksh;
ksh = TEH_keys_get_state ();
if (NULL == ksh)
{
return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
NULL);
}
dk = TEH_keys_denomination_by_hash2 (ksh,
denom_pub_hash,
NULL,
NULL);
if (NULL == dk)
{
return TEH_RESPONSE_reply_unknown_denom_pub_hash (
rc->connection,
&denom_pub_hash[i]);
}
if (GNUNET_TIME_absolute_is_past (dk->meta.expire_withdraw.abs_time))
{
/* This denomination is past the expiration time for withdraws/refreshes*/
return TEH_RESPONSE_reply_expired_denom_pub_hash (
rc->connection,
denom_pub_hash,
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
"csr-melt");
}
if (GNUNET_TIME_absolute_is_future (dk->meta.start.abs_time))
{
/* This denomination is not yet valid, no need to check
for idempotency! */
return TEH_RESPONSE_reply_expired_denom_pub_hash (
rc->connection,
denom_pub_hash,
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
"csr-melt");
}
if (dk->recoup_possible)
{
/* This denomination has been revoked */
return TEH_RESPONSE_reply_expired_denom_pub_hash (
rc->connection,
denom_pub_hash,
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED,
"csr-melt");
}
if (TALER_DENOMINATION_CS != dk->denom_pub.cipher)
{
/* denomination is valid but not for CS */
return TEH_RESPONSE_reply_invalid_denom_cipher_for_operation (
rc->connection,
denom_pub_hash);
}
}
/* derive r_pub */
// FIXME: bundle all requests into one derivation request (TEH_keys_..., crypto helper, security module)
ec = TEH_keys_denomination_cs_r_pub (denom_pub_hash,
nonce,
r_pub);
if (TALER_EC_NONE != ec)
{
GNUNET_break (0);
return TALER_MHD_reply_with_ec (rc->connection,
ec,
NULL);
}
}
}
/* send response */
{
json_t *csr_response_ewvs;
json_t *csr_response;
csr_response_ewvs = json_array ();
for (unsigned int i = 0; i < csr_requests_num; i++)
{
json_t *csr_obj;
csr_obj = GNUNET_JSON_PACK (
TALER_JSON_pack_exchange_withdraw_values ("ewv",
&ewvs[i]));
GNUNET_assert (NULL != csr_obj);
GNUNET_assert (0 ==
json_array_append_new (csr_response_ewvs,
csr_obj));
}
csr_response = GNUNET_JSON_PACK (
GNUNET_JSON_pack_array_steal ("ewvs",
csr_response_ewvs));
GNUNET_assert (NULL != csr_response);
return TALER_MHD_reply_json_steal (rc->connection,
csr_response,
MHD_HTTP_OK);
}
}
GNUNET_JSON_parse_free (spec);
}
struct TALER_ExchangeWithdrawValues ewvs[GNUNET_NZL (csr_requests_num)];
for (unsigned int i = 0; i < csr_requests_num; i++)
MHD_RESULT
TEH_handler_csr_withdraw (struct TEH_RequestContext *rc,
const json_t *root,
const char *const args[])
{
struct TALER_CsNonce nonce;
struct TALER_DenominationHash denom_pub_hash;
struct TALER_ExchangeWithdrawValues ewv = {
.cipher = TALER_DENOMINATION_CS
};
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed ("nonce",
&nonce,
sizeof (struct TALER_CsNonce)),
GNUNET_JSON_spec_fixed ("denom_pub_hash",
&denom_pub_hash,
sizeof (struct TALER_DenominationHash)),
GNUNET_JSON_spec_end ()
};
struct TEH_DenominationKey *dk;
(void) args;
{
const struct TALER_CsNonce *nonce = &nonces[i];
const struct TALER_DenominationHash *denom_pub_hash = &denom_pub_hashes[i];
struct TALER_DenominationCSPublicRPairP *r_pub
= &ewvs[i].details.cs_values;
enum GNUNET_GenericReturnValue res;
ewvs[i].cipher = TALER_DENOMINATION_CS;
// check denomination referenced by denom_pub_hash
res = TALER_MHD_parse_json_data (rc->connection,
root,
spec);
if (GNUNET_OK != res)
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
}
{
struct TEH_KeyStateHandle *ksh;
ksh = TEH_keys_get_state ();
if (NULL == ksh)
{
struct TEH_KeyStateHandle *ksh;
ksh = TEH_keys_get_state ();
if (NULL == ksh)
{
return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
NULL);
}
dk = TEH_keys_denomination_by_hash2 (ksh,
denom_pub_hash,
NULL,
NULL);
if (NULL == dk)
{
return TEH_RESPONSE_reply_unknown_denom_pub_hash (
rc->connection,
&denom_pub_hash[i]);
}
if (GNUNET_TIME_absolute_is_past (dk->meta.expire_withdraw.abs_time))
{
/* This denomination is past the expiration time for withdraws/refreshes*/
return TEH_RESPONSE_reply_expired_denom_pub_hash (
rc->connection,
denom_pub_hash,
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
"CSR");
}
if (GNUNET_TIME_absolute_is_future (dk->meta.start.abs_time))
{
/* This denomination is not yet valid, no need to check
for idempotency! */
return TEH_RESPONSE_reply_expired_denom_pub_hash (
rc->connection,
denom_pub_hash,
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
"CSR");
}
if (dk->recoup_possible)
{
/* This denomination has been revoked */
return TEH_RESPONSE_reply_expired_denom_pub_hash (
rc->connection,
denom_pub_hash,
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED,
"CSR");
}
if (TALER_DENOMINATION_CS != dk->denom_pub.cipher)
{
// denomination is valid but not CS
return TEH_RESPONSE_reply_invalid_denom_cipher_for_operation (
rc->connection,
denom_pub_hash);
}
return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
NULL);
}
dk = TEH_keys_denomination_by_hash2 (ksh,
&denom_pub_hash,
NULL,
NULL);
if (NULL == dk)
{
return TEH_RESPONSE_reply_unknown_denom_pub_hash (
rc->connection,
&denom_pub_hash);
}
if (GNUNET_TIME_absolute_is_past (dk->meta.expire_withdraw.abs_time))
{
/* This denomination is past the expiration time for withdraws/refreshes*/
return TEH_RESPONSE_reply_expired_denom_pub_hash (
rc->connection,
&denom_pub_hash,
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
"csr-withdraw");
}
if (GNUNET_TIME_absolute_is_future (dk->meta.start.abs_time))
{
/* This denomination is not yet valid, no need to check
for idempotency! */
return TEH_RESPONSE_reply_expired_denom_pub_hash (
rc->connection,
&denom_pub_hash,
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
"csr-withdraw");
}
if (dk->recoup_possible)
{
/* This denomination has been revoked */
return TEH_RESPONSE_reply_expired_denom_pub_hash (
rc->connection,
&denom_pub_hash,
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED,
"csr-withdraw");
}
if (TALER_DENOMINATION_CS != dk->denom_pub.cipher)
{
/* denomination is valid but not for CS */
return TEH_RESPONSE_reply_invalid_denom_cipher_for_operation (
rc->connection,
&denom_pub_hash);
}
}
// derive r_pub
// FIXME: bundle all requests into one derivation request (TEH_keys_..., crypto helper, security module)
ec = TEH_keys_denomination_cs_r_pub (denom_pub_hash,
nonce,
r_pub);
/* derive r_pub */
{
enum TALER_ErrorCode ec;
ec = TEH_keys_denomination_cs_r_pub (&denom_pub_hash,
&nonce,
&ewv.details.cs_values);
if (TALER_EC_NONE != ec)
{
GNUNET_break (0);
@ -183,27 +328,17 @@ TEH_handler_csr (struct TEH_RequestContext *rc,
}
}
// send response
csr_response_ewvs = json_array ();
for (unsigned int i = 0; i < csr_requests_num; i++)
{
json_t *csr_obj;
csr_obj = GNUNET_JSON_PACK (
TALER_JSON_pack_exchange_withdraw_values ("ewv",
&ewvs[i]));
&ewv));
GNUNET_assert (NULL != csr_obj);
GNUNET_assert (0 ==
json_array_append_new (csr_response_ewvs,
csr_obj));
return TALER_MHD_reply_json_steal (rc->connection,
csr_obj,
MHD_HTTP_OK);
}
csr_response = GNUNET_JSON_PACK (
GNUNET_JSON_pack_array_steal ("ewvs",
csr_response_ewvs));
GNUNET_assert (NULL != csr_response);
return TALER_MHD_reply_json_steal (rc->connection,
csr_response,
MHD_HTTP_OK);
}

View File

@ -15,7 +15,7 @@
*/
/**
* @file taler-exchange-httpd_csr.h
* @brief Handle /csr requests
* @brief Handle /csr-* requests
* @author Lucien Heuzeveldt
* @author Gian Demarmles
*/
@ -27,8 +27,7 @@
/**
* Handle a "/csr" request. Parses the "nonce" and
* the "denom_pub_hash" (identifying a denomination) used to derive the r_pub.
* Handle a "/csr-melt" request.
*
* @param rc request context
* @param root uploaded JSON data
@ -36,8 +35,22 @@
* @return MHD result code
*/
MHD_RESULT
TEH_handler_csr (struct TEH_RequestContext *rc,
const json_t *root,
const char *const args[]);
TEH_handler_csr_melt (struct TEH_RequestContext *rc,
const json_t *root,
const char *const args[]);
/**
* Handle a "/csr-withdraw" request.
*
* @param rc request context
* @param root uploaded JSON data
* @param args empty array
* @return MHD result code
*/
MHD_RESULT
TEH_handler_csr_withdraw (struct TEH_RequestContext *rc,
const json_t *root,
const char *const args[]);
#endif

View File

@ -370,7 +370,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
NULL);
}
deposit.deposit_fee = dk->meta.fee_deposit;
deposit.deposit_fee = dk->meta.fees.deposit;
/* check coin signature */
if (GNUNET_YES !=
TALER_test_coin_valid (&deposit.coin,

View File

@ -2113,14 +2113,8 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
&dk->denom_pub),
TALER_JSON_pack_amount ("value",
&dk->meta.value),
TALER_JSON_pack_amount ("fee_withdraw",
&dk->meta.fee_withdraw),
TALER_JSON_pack_amount ("fee_deposit",
&dk->meta.fee_deposit),
TALER_JSON_pack_amount ("fee_refresh",
&dk->meta.fee_refresh),
TALER_JSON_pack_amount ("fee_refund",
&dk->meta.fee_refund));
TALER_JSON_PACK_DENOM_FEES ("fee",
&dk->meta.fees));
/* Put the denom into the correct array depending on the settings and
* the properties of the denomination. Also, we build up the right
@ -2810,74 +2804,22 @@ load_extension_data (const char *section_name,
section_name);
return GNUNET_SYSERR;
}
if (GNUNET_OK !=
TALER_config_get_amount (TEH_cfg,
section_name,
"FEE_WITHDRAW",
&meta->fee_withdraw))
{
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
"Need amount for option `%s' in section `%s'\n",
"FEE_WITHDRAW",
section_name);
return GNUNET_SYSERR;
}
if (GNUNET_OK !=
TALER_config_get_amount (TEH_cfg,
section_name,
"FEE_DEPOSIT",
&meta->fee_deposit))
{
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
"Need amount for option `%s' in section `%s'\n",
"FEE_DEPOSIT",
section_name);
return GNUNET_SYSERR;
}
if (GNUNET_OK !=
TALER_config_get_amount (TEH_cfg,
section_name,
"FEE_REFRESH",
&meta->fee_refresh))
{
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
"Need amount for option `%s' in section `%s'\n",
"FEE_REFRESH",
section_name);
return GNUNET_SYSERR;
}
if (GNUNET_OK !=
TALER_config_get_amount (TEH_cfg,
section_name,
"FEE_REFUND",
&meta->fee_refund))
{
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
"Need amount for option `%s' in section `%s'\n",
"FEE_REFUND",
section_name);
return GNUNET_SYSERR;
}
if ( (0 != strcasecmp (TEH_currency,
meta->value.currency)) ||
(0 != strcasecmp (TEH_currency,
meta->fee_withdraw.currency)) ||
(0 != strcasecmp (TEH_currency,
meta->fee_deposit.currency)) ||
(0 != strcasecmp (TEH_currency,
meta->fee_refresh.currency)) ||
(0 != strcasecmp (TEH_currency,
meta->fee_refund.currency)) )
if (0 != strcasecmp (TEH_currency,
meta->value.currency))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Need amounts in section `%s' to use currency `%s'\n",
"Need denomination value in section `%s' to use currency `%s'\n",
section_name,
TEH_currency);
return GNUNET_SYSERR;
}
if (GNUNET_OK !=
TALER_config_get_denom_fees (TEH_cfg,
TEH_currency,
section_name,
&meta->fees))
return GNUNET_SYSERR;
meta->age_mask = load_age_mask (section_name);
return GNUNET_OK;
}
@ -3040,14 +2982,8 @@ add_future_denomkey_cb (void *cls,
meta.expire_legal),
TALER_JSON_pack_denom_pub ("denom_pub",
&hd->denom_pub),
TALER_JSON_pack_amount ("fee_withdraw",
&meta.fee_withdraw),
TALER_JSON_pack_amount ("fee_deposit",
&meta.fee_deposit),
TALER_JSON_pack_amount ("fee_refresh",
&meta.fee_refresh),
TALER_JSON_pack_amount ("fee_refund",
&meta.fee_refund),
TALER_JSON_PACK_DENOM_FEES ("fee",
&meta.fees),
GNUNET_JSON_pack_data_auto ("denom_secmod_sig",
&hd->sm_sig),
GNUNET_JSON_pack_string ("section_name",

View File

@ -187,10 +187,7 @@ add_keys (void *cls,
meta.expire_deposit,
meta.expire_legal,
&meta.value,
&meta.fee_withdraw,
&meta.fee_deposit,
&meta.fee_refresh,
&meta.fee_refund,
&meta.fees,
&TEH_master_public_key,
&d->master_sig))
{

View File

@ -104,6 +104,11 @@ struct MeltContext
*/
struct TALER_Amount coin_refresh_fee;
/**
* Refresh master secret, if any of the fresh denominations use CS.
*/
struct TALER_RefreshMasterSecretP rms;
/**
* Set to true if this coin's denomination was revoked and the operation
* is thus only allowed for zombie coins where the transaction
@ -117,6 +122,10 @@ struct MeltContext
*/
bool coin_is_dirty;
/**
* True if @e rms is set.
*/
bool have_rms;
};
@ -155,6 +164,9 @@ melt_transaction (void *cls,
if (0 >
(qs = TEH_plugin->do_melt (TEH_plugin->cls,
rmc->have_rms
? &rmc->rms
: NULL,
&rmc->refresh_session,
rmc->known_coin_id,
&rmc->zombie_required,
@ -300,7 +312,7 @@ check_melt_valid (struct MHD_Connection *connection,
"MELT");
}
rmc->coin_refresh_fee = dk->meta.fee_refresh;
rmc->coin_refresh_fee = dk->meta.fees.refresh;
rmc->coin_value = dk->meta.value;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@ -422,6 +434,9 @@ TEH_handler_melt (struct MHD_Connection *connection,
&rmc.refresh_session.amount_with_fee),
GNUNET_JSON_spec_fixed_auto ("rc",
&rmc.refresh_session.rc),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_fixed_auto ("rms",
&rmc.rms)),
GNUNET_JSON_spec_end ()
};
@ -429,7 +444,6 @@ TEH_handler_melt (struct MHD_Connection *connection,
0,
sizeof (rmc));
rmc.refresh_session.coin.coin_pub = *coin_pub;
{
enum GNUNET_GenericReturnValue ret;
ret = TALER_MHD_parse_json_data (connection,
@ -438,7 +452,8 @@ TEH_handler_melt (struct MHD_Connection *connection,
if (GNUNET_OK != ret)
return (GNUNET_SYSERR == ret) ? MHD_NO : MHD_YES;
}
rmc.have_rms = (NULL != json_object_get (root,
"rms"));
{
MHD_RESULT res;

View File

@ -42,7 +42,7 @@ struct RecoupContext
/**
* Hash identifying the withdraw request.
*/
struct TALER_WithdrawIdentificationHash wih;
struct TALER_BlindedCoinHash h_coin_ev;
/**
* Set by #recoup_transaction() to the reserve that will
@ -273,9 +273,9 @@ verify_and_execute_recoup (
blinded_planchet.details.cs_blinded_planchet.nonce
= *nonce;
if (GNUNET_OK !=
TALER_withdraw_request_hash (&blinded_planchet,
&coin->denom_pub_hash,
&pc.wih))
TALER_coin_ev_hash (&blinded_planchet,
&coin->denom_pub_hash,
&pc.h_coin_ev))
{
GNUNET_break (0);
return TALER_MHD_reply_with_error (connection,
@ -308,10 +308,10 @@ verify_and_execute_recoup (
{
enum GNUNET_DB_QueryStatus qs;
qs = TEH_plugin->get_reserve_by_wih (TEH_plugin->cls,
&pc.wih,
&pc.reserve_pub,
&pc.reserve_out_serial_id);
qs = TEH_plugin->get_reserve_by_h_blind (TEH_plugin->cls,
&pc.h_coin_ev,
&pc.reserve_pub,
&pc.reserve_out_serial_id);
if (0 > qs)
{
GNUNET_break (0);
@ -319,13 +319,13 @@ verify_and_execute_recoup (
connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_GENERIC_DB_FETCH_FAILED,
"get_reserve_by_wih");
"get_reserve_by_h_blind");
}
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Recoup requested for unknown envelope %s\n",
GNUNET_h2s (&pc.wih.hash));
GNUNET_h2s (&pc.h_coin_ev.hash));
return TALER_MHD_reply_with_error (
connection,
MHD_HTTP_NOT_FOUND,
@ -412,9 +412,6 @@ TEH_handler_recoup (struct MHD_Connection *connection,
return MHD_NO; /* hard failure */
if (GNUNET_NO == ret)
return MHD_YES; /* failure */
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Recoup coin with BKS=%s\n",
TALER_B2S (&coin_bks));
{
MHD_RESULT res;

View File

@ -121,11 +121,20 @@ struct RevealContext
*/
struct TALER_RefreshCoinData *rcds;
/**
* Refresh master secret.
*/
struct TALER_RefreshMasterSecretP rms;
/**
* Size of the @e dks, @e rcds and @e ev_sigs arrays (if non-NULL).
*/
unsigned int num_fresh_coins;
/**
* True if @e rms was provided.
*/
bool have_rms;
};
@ -321,6 +330,9 @@ check_commitment (struct RevealContext *rctx,
}
TALER_refresh_get_commitment (&rc_expected,
TALER_CNC_KAPPA,
rctx->have_rms
? &rctx->rms
: NULL,
rctx->num_fresh_coins,
rcs,
&rctx->melt.session.coin.coin_pub,
@ -369,7 +381,7 @@ check_commitment (struct RevealContext *rctx,
if ( (0 >
TALER_amount_add (&total,
&rctx->dks[i]->meta.fee_withdraw,
&rctx->dks[i]->meta.fees.withdraw,
&rctx->dks[i]->meta.value)) ||
(0 >
TALER_amount_add (&refresh_cost,
@ -464,7 +476,15 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
&ret);
if (NULL == dks[i])
return ret;
if ( (TALER_DENOMINATION_CS == dks[i]->denom_pub.cipher) &&
(! rctx->have_rms) )
{
return TALER_MHD_reply_with_error (
connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MISSING,
"rms");
}
if (GNUNET_TIME_absolute_is_past (dks[i]->meta.expire_withdraw.abs_time))
{
/* This denomination is past the expiration time for withdraws */
@ -907,6 +927,9 @@ TEH_handler_reveal (struct TEH_RequestContext *rc,
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_json ("old_age_commitment",
&old_age_commitment)),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_fixed_auto ("rms",
&rctx.rms)),
GNUNET_JSON_spec_end ()
};
@ -947,6 +970,8 @@ TEH_handler_reveal (struct TEH_RequestContext *rc,
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
}
}
rctx.have_rms = (NULL != json_object_get (root,
"rms"));
/* Check we got enough transfer private keys */
/* Note we do +1 as 1 row (cut-and-choose!) is missing! */

View File

@ -264,8 +264,8 @@ verify_and_execute_refund (struct MHD_Connection *connection,
GNUNET_break (0);
return mret;
}
refund->details.refund_fee = dk->meta.fee_refund;
rctx.deposit_fee = dk->meta.fee_deposit;
refund->details.refund_fee = dk->meta.fees.refund;
rctx.deposit_fee = dk->meta.fees.deposit;
}
/* Finally run the actual transaction logic */

View File

@ -91,11 +91,6 @@ reply_withdraw_insufficient_funds (
struct WithdrawContext
{
/**
* Hash that uniquely identifies the withdraw request.
*/
struct TALER_WithdrawIdentificationHash wih;
/**
* Hash of the (blinded) message to be signed by the Exchange.
*/
@ -157,10 +152,17 @@ withdraw_transaction (void *cls,
bool balance_ok = false;
struct GNUNET_TIME_Timestamp now;
uint64_t ruuid;
const struct TALER_CsNonce *nonce;
const struct TALER_BlindedPlanchet *bp;
now = GNUNET_TIME_timestamp_get ();
bp = &wc->blinded_planchet;
nonce =
(TALER_DENOMINATION_CS == bp->cipher)
? &bp->details.cs_blinded_planchet.nonce
: NULL;
qs = TEH_plugin->do_withdraw (TEH_plugin->cls,
&wc->wih,
nonce,
&wc->collectable,
now,
&found,
@ -300,7 +302,7 @@ check_request_idempotent (struct TEH_RequestContext *rc,
enum GNUNET_DB_QueryStatus qs;
qs = TEH_plugin->get_withdraw_info (TEH_plugin->cls,
&wc->wih,
&wc->h_coin_envelope,
&wc->collectable);
if (0 > qs)
{
@ -465,7 +467,7 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
if (0 >
TALER_amount_add (&wc.collectable.amount_with_fee,
&dk->meta.value,
&dk->meta.fee_withdraw))
&dk->meta.fees.withdraw))
{
GNUNET_JSON_parse_free (spec);
return TALER_MHD_reply_with_error (rc->connection,
@ -502,19 +504,6 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
NULL);
}
if (GNUNET_OK !=
TALER_withdraw_request_hash (&wc.blinded_planchet,
&wc.collectable.denom_pub_hash,
&wc.wih))
{
GNUNET_break (0);
GNUNET_JSON_parse_free (spec);
return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
NULL);
}
/* Sign before transaction! */
ec = TEH_keys_denomination_sign (
&wc.collectable.denom_pub_hash,

View File

@ -1,6 +1,6 @@
--
-- This file is part of TALER
-- Copyright (C) 2014--2021 Taler Systems SA
-- Copyright (C) 2014--2022 Taler Systems SA
--
-- TALER is free software; you can redistribute it and/or modify it under the
-- terms of the GNU General Public License as published by the Free Software
@ -22,7 +22,7 @@ SELECT _v.register_patch('exchange-0001', NULL, NULL);
CREATE TABLE IF NOT EXISTS denominations
(denominations_serial BIGSERIAL UNIQUE
(denominations_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,denom_pub_hash BYTEA PRIMARY KEY CHECK (LENGTH(denom_pub_hash)=64)
,denom_type INT4 NOT NULL DEFAULT (1) -- 1 == RSA (for now, remove default later!)
,age_mask INT4 NOT NULL DEFAULT (0)
@ -58,7 +58,7 @@ CREATE INDEX IF NOT EXISTS denominations_by_expire_legal_index
CREATE TABLE IF NOT EXISTS denomination_revocations
(denom_revocations_serial_id BIGSERIAL UNIQUE
(denom_revocations_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,denominations_serial INT8 PRIMARY KEY REFERENCES denominations (denominations_serial) ON DELETE CASCADE
,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
);
@ -67,7 +67,7 @@ COMMENT ON TABLE denomination_revocations
CREATE TABLE IF NOT EXISTS wire_targets
(wire_target_serial_id BIGSERIAL -- UNIQUE
(wire_target_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,h_payto BYTEA PRIMARY KEY CHECK (LENGTH(h_payto)=64)
,payto_uri VARCHAR NOT NULL
,kyc_ok BOOLEAN NOT NULL DEFAULT (FALSE)
@ -89,7 +89,7 @@ CREATE TABLE IF NOT EXISTS wire_targets_default
FOR VALUES WITH (MODULUS 1, REMAINDER 0);
CREATE TABLE IF NOT EXISTS reserves
(reserve_uuid BIGSERIAL
(reserve_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY
,reserve_pub BYTEA PRIMARY KEY CHECK(LENGTH(reserve_pub)=32)
,current_balance_val INT8 NOT NULL
,current_balance_frac INT4 NOT NULL
@ -130,7 +130,7 @@ COMMENT ON INDEX reserves_by_gc_date_index
CREATE TABLE IF NOT EXISTS reserves_in
(reserve_in_serial_id BIGSERIAL -- UNIQUE
(reserve_in_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,reserve_pub BYTEA PRIMARY KEY REFERENCES reserves (reserve_pub) ON DELETE CASCADE
,wire_reference INT8 NOT NULL
,credit_val INT8 NOT NULL
@ -168,7 +168,7 @@ CREATE INDEX IF NOT EXISTS reserves_in_by_exchange_account_reserve_in_serial_id_
CREATE TABLE IF NOT EXISTS reserves_close
(close_uuid BIGSERIAL -- UNIQUE / PRIMARY KEY
(close_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE / PRIMARY KEY
,reserve_pub BYTEA NOT NULL REFERENCES reserves (reserve_pub) ON DELETE CASCADE
,execution_date INT8 NOT NULL
,wtid BYTEA NOT NULL CHECK (LENGTH(wtid)=32)
@ -195,8 +195,7 @@ CREATE INDEX IF NOT EXISTS reserves_close_by_reserve_pub_index
CREATE TABLE IF NOT EXISTS reserves_out
(reserve_out_serial_id BIGSERIAL -- UNIQUE
,wih BYTEA PRIMARY KEY CHECK (LENGTH(wih)=64)
(reserve_out_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,h_blind_ev BYTEA CHECK (LENGTH(h_blind_ev)=64) -- UNIQUE
,denominations_serial INT8 NOT NULL REFERENCES denominations (denominations_serial)
,denom_sig BYTEA NOT NULL
@ -206,11 +205,9 @@ CREATE TABLE IF NOT EXISTS reserves_out
,amount_with_fee_val INT8 NOT NULL
,amount_with_fee_frac INT4 NOT NULL
)
PARTITION BY HASH (wih);
PARTITION BY HASH (h_blind_ev);
COMMENT ON TABLE reserves_out
IS 'Withdraw operations performed on reserves.';
COMMENT ON COLUMN reserves_out.wih
IS 'Hash that uniquely identifies the withdraw request. Used to detect request replays (crucial for CS) and to check the withdraw existed during recoup.';
COMMENT ON COLUMN reserves_out.h_blind_ev
IS 'Hash of the blinded coin, used as primary key here so that broken clients that use a non-random coin or blinding factor fail to withdraw (otherwise they would fail on deposit when the coin is not unique there).';
COMMENT ON COLUMN reserves_out.denominations_serial
@ -230,7 +227,7 @@ COMMENT ON INDEX reserves_out_by_reserve_uuid_and_execution_date_index
CREATE TABLE IF NOT EXISTS auditors
(auditor_uuid BIGSERIAL UNIQUE
(auditor_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,auditor_pub BYTEA PRIMARY KEY CHECK (LENGTH(auditor_pub)=32)
,auditor_name VARCHAR NOT NULL
,auditor_url VARCHAR NOT NULL
@ -250,7 +247,7 @@ COMMENT ON COLUMN auditors.last_change
CREATE TABLE IF NOT EXISTS auditor_denom_sigs
(auditor_denom_serial BIGSERIAL UNIQUE
(auditor_denom_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,auditor_uuid INT8 NOT NULL REFERENCES auditors (auditor_uuid) ON DELETE CASCADE
,denominations_serial INT8 NOT NULL REFERENCES denominations (denominations_serial) ON DELETE CASCADE
,auditor_sig BYTEA CHECK (LENGTH(auditor_sig)=64)
@ -267,7 +264,7 @@ COMMENT ON COLUMN auditor_denom_sigs.auditor_sig
CREATE TABLE IF NOT EXISTS exchange_sign_keys
(esk_serial BIGSERIAL UNIQUE
(esk_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,exchange_pub BYTEA PRIMARY KEY CHECK (LENGTH(exchange_pub)=32)
,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
,valid_from INT8 NOT NULL
@ -289,7 +286,7 @@ COMMENT ON COLUMN exchange_sign_keys.expire_legal
CREATE TABLE IF NOT EXISTS signkey_revocations
(signkey_revocations_serial_id BIGSERIAL UNIQUE
(signkey_revocations_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,esk_serial INT8 PRIMARY KEY REFERENCES exchange_sign_keys (esk_serial) ON DELETE CASCADE
,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
);
@ -298,7 +295,7 @@ COMMENT ON TABLE signkey_revocations
CREATE TABLE IF NOT EXISTS extensions
(extension_id BIGSERIAL UNIQUE
(extension_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,name VARCHAR NOT NULL UNIQUE
,config BYTEA
);
@ -311,7 +308,7 @@ COMMENT ON COLUMN extensions.config
CREATE TABLE IF NOT EXISTS known_coins
(known_coin_id BIGSERIAL -- UNIQUE
(known_coin_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,denominations_serial INT8 NOT NULL REFERENCES denominations (denominations_serial) ON DELETE CASCADE
,coin_pub BYTEA NOT NULL PRIMARY KEY CHECK (LENGTH(coin_pub)=32)
,age_hash BYTEA CHECK (LENGTH(age_hash)=32)
@ -342,7 +339,7 @@ CREATE INDEX IF NOT EXISTS known_coins_by_known_coin_id_index
CREATE TABLE IF NOT EXISTS refresh_commitments
(melt_serial_id BIGSERIAL -- UNIQUE
(melt_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,rc BYTEA PRIMARY KEY CHECK (LENGTH(rc)=64)
,old_coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) ON DELETE CASCADE
,h_age_commitment BYTEA CHECK(LENGTH(h_age_commitment)=32)
@ -375,7 +372,7 @@ CREATE INDEX IF NOT EXISTS refresh_commitments_by_old_coin_pub_index
CREATE TABLE IF NOT EXISTS refresh_revealed_coins
(rrc_serial BIGSERIAL -- UNIQUE
(rrc_serial BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,melt_serial_id INT8 NOT NULL -- REFERENCES refresh_commitments (melt_serial_id) ON DELETE CASCADE
,freshcoin_index INT4 NOT NULL
,link_sig BYTEA NOT NULL CHECK(LENGTH(link_sig)=64)
@ -419,7 +416,7 @@ CREATE INDEX IF NOT EXISTS refresh_revealed_coins_by_melt_serial_id_index
CREATE TABLE IF NOT EXISTS refresh_transfer_keys
(rtc_serial BIGSERIAL -- UNIQUE
(rtc_serial BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,melt_serial_id INT8 PRIMARY KEY -- REFERENCES refresh_commitments (melt_serial_id) ON DELETE CASCADE
,transfer_pub BYTEA NOT NULL CHECK(LENGTH(transfer_pub)=32)
,transfer_privs BYTEA NOT NULL
@ -445,7 +442,7 @@ CREATE INDEX IF NOT EXISTS refresh_transfer_keys_by_rtc_serial_index
CREATE TABLE IF NOT EXISTS extension_details
(extension_details_serial_id BIGSERIAL PRIMARY KEY
(extension_details_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
,extension_options VARCHAR);
COMMENT ON TABLE extension_details
IS 'Extensions that were provided with deposits (not yet used).';
@ -454,7 +451,7 @@ COMMENT ON COLUMN extension_details.extension_options
CREATE TABLE IF NOT EXISTS deposits
(deposit_serial_id BIGSERIAL -- PRIMARY KEY
(deposit_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- PRIMARY KEY
,shard INT8 NOT NULL
,known_coin_id INT8 NOT NULL -- REFERENCES known_coins (known_coin_id) ON DELETE CASCADE
,amount_with_fee_val INT8 NOT NULL
@ -526,7 +523,7 @@ COMMENT ON INDEX deposits_for_iterate_matching_index
CREATE TABLE IF NOT EXISTS refunds
(refund_serial_id BIGSERIAL -- UNIQUE
(refund_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,deposit_serial_id INT8 NOT NULL -- REFERENCES deposits (deposit_serial_id) ON DELETE CASCADE
,merchant_sig BYTEA NOT NULL CHECK(LENGTH(merchant_sig)=64)
,rtransaction_id INT8 NOT NULL
@ -553,7 +550,7 @@ CREATE INDEX IF NOT EXISTS refunds_by_refund_serial_id_index
CREATE TABLE IF NOT EXISTS wire_out
(wireout_uuid BIGSERIAL -- PRIMARY KEY
(wireout_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY -- PRIMARY KEY
,execution_date INT8 NOT NULL
,wtid_raw BYTEA UNIQUE NOT NULL CHECK (LENGTH(wtid_raw)=32)
,wire_target_serial_id INT8 NOT NULL -- REFERENCES wire_targets (wire_target_serial_id)
@ -582,7 +579,7 @@ CREATE INDEX IF NOT EXISTS wire_out_by_wire_target_serial_id_index
CREATE TABLE IF NOT EXISTS aggregation_tracking
(aggregation_serial_id BIGSERIAL -- UNIQUE
(aggregation_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,deposit_serial_id INT8 PRIMARY KEY -- REFERENCES deposits (deposit_serial_id) ON DELETE CASCADE
,wtid_raw BYTEA CONSTRAINT wire_out_ref REFERENCES wire_out(wtid_raw) ON DELETE CASCADE DEFERRABLE
)
@ -606,7 +603,7 @@ COMMENT ON INDEX aggregation_tracking_by_wtid_raw_index
CREATE TABLE IF NOT EXISTS wire_fee
(wire_fee_serial BIGSERIAL UNIQUE
(wire_fee_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,wire_method VARCHAR NOT NULL
,start_date INT8 NOT NULL
,end_date INT8 NOT NULL
@ -628,7 +625,7 @@ CREATE INDEX IF NOT EXISTS wire_fee_by_end_date_index
CREATE TABLE IF NOT EXISTS recoup
(recoup_uuid BIGSERIAL -- UNIQUE
(recoup_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,known_coin_id INT8 NOT NULL -- REFERENCES known_coins (known_coin_id)
,coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64)
,coin_blind BYTEA NOT NULL CHECK(LENGTH(coin_blind)=32)
@ -643,7 +640,7 @@ COMMENT ON TABLE recoup
COMMENT ON COLUMN recoup.known_coin_id
IS 'Coin that is being debited in the recoup. Do not CASCADE ON DROP on the coin_pub, as we may keep the coin alive!';
COMMENT ON COLUMN recoup.reserve_out_serial_id
IS 'Identifies the wih of the recouped coin and provides the link to the credited reserve.';
IS 'Identifies the h_blind_ev of the recouped coin and provides the link to the credited reserve.';
COMMENT ON COLUMN recoup.coin_sig
IS 'Signature by the coin affirming the recoup, of type TALER_SIGNATURE_WALLET_COIN_RECOUP';
COMMENT ON COLUMN recoup.coin_blind
@ -664,7 +661,7 @@ CREATE INDEX IF NOT EXISTS recoup_by_known_coin_id_index
CREATE TABLE IF NOT EXISTS recoup_refresh
(recoup_refresh_uuid BIGSERIAL -- UNIQUE
(recoup_refresh_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,known_coin_id INT8 NOT NULL -- REFERENCES known_coins (known_coin_id)
,coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64)
,coin_blind BYTEA NOT NULL CHECK(LENGTH(coin_blind)=32)
@ -698,7 +695,7 @@ CREATE INDEX IF NOT EXISTS recoup_refresh_by_known_coin_id_index
CREATE TABLE IF NOT EXISTS prewire
(prewire_uuid BIGSERIAL PRIMARY KEY
(prewire_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
,wire_method TEXT NOT NULL
,finished BOOLEAN NOT NULL DEFAULT false
,failed BOOLEAN NOT NULL DEFAULT false
@ -746,12 +743,29 @@ COMMENT ON COLUMN wire_accounts.is_active
IS 'true if we are currently supporting the use of this account.';
COMMENT ON COLUMN wire_accounts.last_change
IS 'Latest time when active status changed. Used to detect replays of old messages.';
-- "wire_accounts" has no BIGSERIAL because it is a 'mutable' table
-- "wire_accounts" has no sequence because it is a 'mutable' table
-- and is of no concern to the auditor
CREATE TABLE IF NOT EXISTS cs_nonce_locks
(cs_nonce_lock_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,nonce BYTEA PRIMARY KEY CHECK (LENGTH(nonce)=32)
,op_hash BYTEA NOT NULL CHECK (LENGTH(op_hash)=64)
,max_denomination_serial INT8 NOT NULL
)
PARTITION BY HASH (nonce);
COMMENT ON TABLE cs_nonce_locks
IS 'ensures a Clause Schnorr client nonce is locked for use with an operation identified by a hash';
COMMENT ON COLUMN cs_nonce_locks.nonce
IS 'actual nonce submitted by the client';
COMMENT ON COLUMN cs_nonce_locks.op_hash
IS 'hash (RC for refresh, blind coin hash for withdraw) the nonce may be used with';
COMMENT ON COLUMN cs_nonce_locks.max_denomination_serial
IS 'Maximum number of a CS denomination serial the nonce could be used with, for GC';
CREATE TABLE IF NOT EXISTS work_shards
(shard_serial_id BIGSERIAL UNIQUE
(shard_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,last_attempt INT8 NOT NULL
,start_row INT8 NOT NULL
,end_row INT8 NOT NULL
@ -783,7 +797,7 @@ CREATE INDEX IF NOT EXISTS work_shards_by_job_name_completed_last_attempt_index
CREATE UNLOGGED TABLE IF NOT EXISTS revolving_work_shards
(shard_serial_id BIGSERIAL UNIQUE
(shard_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,last_attempt INT8 NOT NULL
,start_row INT4 NOT NULL
,end_row INT4 NOT NULL
@ -818,7 +832,7 @@ CREATE INDEX IF NOT EXISTS revolving_work_shards_by_job_name_active_last_attempt
CREATE OR REPLACE FUNCTION exchange_do_withdraw(
IN in_wih BYTEA,
IN cs_nonce BYTEA,
IN amount_val INT8,
IN amount_frac INT4,
IN h_denom_pub BYTEA,
@ -832,8 +846,7 @@ CREATE OR REPLACE FUNCTION exchange_do_withdraw(
OUT balance_ok BOOLEAN,
OUT kycok BOOLEAN,
OUT account_uuid INT8,
OUT ruuid INT8,
OUT out_denom_sig BYTEA)
OUT ruuid INT8)
LANGUAGE plpgsql
AS $$
DECLARE
@ -851,7 +864,8 @@ BEGIN
-- reserves_in by reserve_pub (SELECT)
-- wire_targets by wire_target_serial_id
SELECT denominations_serial INTO denom_serial
SELECT denominations_serial
INTO denom_serial
FROM denominations
WHERE denom_pub_hash=h_denom_pub;
@ -867,6 +881,7 @@ THEN
RETURN;
END IF;
SELECT
current_balance_val
,current_balance_frac
@ -887,7 +902,7 @@ THEN
balance_ok=FALSE;
kycok=FALSE;
account_uuid=0;
ruuid=0;
ruuid=2;
RETURN;
END IF;
@ -895,7 +910,6 @@ END IF;
-- the query successful due to idempotency.
INSERT INTO reserves_out
(h_blind_ev
,wih
,denominations_serial
,denom_sig
,reserve_uuid
@ -905,7 +919,6 @@ INSERT INTO reserves_out
,amount_with_fee_frac)
VALUES
(h_coin_envelope
,in_wih
,denom_serial
,denom_sig
,ruuid
@ -918,25 +931,6 @@ ON CONFLICT DO NOTHING;
IF NOT FOUND
THEN
-- idempotent query, all constraints must be satisfied
SELECT
denom_sig
INTO
out_denom_sig
FROM reserves_in
WHERE wih=in_wih
LIMIT 1; -- limit 1 should not be required (without p2p transfers)
IF NOT FOUND
THEN
reserve_found=FALSE;
balance_ok=FALSE;
kycok=FALSE;
account_uuid=0;
ruuid=0;
ASSERT false, 'internal logic error';
END IF;
reserve_found=TRUE;
balance_ok=TRUE;
kycok=TRUE;
@ -983,6 +977,44 @@ WHERE
reserve_found=TRUE;
balance_ok=TRUE;
-- Special actions needed for a CS withdraw?
IF NOT NULL cs_nonce
THEN
-- Cache CS signature to prevent replays in the future
-- (and check if cached signature exists at the same time).
INSERT INTO cs_nonce_locks
(nonce
,max_denomination_serial
,op_hash)
VALUES
(cs_nonce
,denom_serial
,h_coin_envelope)
ON CONFLICT DO NOTHING;
IF NOT FOUND
THEN
-- See if the existing entry is identical.
SELECT 1
FROM cs_nonce_locks
WHERE nonce=cs_nonce
AND op_hash=h_coin_envelope;
IF NOT FOUND
THEN
reserve_found=FALSE;
balance_ok=FALSE;
kycok=FALSE;
account_uuid=0;
ruuid=1; -- FIXME: return error message more nicely!
ASSERT false, 'nonce reuse attempted by client';
END IF;
END IF;
END IF;
-- Obtain KYC status based on the last wire transfer into
-- this reserve. FIXME: likely not adequate for reserves that got P2P transfers!
SELECT
@ -996,9 +1028,6 @@ SELECT
WHERE reserve_pub=rpub
LIMIT 1; -- limit 1 should not be required (without p2p transfers)
-- Return denomination signature as result that
-- was given as the argument.
out_denom_sig=denom_sig;
END $$;
@ -1223,6 +1252,7 @@ END $$;
CREATE OR REPLACE FUNCTION exchange_do_melt(
IN in_cs_rms BYTEA,
IN in_amount_with_fee_val INT8,
IN in_amount_with_fee_frac INT4,
IN in_rc BYTEA,
@ -1236,6 +1266,8 @@ CREATE OR REPLACE FUNCTION exchange_do_melt(
OUT out_noreveal_index INT4)
LANGUAGE plpgsql
AS $$
DECLARE
denom_max INT8;
BEGIN
-- Shards: INSERT refresh_commitments (by rc)
-- (rare:) SELECT refresh_commitments (by old_coin_pub) -- crosses shards!
@ -1333,6 +1365,56 @@ THEN
RETURN;
END IF;
-- Special actions needed for a CS melt?
IF NOT NULL in_cs_rms
THEN
-- Get maximum denominations serial value in
-- existence, this will determine how long the
-- nonce will be locked.
SELECT
denominations_serial
INTO
denom_max
FROM denominations
ORDER BY denominations_serial DESC
LIMIT 1;
-- Cache CS signature to prevent replays in the future
-- (and check if cached signature exists at the same time).
INSERT INTO cs_nonce_locks
(nonce
,max_denomination_serial
,op_hash)
VALUES
(cs_rms
,denom_serial
,in_rc)
ON CONFLICT DO NOTHING;
IF NOT FOUND
THEN
-- Record exists, make sure it is the same
SELECT 1
FROM cs_nonce_locks
WHERE nonce=cs_rms
AND op_hash=in_rc;
IF NOT FOUND
THEN
-- Nonce reuse detected
out_balance_ok=FALSE;
out_zombie_bad=FALSE;
out_noreveal_index=42; -- FIXME: return error message more nicely!
ASSERT false, 'nonce reuse attempted by client';
END IF;
END IF;
END IF;
-- Everything fine, return success!
out_balance_ok=TRUE;
out_noreveal_index=in_noreveal_index;
@ -1806,6 +1888,8 @@ DECLARE
deposit_min INT8; -- minimum deposit still alive
DECLARE
reserve_out_min INT8; -- minimum reserve_out still alive
DECLARE
denom_min INT8; -- minimum denomination still alive
BEGIN
DELETE FROM prewire
@ -1901,6 +1985,16 @@ DELETE FROM refunds
DELETE FROM aggregation_tracking
WHERE deposit_serial_id < deposit_min;
SELECT
denominations_serial
INTO
denom_min
FROM denominations
ORDER BY denominations_serial ASC
LIMIT 1;
DELETE FROM cs_nonce_locks
WHERE max_denomination_serial <= denom_min;
END $$;

View File

@ -53,13 +53,13 @@ irbt_cb_table_denominations (struct PostgresClosure *pg,
&td->details.denominations.expire_legal),
TALER_PQ_query_param_amount (&td->details.denominations.coin),
TALER_PQ_query_param_amount (
&td->details.denominations.fee_withdraw),
&td->details.denominations.fees.withdraw),
TALER_PQ_query_param_amount (
&td->details.denominations.fee_deposit),
&td->details.denominations.fees.deposit),
TALER_PQ_query_param_amount (
&td->details.denominations.fee_refresh),
&td->details.denominations.fees.refresh),
TALER_PQ_query_param_amount (
&td->details.denominations.fee_refund),
&td->details.denominations.fees.refund),
GNUNET_PQ_query_param_end
};

View File

@ -80,16 +80,16 @@ lrbt_cb_table_denominations (void *cls,
&td.details.denominations.coin),
TALER_PQ_RESULT_SPEC_AMOUNT (
"fee_withdraw",
&td.details.denominations.fee_withdraw),
&td.details.denominations.fees.withdraw),
TALER_PQ_RESULT_SPEC_AMOUNT (
"fee_deposit",
&td.details.denominations.fee_deposit),
&td.details.denominations.fees.deposit),
TALER_PQ_RESULT_SPEC_AMOUNT (
"fee_refresh",
&td.details.denominations.fee_refresh),
&td.details.denominations.fees.refresh),
TALER_PQ_RESULT_SPEC_AMOUNT (
"fee_refund",
&td.details.denominations.fee_refund),
&td.details.denominations.fees.refund),
GNUNET_PQ_result_spec_end
};

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014--2021 Taler Systems SA
Copyright (C) 2014--2022 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@ -579,7 +579,6 @@ prepare_statements (struct PostgresClosure *pg)
",kycok AS kyc_ok"
",account_uuid AS payment_target_uuid"
",ruuid"
",out_denom_sig"
" FROM exchange_do_withdraw"
" ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);",
10),
@ -612,8 +611,8 @@ prepare_statements (struct PostgresClosure *pg)
",out_zombie_bad AS zombie_required"
",out_noreveal_index AS noreveal_index"
" FROM exchange_do_melt"
" ($1,$2,$3,$4,$5,$6,$7,$8);",
8),
" ($1,$2,$3,$4,$5,$6,$7,$8,$9);",
9),
/* Used in #postgres_do_refund() to refund a deposit. */
GNUNET_PQ_make_prepare (
"call_refund",
@ -667,7 +666,7 @@ prepare_statements (struct PostgresClosure *pg)
" USING (reserve_uuid)"
" JOIN denominations denom"
" USING (denominations_serial)"
" WHERE wih=$1;",
" WHERE h_blind_ev=$1;",
1),
/* Used during #postgres_get_reserve_history() to
obtain all of the /reserve/withdraw operations that
@ -1672,16 +1671,16 @@ prepare_statements (struct PostgresClosure *pg)
" ON (denoms.denominations_serial = coins.denominations_serial)"
" WHERE coins.coin_pub=$1;",
1),
/* Used in #postgres_get_reserve_by_wih() */
/* Used in #postgres_get_reserve_by_h_blind() */
GNUNET_PQ_make_prepare (
"reserve_by_wih",
"reserve_by_h_blind",
"SELECT"
" reserves.reserve_pub"
",reserve_out_serial_id"
" FROM reserves_out"
" JOIN reserves"
" USING (reserve_uuid)"
" WHERE wih=$1"
" WHERE h_blind_ev=$1"
" LIMIT 1;",
1),
/* Used in #postgres_get_old_coin_by_h_blind() */
@ -3091,6 +3090,7 @@ postgres_insert_denomination_info (
const struct TALER_EXCHANGEDB_DenominationKeyInformationP *issue)
{
struct PostgresClosure *pg = cls;
uint32_t age_mask = 0; /* FIXME-OEC */
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (&issue->properties.denom_hash),
TALER_PQ_query_param_denom_pub (denom_pub),
@ -3100,13 +3100,14 @@ postgres_insert_denomination_info (
GNUNET_PQ_query_param_timestamp_nbo (&issue->properties.expire_deposit),
GNUNET_PQ_query_param_timestamp_nbo (&issue->properties.expire_legal),
TALER_PQ_query_param_amount_nbo (&issue->properties.value),
TALER_PQ_query_param_amount_nbo (&issue->properties.fee_withdraw),
TALER_PQ_query_param_amount_nbo (&issue->properties.fee_deposit),
TALER_PQ_query_param_amount_nbo (&issue->properties.fee_refresh),
TALER_PQ_query_param_amount_nbo (&issue->properties.fee_refund),
GNUNET_PQ_query_param_uint32 (&denom_pub->age_mask.mask),
TALER_PQ_query_param_amount_nbo (&issue->properties.fees.withdraw),
TALER_PQ_query_param_amount_nbo (&issue->properties.fees.deposit),
TALER_PQ_query_param_amount_nbo (&issue->properties.fees.refresh),
TALER_PQ_query_param_amount_nbo (&issue->properties.fees.refund),
GNUNET_PQ_query_param_uint32 (&age_mask),
GNUNET_PQ_query_param_end
};
struct TALER_DenomFeeSet fees;
GNUNET_assert (denom_pub->age_mask.mask == issue->age_mask.mask);
@ -3122,20 +3123,13 @@ postgres_insert_denomination_info (
GNUNET_assert (! GNUNET_TIME_absolute_is_zero (
GNUNET_TIME_timestamp_ntoh (
issue->properties.expire_legal).abs_time));
/* check fees match coin currency */
/* check fees match denomination currency */
TALER_denom_fee_set_ntoh (&fees,
&issue->properties.fees);
GNUNET_assert (GNUNET_YES ==
TALER_amount_cmp_currency_nbo (&issue->properties.value,
&issue->properties.fee_withdraw));
GNUNET_assert (GNUNET_YES ==
TALER_amount_cmp_currency_nbo (&issue->properties.value,
&issue->properties.fee_deposit));
GNUNET_assert (GNUNET_YES ==
TALER_amount_cmp_currency_nbo (&issue->properties.value,
&issue->properties.fee_refresh));
GNUNET_assert (GNUNET_YES ==
TALER_amount_cmp_currency_nbo (&issue->properties.value,
&issue->properties.fee_refund));
TALER_denom_fee_check_currency (
issue->properties.value.currency,
&fees));
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
"denomination_insert",
params);
@ -3176,13 +3170,13 @@ postgres_get_denomination_info (
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("coin",
&issue->properties.value),
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_withdraw",
&issue->properties.fee_withdraw),
&issue->properties.fees.withdraw),
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_deposit",
&issue->properties.fee_deposit),
&issue->properties.fees.deposit),
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refresh",
&issue->properties.fee_refresh),
&issue->properties.fees.refresh),
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refund",
&issue->properties.fee_refund),
&issue->properties.fees.refund),
GNUNET_PQ_result_spec_uint32 ("age_mask",
&issue->age_mask.mask),
GNUNET_PQ_result_spec_end
@ -3262,13 +3256,13 @@ domination_cb_helper (void *cls,
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("coin",
&issue.properties.value),
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_withdraw",
&issue.properties.fee_withdraw),
&issue.properties.fees.withdraw),
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_deposit",
&issue.properties.fee_deposit),
&issue.properties.fees.deposit),
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refresh",
&issue.properties.fee_refresh),
&issue.properties.fees.refresh),
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refund",
&issue.properties.fee_refund),
&issue.properties.fees.refund),
TALER_PQ_result_spec_denom_pub ("denom_pub",
&denom_pub),
GNUNET_PQ_result_spec_uint32 ("age_mask",
@ -3401,13 +3395,13 @@ dominations_cb_helper (void *cls,
TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
&meta.value),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
&meta.fee_withdraw),
&meta.fees.withdraw),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
&meta.fee_deposit),
&meta.fees.deposit),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
&meta.fee_refresh),
&meta.fees.refresh),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
&meta.fee_refund),
&meta.fees.refund),
TALER_PQ_result_spec_denom_pub ("denom_pub",
&denom_pub),
GNUNET_PQ_result_spec_uint32 ("age_mask",
@ -4328,7 +4322,7 @@ postgres_reserves_in_insert (void *cls,
* key of the hash of the blinded message.
*
* @param cls the `struct PostgresClosure` with the plugin-specific state
* @param wih hash that uniquely identifies the withdraw operation
* @param bch hash that uniquely identifies the withdraw operation
* @param collectable corresponding collectable coin (blind signature)
* if a coin is found
* @return statement execution status
@ -4336,12 +4330,12 @@ postgres_reserves_in_insert (void *cls,
static enum GNUNET_DB_QueryStatus
postgres_get_withdraw_info (
void *cls,
const struct TALER_WithdrawIdentificationHash *wih,
const struct TALER_BlindedCoinHash *bch,
struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable)
{
struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (wih),
GNUNET_PQ_query_param_auto_from_type (bch),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_ResultSpec rs[] = {
@ -4374,7 +4368,7 @@ postgres_get_withdraw_info (
* and possibly persisting the withdrawal details.
*
* @param cls the `struct PostgresClosure` with the plugin-specific state
* @param wih hash that uniquely identifies the withdraw operation
* @param nonce client-contributed input for CS denominations that must be checked for idempotency, or NULL for non-CS withdrawals
* @param[in,out] collectable corresponding collectable coin (blind signature) if a coin is found; possibly updated if a (different) signature exists already
* @param now current time (rounded)
* @param[out] found set to true if the reserve was found
@ -4386,8 +4380,8 @@ postgres_get_withdraw_info (
static enum GNUNET_DB_QueryStatus
postgres_do_withdraw (
void *cls,
const struct TALER_WithdrawIdentificationHash *wih,
struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable,
const struct TALER_CsNonce *nonce,
const struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable,
struct GNUNET_TIME_Timestamp now,
bool *found,
bool *balance_ok,
@ -4397,7 +4391,9 @@ postgres_do_withdraw (
struct PostgresClosure *pg = cls;
struct GNUNET_TIME_Timestamp gc;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (wih),
NULL == nonce
? GNUNET_PQ_query_param_null ()
: GNUNET_PQ_query_param_auto_from_type (nonce),
TALER_PQ_query_param_amount (&collectable->amount_with_fee),
GNUNET_PQ_query_param_auto_from_type (&collectable->denom_pub_hash),
GNUNET_PQ_query_param_auto_from_type (&collectable->reserve_pub),
@ -4408,9 +4404,6 @@ postgres_do_withdraw (
GNUNET_PQ_query_param_timestamp (&gc),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
bool no_out_sig;
struct TALER_BlindedDenominationSignature out_sig;
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_bool ("reserve_found",
found),
@ -4422,33 +4415,17 @@ postgres_do_withdraw (
&kyc->payment_target_uuid),
GNUNET_PQ_result_spec_uint64 ("ruuid",
ruuid),
GNUNET_PQ_result_spec_allow_null (
TALER_PQ_result_spec_blinded_denom_sig ("out_denom_sig",
&out_sig),
&no_out_sig),
GNUNET_PQ_result_spec_end
};
#if 0
memset (&out_sig,
0,
sizeof (out_sig));
#endif
gc = GNUNET_TIME_absolute_to_timestamp (
GNUNET_TIME_absolute_add (now.abs_time,
pg->legal_reserve_expiration_time));
kyc->type = TALER_EXCHANGEDB_KYC_WITHDRAW;
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
"call_withdraw",
params,
rs);
if ( (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) &&
(! no_out_sig) )
{
TALER_blinded_denom_sig_free (&collectable->sig);
collectable->sig = out_sig;
}
return qs;
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
"call_withdraw",
params,
rs);
}
@ -4600,6 +4577,7 @@ postgres_do_deposit (
static enum GNUNET_DB_QueryStatus
postgres_do_melt (
void *cls,
const struct TALER_RefreshMasterSecretP *rms,
struct TALER_EXCHANGEDB_Refresh *refresh,
uint64_t known_coin_id,
bool *zombie_required,
@ -4607,6 +4585,9 @@ postgres_do_melt (
{
struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = {
NULL == rms
? GNUNET_PQ_query_param_null ()
: GNUNET_PQ_query_param_auto_from_type (rms),
TALER_PQ_query_param_amount (&refresh->amount_with_fee),
GNUNET_PQ_query_param_auto_from_type (&refresh->rc),
GNUNET_PQ_query_param_auto_from_type (&refresh->coin.coin_pub),
@ -9428,21 +9409,21 @@ postgres_select_reserve_closed_above_serial_id (
* from given the hash of the blinded coin.
*
* @param cls closure
* @param wih hash that uniquely identifies the withdraw request
* @param bch hash that uniquely identifies the withdraw request
* @param[out] reserve_pub set to information about the reserve (on success only)
* @param[out] reserve_out_serial_id set to row of the @a h_blind_ev in reserves_out
* @return transaction status code
*/
static enum GNUNET_DB_QueryStatus
postgres_get_reserve_by_wih (
postgres_get_reserve_by_h_blind (
void *cls,
const struct TALER_WithdrawIdentificationHash *wih,
const struct TALER_BlindedCoinHash *bch,
struct TALER_ReservePublicKeyP *reserve_pub,
uint64_t *reserve_out_serial_id)
{
struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (wih),
GNUNET_PQ_query_param_auto_from_type (bch),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_ResultSpec rs[] = {
@ -9454,7 +9435,7 @@ postgres_get_reserve_by_wih (
};
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
"reserve_by_wih",
"reserve_by_h_blind",
params,
rs);
}
@ -10241,13 +10222,13 @@ postgres_lookup_denomination_key (
TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
&meta->value),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
&meta->fee_withdraw),
&meta->fees.withdraw),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
&meta->fee_deposit),
&meta->fees.deposit),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
&meta->fee_refresh),
&meta->fees.refresh),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
&meta->fee_refund),
&meta->fees.refund),
GNUNET_PQ_result_spec_uint32 ("age_mask",
&meta->age_mask.mask),
GNUNET_PQ_result_spec_end
@ -10289,27 +10270,18 @@ postgres_add_denomination_key (
GNUNET_PQ_query_param_timestamp (&meta->expire_deposit),
GNUNET_PQ_query_param_timestamp (&meta->expire_legal),
TALER_PQ_query_param_amount (&meta->value),
TALER_PQ_query_param_amount (&meta->fee_withdraw),
TALER_PQ_query_param_amount (&meta->fee_deposit),
TALER_PQ_query_param_amount (&meta->fee_refresh),
TALER_PQ_query_param_amount (&meta->fee_refund),
TALER_PQ_query_param_amount (&meta->fees.withdraw),
TALER_PQ_query_param_amount (&meta->fees.deposit),
TALER_PQ_query_param_amount (&meta->fees.refresh),
TALER_PQ_query_param_amount (&meta->fees.refund),
GNUNET_PQ_query_param_uint32 (&meta->age_mask.mask),
GNUNET_PQ_query_param_end
};
/* Sanity check: ensure fees match coin currency */
GNUNET_assert (GNUNET_YES ==
TALER_amount_cmp_currency (&meta->value,
&meta->fee_withdraw));
GNUNET_assert (GNUNET_YES ==
TALER_amount_cmp_currency (&meta->value,
&meta->fee_deposit));
GNUNET_assert (GNUNET_YES ==
TALER_amount_cmp_currency (&meta->value,
&meta->fee_refresh));
GNUNET_assert (GNUNET_YES ==
TALER_amount_cmp_currency (&meta->value,
&meta->fee_refund));
TALER_denom_fee_check_currency (meta->value.currency,
&meta->fees));
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
"denomination_insert",
iparams);
@ -11722,8 +11694,8 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
= &postgres_select_recoup_refresh_above_serial_id;
plugin->select_reserve_closed_above_serial_id
= &postgres_select_reserve_closed_above_serial_id;
plugin->get_reserve_by_wih
= &postgres_get_reserve_by_wih;
plugin->get_reserve_by_h_blind
= &postgres_get_reserve_by_h_blind;
plugin->get_old_coin_by_h_blind
= &postgres_get_old_coin_by_h_blind;
plugin->insert_denomination_revocation

View File

@ -263,20 +263,14 @@ destroy_denom_key_pair (struct DenomKeyPair *dkp)
*
* @param size the size of the denomination key
* @param now time to use for key generation, legal expiration will be 3h later.
* @param fee_withdraw withdraw fee to use
* @param fee_deposit deposit fee to use
* @param fee_refresh refresh fee to use
* @param fee_refund refund fee to use
* @param fees fees to use
* @return the denominaiton key pair; NULL upon error
*/
static struct DenomKeyPair *
create_denom_key_pair (unsigned int size,
struct GNUNET_TIME_Timestamp now,
const struct TALER_Amount *value,
const struct TALER_Amount *fee_withdraw,
const struct TALER_Amount *fee_deposit,
const struct TALER_Amount *fee_refresh,
const struct TALER_Amount *fee_refund)
const struct TALER_DenomFeeSet *fees)
{
struct DenomKeyPair *dkp;
struct TALER_EXCHANGEDB_DenominationKey dki;
@ -315,11 +309,10 @@ create_denom_key_pair (unsigned int size,
(now.abs_time,
GNUNET_TIME_relative_multiply (
GNUNET_TIME_UNIT_HOURS, 3))));
TALER_amount_hton (&dki.issue.properties.value, value);
TALER_amount_hton (&dki.issue.properties.fee_withdraw, fee_withdraw);
TALER_amount_hton (&dki.issue.properties.fee_deposit, fee_deposit);
TALER_amount_hton (&dki.issue.properties.fee_refresh, fee_refresh);
TALER_amount_hton (&dki.issue.properties.fee_refund, fee_refund);
TALER_amount_hton (&dki.issue.properties.value,
value);
TALER_denom_fee_set_hton (&dki.issue.properties.fees,
fees);
TALER_denom_pub_hash (&dkp->pub,
&dki.issue.properties.denom_hash);
@ -359,10 +352,7 @@ create_denom_key_pair (unsigned int size,
static struct TALER_Amount value;
static struct TALER_Amount fee_withdraw;
static struct TALER_Amount fee_deposit;
static struct TALER_Amount fee_refresh;
static struct TALER_Amount fee_refund;
static struct TALER_DenomFeeSet fees;
static struct TALER_Amount fee_closing;
static struct TALER_Amount amount_with_fee;
@ -881,10 +871,7 @@ test_gc (void)
dkp = create_denom_key_pair (RSA_KEY_SIZE,
past,
&value,
&fee_withdraw,
&fee_deposit,
&fee_refresh,
&fee_refund);
&fees);
GNUNET_assert (NULL != dkp);
if (GNUNET_OK !=
plugin->gc (plugin->cls))
@ -1080,7 +1067,7 @@ test_wire_out (const struct TALER_EXCHANGEDB_Deposit *deposit)
coin_pub_wt = deposit->coin.coin_pub;
coin_value_wt = deposit->amount_with_fee;
coin_fee_wt = fee_deposit;
coin_fee_wt = fees.deposit;
GNUNET_assert (0 <
TALER_amount_subtract (&transfer_value_wt,
&coin_value_wt,
@ -1349,7 +1336,6 @@ run (void *cls)
struct GNUNET_TIME_Timestamp now;
struct TALER_WireSaltP salt;
struct TALER_CoinPubHash c_hash;
struct TALER_WithdrawIdentificationHash wih;
uint64_t known_coin_id;
uint64_t rrc_serial;
struct TALER_EXCHANGEDB_Refresh refresh;
@ -1410,17 +1396,17 @@ run (void *cls)
&value));
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":0.000010",
&fee_withdraw));
&fees.withdraw));
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":0.000010",
&fee_deposit));
deposit.deposit_fee = fee_deposit;
&fees.deposit));
deposit.deposit_fee = fees.deposit;
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":0.000010",
&fee_refresh));
&fees.refresh));
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":0.000010",
&fee_refund));
&fees.refund));
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":1.000010",
&amount_with_fee));
@ -1464,10 +1450,7 @@ run (void *cls)
dkp = create_denom_key_pair (RSA_KEY_SIZE,
now,
&value,
&fee_withdraw,
&fee_deposit,
&fee_refresh,
&fee_refund);
&fees);
GNUNET_assert (NULL != dkp);
TALER_denom_pub_hash (&dkp->pub,
&cbc.denom_pub_hash);
@ -1502,10 +1485,7 @@ run (void *cls)
TALER_coin_ev_hash (&pd.blinded_planchet,
&cbc.denom_pub_hash,
&cbc.h_coin_envelope));
GNUNET_assert (GNUNET_OK ==
TALER_withdraw_request_hash (&pd.blinded_planchet,
&cbc.denom_pub_hash,
&wih)); GNUNET_assert (
GNUNET_assert (
GNUNET_OK ==
TALER_denom_sign_blinded (
&cbc.sig,
@ -1529,7 +1509,7 @@ run (void *cls)
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->do_withdraw (plugin->cls,
&wih,
NULL,
&cbc,
now,
&found,
@ -1551,16 +1531,16 @@ run (void *cls)
value.fraction,
value.currency));
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->get_reserve_by_wih (plugin->cls,
&wih,
&reserve_pub3,
&reserve_out_serial_id));
plugin->get_reserve_by_h_blind (plugin->cls,
&cbc.h_coin_envelope,
&reserve_pub3,
&reserve_out_serial_id));
FAILIF (0 != GNUNET_memcmp (&reserve_pub,
&reserve_pub3));
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->get_withdraw_info (plugin->cls,
&wih,
&cbc.h_coin_envelope,
&cbc2));
FAILIF (0 != GNUNET_memcmp (&cbc2.reserve_sig,
&cbc.reserve_sig));
@ -1649,12 +1629,12 @@ run (void *cls)
refund.details.h_contract_terms = deposit.h_contract_terms;
refund.details.rtransaction_id = 1;
refund.details.refund_amount = value;
refund.details.refund_fee = fee_refund;
refund.details.refund_fee = fees.refund;
RND_BLK (&refund.details.merchant_sig);
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->do_refund (plugin->cls,
&refund,
&fee_deposit,
&fees.deposit,
known_coin_id,
&not_found,
&refund_ok,
@ -1686,6 +1666,7 @@ run (void *cls)
refresh.noreveal_index = MELT_NOREVEAL_INDEX;
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->do_melt (plugin->cls,
NULL,
&refresh,
known_coin_id,
&zombie_required,
@ -1709,7 +1690,7 @@ run (void *cls)
TALER_amount_cmp (&refresh.amount_with_fee,
&ret_refresh_session.session.amount_with_fee));
FAILIF (0 !=
TALER_amount_cmp (&fee_refresh,
TALER_amount_cmp (&fees.refresh,
&ret_refresh_session.melt_fee));
FAILIF (0 !=
GNUNET_memcmp (&refresh.rc,
@ -1755,10 +1736,7 @@ run (void *cls)
new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
now,
&value,
&fee_withdraw,
&fee_deposit,
&fee_refresh,
&fee_refund);
&fees);
GNUNET_assert (NULL != new_dkp[cnt]);
new_denom_pubs[cnt] = new_dkp[cnt]->pub;
ccoin = &revealed_coins[cnt];
@ -2174,7 +2152,7 @@ run (void *cls)
memset (&deposit,
0,
sizeof (deposit));
deposit.deposit_fee = fee_deposit;
deposit.deposit_fee = fees.deposit;
RND_BLK (&deposit.coin.coin_pub);
TALER_denom_pub_hash (&dkp->pub,
&deposit.coin.denom_pub_hash);
@ -2196,7 +2174,7 @@ run (void *cls)
&deposit.wire_salt,
&h_wire_wt);
deposit.amount_with_fee = value;
deposit.deposit_fee = fee_deposit;
deposit.deposit_fee = fees.deposit;
deposit.refund_deadline = deadline;
deposit.wire_deadline = deadline;

View File

@ -184,6 +184,18 @@ enum GNUNET_GenericReturnValue
TALER_amount_is_valid (const struct TALER_Amount *amount);
/**
* Test if the given amount is in the given currency
*
* @param amount amount to check
* @param currency currency to check for
* @return #GNUNET_OK if @a amount is in @a currency
*/
enum GNUNET_GenericReturnValue
TALER_amount_is_currency (const struct TALER_Amount *amount,
const char *currency);
/**
* Convert amount from host to network representation.
*

View File

@ -563,22 +563,6 @@ struct TALER_BlindedCoinHash
};
/**
* Hash used to uniquely represent a withdraw process so as to perform
* idempotency checks (and prevent clients from harmfully replaying withdraw
* operations with problematic variations on the inputs). In the CS case,
* this is a hash over the DK and nonce, while in the RSA case, it is simply a
* hash over the DK and the blinded coin.
*/
struct TALER_WithdrawIdentificationHash
{
/**
* Actual hash value.
*/
struct GNUNET_HashCode hash;
};
/**
* Hash used to represent the hash of the public
* key of a coin (without blinding).
@ -629,9 +613,99 @@ struct TALER_ExtensionConfigHash
};
/**
* Set of the fees applying to a denomination.
*/
struct TALER_DenomFeeSetNBOP
{
/**
* The fee the exchange charges when a coin of this type is withdrawn.
* (can be zero).
*/
struct TALER_AmountNBO withdraw;
/**
* The fee the exchange charges when a coin of this type is deposited.
* (can be zero).
*/
struct TALER_AmountNBO deposit;
/**
* The fee the exchange charges when a coin of this type is refreshed.
* (can be zero).
*/
struct TALER_AmountNBO refresh;
/**
* The fee the exchange charges when a coin of this type is refunded.
* (can be zero). Note that refund fees are charged to the customer;
* if a refund is given, the deposit fee is also refunded.
*/
struct TALER_AmountNBO refund;
};
GNUNET_NETWORK_STRUCT_END
/**
* Set of the fees applying to a denomination.
*/
struct TALER_DenomFeeSet
{
/**
* The fee the exchange charges when a coin of this type is withdrawn.
* (can be zero).
*/
struct TALER_Amount withdraw;
/**
* The fee the exchange charges when a coin of this type is deposited.
* (can be zero).
*/
struct TALER_Amount deposit;
/**
* The fee the exchange charges when a coin of this type is refreshed.
* (can be zero).
*/
struct TALER_Amount refresh;
/**
* The fee the exchange charges when a coin of this type is refunded.
* (can be zero). Note that refund fees are charged to the customer;
* if a refund is given, the deposit fee is also refunded.
*/
struct TALER_Amount refund;
};
/**
* Convert fee set from host to network byte order.
*
* @param[out] nbo where to write the result
* @param fees fee set to convert
*/
void
TALER_denom_fee_set_hton (struct TALER_DenomFeeSetNBOP *nbo,
const struct TALER_DenomFeeSet *fees);
/**
* Convert fee set from network to host network byte order.
*
* @param[out] fees where to write the result
* @param nbo fee set to convert
*/
void
TALER_denom_fee_set_ntoh (struct TALER_DenomFeeSet *fees,
const struct TALER_DenomFeeSetNBOP *nbo);
/**
* Hash @a rsa.
*
@ -1357,22 +1431,6 @@ TALER_coin_ev_hash (const struct TALER_BlindedPlanchet *blinded_planchet,
struct TALER_BlindedCoinHash *bch);
/**
* Compute the hash to uniquely identify a withdraw
* request.
*
* @param blinded_planchet blinded planchet
* @param denom_hash hash of the denomination publick key
* @param[out] wih where to write the hash
* @return #GNUNET_OK when successful, #GNUNET_SYSERR if an internal error occured
*/
enum GNUNET_GenericReturnValue
TALER_withdraw_request_hash (
const struct TALER_BlindedPlanchet *blinded_planchet,
const struct TALER_DenominationHash *denom_hash,
struct TALER_WithdrawIdentificationHash *wih);
/**
* Compute the hash of a coin.
*
@ -1548,16 +1606,19 @@ TALER_transfer_secret_to_planchet_secret (
/**
* Derive the @a coin_num transfer private key @a tpriv from a refresh from
* the @a rms seed of the refresh operation. The transfer private key
* derivation is based on the @a ps with a KDF salted by the @a coin_num.
* the @a rms seed and the @a old_coin_pub of the refresh operation. The
* transfer private key derivation is based on the @a ps with a KDF salted by
* the @a coin_num.
*
* @param rms seed to use for KDF to derive transfer keys
* @param old_coin_priv private key of the old coin
* @param cnc_num cut and choose number to include in KDF
* @param[out] tpriv value to initialize
*/
void
TALER_planchet_secret_to_transfer_priv (
const struct TALER_RefreshMasterSecretP *rms,
const struct TALER_CoinSpendPrivateKeyP *old_coin_priv,
uint32_t cnc_num,
struct TALER_TransferPrivateKeyP *tpriv);
@ -1675,8 +1736,8 @@ TALER_planchet_to_coin (
* @param[in,out] hash_context hash context to use
*/
void
TALER_blinded_planchet_hash (const struct TALER_BlindedPlanchet *bp,
struct GNUNET_HashContext *hash_context);
TALER_blinded_planchet_hash_ (const struct TALER_BlindedPlanchet *bp,
struct GNUNET_HashContext *hash_context);
/**
@ -1769,6 +1830,7 @@ struct TALER_RefreshCommitmentEntry
*
* @param[out] rc set to the value the wallet must commit to
* @param kappa number of transfer public keys involved (must be #TALER_CNC_KAPPA)
* @param rms refresh master secret to include, can be NULL!
* @param num_new_coins number of new coins to be created
* @param rcs array of @a kappa commitments
* @param coin_pub public key of the coin to be melted
@ -1777,6 +1839,7 @@ struct TALER_RefreshCommitmentEntry
void
TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc,
uint32_t kappa,
const struct TALER_RefreshMasterSecretP *rms,
uint32_t num_new_coins,
const struct TALER_RefreshCommitmentEntry *rcs,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
@ -2723,10 +2786,7 @@ TALER_exchange_offline_signkey_validity_verify (
* @param stamp_expire_deposit how long does the exchange accept the deposit of coins with this key
* @param stamp_expire_legal how long does the exchange preserve information for legal disputes with this key
* @param coin_value what is the value of coins signed with this key
* @param fee_withdraw what withdraw fee does the exchange charge for this denomination
* @param fee_deposit what deposit fee does the exchange charge for this denomination
* @param fee_refresh what refresh fee does the exchange charge for this denomination
* @param fee_refund what refund fee does the exchange charge for this denomination
* @param fees fees for this denomination
* @param master_priv private key to sign with
* @param[out] master_sig where to write the signature
*/
@ -2738,10 +2798,7 @@ TALER_exchange_offline_denom_validity_sign (
struct GNUNET_TIME_Timestamp stamp_expire_deposit,
struct GNUNET_TIME_Timestamp stamp_expire_legal,
const struct TALER_Amount *coin_value,
const struct TALER_Amount *fee_withdraw,
const struct TALER_Amount *fee_deposit,
const struct TALER_Amount *fee_refresh,
const struct TALER_Amount *fee_refund,
const struct TALER_DenomFeeSet *fees,
const struct TALER_MasterPrivateKeyP *master_priv,
struct TALER_MasterSignatureP *master_sig);
@ -2755,10 +2812,7 @@ TALER_exchange_offline_denom_validity_sign (
* @param stamp_expire_deposit how long does the exchange accept the deposit of coins with this key
* @param stamp_expire_legal how long does the exchange preserve information for legal disputes with this key
* @param coin_value what is the value of coins signed with this key
* @param fee_withdraw what withdraw fee does the exchange charge for this denomination
* @param fee_deposit what deposit fee does the exchange charge for this denomination
* @param fee_refresh what refresh fee does the exchange charge for this denomination
* @param fee_refund what refund fee does the exchange charge for this denomination
* @param fees fees for this denomination
* @param master_pub public key to verify against
* @param master_sig the signature the signature
* @return #GNUNET_OK if the signature is valid
@ -2771,10 +2825,7 @@ TALER_exchange_offline_denom_validity_verify (
struct GNUNET_TIME_Timestamp stamp_expire_deposit,
struct GNUNET_TIME_Timestamp stamp_expire_legal,
const struct TALER_Amount *coin_value,
const struct TALER_Amount *fee_withdraw,
const struct TALER_Amount *fee_deposit,
const struct TALER_Amount *fee_refresh,
const struct TALER_Amount *fee_refund,
const struct TALER_DenomFeeSet *fees,
const struct TALER_MasterPublicKeyP *master_pub,
const struct TALER_MasterSignatureP *master_sig);
@ -2909,10 +2960,7 @@ TALER_exchange_secmod_cs_verify (
* @param stamp_expire_deposit how long does the exchange accept the deposit of coins with this key
* @param stamp_expire_legal how long does the exchange preserve information for legal disputes with this key
* @param coin_value what is the value of coins signed with this key
* @param fee_withdraw what withdraw fee does the exchange charge for this denomination
* @param fee_deposit what deposit fee does the exchange charge for this denomination
* @param fee_refresh what refresh fee does the exchange charge for this denomination
* @param fee_refund what refund fee does the exchange charge for this denomination
* @param fees fees the exchange charges for this denomination
* @param auditor_priv private key to sign with
* @param[out] auditor_sig where to write the signature
*/
@ -2926,10 +2974,7 @@ TALER_auditor_denom_validity_sign (
struct GNUNET_TIME_Timestamp stamp_expire_deposit,
struct GNUNET_TIME_Timestamp stamp_expire_legal,
const struct TALER_Amount *coin_value,
const struct TALER_Amount *fee_withdraw,
const struct TALER_Amount *fee_deposit,
const struct TALER_Amount *fee_refresh,
const struct TALER_Amount *fee_refund,
const struct TALER_DenomFeeSet *fees,
const struct TALER_AuditorPrivateKeyP *auditor_priv,
struct TALER_AuditorSignatureP *auditor_sig);
@ -2945,10 +2990,7 @@ TALER_auditor_denom_validity_sign (
* @param stamp_expire_deposit how long does the exchange accept the deposit of coins with this key
* @param stamp_expire_legal how long does the exchange preserve information for legal disputes with this key
* @param coin_value what is the value of coins signed with this key
* @param fee_withdraw what withdraw fee does the exchange charge for this denomination
* @param fee_deposit what deposit fee does the exchange charge for this denomination
* @param fee_refresh what refresh fee does the exchange charge for this denomination
* @param fee_refund what refund fee does the exchange charge for this denomination
* @param fees fees the exchange charges for this denomination
* @param auditor_pub public key to verify against
* @param auditor_sig the signature the signature
* @return #GNUNET_OK if the signature is valid
@ -2963,10 +3005,7 @@ TALER_auditor_denom_validity_verify (
struct GNUNET_TIME_Timestamp stamp_expire_deposit,
struct GNUNET_TIME_Timestamp stamp_expire_legal,
const struct TALER_Amount *coin_value,
const struct TALER_Amount *fee_withdraw,
const struct TALER_Amount *fee_deposit,
const struct TALER_Amount *fee_refresh,
const struct TALER_Amount *fee_refund,
const struct TALER_DenomFeeSet *fees,
const struct TALER_AuditorPublicKeyP *auditor_pub,
const struct TALER_AuditorSignatureP *auditor_sig);

View File

@ -135,24 +135,9 @@ struct TALER_EXCHANGE_DenomPublicKey
struct TALER_Amount value;
/**
* The applicable fee for withdrawing a coin of this denomination
* The applicable fees for this denomination
*/
struct TALER_Amount fee_withdraw;
/**
* The applicable fee to spend a coin of this denomination
*/
struct TALER_Amount fee_deposit;
/**
* The applicable fee to melt/refresh a coin of this denomination
*/
struct TALER_Amount fee_refresh;
/**
* The applicable fee to refund a coin of this denomination
*/
struct TALER_Amount fee_refund;
struct TALER_DenomFeeSet fees;
/**
* Set to true if this denomination key has been
@ -1031,19 +1016,19 @@ void
TALER_EXCHANGE_refund_cancel (struct TALER_EXCHANGE_RefundHandle *refund);
/* ********************* POST /csr *********************** */
/* ********************* POST /csr-melt *********************** */
/**
* @brief A /csr Handle
* @brief A /csr-melt Handle
*/
struct TALER_EXCHANGE_CsRHandle;
struct TALER_EXCHANGE_CsRMeltHandle;
/**
* Details about a response for a CS R request.
*/
struct TALER_EXCHANGE_CsRResponse
struct TALER_EXCHANGE_CsRMeltResponse
{
/**
* HTTP response data.
@ -1092,29 +1077,31 @@ struct TALER_EXCHANGE_CsRResponse
* @param csrr response details
*/
typedef void
(*TALER_EXCHANGE_CsRCallback) (void *cls,
const struct TALER_EXCHANGE_CsRResponse *csrr);
(*TALER_EXCHANGE_CsRMeltCallback) (
void *cls,
const struct TALER_EXCHANGE_CsRMeltResponse *csrr);
/**
* Information we pass per coin to a /csr request.
* Information we pass per coin to a /csr-melt request.
*/
struct TALER_EXCHANGE_NonceKey
{
/**
* Which denomination key is the /csr request for?
* Which denomination key is the /csr-melt request for?
*/
const struct TALER_EXCHANGE_DenomPublicKey *pk;
/**
* What is the client nonce for the request?
* What is number to derive the client nonce for the
* fresh coin?
*/
struct TALER_CsNonce nonce;
uint32_t cnc_num;
};
/**
* Get a CS R using a /csr request.
* Get a set of CS R values using a /csr-melt request.
*
* @param exchange the exchange handle; the exchange must be ready to operate
* @param nks_len length of the @a nks array
@ -1125,23 +1112,117 @@ struct TALER_EXCHANGE_NonceKey
* if the inputs are invalid (i.e. denomination key not with this exchange).
* In this case, the callback is not called.
*/
struct TALER_EXCHANGE_CsRHandle *
TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange,
unsigned int nks_len,
struct TALER_EXCHANGE_NonceKey *nks,
TALER_EXCHANGE_CsRCallback res_cb,
void *res_cb_cls);
struct TALER_EXCHANGE_CsRMeltHandle *
TALER_EXCHANGE_csr_melt (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_RefreshMasterSecretP *rms,
unsigned int nks_len,
struct TALER_EXCHANGE_NonceKey *nks,
TALER_EXCHANGE_CsRMeltCallback res_cb,
void *res_cb_cls);
/**
*
* Cancel a CS R request. This function cannot be used
* Cancel a CS R melt request. This function cannot be used
* on a request handle if a response is already served for it.
*
* @param csrh the withdraw handle
*/
void
TALER_EXCHANGE_csr_cancel (struct TALER_EXCHANGE_CsRHandle *csrh);
TALER_EXCHANGE_csr_melt_cancel (struct TALER_EXCHANGE_CsRMeltHandle *csrh);
/* ********************* POST /csr-withdraw *********************** */
/**
* @brief A /csr-withdraw Handle
*/
struct TALER_EXCHANGE_CsRWithdrawHandle;
/**
* Details about a response for a CS R request.
*/
struct TALER_EXCHANGE_CsRWithdrawResponse
{
/**
* HTTP response data.
*/
struct TALER_EXCHANGE_HttpResponse hr;
/**
* Details about the response.
*/
union
{
/**
* Details if the status is #MHD_HTTP_OK.
*/
struct
{
/**
* Values contributed by the exchange for the
* respective coin's withdraw operation.
*/
struct TALER_ExchangeWithdrawValues alg_values;
} success;
/**
* Details if the status is #MHD_HTTP_GONE.
*/
struct
{
/* TODO: returning full details is not implemented */
} gone;
} details;
};
/**
* Callbacks of this type are used to serve the result of submitting a
* CS R withdraw request to a exchange.
*
* @param cls closure
* @param csrr response details
*/
typedef void
(*TALER_EXCHANGE_CsRWithdrawCallback) (
void *cls,
const struct TALER_EXCHANGE_CsRWithdrawResponse *csrr);
/**
* Get a CS R using a /csr-withdraw request.
*
* @param exchange the exchange handle; the exchange must be ready to operate
* @param dk Which denomination key is the /csr request for
* @param nonce client nonce for the request
* @param res_cb the callback to call when the final result for this request is available
* @param res_cb_cls closure for the above callback
* @return handle for the operation on success, NULL on error, i.e.
* if the inputs are invalid (i.e. denomination key not with this exchange).
* In this case, the callback is not called.
*/
struct TALER_EXCHANGE_CsRWithdrawHandle *
TALER_EXCHANGE_csr_withdraw (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_EXCHANGE_DenomPublicKey *pk,
const struct TALER_CsNonce *nonce,
TALER_EXCHANGE_CsRWithdrawCallback res_cb,
void *res_cb_cls);
/**
*
* Cancel a CS R withdraw request. This function cannot be used
* on a request handle if a response is already served for it.
*
* @param csrh the withdraw handle
*/
void
TALER_EXCHANGE_csr_withdraw_cancel (
struct TALER_EXCHANGE_CsRWithdrawHandle *csrh);
/* ********************* GET /reserves/$RESERVE_PUB *********************** */

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014-2021 Taler Systems SA
Copyright (C) 2014-2022 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@ -208,10 +208,7 @@ struct TALER_EXCHANGEDB_TableData
struct GNUNET_TIME_Timestamp expire_deposit;
struct GNUNET_TIME_Timestamp expire_legal;
struct TALER_Amount coin;
struct TALER_Amount fee_withdraw;
struct TALER_Amount fee_deposit;
struct TALER_Amount fee_refresh;
struct TALER_Amount fee_refund;
struct TALER_DenomFeeSet fees;
} denominations;
struct
@ -612,29 +609,10 @@ struct TALER_EXCHANGEDB_DenominationKeyMetaData
struct TALER_Amount value;
/**
* The fee the exchange charges when a coin of this type is withdrawn.
* (can be zero).
* The fees the exchange charges for operations with
* coins of this denomination.
*/
struct TALER_Amount fee_withdraw;
/**
* The fee the exchange charges when a coin of this type is deposited.
* (can be zero).
*/
struct TALER_Amount fee_deposit;
/**
* The fee the exchange charges when a coin of this type is refreshed.
* (can be zero).
*/
struct TALER_Amount fee_refresh;
/**
* The fee the exchange charges when a coin of this type is refunded.
* (can be zero). Note that refund fees are charged to the customer;
* if a refund is given, the deposit fee is also refunded.
*/
struct TALER_Amount fee_refund;
struct TALER_DenomFeeSet fees;
/**
* Age restriction for the denomination. (can be zero). If not zero, the bits
@ -827,6 +805,23 @@ struct TALER_EXCHANGEDB_Recoup
};
/**
* Public key to which a nonce is locked.
*/
union TALER_EXCHANGEDB_NonceLockTargetP
{
/**
* Nonce is locked to this coin key.
*/
struct TALER_CoinSpendPublicKeyP coin;
/**
* Nonce is locked to this reserve key.
*/
struct TALER_ReservePublicKeyP reserve;
};
/**
* Information the exchange records about a recoup request
* in a coin history.
@ -1702,6 +1697,33 @@ struct TALER_EXCHANGEDB_RefreshRevealedCoin
};
/**
* Information per Clause-Schnorr (CS) fresh coin to
* be persisted for idempotency during refreshes-reveal.
*/
struct TALER_EXCHANGEDB_CsRevealFreshCoinData
{
/**
* Denomination of the fresh coin.
*/
struct TALER_DenominationHash new_denom_pub_hash;
/**
* Blind signature of the fresh coin (possibly updated
* in case if a replay!).
*/
struct TALER_BlindedDenominationSignature bsig;
/**
* Offset of the fresh coin in the reveal operation.
* (May not match the array offset as we may have
* a mixture of RSA and CS coins being created, and
* this request is only made for the CS subset).
*/
uint32_t coin_off;
};
/**
* Types of operations that require KYC checks.
*/
@ -2497,20 +2519,36 @@ struct TALER_EXCHANGEDB_Plugin
uint64_t wire_reference);
/**
* Locate a nonce for use with a particular public key.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param nonce the nonce to be locked
* @param denom_pub_hash hash of the public key of the denomination
* @param target public key the nonce is to be locked to
* @return statement execution status
*/
enum GNUNET_DB_QueryStatus
(*lock_nonce)(void *cls,
const struct TALER_CsNonce *nonce,
const struct TALER_DenominationHash *denom_pub_hash,
const union TALER_EXCHANGEDB_NonceLockTargetP *target);
/**
* Locate the response for a withdraw request under a hash that uniquely
* identifies the withdraw operation. Used to ensure idempotency of the
* request.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param wih hash that uniquely identifies the withdraw operation
* @param bch hash that uniquely identifies the withdraw operation
* @param[out] collectable corresponding collectable coin (blind signature)
* if a coin is found
* @return statement execution status
*/
enum GNUNET_DB_QueryStatus
(*get_withdraw_info)(void *cls,
const struct TALER_WithdrawIdentificationHash *wih,
const struct TALER_BlindedCoinHash *bch,
struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable);
@ -2519,9 +2557,8 @@ struct TALER_EXCHANGEDB_Plugin
* and possibly persisting the withdrawal details.
*
* @param cls the `struct PostgresClosure` with the plugin-specific state
* @param wih hash that uniquely identifies the withdraw operation
* @param[in,out] collectable corresponding collectable coin (blind signature)
* if a coin is found
* @param nonce client-contributed input for CS denominations that must be checked for idempotency, or NULL for non-CS withdrawals
* @param collectable corresponding collectable coin (blind signature)
* @param now current time (rounded)
* @param[out] found set to true if the reserve was found
* @param[out] balance_ok set to true if the balance was sufficient
@ -2532,8 +2569,8 @@ struct TALER_EXCHANGEDB_Plugin
enum GNUNET_DB_QueryStatus
(*do_withdraw)(
void *cls,
const struct TALER_WithdrawIdentificationHash *wih,
struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable,
const struct TALER_CsNonce *nonce,
const struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable,
struct GNUNET_TIME_Timestamp now,
bool *found,
bool *balance_ok,
@ -2591,7 +2628,8 @@ struct TALER_EXCHANGEDB_Plugin
* Perform melt operation, checking for sufficient balance
* of the coin and possibly persisting the melt details.
*
* @param cls the `struct PostgresClosure` with the plugin-specific state
* @param cls the plugin-specific state
* @param rms client-contributed input for CS denominations that must be checked for idempotency, or NULL for non-CS withdrawals
* @param[in,out] refresh refresh operation details; the noreveal_index
* is set in case the coin was already melted before
* @param known_coin_id row of the coin in the known_coins table
@ -2602,12 +2640,35 @@ struct TALER_EXCHANGEDB_Plugin
enum GNUNET_DB_QueryStatus
(*do_melt)(
void *cls,
const struct TALER_RefreshMasterSecretP *rms,
struct TALER_EXCHANGEDB_Refresh *refresh,
uint64_t known_coin_id,
bool *zombie_required,
bool *balance_ok);
/**
* Check if the given @a nonce was properly locked to the given @a old_coin_pub. If so, check if we already
* created CS signatures for the given @a nonce and @a new_denom_pub_hashes,
* and if so, return them in @a s_scalars. Otherwise, persist the
* signatures from @a s_scalars in the database.
*
* @param cls the plugin-specific state
* @param nonce the client-provided nonce where we must prevent reuse
* @param old_coin_pub public key the nonce was locked to
* @param num_fresh_coins array length, number of fresh coins revealed
* @param[in,out] crfcds array of data about the fresh coins, of length @a num_fresh_coins
* @return query execution status
*/
enum GNUNET_DB_QueryStatus
(*cs_refreshes_reveal)(
void *cls,
const struct TALER_CsNonce *nonce,
const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
unsigned int num_fresh_coins,
struct TALER_EXCHANGEDB_CsRevealFreshCoinData *crfcds);
/**
* Perform refund operation, checking for sufficient deposits
* of the coin and possibly persisting the refund details.
@ -3540,16 +3601,16 @@ struct TALER_EXCHANGEDB_Plugin
* from given the hash of the blinded coin.
*
* @param cls closure
* @param wih hash identifying the withdraw operation
* @param bch hash identifying the withdraw operation
* @param[out] reserve_pub set to information about the reserve (on success only)
* @param[out] reserve_out_serial_id set to row of the @a h_blind_ev in reserves_out
* @return transaction status code
*/
enum GNUNET_DB_QueryStatus
(*get_reserve_by_wih)(void *cls,
const struct TALER_WithdrawIdentificationHash *wih,
struct TALER_ReservePublicKeyP *reserve_pub,
uint64_t *reserve_out_serial_id);
(*get_reserve_by_h_blind)(void *cls,
const struct TALER_BlindedCoinHash *bch,
struct TALER_ReservePublicKeyP *reserve_pub,
uint64_t *reserve_out_serial_id);
/**

View File

@ -250,6 +250,35 @@ TALER_JSON_spec_amount_any_nbo (const char *name,
struct TALER_AmountNBO *r_amount);
/**
* Generate specification to parse all fees for
* a denomination under a prefix @a pfx.
*
* @param pfx string prefix to use
* @param currency which currency to expect
* @param[out] dfs a `struct TALER_DenomFeeSet` to initialize
*/
#define TALER_JSON_SPEC_DENOM_FEES(pfx,currency,dfs) \
TALER_JSON_spec_amount (pfx "_withdraw", (currency), &(dfs)->withdraw), \
TALER_JSON_spec_amount (pfx "_deposit", (currency), &(dfs)->deposit), \
TALER_JSON_spec_amount (pfx "_refresh", (currency), &(dfs)->refresh), \
TALER_JSON_spec_amount (pfx "_refund", (currency), &(dfs)->refund)
/**
* Macro to pack all of a denominations' fees under
* a given @a pfx.
*
* @param pfx string prefix to use
* @param dfs a `struct TALER_DenomFeeSet` to pack
*/
#define TALER_JSON_PACK_DENOM_FEES(pfx, dfs) \
TALER_JSON_pack_amount (pfx "_withdraw", &(dfs)->withdraw), \
TALER_JSON_pack_amount (pfx "_deposit", &(dfs)->deposit), \
TALER_JSON_pack_amount (pfx "_refresh", &(dfs)->refresh), \
TALER_JSON_pack_amount (pfx "_refund", &(dfs)->refund)
/**
* Generate line in parser specification for denomination public key.
*

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014-2021 Taler Systems SA
Copyright (C) 2014-2022 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@ -395,6 +395,7 @@ struct TALER_SigningKeyAnnouncementPS
};
/**
* @brief Format used for to allow the wallet to authenticate
* link data provided by the exchange.
@ -999,6 +1000,7 @@ struct TALER_MasterExtensionConfigurationPS
struct TALER_ExtensionConfigHash h_config GNUNET_PACKED;
};
/**
* @brief Information about a denomination key. Denomination keys
* are used to sign coins of a certain value into existence.
@ -1063,29 +1065,9 @@ struct TALER_DenominationKeyValidityPS
struct TALER_AmountNBO value;
/**
* The fee the exchange charges when a coin of this type is withdrawn.
* (can be zero).
* Fees for the coin.
*/
struct TALER_AmountNBO fee_withdraw;
/**
* The fee the exchange charges when a coin of this type is deposited.
* (can be zero).
*/
struct TALER_AmountNBO fee_deposit;
/**
* The fee the exchange charges when a coin of this type is refreshed.
* (can be zero).
*/
struct TALER_AmountNBO fee_refresh;
/**
* The fee the exchange charges when a coin of this type is refunded.
* (can be zero). Note that refund fees are charged to the customer;
* if a refund is given, the deposit fee is also refunded.
*/
struct TALER_AmountNBO fee_refund;
struct TALER_DenomFeeSetNBOP fees;
/**
* Hash code of the denomination public key. (Used to avoid having
@ -1166,28 +1148,9 @@ struct TALER_ExchangeKeyValidityPS
struct TALER_AmountNBO value;
/**
* The fee the exchange charges when a coin of this type is withdrawn.
* (can be zero).
* Fees for the coin.
*/
struct TALER_AmountNBO fee_withdraw;
/**
* The fee the exchange charges when a coin of this type is deposited.
* (can be zero).
*/
struct TALER_AmountNBO fee_deposit;
/**
* The fee the exchange charges when a coin of this type is refreshed.
* (can be zero).
*/
struct TALER_AmountNBO fee_refresh;
/**
* The fee the exchange charges when a coin of this type is refreshed.
* (can be zero).
*/
struct TALER_AmountNBO fee_refund;
struct TALER_DenomFeeSetNBOP fees;
/**
* Hash code of the denomination public key. (Used to avoid having

View File

@ -144,6 +144,39 @@ TALER_config_get_amount (const struct GNUNET_CONFIGURATION_Handle *cfg,
struct TALER_Amount *denom);
/**
* Obtain denomination fee structure of a
* denomination from configuration file. All
* fee options must start with "fee_" and have
* names typical for the respective fees.
*
* @param cfg configuration to extract data from
* @param currency expected currency
* @param section section of the configuration to access
* @param[out] fees set to the denomination fees
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
enum GNUNET_GenericReturnValue
TALER_config_get_denom_fees (const struct GNUNET_CONFIGURATION_Handle *cfg,
const char *currency,
const char *section,
struct TALER_DenomFeeSet *fees);
/**
* Check that all denominations in @a fees use
* @a currency
*
* @param currency desired currency
* @param fees fee set to check
* @return #GNUNET_OK on success
*/
enum GNUNET_GenericReturnValue
TALER_denom_fee_check_currency (
const char *currency,
const struct TALER_DenomFeeSet *fees);
/**
* Load our currency from the @a cfg (in section [taler]
* the option "CURRENCY").

View File

@ -24,7 +24,8 @@ libtalerexchange_la_SOURCES = \
exchange_api_auditor_add_denomination.c \
exchange_api_curl_defaults.c exchange_api_curl_defaults.h \
exchange_api_common.c \
exchange_api_csr.c \
exchange_api_csr_melt.c \
exchange_api_csr_withdraw.c \
exchange_api_handle.c exchange_api_handle.h \
exchange_api_deposit.c \
exchange_api_deposits_get.c \

View File

@ -171,10 +171,10 @@ TALER_EXCHANGE_parse_reserve_history (
&h_denom_pub);
if ( (GNUNET_YES !=
TALER_amount_cmp_currency (&withdraw_fee,
&dki->fee_withdraw)) ||
&dki->fees.withdraw)) ||
(0 !=
TALER_amount_cmp (&withdraw_fee,
&dki->fee_withdraw)) )
&dki->fees.withdraw)) )
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (withdraw_spec);
@ -529,10 +529,10 @@ TALER_EXCHANGE_verify_coin_history (
/* check that deposit fee matches our expectations from /keys! */
if ( (GNUNET_YES !=
TALER_amount_cmp_currency (&fee,
&dk->fee_deposit)) ||
&dk->fees.deposit)) ||
(0 !=
TALER_amount_cmp (&fee,
&dk->fee_deposit)) )
&dk->fees.deposit)) )
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
@ -575,10 +575,10 @@ TALER_EXCHANGE_verify_coin_history (
/* check that melt fee matches our expectations from /keys! */
if ( (GNUNET_YES !=
TALER_amount_cmp_currency (&fee,
&dk->fee_refresh)) ||
&dk->fees.refresh)) ||
(0 !=
TALER_amount_cmp (&fee,
&dk->fee_refresh)) )
&dk->fees.refresh)) )
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
@ -669,10 +669,10 @@ TALER_EXCHANGE_verify_coin_history (
{
if ( (GNUNET_YES !=
TALER_amount_cmp_currency (&refund_fee,
&dk->fee_refund)) ||
&dk->fees.refund)) ||
(0 !=
TALER_amount_cmp (&refund_fee,
&dk->fee_refund)) )
&dk->fees.refund)) )
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
@ -863,6 +863,11 @@ TALER_EXCHANGE_verify_coin_history (
}
add = GNUNET_NO;
}
else if (0 == strcasecmp (type,
"LOCK_NONCE"))
{
GNUNET_break (0); // FIXME: implement!
}
else
{
/* signature not supported, new version on server? */

View File

@ -15,8 +15,8 @@
<http://www.gnu.org/licenses/>
*/
/**
* @file lib/exchange_api_csr.c
* @brief Implementation of /csr requests (get R in exchange used for Clause Schnorr withdraw and refresh)
* @file lib/exchange_api_csr_melt.c
* @brief Implementation of /csr-melt requests (get R in exchange used for Clause Schnorr refresh)
* @author Lucien Heuzeveldt
* @author Gian Demarmels
*/
@ -36,7 +36,7 @@
/**
* @brief A Clause Schnorr R Handle
*/
struct TALER_EXCHANGE_CsRHandle
struct TALER_EXCHANGE_CsRMeltHandle
{
/**
* The connection to exchange this request handle will use
@ -46,7 +46,7 @@ struct TALER_EXCHANGE_CsRHandle
/**
* Function to call with the result.
*/
TALER_EXCHANGE_CsRCallback cb;
TALER_EXCHANGE_CsRMeltCallback cb;
/**
* Closure for @a cb.
@ -86,13 +86,13 @@ struct TALER_EXCHANGE_CsRHandle
* @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
*/
static enum GNUNET_GenericReturnValue
csr_ok (struct TALER_EXCHANGE_CsRHandle *csrh,
json_t *arr,
csr_ok (struct TALER_EXCHANGE_CsRMeltHandle *csrh,
const json_t *arr,
struct TALER_EXCHANGE_HttpResponse *hr)
{
unsigned int alen = json_array_size (arr);
struct TALER_ExchangeWithdrawValues alg_values[GNUNET_NZL (alen)];
struct TALER_EXCHANGE_CsRResponse csrr = {
struct TALER_EXCHANGE_CsRMeltResponse csrr = {
.hr = *hr,
.details.success.alg_values_len = alen,
.details.success.alg_values = alg_values
@ -127,7 +127,7 @@ csr_ok (struct TALER_EXCHANGE_CsRHandle *csrh,
/**
* Function called when we're done processing the HTTP /csr request.
*
* @param cls the `struct TALER_EXCHANGE_CsRHandle`
* @param cls the `struct TALER_EXCHANGE_CsRMeltHandle`
* @param response_code HTTP response code, 0 on error
* @param response parsed JSON result, NULL on error
*/
@ -136,13 +136,13 @@ handle_csr_finished (void *cls,
long response_code,
const void *response)
{
struct TALER_EXCHANGE_CsRHandle *csrh = cls;
struct TALER_EXCHANGE_CsRMeltHandle *csrh = cls;
const json_t *j = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
};
struct TALER_EXCHANGE_CsRResponse csrr = {
struct TALER_EXCHANGE_CsRMeltResponse csrr = {
.hr = hr
};
@ -171,7 +171,7 @@ handle_csr_finished (void *cls,
break;
}
}
TALER_EXCHANGE_csr_cancel (csrh);
TALER_EXCHANGE_csr_melt_cancel (csrh);
return;
case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy
@ -215,18 +215,19 @@ handle_csr_finished (void *cls,
csrh->cb (csrh->cb_cls,
&csrr);
csrh->cb = NULL;
TALER_EXCHANGE_csr_cancel (csrh);
TALER_EXCHANGE_csr_melt_cancel (csrh);
}
struct TALER_EXCHANGE_CsRHandle *
TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange,
unsigned int nks_len,
struct TALER_EXCHANGE_NonceKey *nks,
TALER_EXCHANGE_CsRCallback res_cb,
void *res_cb_cls)
struct TALER_EXCHANGE_CsRMeltHandle *
TALER_EXCHANGE_csr_melt (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_RefreshMasterSecretP *rms,
unsigned int nks_len,
struct TALER_EXCHANGE_NonceKey *nks,
TALER_EXCHANGE_CsRMeltCallback res_cb,
void *res_cb_cls)
{
struct TALER_EXCHANGE_CsRHandle *csrh;
struct TALER_EXCHANGE_CsRMeltHandle *csrh;
json_t *csr_arr;
if (0 == nks_len)
@ -240,12 +241,10 @@ TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange,
GNUNET_break (0);
return NULL;
}
csrh = GNUNET_new (struct TALER_EXCHANGE_CsRHandle);
csrh = GNUNET_new (struct TALER_EXCHANGE_CsRMeltHandle);
csrh->exchange = exchange;
csrh->cb = res_cb;
csrh->cb_cls = res_cb_cls;
csr_arr = json_array ();
GNUNET_assert (NULL != csr_arr);
for (unsigned int i = 0; i<nks_len; i++)
@ -254,19 +253,17 @@ TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange,
json_t *csr_obj;
csr_obj = GNUNET_JSON_PACK (
GNUNET_JSON_pack_data_varsize ("nonce",
&nk->nonce,
sizeof(struct TALER_CsNonce)),
GNUNET_JSON_pack_data_varsize ("denom_pub_hash",
&nk->pk->h_key,
sizeof(struct TALER_DenominationHash)));
GNUNET_JSON_pack_uint64 ("coin_offset",
nk->cnc_num),
GNUNET_JSON_pack_data_auto ("denom_pub_hash",
&nk->pk->h_key));
GNUNET_assert (NULL != csr_obj);
GNUNET_assert (0 ==
json_array_append_new (csr_arr,
csr_obj));
}
csrh->url = TEAH_path_to_url (exchange,
"/csr");
"/csr-melt");
if (NULL == csrh->url)
{
json_decref (csr_arr);
@ -279,6 +276,8 @@ TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange,
json_t *req;
req = GNUNET_JSON_PACK (
GNUNET_JSON_pack_data_auto ("rms",
rms),
GNUNET_JSON_pack_array_steal ("nks",
csr_arr));
ctx = TEAH_handle_to_context (exchange);
@ -309,7 +308,7 @@ TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange,
void
TALER_EXCHANGE_csr_cancel (struct TALER_EXCHANGE_CsRHandle *csrh)
TALER_EXCHANGE_csr_melt_cancel (struct TALER_EXCHANGE_CsRMeltHandle *csrh)
{
if (NULL != csrh->job)
{

View File

@ -0,0 +1,284 @@
/*
This file is part of TALER
Copyright (C) 2014-2022 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
TALER; see the file COPYING. If not, see
<http://www.gnu.org/licenses/>
*/
/**
* @file lib/exchange_api_csr_withdraw.c
* @brief Implementation of /csr-withdraw requests (get R in exchange used for Clause Schnorr withdraw and refresh)
* @author Lucien Heuzeveldt
* @author Gian Demarmels
*/
#include "platform.h"
#include <jansson.h>
#include <microhttpd.h> /* just for HTTP status codes */
#include <gnunet/gnunet_util_lib.h>
#include <gnunet/gnunet_json_lib.h>
#include <gnunet/gnunet_curl_lib.h>
#include "taler_exchange_service.h"
#include "taler_json_lib.h"
#include "exchange_api_handle.h"
#include "taler_signatures.h"
#include "exchange_api_curl_defaults.h"
/**
* @brief A Clause Schnorr R Handle
*/
struct TALER_EXCHANGE_CsRWithdrawHandle
{
/**
* The connection to exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
/**
* Function to call with the result.
*/
TALER_EXCHANGE_CsRWithdrawCallback cb;
/**
* Closure for @a cb.
*/
void *cb_cls;
/**
* The url for this request.
*/
char *url;
/**
* Handle for the request.
*/
struct GNUNET_CURL_Job *job;
/**
* Context for #TEH_curl_easy_post(). Keeps the data that must
* persist for Curl to make the upload.
*/
struct TALER_CURL_PostContext post_ctx;
};
/**
* We got a 200 OK response for the /reserves/$RESERVE_PUB/withdraw operation.
* Extract the coin's signature and return it to the caller. The signature we
* get from the exchange is for the blinded value. Thus, we first must
* unblind it and then should verify its validity against our coin's hash.
*
* If everything checks out, we return the unblinded signature
* to the application via the callback.
*
* @param csrh operation handle
* @param av reply from the exchange
* @param hr http response details
* @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
*/
static enum GNUNET_GenericReturnValue
csr_ok (struct TALER_EXCHANGE_CsRWithdrawHandle *csrh,
const json_t *av,
struct TALER_EXCHANGE_HttpResponse *hr)
{
struct TALER_EXCHANGE_CsRWithdrawResponse csrr = {
.hr = *hr,
};
struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_exchange_withdraw_values (
"ewv",
&csrr.details.success.alg_values),
GNUNET_JSON_spec_end ()
};
if (GNUNET_OK !=
GNUNET_JSON_parse (av,
spec,
NULL, NULL))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
csrh->cb (csrh->cb_cls,
&csrr);
return GNUNET_OK;
}
/**
* Function called when we're done processing the HTTP /csr request.
*
* @param cls the `struct TALER_EXCHANGE_CsRWithdrawHandle`
* @param response_code HTTP response code, 0 on error
* @param response parsed JSON result, NULL on error
*/
static void
handle_csr_finished (void *cls,
long response_code,
const void *response)
{
struct TALER_EXCHANGE_CsRWithdrawHandle *csrh = cls;
const json_t *j = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
.http_status = (unsigned int) response_code
};
struct TALER_EXCHANGE_CsRWithdrawResponse csrr = {
.hr = hr
};
csrh->job = NULL;
switch (response_code)
{
case 0:
csrr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
{
if (GNUNET_OK !=
csr_ok (csrh,
response,
&hr))
{
GNUNET_break_op (0);
csrr.hr.http_status = 0;
csrr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
}
TALER_EXCHANGE_csr_withdraw_cancel (csrh);
return;
case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */
csrr.hr.ec = TALER_JSON_get_error_code (j);
csrr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, the exchange basically just says
that it doesn't know the /csr endpoint or denomination.
Can happen if the exchange doesn't support Clause Schnorr.
We should simply pass the JSON reply to the application. */
csrr.hr.ec = TALER_JSON_get_error_code (j);
csrr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_GONE:
/* could happen if denomination was revoked */
/* Note: one might want to check /keys for revocation
signature here, alas tricky in case our /keys
is outdated => left to clients */
csrr.hr.ec = TALER_JSON_get_error_code (j);
csrr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
csrr.hr.ec = TALER_JSON_get_error_code (j);
csrr.hr.hint = TALER_JSON_get_error_hint (j);
break;
default:
/* unexpected response code */
GNUNET_break_op (0);
csrr.hr.ec = TALER_JSON_get_error_code (j);
csrr.hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for CS R request\n",
(unsigned int) response_code,
(int) hr.ec);
break;
}
csrh->cb (csrh->cb_cls,
&csrr);
csrh->cb = NULL;
TALER_EXCHANGE_csr_withdraw_cancel (csrh);
}
struct TALER_EXCHANGE_CsRWithdrawHandle *
TALER_EXCHANGE_csr_withdraw (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_EXCHANGE_DenomPublicKey *pk,
const struct TALER_CsNonce *nonce,
TALER_EXCHANGE_CsRWithdrawCallback res_cb,
void *res_cb_cls)
{
struct TALER_EXCHANGE_CsRWithdrawHandle *csrh;
if (TALER_DENOMINATION_CS != pk->key.cipher)
{
GNUNET_break (0);
return NULL;
}
csrh = GNUNET_new (struct TALER_EXCHANGE_CsRWithdrawHandle);
csrh->exchange = exchange;
csrh->cb = res_cb;
csrh->cb_cls = res_cb_cls;
csrh->url = TEAH_path_to_url (exchange,
"/csr-withdraw");
if (NULL == csrh->url)
{
GNUNET_free (csrh);
return NULL;
}
{
CURL *eh;
struct GNUNET_CURL_Context *ctx;
json_t *req;
req = GNUNET_JSON_PACK (
GNUNET_JSON_pack_data_varsize ("nonce",
nonce,
sizeof(struct TALER_CsNonce)),
GNUNET_JSON_pack_data_varsize ("denom_pub_hash",
&pk->h_key,
sizeof(struct TALER_DenominationHash)));
GNUNET_assert (NULL != req);
ctx = TEAH_handle_to_context (exchange);
eh = TALER_EXCHANGE_curl_easy_get_ (csrh->url);
if ( (NULL == eh) ||
(GNUNET_OK !=
TALER_curl_easy_post (&csrh->post_ctx,
eh,
req)) )
{
GNUNET_break (0);
if (NULL != eh)
curl_easy_cleanup (eh);
json_decref (req);
GNUNET_free (csrh->url);
GNUNET_free (csrh);
return NULL;
}
json_decref (req);
csrh->job = GNUNET_CURL_job_add2 (ctx,
eh,
csrh->post_ctx.headers,
&handle_csr_finished,
csrh);
}
return csrh;
}
void
TALER_EXCHANGE_csr_withdraw_cancel (struct
TALER_EXCHANGE_CsRWithdrawHandle *csrh)
{
if (NULL != csrh->job)
{
GNUNET_CURL_job_cancel (csrh->job);
csrh->job = NULL;
}
GNUNET_free (csrh->url);
TALER_curl_easy_post_finished (&csrh->post_ctx);
GNUNET_free (csrh);
}

View File

@ -491,7 +491,7 @@ verify_signatures (const struct TALER_EXCHANGE_DenomPublicKey *dki,
{
if (GNUNET_OK !=
TALER_wallet_deposit_verify (amount,
&dki->fee_deposit,
&dki->fees.deposit,
h_wire,
h_contract_terms,
h_age_commitment,
@ -508,7 +508,7 @@ verify_signatures (const struct TALER_EXCHANGE_DenomPublicKey *dki,
TALER_LOG_DEBUG ("... amount_with_fee was %s\n",
TALER_amount2s (amount));
TALER_LOG_DEBUG ("... deposit_fee was %s\n",
TALER_amount2s (&dki->fee_deposit));
TALER_amount2s (&dki->fees.deposit));
return GNUNET_SYSERR;
}
@ -536,7 +536,7 @@ verify_signatures (const struct TALER_EXCHANGE_DenomPublicKey *dki,
}
/* Check coin does make a contribution */
if (0 < TALER_amount_cmp (&dki->fee_deposit,
if (0 < TALER_amount_cmp (&dki->fees.deposit,
amount))
{
GNUNET_break_op (0);
@ -628,7 +628,7 @@ TALER_EXCHANGE_deposit (
if (0 >
TALER_amount_subtract (&amount_without_fee,
amount,
&dki->fee_deposit))
&dki->fees.deposit))
{
*ec = TALER_EC_EXCHANGE_DEPOSIT_FEE_ABOVE_AMOUNT;
GNUNET_break_op (0);

View File

@ -305,6 +305,7 @@ parse_json_signkey (struct TALER_EXCHANGE_SigningPublicKey *sign_key,
/**
* Parse a exchange's denomination key encoded in JSON.
*
* @param currency expected currency of all fees
* @param[out] denom_key where to return the result
* @param check_sigs should we check signatures?
* @param[in] denom_key_obj json to parse
@ -314,7 +315,8 @@ parse_json_signkey (struct TALER_EXCHANGE_SigningPublicKey *sign_key,
* invalid or the json malformed.
*/
static enum GNUNET_GenericReturnValue
parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key,
parse_json_denomkey (const char *currency,
struct TALER_EXCHANGE_DenomPublicKey *denom_key,
int check_sigs,
json_t *denom_key_obj,
struct TALER_MasterPublicKeyP *master_key,
@ -331,16 +333,12 @@ parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key,
&denom_key->valid_from),
GNUNET_JSON_spec_timestamp ("stamp_expire_legal",
&denom_key->expire_legal),
TALER_JSON_spec_amount_any ("value",
&denom_key->value),
TALER_JSON_spec_amount_any ("fee_withdraw",
&denom_key->fee_withdraw),
TALER_JSON_spec_amount_any ("fee_deposit",
&denom_key->fee_deposit),
TALER_JSON_spec_amount_any ("fee_refresh",
&denom_key->fee_refresh),
TALER_JSON_spec_amount_any ("fee_refund",
&denom_key->fee_refund),
TALER_JSON_spec_amount ("value",
currency,
&denom_key->value),
TALER_JSON_SPEC_DENOM_FEES ("fee",
currency,
&denom_key->fees),
TALER_JSON_spec_denom_pub ("denom_pub",
&denom_key->key),
GNUNET_JSON_spec_end ()
@ -372,10 +370,7 @@ parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key,
denom_key->expire_deposit,
denom_key->expire_legal,
&denom_key->value,
&denom_key->fee_withdraw,
&denom_key->fee_deposit,
&denom_key->fee_refresh,
&denom_key->fee_refund,
&denom_key->fees,
master_key,
&denom_key->master_sig));
return GNUNET_OK;
@ -492,10 +487,7 @@ parse_json_auditor (struct TALER_EXCHANGE_AuditorInformation *auditor,
dk->expire_deposit,
dk->expire_legal,
&dk->value,
&dk->fee_withdraw,
&dk->fee_deposit,
&dk->fee_refresh,
&dk->fee_refund,
&dk->fees,
&auditor->auditor_pub,
&auditor_sig))
{
@ -883,7 +875,8 @@ decode_keys_json (const json_t *resp_obj,
0,
sizeof (dk));
EXITIF (GNUNET_SYSERR ==
parse_json_denomkey (&dk,
parse_json_denomkey (key_data->currency,
&dk,
check_sig,
denom_key_obj,
&key_data->master_pub,
@ -1728,14 +1721,8 @@ TALER_EXCHANGE_serialize_data (struct TALER_EXCHANGE_Handle *exchange)
dk->expire_legal),
TALER_JSON_pack_amount ("value",
&dk->value),
TALER_JSON_pack_amount ("fee_withdraw",
&dk->fee_withdraw),
TALER_JSON_pack_amount ("fee_deposit",
&dk->fee_deposit),
TALER_JSON_pack_amount ("fee_refresh",
&dk->fee_refresh),
TALER_JSON_pack_amount ("fee_refund",
&dk->fee_refund),
TALER_JSON_PACK_DENOM_FEES ("fee",
&dk->fees),
GNUNET_JSON_pack_data_auto ("master_sig",
&dk->master_sig),
TALER_JSON_pack_denom_pub ("denom_pub",

View File

@ -94,7 +94,7 @@ struct TALER_EXCHANGE_MeltHandle
/**
* Handle for the preflight request, or NULL.
*/
struct TALER_EXCHANGE_CsRHandle *csr;
struct TALER_EXCHANGE_CsRMeltHandle *csr;
/**
* Public key of the coin being melted.
@ -111,6 +111,10 @@ struct TALER_EXCHANGE_MeltHandle
*/
uint32_t noreveal_index;
/**
* True if we need to include @e rms in our melt request.
*/
bool send_rms;
};
@ -488,7 +492,13 @@ start_melt (struct TALER_EXCHANGE_MeltHandle *mh)
TALER_JSON_pack_amount ("value_with_fee",
&mh->md.melted_coin.melt_amount_with_fee),
GNUNET_JSON_pack_data_auto ("rc",
&mh->md.rc));
&mh->md.rc),
GNUNET_JSON_pack_allow_null (
mh->send_rms
? GNUNET_JSON_pack_data_auto ("rms",
&mh->rms)
: GNUNET_JSON_pack_string ("rms",
NULL)));
{
char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2];
char *end;
@ -571,7 +581,7 @@ fail_mh (struct TALER_EXCHANGE_MeltHandle *mh,
*/
static void
csr_cb (void *cls,
const struct TALER_EXCHANGE_CsRResponse *csrr)
const struct TALER_EXCHANGE_CsRMeltResponse *csrr)
{
struct TALER_EXCHANGE_MeltHandle *mh = cls;
unsigned int nks_off = 0;
@ -583,7 +593,7 @@ csr_cb (void *cls,
.hr = csrr->hr
};
mr.hr.hint = "/csr failed";
mr.hr.hint = "/csr-melt failed";
mh->melt_cb (mh->melt_cb_cls,
&mr);
TALER_EXCHANGE_melt_cancel (mh);
@ -612,6 +622,7 @@ csr_cb (void *cls,
break;
}
}
mh->send_rms = true;
if (GNUNET_OK !=
start_melt (mh))
{
@ -668,20 +679,19 @@ TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
case TALER_DENOMINATION_CS:
wv->cipher = TALER_DENOMINATION_CS;
nks[nks_off].pk = fresh_pk;
TALER_cs_refresh_nonce_derive (rms,
i,
&nks[nks_off].nonce);
nks[nks_off].cnc_num = nks_off;
nks_off++;
break;
}
}
if (0 != nks_off)
{
mh->csr = TALER_EXCHANGE_csr (exchange,
nks_off,
nks,
&csr_cb,
mh);
mh->csr = TALER_EXCHANGE_csr_melt (exchange,
rms,
nks_off,
nks,
&csr_cb,
mh);
if (NULL == mh->csr)
{
GNUNET_break (0);
@ -711,7 +721,7 @@ TALER_EXCHANGE_melt_cancel (struct TALER_EXCHANGE_MeltHandle *mh)
}
if (NULL != mh->csr)
{
TALER_EXCHANGE_csr_cancel (mh->csr);
TALER_EXCHANGE_csr_melt_cancel (mh->csr);
mh->csr = NULL;
}
TALER_EXCHANGE_free_melt_data_ (&mh->md); /* does not free 'md' itself */

View File

@ -178,7 +178,7 @@ handle_recoup_finished (void *cls,
"history");
if (GNUNET_OK !=
TALER_EXCHANGE_verify_coin_history (dki,
dki->fee_deposit.currency,
dki->fees.deposit.currency,
&ph->coin_pub,
history,
&h_denom_pub,

View File

@ -192,7 +192,7 @@ handle_recoup_refresh_finished (void *cls,
"history");
if (GNUNET_OK !=
TALER_EXCHANGE_verify_coin_history (dki,
dki->fee_deposit.currency,
dki->fees.deposit.currency,
&ph->coin_pub,
history,
&h_denom_pub,

View File

@ -64,6 +64,7 @@ TALER_EXCHANGE_get_melt_data_ (
struct TALER_Amount total;
struct TALER_CoinSpendPublicKeyP coin_pub;
struct TALER_CsNonce nonces[rd->fresh_pks_len];
bool uses_cs = false;
GNUNET_CRYPTO_eddsa_key_get_public (&rd->melt_priv.eddsa_priv,
&coin_pub.eddsa_pub);
@ -74,7 +75,7 @@ TALER_EXCHANGE_get_melt_data_ (
md->num_fresh_coins = rd->fresh_pks_len;
md->melted_coin.coin_priv = rd->melt_priv;
md->melted_coin.melt_amount_with_fee = rd->melt_amount;
md->melted_coin.fee_melt = rd->melt_pk.fee_refresh;
md->melted_coin.fee_melt = rd->melt_pk.fees.refresh;
md->melted_coin.original_value = rd->melt_pk.value;
md->melted_coin.expire_deposit = rd->melt_pk.expire_deposit;
md->melted_coin.age_commitment = rd->age_commitment;
@ -100,6 +101,7 @@ TALER_EXCHANGE_get_melt_data_ (
}
if (TALER_DENOMINATION_CS == alg_values[j].cipher)
{
uses_cs = true;
TALER_cs_refresh_nonce_derive (
rms,
j,
@ -114,7 +116,7 @@ TALER_EXCHANGE_get_melt_data_ (
(0 >
TALER_amount_add (&total,
&total,
&rd->fresh_pks[j].fee_withdraw)) )
&rd->fresh_pks[j].fees.withdraw)) )
{
GNUNET_break (0);
TALER_EXCHANGE_free_melt_data_ (md);
@ -141,6 +143,7 @@ TALER_EXCHANGE_get_melt_data_ (
TALER_planchet_secret_to_transfer_priv (
rms,
&rd->melt_priv,
i,
&md->transfer_priv[i]);
@ -239,6 +242,9 @@ TALER_EXCHANGE_get_melt_data_ (
}
TALER_refresh_get_commitment (&md->rc,
TALER_CNC_KAPPA,
uses_cs
? rms
: NULL,
rd->fresh_pks_len,
rce,
&coin_pub,

View File

@ -340,6 +340,7 @@ TALER_EXCHANGE_refreshes_reveal (
struct GNUNET_CURL_Context *ctx;
struct MeltData md;
char arg_str[sizeof (struct TALER_RefreshCommitmentP) * 2 + 32];
bool send_rms = false;
GNUNET_assert (num_coins == rd->fresh_pks_len);
if (noreveal_index >= TALER_CNC_KAPPA)
@ -376,6 +377,8 @@ TALER_EXCHANGE_refreshes_reveal (
const struct TALER_RefreshCoinData *rcd = &md.rcd[noreveal_index][i];
struct TALER_DenominationHash denom_hash;
if (TALER_DENOMINATION_CS == md.fcds[i].fresh_pk.cipher)
send_rms = true;
TALER_denom_pub_hash (&md.fcds[i].fresh_pk,
&denom_hash);
GNUNET_assert (0 ==
@ -428,6 +431,12 @@ TALER_EXCHANGE_refreshes_reveal (
reveal_obj = GNUNET_JSON_PACK (
GNUNET_JSON_pack_data_auto ("transfer_pub",
&md.transfer_pub[noreveal_index]),
GNUNET_JSON_pack_allow_null (
send_rms
? GNUNET_JSON_pack_data_auto ("rms",
rms)
: GNUNET_JSON_pack_string ("rms",
NULL)),
GNUNET_JSON_pack_array_steal ("transfer_privs",
transfer_privs),
GNUNET_JSON_pack_array_steal ("link_sigs",

View File

@ -106,7 +106,7 @@ struct TALER_EXCHANGE_WithdrawHandle
/**
* Handler for the CS R request (only used for TALER_DENOMINATION_CS denominations)
*/
struct TALER_EXCHANGE_CsRHandle *csrh;
struct TALER_EXCHANGE_CsRWithdrawHandle *csrh;
};
@ -192,11 +192,12 @@ handle_reserve_withdraw_finished (
* Function called when stage 1 of CS withdraw is finished (request r_pub's)
*
* @param cls the `struct TALER_EXCHANGE_WithdrawHandle`
* @param csrr replies from the /csr request
* @param csrr replies from the /csr-withdraw request
*/
static void
withdraw_cs_stage_two_callback (void *cls,
const struct TALER_EXCHANGE_CsRResponse *csrr)
withdraw_cs_stage_two_callback (
void *cls,
const struct TALER_EXCHANGE_CsRWithdrawResponse *csrr)
{
struct TALER_EXCHANGE_WithdrawHandle *wh = cls;
struct TALER_EXCHANGE_WithdrawResponse wr = {
@ -208,13 +209,7 @@ withdraw_cs_stage_two_callback (void *cls,
switch (csrr->hr.http_status)
{
case MHD_HTTP_OK:
if (1 != csrr->details.success.alg_values_len)
{
GNUNET_break (0);
wr.hr.http_status = 0;
break;
}
wh->alg_values = csrr->details.success.alg_values[0];
wh->alg_values = csrr->details.success.alg_values;
TALER_planchet_setup_coin_priv (&wh->ps,
&wh->alg_values,
&wh->priv);
@ -306,22 +301,19 @@ TALER_EXCHANGE_withdraw (
}
case TALER_DENOMINATION_CS:
{
struct TALER_EXCHANGE_NonceKey nk = {
.pk = pk,
};
TALER_cs_withdraw_nonce_derive (ps,
&nk.nonce);
TALER_cs_withdraw_nonce_derive (
ps,
&wh->pd.blinded_planchet.details.cs_blinded_planchet.nonce);
/* Note that we only initialize the first half
of the blinded_planchet here; the other part
will be done after the /csr request! */
will be done after the /csr-withdraw request! */
wh->pd.blinded_planchet.cipher = TALER_DENOMINATION_CS;
wh->pd.blinded_planchet.details.cs_blinded_planchet.nonce = nk.nonce;
wh->csrh = TALER_EXCHANGE_csr (exchange,
1, /* "array" length */
&nk,
&withdraw_cs_stage_two_callback,
wh);
wh->csrh = TALER_EXCHANGE_csr_withdraw (
exchange,
pk,
&wh->pd.blinded_planchet.details.cs_blinded_planchet.nonce,
&withdraw_cs_stage_two_callback,
wh);
break;
}
default:
@ -339,7 +331,7 @@ TALER_EXCHANGE_withdraw_cancel (struct TALER_EXCHANGE_WithdrawHandle *wh)
TALER_blinded_planchet_free (&wh->pd.blinded_planchet);
if (NULL != wh->csrh)
{
TALER_EXCHANGE_csr_cancel (wh->csrh);
TALER_EXCHANGE_csr_withdraw_cancel (wh->csrh);
wh->csrh = NULL;
}
if (NULL != wh->wh2)

View File

@ -403,7 +403,7 @@ TALER_EXCHANGE_withdraw2 (
if (0 >
TALER_amount_add (&wh->requested_amount,
&dk->value,
&dk->fee_withdraw))
&dk->fees.withdraw))
{
/* Overflow here? Very strange, our CPU must be fried... */
GNUNET_break (0);

View File

@ -152,10 +152,7 @@ auditor_add_run (void *cls,
dk->expire_deposit,
dk->expire_legal,
&dk->value,
&dk->fee_withdraw,
&dk->fee_deposit,
&dk->fee_refresh,
&dk->fee_refund,
&dk->fees,
&is->auditor_priv,
&auditor_sig);
}

View File

@ -409,8 +409,7 @@ deposit_run (void *cls,
{
TALER_age_commitment_hash (age_commitment, &h_age_commitment);
}
ds->deposit_fee = denom_pub->fee_deposit;
ds->deposit_fee = denom_pub->fees.deposit;
GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
&coin_pub.eddsa_pub);
@ -440,7 +439,7 @@ deposit_run (void *cls,
TALER_JSON_merchant_wire_signature_hash (ds->wire_details,
&h_wire));
TALER_wallet_deposit_sign (&ds->amount,
&denom_pub->fee_deposit,
&denom_pub->fees.deposit,
&h_wire,
&h_contract_terms,
&h_age_commitment,

View File

@ -103,16 +103,16 @@ fake_issue (struct TALER_EXCHANGEDB_DenominationKeyInformationP *issue)
&issue->properties.value));
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount_nbo ("EUR:0.1",
&issue->properties.fee_withdraw));
&issue->properties.fees.withdraw));
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount_nbo ("EUR:0.1",
&issue->properties.fee_deposit));
&issue->properties.fees.deposit));
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount_nbo ("EUR:0.1",
&issue->properties.fee_refresh));
&issue->properties.fees.refresh));
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount_nbo ("EUR:0.1",
&issue->properties.fee_refund));
&issue->properties.fees.refund));
}

View File

@ -1102,7 +1102,7 @@ melt_run (void *cls,
/* Melt amount starts with the melt fee of the old coin; we'll add the
values and withdraw fees of the fresh coins next */
melt_amount = melt_denom_pub->fee_refresh;
melt_amount = melt_denom_pub->fees.refresh;
age_restricted = melt_denom_pub->key.age_mask.mask != 0;
for (unsigned int i = 0; i<num_fresh_coins; i++)
{
@ -1137,7 +1137,7 @@ melt_run (void *cls,
GNUNET_assert (0 <=
TALER_amount_add (&melt_amount,
&melt_amount,
&fresh_pk->fee_withdraw));
&fresh_pk->fees.withdraw));
rms->fresh_pks[i] = *fresh_pk;
/* Make a deep copy of the RSA key */
TALER_denom_pub_deep_copy (&rms->fresh_pks[i].key,

View File

@ -474,19 +474,15 @@ withdraw_run (void *cls,
GNUNET_assert (0 <=
TALER_amount_add (&ws->reserve_history.amount,
&ws->amount,
&ws->pk->fee_withdraw));
ws->reserve_history.details.withdraw.fee = ws->pk->fee_withdraw;
{
ws->wsh = TALER_EXCHANGE_withdraw (is->exchange,
ws->pk,
rp,
&ws->ps,
ws->h_age_commitment,
&reserve_withdraw_cb,
ws);
}
&ws->pk->fees.withdraw));
ws->reserve_history.details.withdraw.fee = ws->pk->fees.withdraw;
ws->wsh = TALER_EXCHANGE_withdraw (is->exchange,
ws->pk,
rp,
&ws->ps,
ws->h_age_commitment,
&reserve_withdraw_cb,
ws);
if (NULL == ws->wsh)
{
GNUNET_break (0);

View File

@ -253,6 +253,20 @@ TALER_amount_is_zero (const struct TALER_Amount *amount)
}
enum GNUNET_GenericReturnValue
TALER_amount_is_currency (const struct TALER_Amount *amount,
const char *currency)
{
if (GNUNET_OK !=
TALER_amount_is_valid (amount))
return GNUNET_SYSERR;
return (0 == strcasecmp (currency,
amount->currency))
? GNUNET_OK
: GNUNET_NO;
}
/**
* Test if @a a is valid, NBO variant.
*

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2020 Taler Systems SA
Copyright (C) 2020, 2022 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@ -33,10 +33,7 @@ TALER_auditor_denom_validity_sign (
struct GNUNET_TIME_Timestamp stamp_expire_deposit,
struct GNUNET_TIME_Timestamp stamp_expire_legal,
const struct TALER_Amount *coin_value,
const struct TALER_Amount *fee_withdraw,
const struct TALER_Amount *fee_deposit,
const struct TALER_Amount *fee_refresh,
const struct TALER_Amount *fee_refund,
const struct TALER_DenomFeeSet *fees,
const struct TALER_AuditorPrivateKeyP *auditor_priv,
struct TALER_AuditorSignatureP *auditor_sig)
{
@ -53,14 +50,8 @@ TALER_auditor_denom_validity_sign (
TALER_amount_hton (&kv.value,
coin_value);
TALER_amount_hton (&kv.fee_withdraw,
fee_withdraw);
TALER_amount_hton (&kv.fee_deposit,
fee_deposit);
TALER_amount_hton (&kv.fee_refresh,
fee_refresh);
TALER_amount_hton (&kv.fee_refund,
fee_refund);
TALER_denom_fee_set_hton (&kv.fees,
fees);
GNUNET_CRYPTO_hash (auditor_url,
strlen (auditor_url) + 1,
&kv.auditor_url_hash);
@ -80,10 +71,7 @@ TALER_auditor_denom_validity_verify (
struct GNUNET_TIME_Timestamp stamp_expire_deposit,
struct GNUNET_TIME_Timestamp stamp_expire_legal,
const struct TALER_Amount *coin_value,
const struct TALER_Amount *fee_withdraw,
const struct TALER_Amount *fee_deposit,
const struct TALER_Amount *fee_refresh,
const struct TALER_Amount *fee_refund,
const struct TALER_DenomFeeSet *fees,
const struct TALER_AuditorPublicKeyP *auditor_pub,
const struct TALER_AuditorSignatureP *auditor_sig)
{
@ -100,14 +88,8 @@ TALER_auditor_denom_validity_verify (
TALER_amount_hton (&kv.value,
coin_value);
TALER_amount_hton (&kv.fee_withdraw,
fee_withdraw);
TALER_amount_hton (&kv.fee_deposit,
fee_deposit);
TALER_amount_hton (&kv.fee_refresh,
fee_refresh);
TALER_amount_hton (&kv.fee_refund,
fee_refund);
TALER_denom_fee_set_hton (&kv.fees,
fees);
GNUNET_CRYPTO_hash (auditor_url,
strlen (auditor_url) + 1,
&kv.auditor_url_hash);

View File

@ -58,6 +58,74 @@ TALER_config_get_amount (const struct GNUNET_CONFIGURATION_Handle *cfg,
}
enum GNUNET_GenericReturnValue
TALER_config_get_denom_fees (const struct GNUNET_CONFIGURATION_Handle *cfg,
const char *currency,
const char *section,
struct TALER_DenomFeeSet *fees)
{
if (GNUNET_OK !=
TALER_config_get_amount (cfg,
section,
"FEE_WITHDRAW",
&fees->withdraw))
{
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
"Need amount for option `%s' in section `%s'\n",
"FEE_WITHDRAW",
section);
return GNUNET_SYSERR;
}
if (GNUNET_OK !=
TALER_config_get_amount (cfg,
section,
"FEE_DEPOSIT",
&fees->deposit))
{
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
"Need amount for option `%s' in section `%s'\n",
"FEE_DEPOSIT",
section);
return GNUNET_SYSERR;
}
if (GNUNET_OK !=
TALER_config_get_amount (cfg,
section,
"FEE_REFRESH",
&fees->refresh))
{
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
"Need amount for option `%s' in section `%s'\n",
"FEE_REFRESH",
section);
return GNUNET_SYSERR;
}
if (GNUNET_OK !=
TALER_config_get_amount (cfg,
section,
"FEE_REFUND",
&fees->refund))
{
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
"Need amount for option `%s' in section `%s'\n",
"FEE_REFUND",
section);
return GNUNET_SYSERR;
}
if (GNUNET_OK !=
TALER_denom_fee_check_currency (currency,
fees))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Need fee amounts in section `%s' to use currency `%s'\n",
section,
currency);
return GNUNET_SYSERR;
}
return GNUNET_OK;
}
enum GNUNET_GenericReturnValue
TALER_config_get_currency (const struct GNUNET_CONFIGURATION_Handle *cfg,
char **currency)

View File

@ -193,6 +193,7 @@ TALER_transfer_secret_to_planchet_secret (
void
TALER_planchet_secret_to_transfer_priv (
const struct TALER_RefreshMasterSecretP *rms,
const struct TALER_CoinSpendPrivateKeyP *old_coin_priv,
uint32_t cnc_num,
struct TALER_TransferPrivateKeyP *tpriv)
{
@ -203,6 +204,8 @@ TALER_planchet_secret_to_transfer_priv (
sizeof (*tpriv),
&be_salt,
sizeof (be_salt),
old_coin_priv,
sizeof (*old_coin_priv),
rms,
sizeof (*rms),
"taler-transfer-priv-derivation",
@ -337,6 +340,7 @@ TALER_planchet_to_coin (
void
TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc,
uint32_t kappa,
const struct TALER_RefreshMasterSecretP *rms,
uint32_t num_new_coins,
const struct TALER_RefreshCommitmentEntry *rcs,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
@ -345,6 +349,10 @@ TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc,
struct GNUNET_HashContext *hash_context;
hash_context = GNUNET_CRYPTO_hash_context_start ();
if (NULL != rms)
GNUNET_CRYPTO_hash_context_read (hash_context,
rms,
sizeof (*rms));
/* first, iterate over transfer public keys for hash_context */
for (unsigned int i = 0; i<kappa; i++)
{
@ -391,8 +399,8 @@ TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc,
{
const struct TALER_RefreshCoinData *rcd = &rce->new_coins[j];
TALER_blinded_planchet_hash (&rcd->blinded_planchet,
hash_context);
TALER_blinded_planchet_hash_ (&rcd->blinded_planchet,
hash_context);
}
}
@ -707,4 +715,23 @@ TALER_age_commitment_free (
}
enum GNUNET_GenericReturnValue
TALER_coin_ev_hash (const struct TALER_BlindedPlanchet *blinded_planchet,
const struct TALER_DenominationHash *denom_hash,
struct TALER_BlindedCoinHash *bch)
{
struct GNUNET_HashContext *hash_context;
hash_context = GNUNET_CRYPTO_hash_context_start ();
GNUNET_CRYPTO_hash_context_read (hash_context,
denom_hash,
sizeof(*denom_hash));
TALER_blinded_planchet_hash_ (blinded_planchet,
hash_context);
GNUNET_CRYPTO_hash_context_finish (hash_context,
&bch->hash);
return GNUNET_OK;
}
/* end of crypto.c */

View File

@ -652,8 +652,8 @@ TALER_blinded_denom_sig_cmp (
void
TALER_blinded_planchet_hash (const struct TALER_BlindedPlanchet *bp,
struct GNUNET_HashContext *hash_context)
TALER_blinded_planchet_hash_ (const struct TALER_BlindedPlanchet *bp,
struct GNUNET_HashContext *hash_context)
{
uint32_t cipher = htonl (bp->cipher);
@ -771,97 +771,20 @@ TALER_blinded_planchet_free (struct TALER_BlindedPlanchet *blinded_planchet)
{
switch (blinded_planchet->cipher)
{
case TALER_DENOMINATION_INVALID:
GNUNET_break (0);
return;
case TALER_DENOMINATION_RSA:
GNUNET_free (blinded_planchet->details.rsa_blinded_planchet.blinded_msg);
break;
return;
case TALER_DENOMINATION_CS:
memset (blinded_planchet,
0,
sizeof (*blinded_planchet));
/* nothing to do for CS */
break;
default:
GNUNET_break (0);
return;
}
}
enum GNUNET_GenericReturnValue
TALER_coin_ev_hash (const struct TALER_BlindedPlanchet *blinded_planchet,
const struct TALER_DenominationHash *denom_hash,
struct TALER_BlindedCoinHash *bch)
{
struct GNUNET_HashContext *hash_context;
hash_context = GNUNET_CRYPTO_hash_context_start ();
GNUNET_CRYPTO_hash_context_read (hash_context,
denom_hash,
sizeof(*denom_hash));
switch (blinded_planchet->cipher)
{
case TALER_DENOMINATION_RSA:
GNUNET_CRYPTO_hash_context_read (
hash_context,
blinded_planchet->details.rsa_blinded_planchet.blinded_msg,
blinded_planchet->details.rsa_blinded_planchet.blinded_msg_size);
break;
case TALER_DENOMINATION_CS:
// FIXME: c-values MUST NOT be included in idempotency check
// during withdraw (or recoup), but right now they are!!!
GNUNET_CRYPTO_hash_context_read (
hash_context,
&blinded_planchet->details.cs_blinded_planchet.c[0],
sizeof (struct GNUNET_CRYPTO_CsC) * 2);
GNUNET_CRYPTO_hash_context_read (
hash_context,
&blinded_planchet->details.cs_blinded_planchet.nonce,
sizeof (struct TALER_CsNonce));
break;
default:
GNUNET_break (0);
GNUNET_CRYPTO_hash_context_abort (hash_context);
return GNUNET_SYSERR;
}
GNUNET_CRYPTO_hash_context_finish (hash_context,
&bch->hash);
return GNUNET_OK;
}
enum GNUNET_GenericReturnValue
TALER_withdraw_request_hash (
const struct TALER_BlindedPlanchet *blinded_planchet,
const struct TALER_DenominationHash *denom_hash,
struct TALER_WithdrawIdentificationHash *wih)
{
struct GNUNET_HashContext *hash_context;
hash_context = GNUNET_CRYPTO_hash_context_start ();
GNUNET_CRYPTO_hash_context_read (hash_context,
denom_hash,
sizeof(*denom_hash));
switch (blinded_planchet->cipher)
{
case TALER_DENOMINATION_RSA:
GNUNET_CRYPTO_hash_context_read (
hash_context,
blinded_planchet->details.rsa_blinded_planchet.blinded_msg,
blinded_planchet->details.rsa_blinded_planchet.blinded_msg_size);
break;
case TALER_DENOMINATION_CS:
GNUNET_CRYPTO_hash_context_read (
hash_context,
&blinded_planchet->details.cs_blinded_planchet.nonce,
sizeof (struct TALER_CsNonce));
break;
default:
GNUNET_break (0);
GNUNET_CRYPTO_hash_context_abort (hash_context);
return GNUNET_SYSERR;
}
GNUNET_CRYPTO_hash_context_finish (hash_context,
&wih->hash);
return GNUNET_OK;
GNUNET_assert (0);
}

View File

@ -255,10 +255,7 @@ TALER_exchange_offline_denom_validity_sign (
struct GNUNET_TIME_Timestamp stamp_expire_deposit,
struct GNUNET_TIME_Timestamp stamp_expire_legal,
const struct TALER_Amount *coin_value,
const struct TALER_Amount *fee_withdraw,
const struct TALER_Amount *fee_deposit,
const struct TALER_Amount *fee_refresh,
const struct TALER_Amount *fee_refund,
const struct TALER_DenomFeeSet *fees,
const struct TALER_MasterPrivateKeyP *master_priv,
struct TALER_MasterSignatureP *master_sig)
{
@ -278,14 +275,8 @@ TALER_exchange_offline_denom_validity_sign (
&issue.master.eddsa_pub);
TALER_amount_hton (&issue.value,
coin_value);
TALER_amount_hton (&issue.fee_withdraw,
fee_withdraw);
TALER_amount_hton (&issue.fee_deposit,
fee_deposit);
TALER_amount_hton (&issue.fee_refresh,
fee_refresh);
TALER_amount_hton (&issue.fee_refund,
fee_refund);
TALER_denom_fee_set_hton (&issue.fees,
fees);
GNUNET_CRYPTO_eddsa_sign (&master_priv->eddsa_priv,
&issue,
&master_sig->eddsa_signature);
@ -300,10 +291,7 @@ TALER_exchange_offline_denom_validity_verify (
struct GNUNET_TIME_Timestamp stamp_expire_deposit,
struct GNUNET_TIME_Timestamp stamp_expire_legal,
const struct TALER_Amount *coin_value,
const struct TALER_Amount *fee_withdraw,
const struct TALER_Amount *fee_deposit,
const struct TALER_Amount *fee_refresh,
const struct TALER_Amount *fee_refund,
const struct TALER_DenomFeeSet *fees,
const struct TALER_MasterPublicKeyP *master_pub,
const struct TALER_MasterSignatureP *master_sig)
{
@ -321,14 +309,8 @@ TALER_exchange_offline_denom_validity_verify (
TALER_amount_hton (&dkv.value,
coin_value);
TALER_amount_hton (&dkv.fee_withdraw,
fee_withdraw);
TALER_amount_hton (&dkv.fee_deposit,
fee_deposit);
TALER_amount_hton (&dkv.fee_refresh,
fee_refresh);
TALER_amount_hton (&dkv.fee_refund,
fee_refund);
TALER_denom_fee_set_hton (&dkv.fees,
fees);
return
GNUNET_CRYPTO_eddsa_verify (
TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY,

View File

@ -258,6 +258,7 @@ test_planchets_cs (void)
&alg_values,
&bks,
&coin_priv,
NULL,
&c_hash,
&pd));
GNUNET_assert (GNUNET_OK ==
@ -270,6 +271,7 @@ test_planchets_cs (void)
&blind_sig,
&bks,
&coin_priv,
NULL,
&c_hash,
&alg_values,
&coin));
@ -396,8 +398,10 @@ main (int argc,
return 1;
if (0 != test_planchets ())
return 2;
#if FIXME_OEC
if (0 != test_planchets_with_age_commitment ())
return 3;
#endif
if (0 != test_exchange_sigs ())
return 4;
if (0 != test_merchant_sigs ())

View File

@ -330,6 +330,7 @@ test_r_derive (struct TALER_CRYPTO_CsDenominationHelper *dh)
&alg_values,
&bks,
&coin_priv,
NULL, /* no age commitment */
&c_hash,
&pd));
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@ -450,6 +451,7 @@ test_signing (struct TALER_CRYPTO_CsDenominationHelper *dh)
&alg_values,
&bks,
&coin_priv,
NULL, /* no age commitment */
&c_hash,
&pd));
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@ -484,11 +486,13 @@ test_signing (struct TALER_CRYPTO_CsDenominationHelper *dh)
}
{
struct TALER_FreshCoin coin;
if (GNUNET_OK !=
TALER_planchet_to_coin (&keys[i].denom_pub,
&ds,
&bks,
&coin_priv,
NULL, /* no age commitment */
&c_hash,
&alg_values,
&coin))
@ -548,6 +552,7 @@ test_signing (struct TALER_CRYPTO_CsDenominationHelper *dh)
&alg_values,
&bks,
&coin_priv,
NULL, /* no age commitment */
&c_hash,
&pd));
@ -636,6 +641,7 @@ perf_signing (struct TALER_CRYPTO_CsDenominationHelper *dh,
&alg_values,
&bks,
&coin_priv,
NULL, /* no age commitment */
&c_hash,
&pd));
/* use this key as long as it works */

View File

@ -46,6 +46,73 @@ TALER_b2s (const void *buf,
}
void
TALER_denom_fee_set_hton (struct TALER_DenomFeeSetNBOP *nbo,
const struct TALER_DenomFeeSet *fees)
{
TALER_amount_hton (&nbo->withdraw,
&fees->withdraw);
TALER_amount_hton (&nbo->deposit,
&fees->deposit);
TALER_amount_hton (&nbo->refresh,
&fees->refresh);
TALER_amount_hton (&nbo->refund,
&fees->refund);
}
void
TALER_denom_fee_set_ntoh (struct TALER_DenomFeeSet *fees,
const struct TALER_DenomFeeSetNBOP *nbo)
{
TALER_amount_ntoh (&fees->withdraw,
&nbo->withdraw);
TALER_amount_ntoh (&fees->deposit,
&nbo->deposit);
TALER_amount_ntoh (&fees->refresh,
&nbo->refresh);
TALER_amount_ntoh (&fees->refund,
&nbo->refund);
}
enum GNUNET_GenericReturnValue
TALER_denom_fee_check_currency (
const char *currency,
const struct TALER_DenomFeeSet *fees)
{
if (GNUNET_YES !=
TALER_amount_is_currency (&fees->withdraw,
currency))
{
GNUNET_break (0);
return GNUNET_NO;
}
if (GNUNET_YES !=
TALER_amount_is_currency (&fees->deposit,
currency))
{
GNUNET_break (0);
return GNUNET_NO;
}
if (GNUNET_YES !=
TALER_amount_is_currency (&fees->refresh,
currency))
{
GNUNET_break (0);
return GNUNET_NO;
}
if (GNUNET_YES !=
TALER_amount_is_currency (&fees->refund,
currency))
{
GNUNET_break (0);
return GNUNET_NO;
}
return GNUNET_OK;
}
#ifdef __APPLE__
char *
strchrnul (const char *s,