-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"}) \\ & & b := \text{HKDF}(1,n_w || d_s, \text{"b"})
\\ & & s \leftarrow \text{GetWithdraw}(n_w, D_p) \\ & & s \leftarrow \text{GetWithdraw}(n_w, D_p)
\\ & & \textbf{if } s = \bot \\ & & \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{"}) \\ & & r_b := \text{HKDF}(256,n_w || d_s, \text{"r}b\text{"})
% sign coin % sign coin
\\ & & s := r_b + c_b d_s \mod p \\ & & s := r_b + c_b d_s \mod p
% the following db operations are atomic % the following db operations are atomic
\\ & & \text{decrease balance if sufficient and} \\ & & \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} \\ & & \textbf{endif}
\\ & \xleftarrow[\rule{2.5cm}{0pt}]{b,s} & \\ & \xleftarrow[\rule{2.5cm}{0pt}]{b,s} &
% verify signature % 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 & & \\ \textbf{check if } s'G = R'_b + c'_b D_p & &
\\ \sigma_C := \langle R'_b, s' \rangle & & \\ \sigma_C := \langle R'_b, s' \rangle & &
\\ \text{resulting coin: } c_s, C_p, \sigma_C, D_p & & \\ \text{resulting coin: } c_s, C_p, \sigma_C, D_p & &
\end{array}$ \end{array}$
} }
\end{equation*} \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_T := H(T_1, \dots, T_k)
\\ h_{\overline{c_0}} := H(\overline{c_{0_1}},\dots, \overline{c}_{0_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_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}}) \\ 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}) \\ \sigma_{RC} := \text{Ed25519.Sign}(c_s^{(0)}, \rho_{RC})
\\ \text{Persist refresh-request} \\ \text{Persist refresh-request}
\\ \langle \omega, R_0, R_1, \rho_{RC}, \sigma_{RC} \rangle \\ \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{Continuation of}
\\ & \textit{figure \ref{fig:refresh-commit-part1}} \\ & \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 % Exchange checks refresh request
\\ & & \langle h_C, D_p, D_{p(0)}, C_p^{(0)}, \sigma_C^{(0)} \rangle := \rho_{RC} \\ & & \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}) \\ & & \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) \\ & & v := \text{Denomination}(D_p)
\\ & & \textbf{check } \text{IsOverspending}(C_p^{(0)}, D_ {p(0)}, v) \\ & & \textbf{check } \text{IsOverspending}(C_p^{(0)}, D_ {p(0)}, v)
\\ & & \text{verify if } D_p \text{ is valid} \\ & & \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)}) \\ & & \textbf{check } \text{Schnorr.Verify}(D_{p(0)}, C_p^{(0)}, \sigma_C^{(0)})
\\ & & \text{MarkFractionalSpend}(C_p^{(0)}, v) \\ & & \text{MarkFractionalSpend}(C_p^{(0)}, v)
\\ & & \gamma \leftarrow \{1, \dots, \kappa\} \\ & & \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} & \\ & \xleftarrow[\rule{2cm}{0pt}]{\gamma} &
% Check challenge and send challenge response (reveal not selected msgs) % Check challenge and send challenge response (reveal not selected msgs)
\\ \textbf{check } \text{IsConsistentChallenge}(\rho_{RC}, \gamma) \\ \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 \\ \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 \\ 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 \\ \rho_{RR} := \langle \rho_L, S \rangle
\\ \sigma_{L} := \text{Ed25519.Sign}(c_s^{(0)}, \rho_{L}) \\ \sigma_{L} := \text{Ed25519.Sign}(c_s^{(0)}, \rho_{L})
\\ & \xrightarrow[\rule{2.5cm}{0pt}]{\rho_{RR},\rho_L, \sigma_{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}} & \\ & \xrightarrow[\rule{2.5cm}{0pt}]{\rho_{RR},\rho_L, \sigma_{L}} &
% check revealed msgs and sign coin % 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'_\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 \\ & & \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) \\ & & \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_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_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_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}}') \\ & & h_C' = H(h_T', h_{\overline{c}}')
\\ & & \textbf{check } h_C = h_C' \\ & & \textbf{check } h_C = h_C'
\\ & & r_b := \text{HKDF}(256,n_r || d_s, \text{"r}b\text{"}) \\ & & 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), GNUNET_h2s (&issue->denom_hash.hash),
TALER_amount2s (&value)); TALER_amount2s (&value));
TALER_amount_ntoh (&value, TALER_amount_ntoh (&value,
&issue->fee_withdraw); &issue->fees.withdraw);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Withdraw fee is %s\n", "Withdraw fee is %s\n",
TALER_amount2s (&value)); TALER_amount2s (&value));

View File

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

View File

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

View File

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

View File

@ -505,10 +505,10 @@ run (void *cls,
TALER_denom_pub_hash (&denom_pub, TALER_denom_pub_hash (&denom_pub,
&h_denom_pub); &h_denom_pub);
make_amountN (2, 0, &issue.properties.value); make_amountN (2, 0, &issue.properties.value);
make_amountN (0, 5, &issue.properties.fee_withdraw); make_amountN (0, 5, &issue.properties.fees.withdraw);
make_amountN (0, 5, &issue.properties.fee_deposit); make_amountN (0, 5, &issue.properties.fees.deposit);
make_amountN (0, 5, &issue.properties.fee_refresh); make_amountN (0, 5, &issue.properties.fees.refresh);
make_amountN (0, 5, &issue.properties.fee_refund); make_amountN (0, 5, &issue.properties.fees.refund);
issue.properties.denom_hash = h_denom_pub; issue.properties.denom_hash = h_denom_pub;
if (0 >= if (0 >=
plugin->insert_denomination_info (plugin->cls, 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_deposit;
struct GNUNET_TIME_Timestamp stamp_expire_legal; struct GNUNET_TIME_Timestamp stamp_expire_legal;
struct TALER_Amount coin_value; struct TALER_Amount coin_value;
struct TALER_Amount fee_withdraw; struct TALER_DenomFeeSet fees;
struct TALER_Amount fee_deposit;
struct TALER_Amount fee_refresh;
struct TALER_Amount fee_refund;
struct TALER_MasterSignatureP master_sig; struct TALER_MasterSignatureP master_sig;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_denom_pub ("denom_pub", TALER_JSON_spec_denom_pub ("denom_pub",
@ -768,18 +765,9 @@ show_denomkeys (const json_t *denomkeys)
TALER_JSON_spec_amount ("value", TALER_JSON_spec_amount ("value",
currency, currency,
&coin_value), &coin_value),
TALER_JSON_spec_amount ("fee_withdraw", TALER_JSON_SPEC_DENOM_FEES ("fee",
currency, currency,
&fee_withdraw), &fees),
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),
GNUNET_JSON_spec_timestamp ("stamp_start", GNUNET_JSON_spec_timestamp ("stamp_start",
&stamp_start), &stamp_start),
GNUNET_JSON_spec_timestamp ("stamp_expire_withdraw", GNUNET_JSON_spec_timestamp ("stamp_expire_withdraw",
@ -824,10 +812,7 @@ show_denomkeys (const json_t *denomkeys)
stamp_expire_deposit, stamp_expire_deposit,
stamp_expire_legal, stamp_expire_legal,
&coin_value, &coin_value,
&fee_withdraw, &fees,
&fee_deposit,
&fee_refresh,
&fee_refund,
&master_pub, &master_pub,
&master_sig)) &master_sig))
{ {
@ -847,10 +832,10 @@ show_denomkeys (const json_t *denomkeys)
char *deposit_s; char *deposit_s;
char *legal_s; char *legal_s;
withdraw_fee_s = TALER_amount_to_string (&fee_withdraw); withdraw_fee_s = TALER_amount_to_string (&fees.withdraw);
deposit_fee_s = TALER_amount_to_string (&fee_deposit); deposit_fee_s = TALER_amount_to_string (&fees.deposit);
refresh_fee_s = TALER_amount_to_string (&fee_refresh); refresh_fee_s = TALER_amount_to_string (&fees.refresh);
refund_fee_s = TALER_amount_to_string (&fee_refund); refund_fee_s = TALER_amount_to_string (&fees.refund);
deposit_s = GNUNET_strdup ( deposit_s = GNUNET_strdup (
GNUNET_TIME_timestamp2s (stamp_expire_deposit)); GNUNET_TIME_timestamp2s (stamp_expire_deposit));
legal_s = GNUNET_strdup ( 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_deposit;
struct GNUNET_TIME_Timestamp stamp_expire_legal; struct GNUNET_TIME_Timestamp stamp_expire_legal;
struct TALER_Amount coin_value; struct TALER_Amount coin_value;
struct TALER_Amount fee_withdraw; struct TALER_DenomFeeSet fees;
struct TALER_Amount fee_deposit;
struct TALER_Amount fee_refresh;
struct TALER_Amount fee_refund;
struct TALER_MasterSignatureP master_sig; struct TALER_MasterSignatureP master_sig;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_denom_pub ("denom_pub", TALER_JSON_spec_denom_pub ("denom_pub",
@ -1069,18 +1051,9 @@ sign_denomkeys (const json_t *denomkeys)
TALER_JSON_spec_amount ("value", TALER_JSON_spec_amount ("value",
currency, currency,
&coin_value), &coin_value),
TALER_JSON_spec_amount ("fee_withdraw", TALER_JSON_SPEC_DENOM_FEES ("fee",
currency, currency,
&fee_withdraw), &fees),
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),
GNUNET_JSON_spec_timestamp ("stamp_start", GNUNET_JSON_spec_timestamp ("stamp_start",
&stamp_start), &stamp_start),
GNUNET_JSON_spec_timestamp ("stamp_expire_withdraw", GNUNET_JSON_spec_timestamp ("stamp_expire_withdraw",
@ -1121,10 +1094,7 @@ sign_denomkeys (const json_t *denomkeys)
stamp_expire_deposit, stamp_expire_deposit,
stamp_expire_legal, stamp_expire_legal,
&coin_value, &coin_value,
&fee_withdraw, &fees,
&fee_deposit,
&fee_refresh,
&fee_refund,
&master_pub, &master_pub,
&master_sig)) &master_sig))
{ {
@ -1147,10 +1117,7 @@ sign_denomkeys (const json_t *denomkeys)
stamp_expire_deposit, stamp_expire_deposit,
stamp_expire_legal, stamp_expire_legal,
&coin_value, &coin_value,
&fee_withdraw, &fees,
&fee_deposit,
&fee_refresh,
&fee_refund,
&auditor_priv, &auditor_priv,
&auditor_sig); &auditor_sig);
output_operation (OP_SIGN_DENOMINATION, output_operation (OP_SIGN_DENOMINATION,

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER 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 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 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_deposit;
struct GNUNET_TIME_Timestamp stamp_expire_legal; struct GNUNET_TIME_Timestamp stamp_expire_legal;
struct TALER_Amount coin_value; struct TALER_Amount coin_value;
struct TALER_Amount fee_withdraw; struct TALER_DenomFeeSet fees;
struct TALER_Amount fee_deposit;
struct TALER_Amount fee_refresh;
struct TALER_Amount fee_refund;
struct TALER_SecurityModuleSignatureP secm_sig; struct TALER_SecurityModuleSignatureP secm_sig;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("section_name", GNUNET_JSON_spec_string ("section_name",
@ -2844,18 +2841,9 @@ show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
TALER_JSON_spec_amount ("value", TALER_JSON_spec_amount ("value",
currency, currency,
&coin_value), &coin_value),
TALER_JSON_spec_amount ("fee_withdraw", TALER_JSON_SPEC_DENOM_FEES ("fee",
currency, currency,
&fee_withdraw), &fees),
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),
GNUNET_JSON_spec_timestamp ("stamp_start", GNUNET_JSON_spec_timestamp ("stamp_start",
&stamp_start), &stamp_start),
GNUNET_JSON_spec_timestamp ("stamp_expire_withdraw", GNUNET_JSON_spec_timestamp ("stamp_expire_withdraw",
@ -2949,10 +2937,10 @@ show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
char *deposit_s; char *deposit_s;
char *legal_s; char *legal_s;
withdraw_fee_s = TALER_amount_to_string (&fee_withdraw); withdraw_fee_s = TALER_amount_to_string (&fees.withdraw);
deposit_fee_s = TALER_amount_to_string (&fee_deposit); deposit_fee_s = TALER_amount_to_string (&fees.deposit);
refresh_fee_s = TALER_amount_to_string (&fee_refresh); refresh_fee_s = TALER_amount_to_string (&fees.refresh);
refund_fee_s = TALER_amount_to_string (&fee_refund); refund_fee_s = TALER_amount_to_string (&fees.refund);
deposit_s = GNUNET_strdup ( deposit_s = GNUNET_strdup (
GNUNET_TIME_timestamp2s (stamp_expire_deposit)); GNUNET_TIME_timestamp2s (stamp_expire_deposit));
legal_s = GNUNET_strdup ( 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_deposit;
struct GNUNET_TIME_Timestamp stamp_expire_legal; struct GNUNET_TIME_Timestamp stamp_expire_legal;
struct TALER_Amount coin_value; struct TALER_Amount coin_value;
struct TALER_Amount fee_withdraw; struct TALER_DenomFeeSet fees;
struct TALER_Amount fee_deposit;
struct TALER_Amount fee_refresh;
struct TALER_Amount fee_refund;
struct TALER_SecurityModuleSignatureP secm_sig; struct TALER_SecurityModuleSignatureP secm_sig;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("section_name", GNUNET_JSON_spec_string ("section_name",
@ -3337,18 +3322,9 @@ sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
TALER_JSON_spec_amount ("value", TALER_JSON_spec_amount ("value",
currency, currency,
&coin_value), &coin_value),
TALER_JSON_spec_amount ("fee_withdraw", TALER_JSON_SPEC_DENOM_FEES ("fee",
currency, currency,
&fee_withdraw), &fees),
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),
GNUNET_JSON_spec_timestamp ("stamp_start", GNUNET_JSON_spec_timestamp ("stamp_start",
&stamp_start), &stamp_start),
GNUNET_JSON_spec_timestamp ("stamp_expire_withdraw", 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_deposit,
stamp_expire_legal, stamp_expire_legal,
&coin_value, &coin_value,
&fee_withdraw, &fees,
&fee_deposit,
&fee_refresh,
&fee_refund,
&master_priv, &master_priv,
&master_sig); &master_sig);
GNUNET_assert (0 == GNUNET_assert (0 ==

View File

@ -925,9 +925,15 @@ handle_mhd_request (void *cls,
}, },
/* request R, used in clause schnorr withdraw and refresh */ /* request R, used in clause schnorr withdraw and refresh */
{ {
.url = "csr", .url = "csr-melt",
.method = MHD_HTTP_METHOD_POST, .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 .nargs = 0
}, },
/* Withdrawing coins / interaction with reserves */ /* Withdrawing coins / interaction with reserves */

View File

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

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER 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 TALER is free software; you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as it under the terms of the GNU Affero General Public License as
@ -33,15 +33,16 @@
MHD_RESULT MHD_RESULT
TEH_handler_csr (struct TEH_RequestContext *rc, TEH_handler_csr_melt (struct TEH_RequestContext *rc,
const json_t *root, const json_t *root,
const char *const args[]) const char *const args[])
{ {
struct TALER_RefreshMasterSecretP rms;
unsigned int csr_requests_num; unsigned int csr_requests_num;
json_t *csr_requests; json_t *csr_requests;
json_t *csr_response_ewvs;
json_t *csr_response;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("rms",
&rms),
GNUNET_JSON_spec_json ("nks", GNUNET_JSON_spec_json ("nks",
&csr_requests), &csr_requests),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
@ -50,8 +51,7 @@ TEH_handler_csr (struct TEH_RequestContext *rc,
struct TEH_DenominationKey *dk; struct TEH_DenominationKey *dk;
(void) args; (void) args;
/* parse input */
// parse input
{ {
enum GNUNET_GenericReturnValue res; enum GNUNET_GenericReturnValue res;
@ -62,7 +62,8 @@ TEH_handler_csr (struct TEH_RequestContext *rc,
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
} }
csr_requests_num = json_array_size (csr_requests); 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); GNUNET_JSON_parse_free (spec);
return TALER_MHD_reply_with_error ( 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, TALER_EC_EXCHANGE_GENERIC_NEW_DENOMS_ARRAY_SIZE_EXCESSIVE,
NULL); 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, struct TALER_ExchangeWithdrawValues ewvs[csr_requests_num];
csr_spec,
i,
-1);
if (GNUNET_OK != res)
{ {
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); 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]; enum GNUNET_GenericReturnValue res;
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; res = TALER_MHD_parse_json_data (rc->connection,
// check denomination referenced by denom_pub_hash 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; return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
ksh = TEH_keys_get_state (); TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
if (NULL == ksh) NULL);
{
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);
}
} }
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 /* 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, enum TALER_ErrorCode ec;
nonce,
r_pub); ec = TEH_keys_denomination_cs_r_pub (&denom_pub_hash,
&nonce,
&ewv.details.cs_values);
if (TALER_EC_NONE != ec) if (TALER_EC_NONE != ec)
{ {
GNUNET_break (0); 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; json_t *csr_obj;
csr_obj = GNUNET_JSON_PACK ( csr_obj = GNUNET_JSON_PACK (
TALER_JSON_pack_exchange_withdraw_values ("ewv", TALER_JSON_pack_exchange_withdraw_values ("ewv",
&ewvs[i])); &ewv));
GNUNET_assert (NULL != csr_obj); GNUNET_assert (NULL != csr_obj);
GNUNET_assert (0 == return TALER_MHD_reply_json_steal (rc->connection,
json_array_append_new (csr_response_ewvs, csr_obj,
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 * @file taler-exchange-httpd_csr.h
* @brief Handle /csr requests * @brief Handle /csr-* requests
* @author Lucien Heuzeveldt * @author Lucien Heuzeveldt
* @author Gian Demarmles * @author Gian Demarmles
*/ */
@ -27,8 +27,7 @@
/** /**
* Handle a "/csr" request. Parses the "nonce" and * Handle a "/csr-melt" request.
* the "denom_pub_hash" (identifying a denomination) used to derive the r_pub.
* *
* @param rc request context * @param rc request context
* @param root uploaded JSON data * @param root uploaded JSON data
@ -36,8 +35,22 @@
* @return MHD result code * @return MHD result code
*/ */
MHD_RESULT MHD_RESULT
TEH_handler_csr (struct TEH_RequestContext *rc, TEH_handler_csr_melt (struct TEH_RequestContext *rc,
const json_t *root, const json_t *root,
const char *const args[]); 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 #endif

View File

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

View File

@ -2113,14 +2113,8 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
&dk->denom_pub), &dk->denom_pub),
TALER_JSON_pack_amount ("value", TALER_JSON_pack_amount ("value",
&dk->meta.value), &dk->meta.value),
TALER_JSON_pack_amount ("fee_withdraw", TALER_JSON_PACK_DENOM_FEES ("fee",
&dk->meta.fee_withdraw), &dk->meta.fees));
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));
/* Put the denom into the correct array depending on the settings and /* Put the denom into the correct array depending on the settings and
* the properties of the denomination. Also, we build up the right * the properties of the denomination. Also, we build up the right
@ -2810,74 +2804,22 @@ load_extension_data (const char *section_name,
section_name); section_name);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
if (GNUNET_OK != if (0 != strcasecmp (TEH_currency,
TALER_config_get_amount (TEH_cfg, meta->value.currency))
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)) )
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 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, section_name,
TEH_currency); TEH_currency);
return GNUNET_SYSERR; 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); meta->age_mask = load_age_mask (section_name);
return GNUNET_OK; return GNUNET_OK;
} }
@ -3040,14 +2982,8 @@ add_future_denomkey_cb (void *cls,
meta.expire_legal), meta.expire_legal),
TALER_JSON_pack_denom_pub ("denom_pub", TALER_JSON_pack_denom_pub ("denom_pub",
&hd->denom_pub), &hd->denom_pub),
TALER_JSON_pack_amount ("fee_withdraw", TALER_JSON_PACK_DENOM_FEES ("fee",
&meta.fee_withdraw), &meta.fees),
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),
GNUNET_JSON_pack_data_auto ("denom_secmod_sig", GNUNET_JSON_pack_data_auto ("denom_secmod_sig",
&hd->sm_sig), &hd->sm_sig),
GNUNET_JSON_pack_string ("section_name", GNUNET_JSON_pack_string ("section_name",

View File

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

View File

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

View File

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

View File

@ -121,11 +121,20 @@ struct RevealContext
*/ */
struct TALER_RefreshCoinData *rcds; 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). * Size of the @e dks, @e rcds and @e ev_sigs arrays (if non-NULL).
*/ */
unsigned int num_fresh_coins; 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_refresh_get_commitment (&rc_expected,
TALER_CNC_KAPPA, TALER_CNC_KAPPA,
rctx->have_rms
? &rctx->rms
: NULL,
rctx->num_fresh_coins, rctx->num_fresh_coins,
rcs, rcs,
&rctx->melt.session.coin.coin_pub, &rctx->melt.session.coin.coin_pub,
@ -369,7 +381,7 @@ check_commitment (struct RevealContext *rctx,
if ( (0 > if ( (0 >
TALER_amount_add (&total, TALER_amount_add (&total,
&rctx->dks[i]->meta.fee_withdraw, &rctx->dks[i]->meta.fees.withdraw,
&rctx->dks[i]->meta.value)) || &rctx->dks[i]->meta.value)) ||
(0 > (0 >
TALER_amount_add (&refresh_cost, TALER_amount_add (&refresh_cost,
@ -464,7 +476,15 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
&ret); &ret);
if (NULL == dks[i]) if (NULL == dks[i])
return ret; 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)) if (GNUNET_TIME_absolute_is_past (dks[i]->meta.expire_withdraw.abs_time))
{ {
/* This denomination is past the expiration time for withdraws */ /* 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_mark_optional (
GNUNET_JSON_spec_json ("old_age_commitment", GNUNET_JSON_spec_json ("old_age_commitment",
&old_age_commitment)), &old_age_commitment)),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_fixed_auto ("rms",
&rctx.rms)),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
@ -947,6 +970,8 @@ TEH_handler_reveal (struct TEH_RequestContext *rc,
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
} }
} }
rctx.have_rms = (NULL != json_object_get (root,
"rms"));
/* Check we got enough transfer private keys */ /* Check we got enough transfer private keys */
/* Note we do +1 as 1 row (cut-and-choose!) is missing! */ /* 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); GNUNET_break (0);
return mret; return mret;
} }
refund->details.refund_fee = dk->meta.fee_refund; refund->details.refund_fee = dk->meta.fees.refund;
rctx.deposit_fee = dk->meta.fee_deposit; rctx.deposit_fee = dk->meta.fees.deposit;
} }
/* Finally run the actual transaction logic */ /* Finally run the actual transaction logic */

View File

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

View File

@ -1,6 +1,6 @@
-- --
-- This file is part of TALER -- 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 -- 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 -- 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 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_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!) ,denom_type INT4 NOT NULL DEFAULT (1) -- 1 == RSA (for now, remove default later!)
,age_mask INT4 NOT NULL DEFAULT (0) ,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 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 ,denominations_serial INT8 PRIMARY KEY REFERENCES denominations (denominations_serial) ON DELETE CASCADE
,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64) ,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 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) ,h_payto BYTEA PRIMARY KEY CHECK (LENGTH(h_payto)=64)
,payto_uri VARCHAR NOT NULL ,payto_uri VARCHAR NOT NULL
,kyc_ok BOOLEAN NOT NULL DEFAULT (FALSE) ,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); FOR VALUES WITH (MODULUS 1, REMAINDER 0);
CREATE TABLE IF NOT EXISTS reserves 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) ,reserve_pub BYTEA PRIMARY KEY CHECK(LENGTH(reserve_pub)=32)
,current_balance_val INT8 NOT NULL ,current_balance_val INT8 NOT NULL
,current_balance_frac INT4 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 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 ,reserve_pub BYTEA PRIMARY KEY REFERENCES reserves (reserve_pub) ON DELETE CASCADE
,wire_reference INT8 NOT NULL ,wire_reference INT8 NOT NULL
,credit_val 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 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 ,reserve_pub BYTEA NOT NULL REFERENCES reserves (reserve_pub) ON DELETE CASCADE
,execution_date INT8 NOT NULL ,execution_date INT8 NOT NULL
,wtid BYTEA NOT NULL CHECK (LENGTH(wtid)=32) ,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 CREATE TABLE IF NOT EXISTS reserves_out
(reserve_out_serial_id BIGSERIAL -- UNIQUE (reserve_out_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
,wih BYTEA PRIMARY KEY CHECK (LENGTH(wih)=64)
,h_blind_ev BYTEA CHECK (LENGTH(h_blind_ev)=64) -- UNIQUE ,h_blind_ev BYTEA CHECK (LENGTH(h_blind_ev)=64) -- UNIQUE
,denominations_serial INT8 NOT NULL REFERENCES denominations (denominations_serial) ,denominations_serial INT8 NOT NULL REFERENCES denominations (denominations_serial)
,denom_sig BYTEA NOT NULL ,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_val INT8 NOT NULL
,amount_with_fee_frac INT4 NOT NULL ,amount_with_fee_frac INT4 NOT NULL
) )
PARTITION BY HASH (wih); PARTITION BY HASH (h_blind_ev);
COMMENT ON TABLE reserves_out COMMENT ON TABLE reserves_out
IS 'Withdraw operations performed on reserves.'; 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 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).'; 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 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 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_pub BYTEA PRIMARY KEY CHECK (LENGTH(auditor_pub)=32)
,auditor_name VARCHAR NOT NULL ,auditor_name VARCHAR NOT NULL
,auditor_url 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 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 ,auditor_uuid INT8 NOT NULL REFERENCES auditors (auditor_uuid) ON DELETE CASCADE
,denominations_serial INT8 NOT NULL REFERENCES denominations (denominations_serial) ON DELETE CASCADE ,denominations_serial INT8 NOT NULL REFERENCES denominations (denominations_serial) ON DELETE CASCADE
,auditor_sig BYTEA CHECK (LENGTH(auditor_sig)=64) ,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 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) ,exchange_pub BYTEA PRIMARY KEY CHECK (LENGTH(exchange_pub)=32)
,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64) ,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
,valid_from INT8 NOT NULL ,valid_from INT8 NOT NULL
@ -289,7 +286,7 @@ COMMENT ON COLUMN exchange_sign_keys.expire_legal
CREATE TABLE IF NOT EXISTS signkey_revocations 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 ,esk_serial INT8 PRIMARY KEY REFERENCES exchange_sign_keys (esk_serial) ON DELETE CASCADE
,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64) ,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 CREATE TABLE IF NOT EXISTS extensions
(extension_id BIGSERIAL UNIQUE (extension_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,name VARCHAR NOT NULL UNIQUE ,name VARCHAR NOT NULL UNIQUE
,config BYTEA ,config BYTEA
); );
@ -311,7 +308,7 @@ COMMENT ON COLUMN extensions.config
CREATE TABLE IF NOT EXISTS known_coins 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 ,denominations_serial INT8 NOT NULL REFERENCES denominations (denominations_serial) ON DELETE CASCADE
,coin_pub BYTEA NOT NULL PRIMARY KEY CHECK (LENGTH(coin_pub)=32) ,coin_pub BYTEA NOT NULL PRIMARY KEY CHECK (LENGTH(coin_pub)=32)
,age_hash BYTEA CHECK (LENGTH(age_hash)=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 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) ,rc BYTEA PRIMARY KEY CHECK (LENGTH(rc)=64)
,old_coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) ON DELETE CASCADE ,old_coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) ON DELETE CASCADE
,h_age_commitment BYTEA CHECK(LENGTH(h_age_commitment)=32) ,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 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 ,melt_serial_id INT8 NOT NULL -- REFERENCES refresh_commitments (melt_serial_id) ON DELETE CASCADE
,freshcoin_index INT4 NOT NULL ,freshcoin_index INT4 NOT NULL
,link_sig BYTEA NOT NULL CHECK(LENGTH(link_sig)=64) ,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 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 ,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_pub BYTEA NOT NULL CHECK(LENGTH(transfer_pub)=32)
,transfer_privs BYTEA NOT NULL ,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 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); ,extension_options VARCHAR);
COMMENT ON TABLE extension_details COMMENT ON TABLE extension_details
IS 'Extensions that were provided with deposits (not yet used).'; 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 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 ,shard INT8 NOT NULL
,known_coin_id INT8 NOT NULL -- REFERENCES known_coins (known_coin_id) ON DELETE CASCADE ,known_coin_id INT8 NOT NULL -- REFERENCES known_coins (known_coin_id) ON DELETE CASCADE
,amount_with_fee_val INT8 NOT NULL ,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 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 ,deposit_serial_id INT8 NOT NULL -- REFERENCES deposits (deposit_serial_id) ON DELETE CASCADE
,merchant_sig BYTEA NOT NULL CHECK(LENGTH(merchant_sig)=64) ,merchant_sig BYTEA NOT NULL CHECK(LENGTH(merchant_sig)=64)
,rtransaction_id INT8 NOT NULL ,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 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 ,execution_date INT8 NOT NULL
,wtid_raw BYTEA UNIQUE NOT NULL CHECK (LENGTH(wtid_raw)=32) ,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) ,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 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 ,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 ,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 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 ,wire_method VARCHAR NOT NULL
,start_date INT8 NOT NULL ,start_date INT8 NOT NULL
,end_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 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) ,known_coin_id INT8 NOT NULL -- REFERENCES known_coins (known_coin_id)
,coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64) ,coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64)
,coin_blind BYTEA NOT NULL CHECK(LENGTH(coin_blind)=32) ,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 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!'; 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 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 COMMENT ON COLUMN recoup.coin_sig
IS 'Signature by the coin affirming the recoup, of type TALER_SIGNATURE_WALLET_COIN_RECOUP'; IS 'Signature by the coin affirming the recoup, of type TALER_SIGNATURE_WALLET_COIN_RECOUP';
COMMENT ON COLUMN recoup.coin_blind 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 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) ,known_coin_id INT8 NOT NULL -- REFERENCES known_coins (known_coin_id)
,coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64) ,coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64)
,coin_blind BYTEA NOT NULL CHECK(LENGTH(coin_blind)=32) ,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 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 ,wire_method TEXT NOT NULL
,finished BOOLEAN NOT NULL DEFAULT false ,finished BOOLEAN NOT NULL DEFAULT false
,failed 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.'; IS 'true if we are currently supporting the use of this account.';
COMMENT ON COLUMN wire_accounts.last_change COMMENT ON COLUMN wire_accounts.last_change
IS 'Latest time when active status changed. Used to detect replays of old messages.'; 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 -- 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 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 ,last_attempt INT8 NOT NULL
,start_row INT8 NOT NULL ,start_row INT8 NOT NULL
,end_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 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 ,last_attempt INT8 NOT NULL
,start_row INT4 NOT NULL ,start_row INT4 NOT NULL
,end_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( CREATE OR REPLACE FUNCTION exchange_do_withdraw(
IN in_wih BYTEA, IN cs_nonce BYTEA,
IN amount_val INT8, IN amount_val INT8,
IN amount_frac INT4, IN amount_frac INT4,
IN h_denom_pub BYTEA, IN h_denom_pub BYTEA,
@ -832,8 +846,7 @@ CREATE OR REPLACE FUNCTION exchange_do_withdraw(
OUT balance_ok BOOLEAN, OUT balance_ok BOOLEAN,
OUT kycok BOOLEAN, OUT kycok BOOLEAN,
OUT account_uuid INT8, OUT account_uuid INT8,
OUT ruuid INT8, OUT ruuid INT8)
OUT out_denom_sig BYTEA)
LANGUAGE plpgsql LANGUAGE plpgsql
AS $$ AS $$
DECLARE DECLARE
@ -851,7 +864,8 @@ BEGIN
-- reserves_in by reserve_pub (SELECT) -- reserves_in by reserve_pub (SELECT)
-- wire_targets by wire_target_serial_id -- wire_targets by wire_target_serial_id
SELECT denominations_serial INTO denom_serial SELECT denominations_serial
INTO denom_serial
FROM denominations FROM denominations
WHERE denom_pub_hash=h_denom_pub; WHERE denom_pub_hash=h_denom_pub;
@ -867,6 +881,7 @@ THEN
RETURN; RETURN;
END IF; END IF;
SELECT SELECT
current_balance_val current_balance_val
,current_balance_frac ,current_balance_frac
@ -887,7 +902,7 @@ THEN
balance_ok=FALSE; balance_ok=FALSE;
kycok=FALSE; kycok=FALSE;
account_uuid=0; account_uuid=0;
ruuid=0; ruuid=2;
RETURN; RETURN;
END IF; END IF;
@ -895,7 +910,6 @@ END IF;
-- the query successful due to idempotency. -- the query successful due to idempotency.
INSERT INTO reserves_out INSERT INTO reserves_out
(h_blind_ev (h_blind_ev
,wih
,denominations_serial ,denominations_serial
,denom_sig ,denom_sig
,reserve_uuid ,reserve_uuid
@ -905,7 +919,6 @@ INSERT INTO reserves_out
,amount_with_fee_frac) ,amount_with_fee_frac)
VALUES VALUES
(h_coin_envelope (h_coin_envelope
,in_wih
,denom_serial ,denom_serial
,denom_sig ,denom_sig
,ruuid ,ruuid
@ -918,25 +931,6 @@ ON CONFLICT DO NOTHING;
IF NOT FOUND IF NOT FOUND
THEN THEN
-- idempotent query, all constraints must be satisfied -- 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; reserve_found=TRUE;
balance_ok=TRUE; balance_ok=TRUE;
kycok=TRUE; kycok=TRUE;
@ -983,6 +977,44 @@ WHERE
reserve_found=TRUE; reserve_found=TRUE;
balance_ok=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 -- Obtain KYC status based on the last wire transfer into
-- this reserve. FIXME: likely not adequate for reserves that got P2P transfers! -- this reserve. FIXME: likely not adequate for reserves that got P2P transfers!
SELECT SELECT
@ -996,9 +1028,6 @@ SELECT
WHERE reserve_pub=rpub WHERE reserve_pub=rpub
LIMIT 1; -- limit 1 should not be required (without p2p transfers) 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 $$; END $$;
@ -1223,6 +1252,7 @@ END $$;
CREATE OR REPLACE FUNCTION exchange_do_melt( CREATE OR REPLACE FUNCTION exchange_do_melt(
IN in_cs_rms BYTEA,
IN in_amount_with_fee_val INT8, IN in_amount_with_fee_val INT8,
IN in_amount_with_fee_frac INT4, IN in_amount_with_fee_frac INT4,
IN in_rc BYTEA, IN in_rc BYTEA,
@ -1236,6 +1266,8 @@ CREATE OR REPLACE FUNCTION exchange_do_melt(
OUT out_noreveal_index INT4) OUT out_noreveal_index INT4)
LANGUAGE plpgsql LANGUAGE plpgsql
AS $$ AS $$
DECLARE
denom_max INT8;
BEGIN BEGIN
-- Shards: INSERT refresh_commitments (by rc) -- Shards: INSERT refresh_commitments (by rc)
-- (rare:) SELECT refresh_commitments (by old_coin_pub) -- crosses shards! -- (rare:) SELECT refresh_commitments (by old_coin_pub) -- crosses shards!
@ -1333,6 +1365,56 @@ THEN
RETURN; RETURN;
END IF; 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! -- Everything fine, return success!
out_balance_ok=TRUE; out_balance_ok=TRUE;
out_noreveal_index=in_noreveal_index; out_noreveal_index=in_noreveal_index;
@ -1806,6 +1888,8 @@ DECLARE
deposit_min INT8; -- minimum deposit still alive deposit_min INT8; -- minimum deposit still alive
DECLARE DECLARE
reserve_out_min INT8; -- minimum reserve_out still alive reserve_out_min INT8; -- minimum reserve_out still alive
DECLARE
denom_min INT8; -- minimum denomination still alive
BEGIN BEGIN
DELETE FROM prewire DELETE FROM prewire
@ -1901,6 +1985,16 @@ DELETE FROM refunds
DELETE FROM aggregation_tracking DELETE FROM aggregation_tracking
WHERE deposit_serial_id < deposit_min; 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 $$; END $$;

View File

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

View File

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

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER 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 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 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" ",kycok AS kyc_ok"
",account_uuid AS payment_target_uuid" ",account_uuid AS payment_target_uuid"
",ruuid" ",ruuid"
",out_denom_sig"
" FROM exchange_do_withdraw" " FROM exchange_do_withdraw"
" ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);", " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);",
10), 10),
@ -612,8 +611,8 @@ prepare_statements (struct PostgresClosure *pg)
",out_zombie_bad AS zombie_required" ",out_zombie_bad AS zombie_required"
",out_noreveal_index AS noreveal_index" ",out_noreveal_index AS noreveal_index"
" FROM exchange_do_melt" " FROM exchange_do_melt"
" ($1,$2,$3,$4,$5,$6,$7,$8);", " ($1,$2,$3,$4,$5,$6,$7,$8,$9);",
8), 9),
/* Used in #postgres_do_refund() to refund a deposit. */ /* Used in #postgres_do_refund() to refund a deposit. */
GNUNET_PQ_make_prepare ( GNUNET_PQ_make_prepare (
"call_refund", "call_refund",
@ -667,7 +666,7 @@ prepare_statements (struct PostgresClosure *pg)
" USING (reserve_uuid)" " USING (reserve_uuid)"
" JOIN denominations denom" " JOIN denominations denom"
" USING (denominations_serial)" " USING (denominations_serial)"
" WHERE wih=$1;", " WHERE h_blind_ev=$1;",
1), 1),
/* Used during #postgres_get_reserve_history() to /* Used during #postgres_get_reserve_history() to
obtain all of the /reserve/withdraw operations that obtain all of the /reserve/withdraw operations that
@ -1672,16 +1671,16 @@ prepare_statements (struct PostgresClosure *pg)
" ON (denoms.denominations_serial = coins.denominations_serial)" " ON (denoms.denominations_serial = coins.denominations_serial)"
" WHERE coins.coin_pub=$1;", " WHERE coins.coin_pub=$1;",
1), 1),
/* Used in #postgres_get_reserve_by_wih() */ /* Used in #postgres_get_reserve_by_h_blind() */
GNUNET_PQ_make_prepare ( GNUNET_PQ_make_prepare (
"reserve_by_wih", "reserve_by_h_blind",
"SELECT" "SELECT"
" reserves.reserve_pub" " reserves.reserve_pub"
",reserve_out_serial_id" ",reserve_out_serial_id"
" FROM reserves_out" " FROM reserves_out"
" JOIN reserves" " JOIN reserves"
" USING (reserve_uuid)" " USING (reserve_uuid)"
" WHERE wih=$1" " WHERE h_blind_ev=$1"
" LIMIT 1;", " LIMIT 1;",
1), 1),
/* Used in #postgres_get_old_coin_by_h_blind() */ /* Used in #postgres_get_old_coin_by_h_blind() */
@ -3091,6 +3090,7 @@ postgres_insert_denomination_info (
const struct TALER_EXCHANGEDB_DenominationKeyInformationP *issue) const struct TALER_EXCHANGEDB_DenominationKeyInformationP *issue)
{ {
struct PostgresClosure *pg = cls; struct PostgresClosure *pg = cls;
uint32_t age_mask = 0; /* FIXME-OEC */
struct GNUNET_PQ_QueryParam params[] = { struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (&issue->properties.denom_hash), GNUNET_PQ_query_param_auto_from_type (&issue->properties.denom_hash),
TALER_PQ_query_param_denom_pub (denom_pub), 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_deposit),
GNUNET_PQ_query_param_timestamp_nbo (&issue->properties.expire_legal), 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.value),
TALER_PQ_query_param_amount_nbo (&issue->properties.fee_withdraw), TALER_PQ_query_param_amount_nbo (&issue->properties.fees.withdraw),
TALER_PQ_query_param_amount_nbo (&issue->properties.fee_deposit), TALER_PQ_query_param_amount_nbo (&issue->properties.fees.deposit),
TALER_PQ_query_param_amount_nbo (&issue->properties.fee_refresh), TALER_PQ_query_param_amount_nbo (&issue->properties.fees.refresh),
TALER_PQ_query_param_amount_nbo (&issue->properties.fee_refund), TALER_PQ_query_param_amount_nbo (&issue->properties.fees.refund),
GNUNET_PQ_query_param_uint32 (&denom_pub->age_mask.mask), GNUNET_PQ_query_param_uint32 (&age_mask),
GNUNET_PQ_query_param_end GNUNET_PQ_query_param_end
}; };
struct TALER_DenomFeeSet fees;
GNUNET_assert (denom_pub->age_mask.mask == issue->age_mask.mask); 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_assert (! GNUNET_TIME_absolute_is_zero (
GNUNET_TIME_timestamp_ntoh ( GNUNET_TIME_timestamp_ntoh (
issue->properties.expire_legal).abs_time)); 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 == GNUNET_assert (GNUNET_YES ==
TALER_amount_cmp_currency_nbo (&issue->properties.value, TALER_denom_fee_check_currency (
&issue->properties.fee_withdraw)); issue->properties.value.currency,
GNUNET_assert (GNUNET_YES == &fees));
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));
return GNUNET_PQ_eval_prepared_non_select (pg->conn, return GNUNET_PQ_eval_prepared_non_select (pg->conn,
"denomination_insert", "denomination_insert",
params); params);
@ -3176,13 +3170,13 @@ postgres_get_denomination_info (
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("coin", TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("coin",
&issue->properties.value), &issue->properties.value),
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_withdraw", TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_withdraw",
&issue->properties.fee_withdraw), &issue->properties.fees.withdraw),
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_deposit", TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_deposit",
&issue->properties.fee_deposit), &issue->properties.fees.deposit),
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refresh", TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refresh",
&issue->properties.fee_refresh), &issue->properties.fees.refresh),
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refund", TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refund",
&issue->properties.fee_refund), &issue->properties.fees.refund),
GNUNET_PQ_result_spec_uint32 ("age_mask", GNUNET_PQ_result_spec_uint32 ("age_mask",
&issue->age_mask.mask), &issue->age_mask.mask),
GNUNET_PQ_result_spec_end GNUNET_PQ_result_spec_end
@ -3262,13 +3256,13 @@ domination_cb_helper (void *cls,
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("coin", TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("coin",
&issue.properties.value), &issue.properties.value),
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_withdraw", TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_withdraw",
&issue.properties.fee_withdraw), &issue.properties.fees.withdraw),
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_deposit", TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_deposit",
&issue.properties.fee_deposit), &issue.properties.fees.deposit),
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refresh", TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refresh",
&issue.properties.fee_refresh), &issue.properties.fees.refresh),
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refund", TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refund",
&issue.properties.fee_refund), &issue.properties.fees.refund),
TALER_PQ_result_spec_denom_pub ("denom_pub", TALER_PQ_result_spec_denom_pub ("denom_pub",
&denom_pub), &denom_pub),
GNUNET_PQ_result_spec_uint32 ("age_mask", GNUNET_PQ_result_spec_uint32 ("age_mask",
@ -3401,13 +3395,13 @@ dominations_cb_helper (void *cls,
TALER_PQ_RESULT_SPEC_AMOUNT ("coin", TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
&meta.value), &meta.value),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
&meta.fee_withdraw), &meta.fees.withdraw),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
&meta.fee_deposit), &meta.fees.deposit),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
&meta.fee_refresh), &meta.fees.refresh),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
&meta.fee_refund), &meta.fees.refund),
TALER_PQ_result_spec_denom_pub ("denom_pub", TALER_PQ_result_spec_denom_pub ("denom_pub",
&denom_pub), &denom_pub),
GNUNET_PQ_result_spec_uint32 ("age_mask", 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. * key of the hash of the blinded message.
* *
* @param cls the `struct PostgresClosure` with the plugin-specific state * @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) * @param collectable corresponding collectable coin (blind signature)
* if a coin is found * if a coin is found
* @return statement execution status * @return statement execution status
@ -4336,12 +4330,12 @@ postgres_reserves_in_insert (void *cls,
static enum GNUNET_DB_QueryStatus static enum GNUNET_DB_QueryStatus
postgres_get_withdraw_info ( postgres_get_withdraw_info (
void *cls, void *cls,
const struct TALER_WithdrawIdentificationHash *wih, const struct TALER_BlindedCoinHash *bch,
struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable) struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable)
{ {
struct PostgresClosure *pg = cls; struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = { 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 GNUNET_PQ_query_param_end
}; };
struct GNUNET_PQ_ResultSpec rs[] = { struct GNUNET_PQ_ResultSpec rs[] = {
@ -4374,7 +4368,7 @@ postgres_get_withdraw_info (
* and possibly persisting the withdrawal details. * and possibly persisting the withdrawal details.
* *
* @param cls the `struct PostgresClosure` with the plugin-specific state * @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[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 now current time (rounded)
* @param[out] found set to true if the reserve was found * @param[out] found set to true if the reserve was found
@ -4386,8 +4380,8 @@ postgres_get_withdraw_info (
static enum GNUNET_DB_QueryStatus static enum GNUNET_DB_QueryStatus
postgres_do_withdraw ( postgres_do_withdraw (
void *cls, void *cls,
const struct TALER_WithdrawIdentificationHash *wih, const struct TALER_CsNonce *nonce,
struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable, const struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable,
struct GNUNET_TIME_Timestamp now, struct GNUNET_TIME_Timestamp now,
bool *found, bool *found,
bool *balance_ok, bool *balance_ok,
@ -4397,7 +4391,9 @@ postgres_do_withdraw (
struct PostgresClosure *pg = cls; struct PostgresClosure *pg = cls;
struct GNUNET_TIME_Timestamp gc; struct GNUNET_TIME_Timestamp gc;
struct GNUNET_PQ_QueryParam params[] = { 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), 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->denom_pub_hash),
GNUNET_PQ_query_param_auto_from_type (&collectable->reserve_pub), 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_timestamp (&gc),
GNUNET_PQ_query_param_end GNUNET_PQ_query_param_end
}; };
enum GNUNET_DB_QueryStatus qs;
bool no_out_sig;
struct TALER_BlindedDenominationSignature out_sig;
struct GNUNET_PQ_ResultSpec rs[] = { struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_bool ("reserve_found", GNUNET_PQ_result_spec_bool ("reserve_found",
found), found),
@ -4422,33 +4415,17 @@ postgres_do_withdraw (
&kyc->payment_target_uuid), &kyc->payment_target_uuid),
GNUNET_PQ_result_spec_uint64 ("ruuid", GNUNET_PQ_result_spec_uint64 ("ruuid",
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 GNUNET_PQ_result_spec_end
}; };
#if 0
memset (&out_sig,
0,
sizeof (out_sig));
#endif
gc = GNUNET_TIME_absolute_to_timestamp ( gc = GNUNET_TIME_absolute_to_timestamp (
GNUNET_TIME_absolute_add (now.abs_time, GNUNET_TIME_absolute_add (now.abs_time,
pg->legal_reserve_expiration_time)); pg->legal_reserve_expiration_time));
kyc->type = TALER_EXCHANGEDB_KYC_WITHDRAW; kyc->type = TALER_EXCHANGEDB_KYC_WITHDRAW;
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
"call_withdraw", "call_withdraw",
params, params,
rs); 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;
} }
@ -4600,6 +4577,7 @@ postgres_do_deposit (
static enum GNUNET_DB_QueryStatus static enum GNUNET_DB_QueryStatus
postgres_do_melt ( postgres_do_melt (
void *cls, void *cls,
const struct TALER_RefreshMasterSecretP *rms,
struct TALER_EXCHANGEDB_Refresh *refresh, struct TALER_EXCHANGEDB_Refresh *refresh,
uint64_t known_coin_id, uint64_t known_coin_id,
bool *zombie_required, bool *zombie_required,
@ -4607,6 +4585,9 @@ postgres_do_melt (
{ {
struct PostgresClosure *pg = cls; struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = { 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), 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->rc),
GNUNET_PQ_query_param_auto_from_type (&refresh->coin.coin_pub), 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. * from given the hash of the blinded coin.
* *
* @param cls closure * @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_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 * @param[out] reserve_out_serial_id set to row of the @a h_blind_ev in reserves_out
* @return transaction status code * @return transaction status code
*/ */
static enum GNUNET_DB_QueryStatus static enum GNUNET_DB_QueryStatus
postgres_get_reserve_by_wih ( postgres_get_reserve_by_h_blind (
void *cls, void *cls,
const struct TALER_WithdrawIdentificationHash *wih, const struct TALER_BlindedCoinHash *bch,
struct TALER_ReservePublicKeyP *reserve_pub, struct TALER_ReservePublicKeyP *reserve_pub,
uint64_t *reserve_out_serial_id) uint64_t *reserve_out_serial_id)
{ {
struct PostgresClosure *pg = cls; struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = { 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 GNUNET_PQ_query_param_end
}; };
struct GNUNET_PQ_ResultSpec rs[] = { struct GNUNET_PQ_ResultSpec rs[] = {
@ -9454,7 +9435,7 @@ postgres_get_reserve_by_wih (
}; };
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
"reserve_by_wih", "reserve_by_h_blind",
params, params,
rs); rs);
} }
@ -10241,13 +10222,13 @@ postgres_lookup_denomination_key (
TALER_PQ_RESULT_SPEC_AMOUNT ("coin", TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
&meta->value), &meta->value),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
&meta->fee_withdraw), &meta->fees.withdraw),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
&meta->fee_deposit), &meta->fees.deposit),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
&meta->fee_refresh), &meta->fees.refresh),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
&meta->fee_refund), &meta->fees.refund),
GNUNET_PQ_result_spec_uint32 ("age_mask", GNUNET_PQ_result_spec_uint32 ("age_mask",
&meta->age_mask.mask), &meta->age_mask.mask),
GNUNET_PQ_result_spec_end 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_deposit),
GNUNET_PQ_query_param_timestamp (&meta->expire_legal), GNUNET_PQ_query_param_timestamp (&meta->expire_legal),
TALER_PQ_query_param_amount (&meta->value), TALER_PQ_query_param_amount (&meta->value),
TALER_PQ_query_param_amount (&meta->fee_withdraw), TALER_PQ_query_param_amount (&meta->fees.withdraw),
TALER_PQ_query_param_amount (&meta->fee_deposit), TALER_PQ_query_param_amount (&meta->fees.deposit),
TALER_PQ_query_param_amount (&meta->fee_refresh), TALER_PQ_query_param_amount (&meta->fees.refresh),
TALER_PQ_query_param_amount (&meta->fee_refund), TALER_PQ_query_param_amount (&meta->fees.refund),
GNUNET_PQ_query_param_uint32 (&meta->age_mask.mask), GNUNET_PQ_query_param_uint32 (&meta->age_mask.mask),
GNUNET_PQ_query_param_end GNUNET_PQ_query_param_end
}; };
/* Sanity check: ensure fees match coin currency */ /* Sanity check: ensure fees match coin currency */
GNUNET_assert (GNUNET_YES == GNUNET_assert (GNUNET_YES ==
TALER_amount_cmp_currency (&meta->value, TALER_denom_fee_check_currency (meta->value.currency,
&meta->fee_withdraw)); &meta->fees));
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));
return GNUNET_PQ_eval_prepared_non_select (pg->conn, return GNUNET_PQ_eval_prepared_non_select (pg->conn,
"denomination_insert", "denomination_insert",
iparams); iparams);
@ -11722,8 +11694,8 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
= &postgres_select_recoup_refresh_above_serial_id; = &postgres_select_recoup_refresh_above_serial_id;
plugin->select_reserve_closed_above_serial_id plugin->select_reserve_closed_above_serial_id
= &postgres_select_reserve_closed_above_serial_id; = &postgres_select_reserve_closed_above_serial_id;
plugin->get_reserve_by_wih plugin->get_reserve_by_h_blind
= &postgres_get_reserve_by_wih; = &postgres_get_reserve_by_h_blind;
plugin->get_old_coin_by_h_blind plugin->get_old_coin_by_h_blind
= &postgres_get_old_coin_by_h_blind; = &postgres_get_old_coin_by_h_blind;
plugin->insert_denomination_revocation 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 size the size of the denomination key
* @param now time to use for key generation, legal expiration will be 3h later. * @param now time to use for key generation, legal expiration will be 3h later.
* @param fee_withdraw withdraw fee to use * @param fees fees to use
* @param fee_deposit deposit fee to use
* @param fee_refresh refresh fee to use
* @param fee_refund refund fee to use
* @return the denominaiton key pair; NULL upon error * @return the denominaiton key pair; NULL upon error
*/ */
static struct DenomKeyPair * static struct DenomKeyPair *
create_denom_key_pair (unsigned int size, create_denom_key_pair (unsigned int size,
struct GNUNET_TIME_Timestamp now, struct GNUNET_TIME_Timestamp now,
const struct TALER_Amount *value, const struct TALER_Amount *value,
const struct TALER_Amount *fee_withdraw, const struct TALER_DenomFeeSet *fees)
const struct TALER_Amount *fee_deposit,
const struct TALER_Amount *fee_refresh,
const struct TALER_Amount *fee_refund)
{ {
struct DenomKeyPair *dkp; struct DenomKeyPair *dkp;
struct TALER_EXCHANGEDB_DenominationKey dki; struct TALER_EXCHANGEDB_DenominationKey dki;
@ -315,11 +309,10 @@ create_denom_key_pair (unsigned int size,
(now.abs_time, (now.abs_time,
GNUNET_TIME_relative_multiply ( GNUNET_TIME_relative_multiply (
GNUNET_TIME_UNIT_HOURS, 3)))); GNUNET_TIME_UNIT_HOURS, 3))));
TALER_amount_hton (&dki.issue.properties.value, value); TALER_amount_hton (&dki.issue.properties.value,
TALER_amount_hton (&dki.issue.properties.fee_withdraw, fee_withdraw); value);
TALER_amount_hton (&dki.issue.properties.fee_deposit, fee_deposit); TALER_denom_fee_set_hton (&dki.issue.properties.fees,
TALER_amount_hton (&dki.issue.properties.fee_refresh, fee_refresh); fees);
TALER_amount_hton (&dki.issue.properties.fee_refund, fee_refund);
TALER_denom_pub_hash (&dkp->pub, TALER_denom_pub_hash (&dkp->pub,
&dki.issue.properties.denom_hash); &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 value;
static struct TALER_Amount fee_withdraw; static struct TALER_DenomFeeSet fees;
static struct TALER_Amount fee_deposit;
static struct TALER_Amount fee_refresh;
static struct TALER_Amount fee_refund;
static struct TALER_Amount fee_closing; static struct TALER_Amount fee_closing;
static struct TALER_Amount amount_with_fee; static struct TALER_Amount amount_with_fee;
@ -881,10 +871,7 @@ test_gc (void)
dkp = create_denom_key_pair (RSA_KEY_SIZE, dkp = create_denom_key_pair (RSA_KEY_SIZE,
past, past,
&value, &value,
&fee_withdraw, &fees);
&fee_deposit,
&fee_refresh,
&fee_refund);
GNUNET_assert (NULL != dkp); GNUNET_assert (NULL != dkp);
if (GNUNET_OK != if (GNUNET_OK !=
plugin->gc (plugin->cls)) 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_pub_wt = deposit->coin.coin_pub;
coin_value_wt = deposit->amount_with_fee; coin_value_wt = deposit->amount_with_fee;
coin_fee_wt = fee_deposit; coin_fee_wt = fees.deposit;
GNUNET_assert (0 < GNUNET_assert (0 <
TALER_amount_subtract (&transfer_value_wt, TALER_amount_subtract (&transfer_value_wt,
&coin_value_wt, &coin_value_wt,
@ -1349,7 +1336,6 @@ run (void *cls)
struct GNUNET_TIME_Timestamp now; struct GNUNET_TIME_Timestamp now;
struct TALER_WireSaltP salt; struct TALER_WireSaltP salt;
struct TALER_CoinPubHash c_hash; struct TALER_CoinPubHash c_hash;
struct TALER_WithdrawIdentificationHash wih;
uint64_t known_coin_id; uint64_t known_coin_id;
uint64_t rrc_serial; uint64_t rrc_serial;
struct TALER_EXCHANGEDB_Refresh refresh; struct TALER_EXCHANGEDB_Refresh refresh;
@ -1410,17 +1396,17 @@ run (void *cls)
&value)); &value));
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":0.000010", TALER_string_to_amount (CURRENCY ":0.000010",
&fee_withdraw)); &fees.withdraw));
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":0.000010", TALER_string_to_amount (CURRENCY ":0.000010",
&fee_deposit)); &fees.deposit));
deposit.deposit_fee = fee_deposit; deposit.deposit_fee = fees.deposit;
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":0.000010", TALER_string_to_amount (CURRENCY ":0.000010",
&fee_refresh)); &fees.refresh));
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":0.000010", TALER_string_to_amount (CURRENCY ":0.000010",
&fee_refund)); &fees.refund));
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":1.000010", TALER_string_to_amount (CURRENCY ":1.000010",
&amount_with_fee)); &amount_with_fee));
@ -1464,10 +1450,7 @@ run (void *cls)
dkp = create_denom_key_pair (RSA_KEY_SIZE, dkp = create_denom_key_pair (RSA_KEY_SIZE,
now, now,
&value, &value,
&fee_withdraw, &fees);
&fee_deposit,
&fee_refresh,
&fee_refund);
GNUNET_assert (NULL != dkp); GNUNET_assert (NULL != dkp);
TALER_denom_pub_hash (&dkp->pub, TALER_denom_pub_hash (&dkp->pub,
&cbc.denom_pub_hash); &cbc.denom_pub_hash);
@ -1502,10 +1485,7 @@ run (void *cls)
TALER_coin_ev_hash (&pd.blinded_planchet, TALER_coin_ev_hash (&pd.blinded_planchet,
&cbc.denom_pub_hash, &cbc.denom_pub_hash,
&cbc.h_coin_envelope)); &cbc.h_coin_envelope));
GNUNET_assert (GNUNET_OK == GNUNET_assert (
TALER_withdraw_request_hash (&pd.blinded_planchet,
&cbc.denom_pub_hash,
&wih)); GNUNET_assert (
GNUNET_OK == GNUNET_OK ==
TALER_denom_sign_blinded ( TALER_denom_sign_blinded (
&cbc.sig, &cbc.sig,
@ -1529,7 +1509,7 @@ run (void *cls)
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->do_withdraw (plugin->cls, plugin->do_withdraw (plugin->cls,
&wih, NULL,
&cbc, &cbc,
now, now,
&found, &found,
@ -1551,16 +1531,16 @@ run (void *cls)
value.fraction, value.fraction,
value.currency)); value.currency));
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->get_reserve_by_wih (plugin->cls, plugin->get_reserve_by_h_blind (plugin->cls,
&wih, &cbc.h_coin_envelope,
&reserve_pub3, &reserve_pub3,
&reserve_out_serial_id)); &reserve_out_serial_id));
FAILIF (0 != GNUNET_memcmp (&reserve_pub, FAILIF (0 != GNUNET_memcmp (&reserve_pub,
&reserve_pub3)); &reserve_pub3));
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->get_withdraw_info (plugin->cls, plugin->get_withdraw_info (plugin->cls,
&wih, &cbc.h_coin_envelope,
&cbc2)); &cbc2));
FAILIF (0 != GNUNET_memcmp (&cbc2.reserve_sig, FAILIF (0 != GNUNET_memcmp (&cbc2.reserve_sig,
&cbc.reserve_sig)); &cbc.reserve_sig));
@ -1649,12 +1629,12 @@ run (void *cls)
refund.details.h_contract_terms = deposit.h_contract_terms; refund.details.h_contract_terms = deposit.h_contract_terms;
refund.details.rtransaction_id = 1; refund.details.rtransaction_id = 1;
refund.details.refund_amount = value; refund.details.refund_amount = value;
refund.details.refund_fee = fee_refund; refund.details.refund_fee = fees.refund;
RND_BLK (&refund.details.merchant_sig); RND_BLK (&refund.details.merchant_sig);
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->do_refund (plugin->cls, plugin->do_refund (plugin->cls,
&refund, &refund,
&fee_deposit, &fees.deposit,
known_coin_id, known_coin_id,
&not_found, &not_found,
&refund_ok, &refund_ok,
@ -1686,6 +1666,7 @@ run (void *cls)
refresh.noreveal_index = MELT_NOREVEAL_INDEX; refresh.noreveal_index = MELT_NOREVEAL_INDEX;
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->do_melt (plugin->cls, plugin->do_melt (plugin->cls,
NULL,
&refresh, &refresh,
known_coin_id, known_coin_id,
&zombie_required, &zombie_required,
@ -1709,7 +1690,7 @@ run (void *cls)
TALER_amount_cmp (&refresh.amount_with_fee, TALER_amount_cmp (&refresh.amount_with_fee,
&ret_refresh_session.session.amount_with_fee)); &ret_refresh_session.session.amount_with_fee));
FAILIF (0 != FAILIF (0 !=
TALER_amount_cmp (&fee_refresh, TALER_amount_cmp (&fees.refresh,
&ret_refresh_session.melt_fee)); &ret_refresh_session.melt_fee));
FAILIF (0 != FAILIF (0 !=
GNUNET_memcmp (&refresh.rc, GNUNET_memcmp (&refresh.rc,
@ -1755,10 +1736,7 @@ run (void *cls)
new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE, new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
now, now,
&value, &value,
&fee_withdraw, &fees);
&fee_deposit,
&fee_refresh,
&fee_refund);
GNUNET_assert (NULL != new_dkp[cnt]); GNUNET_assert (NULL != new_dkp[cnt]);
new_denom_pubs[cnt] = new_dkp[cnt]->pub; new_denom_pubs[cnt] = new_dkp[cnt]->pub;
ccoin = &revealed_coins[cnt]; ccoin = &revealed_coins[cnt];
@ -2174,7 +2152,7 @@ run (void *cls)
memset (&deposit, memset (&deposit,
0, 0,
sizeof (deposit)); sizeof (deposit));
deposit.deposit_fee = fee_deposit; deposit.deposit_fee = fees.deposit;
RND_BLK (&deposit.coin.coin_pub); RND_BLK (&deposit.coin.coin_pub);
TALER_denom_pub_hash (&dkp->pub, TALER_denom_pub_hash (&dkp->pub,
&deposit.coin.denom_pub_hash); &deposit.coin.denom_pub_hash);
@ -2196,7 +2174,7 @@ run (void *cls)
&deposit.wire_salt, &deposit.wire_salt,
&h_wire_wt); &h_wire_wt);
deposit.amount_with_fee = value; deposit.amount_with_fee = value;
deposit.deposit_fee = fee_deposit; deposit.deposit_fee = fees.deposit;
deposit.refund_deadline = deadline; deposit.refund_deadline = deadline;
deposit.wire_deadline = deadline; deposit.wire_deadline = deadline;

View File

@ -184,6 +184,18 @@ enum GNUNET_GenericReturnValue
TALER_amount_is_valid (const struct TALER_Amount *amount); 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. * 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 * Hash used to represent the hash of the public
* key of a coin (without blinding). * 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 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. * Hash @a rsa.
* *
@ -1357,22 +1431,6 @@ TALER_coin_ev_hash (const struct TALER_BlindedPlanchet *blinded_planchet,
struct TALER_BlindedCoinHash *bch); 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. * 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 * 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 * the @a rms seed and the @a old_coin_pub of the refresh operation. The
* derivation is based on the @a ps with a KDF salted by the @a coin_num. * 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 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 cnc_num cut and choose number to include in KDF
* @param[out] tpriv value to initialize * @param[out] tpriv value to initialize
*/ */
void void
TALER_planchet_secret_to_transfer_priv ( TALER_planchet_secret_to_transfer_priv (
const struct TALER_RefreshMasterSecretP *rms, const struct TALER_RefreshMasterSecretP *rms,
const struct TALER_CoinSpendPrivateKeyP *old_coin_priv,
uint32_t cnc_num, uint32_t cnc_num,
struct TALER_TransferPrivateKeyP *tpriv); struct TALER_TransferPrivateKeyP *tpriv);
@ -1675,8 +1736,8 @@ TALER_planchet_to_coin (
* @param[in,out] hash_context hash context to use * @param[in,out] hash_context hash context to use
*/ */
void void
TALER_blinded_planchet_hash (const struct TALER_BlindedPlanchet *bp, TALER_blinded_planchet_hash_ (const struct TALER_BlindedPlanchet *bp,
struct GNUNET_HashContext *hash_context); 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[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 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 num_new_coins number of new coins to be created
* @param rcs array of @a kappa commitments * @param rcs array of @a kappa commitments
* @param coin_pub public key of the coin to be melted * @param coin_pub public key of the coin to be melted
@ -1777,6 +1839,7 @@ struct TALER_RefreshCommitmentEntry
void void
TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc, TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc,
uint32_t kappa, uint32_t kappa,
const struct TALER_RefreshMasterSecretP *rms,
uint32_t num_new_coins, uint32_t num_new_coins,
const struct TALER_RefreshCommitmentEntry *rcs, const struct TALER_RefreshCommitmentEntry *rcs,
const struct TALER_CoinSpendPublicKeyP *coin_pub, 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_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 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 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 fees fees 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 master_priv private key to sign with * @param master_priv private key to sign with
* @param[out] master_sig where to write the signature * @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_deposit,
struct GNUNET_TIME_Timestamp stamp_expire_legal, struct GNUNET_TIME_Timestamp stamp_expire_legal,
const struct TALER_Amount *coin_value, const struct TALER_Amount *coin_value,
const struct TALER_Amount *fee_withdraw, const struct TALER_DenomFeeSet *fees,
const struct TALER_Amount *fee_deposit,
const struct TALER_Amount *fee_refresh,
const struct TALER_Amount *fee_refund,
const struct TALER_MasterPrivateKeyP *master_priv, const struct TALER_MasterPrivateKeyP *master_priv,
struct TALER_MasterSignatureP *master_sig); 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_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 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 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 fees fees 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 master_pub public key to verify against * @param master_pub public key to verify against
* @param master_sig the signature the signature * @param master_sig the signature the signature
* @return #GNUNET_OK if the signature is valid * @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_deposit,
struct GNUNET_TIME_Timestamp stamp_expire_legal, struct GNUNET_TIME_Timestamp stamp_expire_legal,
const struct TALER_Amount *coin_value, const struct TALER_Amount *coin_value,
const struct TALER_Amount *fee_withdraw, const struct TALER_DenomFeeSet *fees,
const struct TALER_Amount *fee_deposit,
const struct TALER_Amount *fee_refresh,
const struct TALER_Amount *fee_refund,
const struct TALER_MasterPublicKeyP *master_pub, const struct TALER_MasterPublicKeyP *master_pub,
const struct TALER_MasterSignatureP *master_sig); 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_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 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 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 fees fees the exchange charges 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 auditor_priv private key to sign with * @param auditor_priv private key to sign with
* @param[out] auditor_sig where to write the signature * @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_deposit,
struct GNUNET_TIME_Timestamp stamp_expire_legal, struct GNUNET_TIME_Timestamp stamp_expire_legal,
const struct TALER_Amount *coin_value, const struct TALER_Amount *coin_value,
const struct TALER_Amount *fee_withdraw, const struct TALER_DenomFeeSet *fees,
const struct TALER_Amount *fee_deposit,
const struct TALER_Amount *fee_refresh,
const struct TALER_Amount *fee_refund,
const struct TALER_AuditorPrivateKeyP *auditor_priv, const struct TALER_AuditorPrivateKeyP *auditor_priv,
struct TALER_AuditorSignatureP *auditor_sig); 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_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 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 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 fees fees the exchange charges 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 auditor_pub public key to verify against * @param auditor_pub public key to verify against
* @param auditor_sig the signature the signature * @param auditor_sig the signature the signature
* @return #GNUNET_OK if the signature is valid * @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_deposit,
struct GNUNET_TIME_Timestamp stamp_expire_legal, struct GNUNET_TIME_Timestamp stamp_expire_legal,
const struct TALER_Amount *coin_value, const struct TALER_Amount *coin_value,
const struct TALER_Amount *fee_withdraw, const struct TALER_DenomFeeSet *fees,
const struct TALER_Amount *fee_deposit,
const struct TALER_Amount *fee_refresh,
const struct TALER_Amount *fee_refund,
const struct TALER_AuditorPublicKeyP *auditor_pub, const struct TALER_AuditorPublicKeyP *auditor_pub,
const struct TALER_AuditorSignatureP *auditor_sig); const struct TALER_AuditorSignatureP *auditor_sig);

View File

@ -135,24 +135,9 @@ struct TALER_EXCHANGE_DenomPublicKey
struct TALER_Amount value; 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; struct TALER_DenomFeeSet fees;
/**
* 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;
/** /**
* Set to true if this denomination key has been * Set to true if this denomination key has been
@ -1031,19 +1016,19 @@ void
TALER_EXCHANGE_refund_cancel (struct TALER_EXCHANGE_RefundHandle *refund); 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. * Details about a response for a CS R request.
*/ */
struct TALER_EXCHANGE_CsRResponse struct TALER_EXCHANGE_CsRMeltResponse
{ {
/** /**
* HTTP response data. * HTTP response data.
@ -1092,29 +1077,31 @@ struct TALER_EXCHANGE_CsRResponse
* @param csrr response details * @param csrr response details
*/ */
typedef void typedef void
(*TALER_EXCHANGE_CsRCallback) (void *cls, (*TALER_EXCHANGE_CsRMeltCallback) (
const struct TALER_EXCHANGE_CsRResponse *csrr); 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 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; 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 exchange the exchange handle; the exchange must be ready to operate
* @param nks_len length of the @a nks array * @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). * if the inputs are invalid (i.e. denomination key not with this exchange).
* In this case, the callback is not called. * In this case, the callback is not called.
*/ */
struct TALER_EXCHANGE_CsRHandle * struct TALER_EXCHANGE_CsRMeltHandle *
TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange, TALER_EXCHANGE_csr_melt (struct TALER_EXCHANGE_Handle *exchange,
unsigned int nks_len, const struct TALER_RefreshMasterSecretP *rms,
struct TALER_EXCHANGE_NonceKey *nks, unsigned int nks_len,
TALER_EXCHANGE_CsRCallback res_cb, struct TALER_EXCHANGE_NonceKey *nks,
void *res_cb_cls); 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. * on a request handle if a response is already served for it.
* *
* @param csrh the withdraw handle * @param csrh the withdraw handle
*/ */
void 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 *********************** */ /* ********************* GET /reserves/$RESERVE_PUB *********************** */

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER 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 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 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_deposit;
struct GNUNET_TIME_Timestamp expire_legal; struct GNUNET_TIME_Timestamp expire_legal;
struct TALER_Amount coin; struct TALER_Amount coin;
struct TALER_Amount fee_withdraw; struct TALER_DenomFeeSet fees;
struct TALER_Amount fee_deposit;
struct TALER_Amount fee_refresh;
struct TALER_Amount fee_refund;
} denominations; } denominations;
struct struct
@ -612,29 +609,10 @@ struct TALER_EXCHANGEDB_DenominationKeyMetaData
struct TALER_Amount value; struct TALER_Amount value;
/** /**
* The fee the exchange charges when a coin of this type is withdrawn. * The fees the exchange charges for operations with
* (can be zero). * coins of this denomination.
*/ */
struct TALER_Amount fee_withdraw; struct TALER_DenomFeeSet fees;
/**
* 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;
/** /**
* Age restriction for the denomination. (can be zero). If not zero, the bits * 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 * Information the exchange records about a recoup request
* in a coin history. * 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. * Types of operations that require KYC checks.
*/ */
@ -2497,20 +2519,36 @@ struct TALER_EXCHANGEDB_Plugin
uint64_t wire_reference); 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 * Locate the response for a withdraw request under a hash that uniquely
* identifies the withdraw operation. Used to ensure idempotency of the * identifies the withdraw operation. Used to ensure idempotency of the
* request. * request.
* *
* @param cls the @e cls of this struct with the plugin-specific state * @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) * @param[out] collectable corresponding collectable coin (blind signature)
* if a coin is found * if a coin is found
* @return statement execution status * @return statement execution status
*/ */
enum GNUNET_DB_QueryStatus enum GNUNET_DB_QueryStatus
(*get_withdraw_info)(void *cls, (*get_withdraw_info)(void *cls,
const struct TALER_WithdrawIdentificationHash *wih, const struct TALER_BlindedCoinHash *bch,
struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable); struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable);
@ -2519,9 +2557,8 @@ struct TALER_EXCHANGEDB_Plugin
* and possibly persisting the withdrawal details. * and possibly persisting the withdrawal details.
* *
* @param cls the `struct PostgresClosure` with the plugin-specific state * @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) * @param collectable corresponding collectable coin (blind signature)
* if a coin is found
* @param now current time (rounded) * @param now current time (rounded)
* @param[out] found set to true if the reserve was found * @param[out] found set to true if the reserve was found
* @param[out] balance_ok set to true if the balance was sufficient * @param[out] balance_ok set to true if the balance was sufficient
@ -2532,8 +2569,8 @@ struct TALER_EXCHANGEDB_Plugin
enum GNUNET_DB_QueryStatus enum GNUNET_DB_QueryStatus
(*do_withdraw)( (*do_withdraw)(
void *cls, void *cls,
const struct TALER_WithdrawIdentificationHash *wih, const struct TALER_CsNonce *nonce,
struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable, const struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable,
struct GNUNET_TIME_Timestamp now, struct GNUNET_TIME_Timestamp now,
bool *found, bool *found,
bool *balance_ok, bool *balance_ok,
@ -2591,7 +2628,8 @@ struct TALER_EXCHANGEDB_Plugin
* Perform melt operation, checking for sufficient balance * Perform melt operation, checking for sufficient balance
* of the coin and possibly persisting the melt details. * 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 * @param[in,out] refresh refresh operation details; the noreveal_index
* is set in case the coin was already melted before * is set in case the coin was already melted before
* @param known_coin_id row of the coin in the known_coins table * @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 enum GNUNET_DB_QueryStatus
(*do_melt)( (*do_melt)(
void *cls, void *cls,
const struct TALER_RefreshMasterSecretP *rms,
struct TALER_EXCHANGEDB_Refresh *refresh, struct TALER_EXCHANGEDB_Refresh *refresh,
uint64_t known_coin_id, uint64_t known_coin_id,
bool *zombie_required, bool *zombie_required,
bool *balance_ok); 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 * Perform refund operation, checking for sufficient deposits
* of the coin and possibly persisting the refund details. * 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. * from given the hash of the blinded coin.
* *
* @param cls closure * @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_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 * @param[out] reserve_out_serial_id set to row of the @a h_blind_ev in reserves_out
* @return transaction status code * @return transaction status code
*/ */
enum GNUNET_DB_QueryStatus enum GNUNET_DB_QueryStatus
(*get_reserve_by_wih)(void *cls, (*get_reserve_by_h_blind)(void *cls,
const struct TALER_WithdrawIdentificationHash *wih, const struct TALER_BlindedCoinHash *bch,
struct TALER_ReservePublicKeyP *reserve_pub, struct TALER_ReservePublicKeyP *reserve_pub,
uint64_t *reserve_out_serial_id); 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); 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. * Generate line in parser specification for denomination public key.
* *

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER 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 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 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 * @brief Format used for to allow the wallet to authenticate
* link data provided by the exchange. * link data provided by the exchange.
@ -999,6 +1000,7 @@ struct TALER_MasterExtensionConfigurationPS
struct TALER_ExtensionConfigHash h_config GNUNET_PACKED; struct TALER_ExtensionConfigHash h_config GNUNET_PACKED;
}; };
/** /**
* @brief Information about a denomination key. Denomination keys * @brief Information about a denomination key. Denomination keys
* are used to sign coins of a certain value into existence. * are used to sign coins of a certain value into existence.
@ -1063,29 +1065,9 @@ struct TALER_DenominationKeyValidityPS
struct TALER_AmountNBO value; struct TALER_AmountNBO value;
/** /**
* The fee the exchange charges when a coin of this type is withdrawn. * Fees for the coin.
* (can be zero).
*/ */
struct TALER_AmountNBO fee_withdraw; struct TALER_DenomFeeSetNBOP fees;
/**
* 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;
/** /**
* Hash code of the denomination public key. (Used to avoid having * Hash code of the denomination public key. (Used to avoid having
@ -1166,28 +1148,9 @@ struct TALER_ExchangeKeyValidityPS
struct TALER_AmountNBO value; struct TALER_AmountNBO value;
/** /**
* The fee the exchange charges when a coin of this type is withdrawn. * Fees for the coin.
* (can be zero).
*/ */
struct TALER_AmountNBO fee_withdraw; struct TALER_DenomFeeSetNBOP fees;
/**
* 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;
/** /**
* Hash code of the denomination public key. (Used to avoid having * 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); 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] * Load our currency from the @a cfg (in section [taler]
* the option "CURRENCY"). * the option "CURRENCY").

View File

@ -24,7 +24,8 @@ libtalerexchange_la_SOURCES = \
exchange_api_auditor_add_denomination.c \ exchange_api_auditor_add_denomination.c \
exchange_api_curl_defaults.c exchange_api_curl_defaults.h \ exchange_api_curl_defaults.c exchange_api_curl_defaults.h \
exchange_api_common.c \ 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_handle.c exchange_api_handle.h \
exchange_api_deposit.c \ exchange_api_deposit.c \
exchange_api_deposits_get.c \ exchange_api_deposits_get.c \

View File

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

View File

@ -15,8 +15,8 @@
<http://www.gnu.org/licenses/> <http://www.gnu.org/licenses/>
*/ */
/** /**
* @file lib/exchange_api_csr.c * @file lib/exchange_api_csr_melt.c
* @brief Implementation of /csr requests (get R in exchange used for Clause Schnorr withdraw and refresh) * @brief Implementation of /csr-melt requests (get R in exchange used for Clause Schnorr refresh)
* @author Lucien Heuzeveldt * @author Lucien Heuzeveldt
* @author Gian Demarmels * @author Gian Demarmels
*/ */
@ -36,7 +36,7 @@
/** /**
* @brief A Clause Schnorr R Handle * @brief A Clause Schnorr R Handle
*/ */
struct TALER_EXCHANGE_CsRHandle struct TALER_EXCHANGE_CsRMeltHandle
{ {
/** /**
* The connection to exchange this request handle will use * The connection to exchange this request handle will use
@ -46,7 +46,7 @@ struct TALER_EXCHANGE_CsRHandle
/** /**
* Function to call with the result. * Function to call with the result.
*/ */
TALER_EXCHANGE_CsRCallback cb; TALER_EXCHANGE_CsRMeltCallback cb;
/** /**
* Closure for @a cb. * Closure for @a cb.
@ -86,13 +86,13 @@ struct TALER_EXCHANGE_CsRHandle
* @return #GNUNET_OK on success, #GNUNET_SYSERR on errors * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
*/ */
static enum GNUNET_GenericReturnValue static enum GNUNET_GenericReturnValue
csr_ok (struct TALER_EXCHANGE_CsRHandle *csrh, csr_ok (struct TALER_EXCHANGE_CsRMeltHandle *csrh,
json_t *arr, const json_t *arr,
struct TALER_EXCHANGE_HttpResponse *hr) struct TALER_EXCHANGE_HttpResponse *hr)
{ {
unsigned int alen = json_array_size (arr); unsigned int alen = json_array_size (arr);
struct TALER_ExchangeWithdrawValues alg_values[GNUNET_NZL (alen)]; struct TALER_ExchangeWithdrawValues alg_values[GNUNET_NZL (alen)];
struct TALER_EXCHANGE_CsRResponse csrr = { struct TALER_EXCHANGE_CsRMeltResponse csrr = {
.hr = *hr, .hr = *hr,
.details.success.alg_values_len = alen, .details.success.alg_values_len = alen,
.details.success.alg_values = alg_values .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. * 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_code HTTP response code, 0 on error
* @param response parsed JSON result, NULL on error * @param response parsed JSON result, NULL on error
*/ */
@ -136,13 +136,13 @@ handle_csr_finished (void *cls,
long response_code, long response_code,
const void *response) const void *response)
{ {
struct TALER_EXCHANGE_CsRHandle *csrh = cls; struct TALER_EXCHANGE_CsRMeltHandle *csrh = cls;
const json_t *j = response; const json_t *j = response;
struct TALER_EXCHANGE_HttpResponse hr = { struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j, .reply = j,
.http_status = (unsigned int) response_code .http_status = (unsigned int) response_code
}; };
struct TALER_EXCHANGE_CsRResponse csrr = { struct TALER_EXCHANGE_CsRMeltResponse csrr = {
.hr = hr .hr = hr
}; };
@ -171,7 +171,7 @@ handle_csr_finished (void *cls,
break; break;
} }
} }
TALER_EXCHANGE_csr_cancel (csrh); TALER_EXCHANGE_csr_melt_cancel (csrh);
return; return;
case MHD_HTTP_BAD_REQUEST: case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy /* 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, csrh->cb (csrh->cb_cls,
&csrr); &csrr);
csrh->cb = NULL; csrh->cb = NULL;
TALER_EXCHANGE_csr_cancel (csrh); TALER_EXCHANGE_csr_melt_cancel (csrh);
} }
struct TALER_EXCHANGE_CsRHandle * struct TALER_EXCHANGE_CsRMeltHandle *
TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange, TALER_EXCHANGE_csr_melt (struct TALER_EXCHANGE_Handle *exchange,
unsigned int nks_len, const struct TALER_RefreshMasterSecretP *rms,
struct TALER_EXCHANGE_NonceKey *nks, unsigned int nks_len,
TALER_EXCHANGE_CsRCallback res_cb, struct TALER_EXCHANGE_NonceKey *nks,
void *res_cb_cls) TALER_EXCHANGE_CsRMeltCallback res_cb,
void *res_cb_cls)
{ {
struct TALER_EXCHANGE_CsRHandle *csrh; struct TALER_EXCHANGE_CsRMeltHandle *csrh;
json_t *csr_arr; json_t *csr_arr;
if (0 == nks_len) if (0 == nks_len)
@ -240,12 +241,10 @@ TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange,
GNUNET_break (0); GNUNET_break (0);
return NULL; return NULL;
} }
csrh = GNUNET_new (struct TALER_EXCHANGE_CsRMeltHandle);
csrh = GNUNET_new (struct TALER_EXCHANGE_CsRHandle);
csrh->exchange = exchange; csrh->exchange = exchange;
csrh->cb = res_cb; csrh->cb = res_cb;
csrh->cb_cls = res_cb_cls; csrh->cb_cls = res_cb_cls;
csr_arr = json_array (); csr_arr = json_array ();
GNUNET_assert (NULL != csr_arr); GNUNET_assert (NULL != csr_arr);
for (unsigned int i = 0; i<nks_len; i++) 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; json_t *csr_obj;
csr_obj = GNUNET_JSON_PACK ( csr_obj = GNUNET_JSON_PACK (
GNUNET_JSON_pack_data_varsize ("nonce", GNUNET_JSON_pack_uint64 ("coin_offset",
&nk->nonce, nk->cnc_num),
sizeof(struct TALER_CsNonce)), GNUNET_JSON_pack_data_auto ("denom_pub_hash",
GNUNET_JSON_pack_data_varsize ("denom_pub_hash", &nk->pk->h_key));
&nk->pk->h_key,
sizeof(struct TALER_DenominationHash)));
GNUNET_assert (NULL != csr_obj); GNUNET_assert (NULL != csr_obj);
GNUNET_assert (0 == GNUNET_assert (0 ==
json_array_append_new (csr_arr, json_array_append_new (csr_arr,
csr_obj)); csr_obj));
} }
csrh->url = TEAH_path_to_url (exchange, csrh->url = TEAH_path_to_url (exchange,
"/csr"); "/csr-melt");
if (NULL == csrh->url) if (NULL == csrh->url)
{ {
json_decref (csr_arr); json_decref (csr_arr);
@ -279,6 +276,8 @@ TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange,
json_t *req; json_t *req;
req = GNUNET_JSON_PACK ( req = GNUNET_JSON_PACK (
GNUNET_JSON_pack_data_auto ("rms",
rms),
GNUNET_JSON_pack_array_steal ("nks", GNUNET_JSON_pack_array_steal ("nks",
csr_arr)); csr_arr));
ctx = TEAH_handle_to_context (exchange); ctx = TEAH_handle_to_context (exchange);
@ -309,7 +308,7 @@ TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange,
void void
TALER_EXCHANGE_csr_cancel (struct TALER_EXCHANGE_CsRHandle *csrh) TALER_EXCHANGE_csr_melt_cancel (struct TALER_EXCHANGE_CsRMeltHandle *csrh)
{ {
if (NULL != csrh->job) 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 != if (GNUNET_OK !=
TALER_wallet_deposit_verify (amount, TALER_wallet_deposit_verify (amount,
&dki->fee_deposit, &dki->fees.deposit,
h_wire, h_wire,
h_contract_terms, h_contract_terms,
h_age_commitment, 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_LOG_DEBUG ("... amount_with_fee was %s\n",
TALER_amount2s (amount)); TALER_amount2s (amount));
TALER_LOG_DEBUG ("... deposit_fee was %s\n", TALER_LOG_DEBUG ("... deposit_fee was %s\n",
TALER_amount2s (&dki->fee_deposit)); TALER_amount2s (&dki->fees.deposit));
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
@ -536,7 +536,7 @@ verify_signatures (const struct TALER_EXCHANGE_DenomPublicKey *dki,
} }
/* Check coin does make a contribution */ /* Check coin does make a contribution */
if (0 < TALER_amount_cmp (&dki->fee_deposit, if (0 < TALER_amount_cmp (&dki->fees.deposit,
amount)) amount))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
@ -628,7 +628,7 @@ TALER_EXCHANGE_deposit (
if (0 > if (0 >
TALER_amount_subtract (&amount_without_fee, TALER_amount_subtract (&amount_without_fee,
amount, amount,
&dki->fee_deposit)) &dki->fees.deposit))
{ {
*ec = TALER_EC_EXCHANGE_DEPOSIT_FEE_ABOVE_AMOUNT; *ec = TALER_EC_EXCHANGE_DEPOSIT_FEE_ABOVE_AMOUNT;
GNUNET_break_op (0); 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. * 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[out] denom_key where to return the result
* @param check_sigs should we check signatures? * @param check_sigs should we check signatures?
* @param[in] denom_key_obj json to parse * @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. * invalid or the json malformed.
*/ */
static enum GNUNET_GenericReturnValue 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, int check_sigs,
json_t *denom_key_obj, json_t *denom_key_obj,
struct TALER_MasterPublicKeyP *master_key, struct TALER_MasterPublicKeyP *master_key,
@ -331,16 +333,12 @@ parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key,
&denom_key->valid_from), &denom_key->valid_from),
GNUNET_JSON_spec_timestamp ("stamp_expire_legal", GNUNET_JSON_spec_timestamp ("stamp_expire_legal",
&denom_key->expire_legal), &denom_key->expire_legal),
TALER_JSON_spec_amount_any ("value", TALER_JSON_spec_amount ("value",
&denom_key->value), currency,
TALER_JSON_spec_amount_any ("fee_withdraw", &denom_key->value),
&denom_key->fee_withdraw), TALER_JSON_SPEC_DENOM_FEES ("fee",
TALER_JSON_spec_amount_any ("fee_deposit", currency,
&denom_key->fee_deposit), &denom_key->fees),
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_denom_pub ("denom_pub", TALER_JSON_spec_denom_pub ("denom_pub",
&denom_key->key), &denom_key->key),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
@ -372,10 +370,7 @@ parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key,
denom_key->expire_deposit, denom_key->expire_deposit,
denom_key->expire_legal, denom_key->expire_legal,
&denom_key->value, &denom_key->value,
&denom_key->fee_withdraw, &denom_key->fees,
&denom_key->fee_deposit,
&denom_key->fee_refresh,
&denom_key->fee_refund,
master_key, master_key,
&denom_key->master_sig)); &denom_key->master_sig));
return GNUNET_OK; return GNUNET_OK;
@ -492,10 +487,7 @@ parse_json_auditor (struct TALER_EXCHANGE_AuditorInformation *auditor,
dk->expire_deposit, dk->expire_deposit,
dk->expire_legal, dk->expire_legal,
&dk->value, &dk->value,
&dk->fee_withdraw, &dk->fees,
&dk->fee_deposit,
&dk->fee_refresh,
&dk->fee_refund,
&auditor->auditor_pub, &auditor->auditor_pub,
&auditor_sig)) &auditor_sig))
{ {
@ -883,7 +875,8 @@ decode_keys_json (const json_t *resp_obj,
0, 0,
sizeof (dk)); sizeof (dk));
EXITIF (GNUNET_SYSERR == EXITIF (GNUNET_SYSERR ==
parse_json_denomkey (&dk, parse_json_denomkey (key_data->currency,
&dk,
check_sig, check_sig,
denom_key_obj, denom_key_obj,
&key_data->master_pub, &key_data->master_pub,
@ -1728,14 +1721,8 @@ TALER_EXCHANGE_serialize_data (struct TALER_EXCHANGE_Handle *exchange)
dk->expire_legal), dk->expire_legal),
TALER_JSON_pack_amount ("value", TALER_JSON_pack_amount ("value",
&dk->value), &dk->value),
TALER_JSON_pack_amount ("fee_withdraw", TALER_JSON_PACK_DENOM_FEES ("fee",
&dk->fee_withdraw), &dk->fees),
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),
GNUNET_JSON_pack_data_auto ("master_sig", GNUNET_JSON_pack_data_auto ("master_sig",
&dk->master_sig), &dk->master_sig),
TALER_JSON_pack_denom_pub ("denom_pub", TALER_JSON_pack_denom_pub ("denom_pub",

View File

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

View File

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

View File

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

View File

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

View File

@ -340,6 +340,7 @@ TALER_EXCHANGE_refreshes_reveal (
struct GNUNET_CURL_Context *ctx; struct GNUNET_CURL_Context *ctx;
struct MeltData md; struct MeltData md;
char arg_str[sizeof (struct TALER_RefreshCommitmentP) * 2 + 32]; char arg_str[sizeof (struct TALER_RefreshCommitmentP) * 2 + 32];
bool send_rms = false;
GNUNET_assert (num_coins == rd->fresh_pks_len); GNUNET_assert (num_coins == rd->fresh_pks_len);
if (noreveal_index >= TALER_CNC_KAPPA) if (noreveal_index >= TALER_CNC_KAPPA)
@ -376,6 +377,8 @@ TALER_EXCHANGE_refreshes_reveal (
const struct TALER_RefreshCoinData *rcd = &md.rcd[noreveal_index][i]; const struct TALER_RefreshCoinData *rcd = &md.rcd[noreveal_index][i];
struct TALER_DenominationHash denom_hash; 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, TALER_denom_pub_hash (&md.fcds[i].fresh_pk,
&denom_hash); &denom_hash);
GNUNET_assert (0 == GNUNET_assert (0 ==
@ -428,6 +431,12 @@ TALER_EXCHANGE_refreshes_reveal (
reveal_obj = GNUNET_JSON_PACK ( reveal_obj = GNUNET_JSON_PACK (
GNUNET_JSON_pack_data_auto ("transfer_pub", GNUNET_JSON_pack_data_auto ("transfer_pub",
&md.transfer_pub[noreveal_index]), &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", GNUNET_JSON_pack_array_steal ("transfer_privs",
transfer_privs), transfer_privs),
GNUNET_JSON_pack_array_steal ("link_sigs", 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) * 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) * Function called when stage 1 of CS withdraw is finished (request r_pub's)
* *
* @param cls the `struct TALER_EXCHANGE_WithdrawHandle` * @param cls the `struct TALER_EXCHANGE_WithdrawHandle`
* @param csrr replies from the /csr request * @param csrr replies from the /csr-withdraw request
*/ */
static void static void
withdraw_cs_stage_two_callback (void *cls, withdraw_cs_stage_two_callback (
const struct TALER_EXCHANGE_CsRResponse *csrr) void *cls,
const struct TALER_EXCHANGE_CsRWithdrawResponse *csrr)
{ {
struct TALER_EXCHANGE_WithdrawHandle *wh = cls; struct TALER_EXCHANGE_WithdrawHandle *wh = cls;
struct TALER_EXCHANGE_WithdrawResponse wr = { struct TALER_EXCHANGE_WithdrawResponse wr = {
@ -208,13 +209,7 @@ withdraw_cs_stage_two_callback (void *cls,
switch (csrr->hr.http_status) switch (csrr->hr.http_status)
{ {
case MHD_HTTP_OK: case MHD_HTTP_OK:
if (1 != csrr->details.success.alg_values_len) wh->alg_values = csrr->details.success.alg_values;
{
GNUNET_break (0);
wr.hr.http_status = 0;
break;
}
wh->alg_values = csrr->details.success.alg_values[0];
TALER_planchet_setup_coin_priv (&wh->ps, TALER_planchet_setup_coin_priv (&wh->ps,
&wh->alg_values, &wh->alg_values,
&wh->priv); &wh->priv);
@ -306,22 +301,19 @@ TALER_EXCHANGE_withdraw (
} }
case TALER_DENOMINATION_CS: case TALER_DENOMINATION_CS:
{ {
struct TALER_EXCHANGE_NonceKey nk = { TALER_cs_withdraw_nonce_derive (
.pk = pk, ps,
}; &wh->pd.blinded_planchet.details.cs_blinded_planchet.nonce);
TALER_cs_withdraw_nonce_derive (ps,
&nk.nonce);
/* Note that we only initialize the first half /* Note that we only initialize the first half
of the blinded_planchet here; the other part 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.cipher = TALER_DENOMINATION_CS;
wh->pd.blinded_planchet.details.cs_blinded_planchet.nonce = nk.nonce; wh->csrh = TALER_EXCHANGE_csr_withdraw (
wh->csrh = TALER_EXCHANGE_csr (exchange, exchange,
1, /* "array" length */ pk,
&nk, &wh->pd.blinded_planchet.details.cs_blinded_planchet.nonce,
&withdraw_cs_stage_two_callback, &withdraw_cs_stage_two_callback,
wh); wh);
break; break;
} }
default: default:
@ -339,7 +331,7 @@ TALER_EXCHANGE_withdraw_cancel (struct TALER_EXCHANGE_WithdrawHandle *wh)
TALER_blinded_planchet_free (&wh->pd.blinded_planchet); TALER_blinded_planchet_free (&wh->pd.blinded_planchet);
if (NULL != wh->csrh) if (NULL != wh->csrh)
{ {
TALER_EXCHANGE_csr_cancel (wh->csrh); TALER_EXCHANGE_csr_withdraw_cancel (wh->csrh);
wh->csrh = NULL; wh->csrh = NULL;
} }
if (NULL != wh->wh2) if (NULL != wh->wh2)

View File

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

View File

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

View File

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

View File

@ -103,16 +103,16 @@ fake_issue (struct TALER_EXCHANGEDB_DenominationKeyInformationP *issue)
&issue->properties.value)); &issue->properties.value));
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount_nbo ("EUR:0.1", TALER_string_to_amount_nbo ("EUR:0.1",
&issue->properties.fee_withdraw)); &issue->properties.fees.withdraw));
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount_nbo ("EUR:0.1", TALER_string_to_amount_nbo ("EUR:0.1",
&issue->properties.fee_deposit)); &issue->properties.fees.deposit));
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount_nbo ("EUR:0.1", TALER_string_to_amount_nbo ("EUR:0.1",
&issue->properties.fee_refresh)); &issue->properties.fees.refresh));
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount_nbo ("EUR:0.1", 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 /* Melt amount starts with the melt fee of the old coin; we'll add the
values and withdraw fees of the fresh coins next */ 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; age_restricted = melt_denom_pub->key.age_mask.mask != 0;
for (unsigned int i = 0; i<num_fresh_coins; i++) for (unsigned int i = 0; i<num_fresh_coins; i++)
{ {
@ -1137,7 +1137,7 @@ melt_run (void *cls,
GNUNET_assert (0 <= GNUNET_assert (0 <=
TALER_amount_add (&melt_amount, TALER_amount_add (&melt_amount,
&melt_amount, &melt_amount,
&fresh_pk->fee_withdraw)); &fresh_pk->fees.withdraw));
rms->fresh_pks[i] = *fresh_pk; rms->fresh_pks[i] = *fresh_pk;
/* Make a deep copy of the RSA key */ /* Make a deep copy of the RSA key */
TALER_denom_pub_deep_copy (&rms->fresh_pks[i].key, TALER_denom_pub_deep_copy (&rms->fresh_pks[i].key,

View File

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

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER 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 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 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_deposit,
struct GNUNET_TIME_Timestamp stamp_expire_legal, struct GNUNET_TIME_Timestamp stamp_expire_legal,
const struct TALER_Amount *coin_value, const struct TALER_Amount *coin_value,
const struct TALER_Amount *fee_withdraw, const struct TALER_DenomFeeSet *fees,
const struct TALER_Amount *fee_deposit,
const struct TALER_Amount *fee_refresh,
const struct TALER_Amount *fee_refund,
const struct TALER_AuditorPrivateKeyP *auditor_priv, const struct TALER_AuditorPrivateKeyP *auditor_priv,
struct TALER_AuditorSignatureP *auditor_sig) struct TALER_AuditorSignatureP *auditor_sig)
{ {
@ -53,14 +50,8 @@ TALER_auditor_denom_validity_sign (
TALER_amount_hton (&kv.value, TALER_amount_hton (&kv.value,
coin_value); coin_value);
TALER_amount_hton (&kv.fee_withdraw, TALER_denom_fee_set_hton (&kv.fees,
fee_withdraw); fees);
TALER_amount_hton (&kv.fee_deposit,
fee_deposit);
TALER_amount_hton (&kv.fee_refresh,
fee_refresh);
TALER_amount_hton (&kv.fee_refund,
fee_refund);
GNUNET_CRYPTO_hash (auditor_url, GNUNET_CRYPTO_hash (auditor_url,
strlen (auditor_url) + 1, strlen (auditor_url) + 1,
&kv.auditor_url_hash); &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_deposit,
struct GNUNET_TIME_Timestamp stamp_expire_legal, struct GNUNET_TIME_Timestamp stamp_expire_legal,
const struct TALER_Amount *coin_value, const struct TALER_Amount *coin_value,
const struct TALER_Amount *fee_withdraw, const struct TALER_DenomFeeSet *fees,
const struct TALER_Amount *fee_deposit,
const struct TALER_Amount *fee_refresh,
const struct TALER_Amount *fee_refund,
const struct TALER_AuditorPublicKeyP *auditor_pub, const struct TALER_AuditorPublicKeyP *auditor_pub,
const struct TALER_AuditorSignatureP *auditor_sig) const struct TALER_AuditorSignatureP *auditor_sig)
{ {
@ -100,14 +88,8 @@ TALER_auditor_denom_validity_verify (
TALER_amount_hton (&kv.value, TALER_amount_hton (&kv.value,
coin_value); coin_value);
TALER_amount_hton (&kv.fee_withdraw, TALER_denom_fee_set_hton (&kv.fees,
fee_withdraw); fees);
TALER_amount_hton (&kv.fee_deposit,
fee_deposit);
TALER_amount_hton (&kv.fee_refresh,
fee_refresh);
TALER_amount_hton (&kv.fee_refund,
fee_refund);
GNUNET_CRYPTO_hash (auditor_url, GNUNET_CRYPTO_hash (auditor_url,
strlen (auditor_url) + 1, strlen (auditor_url) + 1,
&kv.auditor_url_hash); &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 enum GNUNET_GenericReturnValue
TALER_config_get_currency (const struct GNUNET_CONFIGURATION_Handle *cfg, TALER_config_get_currency (const struct GNUNET_CONFIGURATION_Handle *cfg,
char **currency) char **currency)

View File

@ -193,6 +193,7 @@ TALER_transfer_secret_to_planchet_secret (
void void
TALER_planchet_secret_to_transfer_priv ( TALER_planchet_secret_to_transfer_priv (
const struct TALER_RefreshMasterSecretP *rms, const struct TALER_RefreshMasterSecretP *rms,
const struct TALER_CoinSpendPrivateKeyP *old_coin_priv,
uint32_t cnc_num, uint32_t cnc_num,
struct TALER_TransferPrivateKeyP *tpriv) struct TALER_TransferPrivateKeyP *tpriv)
{ {
@ -203,6 +204,8 @@ TALER_planchet_secret_to_transfer_priv (
sizeof (*tpriv), sizeof (*tpriv),
&be_salt, &be_salt,
sizeof (be_salt), sizeof (be_salt),
old_coin_priv,
sizeof (*old_coin_priv),
rms, rms,
sizeof (*rms), sizeof (*rms),
"taler-transfer-priv-derivation", "taler-transfer-priv-derivation",
@ -337,6 +340,7 @@ TALER_planchet_to_coin (
void void
TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc, TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc,
uint32_t kappa, uint32_t kappa,
const struct TALER_RefreshMasterSecretP *rms,
uint32_t num_new_coins, uint32_t num_new_coins,
const struct TALER_RefreshCommitmentEntry *rcs, const struct TALER_RefreshCommitmentEntry *rcs,
const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_CoinSpendPublicKeyP *coin_pub,
@ -345,6 +349,10 @@ TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc,
struct GNUNET_HashContext *hash_context; struct GNUNET_HashContext *hash_context;
hash_context = GNUNET_CRYPTO_hash_context_start (); 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 */ /* first, iterate over transfer public keys for hash_context */
for (unsigned int i = 0; i<kappa; i++) 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]; const struct TALER_RefreshCoinData *rcd = &rce->new_coins[j];
TALER_blinded_planchet_hash (&rcd->blinded_planchet, TALER_blinded_planchet_hash_ (&rcd->blinded_planchet,
hash_context); 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 */ /* end of crypto.c */

View File

@ -652,8 +652,8 @@ TALER_blinded_denom_sig_cmp (
void void
TALER_blinded_planchet_hash (const struct TALER_BlindedPlanchet *bp, TALER_blinded_planchet_hash_ (const struct TALER_BlindedPlanchet *bp,
struct GNUNET_HashContext *hash_context) struct GNUNET_HashContext *hash_context)
{ {
uint32_t cipher = htonl (bp->cipher); uint32_t cipher = htonl (bp->cipher);
@ -771,97 +771,20 @@ TALER_blinded_planchet_free (struct TALER_BlindedPlanchet *blinded_planchet)
{ {
switch (blinded_planchet->cipher) switch (blinded_planchet->cipher)
{ {
case TALER_DENOMINATION_INVALID:
GNUNET_break (0);
return;
case TALER_DENOMINATION_RSA: case TALER_DENOMINATION_RSA:
GNUNET_free (blinded_planchet->details.rsa_blinded_planchet.blinded_msg); GNUNET_free (blinded_planchet->details.rsa_blinded_planchet.blinded_msg);
break; return;
case TALER_DENOMINATION_CS: case TALER_DENOMINATION_CS:
memset (blinded_planchet, memset (blinded_planchet,
0, 0,
sizeof (*blinded_planchet)); sizeof (*blinded_planchet));
/* nothing to do for CS */ /* nothing to do for CS */
break; return;
default:
GNUNET_break (0);
} }
} GNUNET_assert (0);
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;
} }

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

View File

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

View File

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