-minor merge conflict resolves
This commit is contained in:
commit
f4f502d037
@ -169,12 +169,14 @@ The denomination key was chosen because it has the recopu protocol in place that
|
||||
\\ & & b := \text{HKDF}(1,n_w || d_s, \text{"b"})
|
||||
\\ & & s \leftarrow \text{GetWithdraw}(n_w, D_p)
|
||||
\\ & & \textbf{if } s = \bot
|
||||
\\ & & \textbf{check !} \text{NonceReuse} (n_w, D_p)
|
||||
\\ & & r_b := \text{HKDF}(256,n_w || d_s, \text{"r}b\text{"})
|
||||
% sign coin
|
||||
\\ & & s := r_b + c_b d_s \mod p
|
||||
% the following db operations are atomic
|
||||
\\ & & \text{decrease balance if sufficient and}
|
||||
\\ & & \text{persist } \langle n_w, D_p, s \rangle
|
||||
\\ & & \text{persist NonceUse } \langle n_w, D_p, s \rangle
|
||||
\\ & & \text{persist } \langle D_p, s \rangle
|
||||
\\ & & \textbf{endif}
|
||||
\\ & \xleftarrow[\rule{2.5cm}{0pt}]{b,s} &
|
||||
% verify signature
|
||||
@ -187,7 +189,6 @@ The denomination key was chosen because it has the recopu protocol in place that
|
||||
\\ \textbf{check if } s'G = R'_b + c'_b D_p & &
|
||||
\\ \sigma_C := \langle R'_b, s' \rangle & &
|
||||
\\ \text{resulting coin: } c_s, C_p, \sigma_C, D_p & &
|
||||
|
||||
\end{array}$
|
||||
}
|
||||
\end{equation*}
|
||||
@ -287,7 +288,7 @@ In the reveal phase, the RSA signing and unblinding is exchanged with Schnorr's
|
||||
\\ h_T := H(T_1, \dots, T_k)
|
||||
\\ h_{\overline{c_0}} := H(\overline{c_{0_1}},\dots, \overline{c}_{0_k})
|
||||
\\ h_{\overline{c_1}} := H(\overline{c_{1_1}},\dots, \overline{c}_{1_k})
|
||||
\\ h_{\overline{c}} := H(h_{\overline{c_0}}, h_{\overline{c_1}})
|
||||
\\ h_{\overline{c}} := H(h_{\overline{c_0}}, h_{\overline{c_1}}, n_r)
|
||||
\\ h_C := H(h_T, h_{\overline{c}})
|
||||
\\ \rho_{RC} := \langle h_C, D_p, \text{ } D_{p(0)}, C_p^{(0)}, \sigma_C^{(0)} \rangle
|
||||
\\ \sigma_{RC} := \text{Ed25519.Sign}(c_s^{(0)}, \rho_{RC})
|
||||
@ -311,7 +312,7 @@ In the reveal phase, the RSA signing and unblinding is exchanged with Schnorr's
|
||||
\\ & \textit{Continuation of}
|
||||
\\ & \textit{figure \ref{fig:refresh-commit-part1}}
|
||||
\\
|
||||
\\ & \xrightarrow[\rule{2cm}{0pt}]{\rho_{RC}, \sigma_{RC}} &
|
||||
\\ & \xrightarrow[\rule{2cm}{0pt}]{\rho_{RC}, \sigma_{RC}, n_r} &
|
||||
% Exchange checks refresh request
|
||||
\\ & & \langle h_C, D_p, D_{p(0)}, C_p^{(0)}, \sigma_C^{(0)} \rangle := \rho_{RC}
|
||||
\\ & & \textbf{check} \text{ Ed25519.Verify}(C_p^{(0)}, \sigma_{RC}, \rho_{RC})
|
||||
@ -323,10 +324,12 @@ In the reveal phase, the RSA signing and unblinding is exchanged with Schnorr's
|
||||
\\ & & v := \text{Denomination}(D_p)
|
||||
\\ & & \textbf{check } \text{IsOverspending}(C_p^{(0)}, D_ {p(0)}, v)
|
||||
\\ & & \text{verify if } D_p \text{ is valid}
|
||||
\\ & & \textbf{check !} \text{NonceReuse} (n_r, D_p)
|
||||
\\ & & \textbf{check } \text{Schnorr.Verify}(D_{p(0)}, C_p^{(0)}, \sigma_C^{(0)})
|
||||
\\ & & \text{MarkFractionalSpend}(C_p^{(0)}, v)
|
||||
\\ & & \gamma \leftarrow \{1, \dots, \kappa\}
|
||||
\\ & & \text{Persist refresh-record } \langle \rho_{RC},\gamma \rangle
|
||||
\\ & & \text{persist NonceUse } \langle n_r, D_p, \rho_{RC} \rangle
|
||||
\\ & & \text{persist refresh-record } \langle \rho_{RC},\gamma \rangle
|
||||
\\ & \xleftarrow[\rule{2cm}{0pt}]{\gamma} &
|
||||
% Check challenge and send challenge response (reveal not selected msgs)
|
||||
\\ \textbf{check } \text{IsConsistentChallenge}(\rho_{RC}, \gamma)
|
||||
@ -334,7 +337,7 @@ In the reveal phase, the RSA signing and unblinding is exchanged with Schnorr's
|
||||
\\
|
||||
\\ \text{Persist refresh-challenge} \langle \rho_{RC}, \gamma \rangle
|
||||
\\ S := \langle t_1, \dots, t_{\gamma-1}, t_{\gamma+1}, \dots,t_\kappa \rangle % all seeds without the gamma seed
|
||||
\\ \rho_L := \langle C_p^{(0)}, D_p, T_{\gamma}, \overline{c_0}_\gamma, \overline{c_1}_\gamma, n_r \rangle
|
||||
\\ \rho_L := \langle C_p^{(0)}, D_p, T_{\gamma}, \overline{c_0}_\gamma, \overline{c_1}_\gamma \rangle
|
||||
\\ \rho_{RR} := \langle \rho_L, S \rangle
|
||||
\\ \sigma_{L} := \text{Ed25519.Sign}(c_s^{(0)}, \rho_{L})
|
||||
\\ & \xrightarrow[\rule{2.5cm}{0pt}]{\rho_{RR},\rho_L, \sigma_{L}} &
|
||||
@ -359,7 +362,7 @@ In the reveal phase, the RSA signing and unblinding is exchanged with Schnorr's
|
||||
\\
|
||||
\\ & \xrightarrow[\rule{2.5cm}{0pt}]{\rho_{RR},\rho_L, \sigma_{L}} &
|
||||
% check revealed msgs and sign coin
|
||||
\\ & & \langle C_p^{(0)}, D_p, T_{\gamma}, \overline{c_0}_\gamma, \overline{c_1}_\gamma, n_r \rangle := \rho_L
|
||||
\\ & & \langle C_p^{(0)}, D_p, T_{\gamma}, \overline{c_0}_\gamma, \overline{c_1}_\gamma \rangle := \rho_L
|
||||
\\ & & \langle T'_\gamma, \overline{c_0}_\gamma, \overline{c_1}_\gamma, S \rangle := \rho_{RR}
|
||||
\\ & & \langle t_1,\dots,t_{\gamma-1},t_{\gamma+1},\dots,t_\kappa \rangle := S
|
||||
\\ & & \textbf{check } \text{Ed25519.Verify}(C_p^{(0)}, \sigma_L, \rho_L)
|
||||
@ -371,7 +374,7 @@ In the reveal phase, the RSA signing and unblinding is exchanged with Schnorr's
|
||||
\\ & & h_T' = H(T_1,\dots,T_{\gamma-1},T'_{\gamma},T_{\gamma+1},\dots,T_\kappa)
|
||||
\\ & & h_{\overline{c_0}}' := H(\overline{c_{0_1}},\dots, \overline{c}_{0_k})
|
||||
\\ & & h_{\overline{c_1}}' := H(\overline{c_{1_1}},\dots, \overline{c}_{1_k})
|
||||
\\ & & h_{\overline{c}}' := H(h_{\overline{c_0}}, h_{\overline{c_1}})
|
||||
\\ & & h_{\overline{c}}' := H(h_{\overline{c_0}}, h_{\overline{c_1}}, n_r)
|
||||
\\ & & h_C' = H(h_T', h_{\overline{c}}')
|
||||
\\ & & \textbf{check } h_C = h_C'
|
||||
\\ & & r_b := \text{HKDF}(256,n_r || d_s, \text{"r}b\text{"})
|
||||
|
@ -141,7 +141,7 @@ add_denomination (
|
||||
GNUNET_h2s (&issue->denom_hash.hash),
|
||||
TALER_amount2s (&value));
|
||||
TALER_amount_ntoh (&value,
|
||||
&issue->fee_withdraw);
|
||||
&issue->fees.withdraw);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Withdraw fee is %s\n",
|
||||
TALER_amount2s (&value));
|
||||
|
@ -471,7 +471,7 @@ check_transaction_history_for_deposit (
|
||||
|
||||
/* Fee according to denomination data of auditor */
|
||||
TALER_amount_ntoh (&fee_expected,
|
||||
&issue->fee_deposit);
|
||||
&issue->fees.deposit);
|
||||
if (0 !=
|
||||
TALER_amount_cmp (&fee_expected,
|
||||
fee_claimed))
|
||||
@ -496,7 +496,7 @@ check_transaction_history_for_deposit (
|
||||
struct TALER_Amount fee_expected;
|
||||
|
||||
TALER_amount_ntoh (&fee_expected,
|
||||
&issue->fee_refresh);
|
||||
&issue->fees.refresh);
|
||||
if (0 !=
|
||||
TALER_amount_cmp (&fee_expected,
|
||||
fee_claimed))
|
||||
@ -540,7 +540,7 @@ check_transaction_history_for_deposit (
|
||||
struct TALER_Amount fee_expected;
|
||||
|
||||
TALER_amount_ntoh (&fee_expected,
|
||||
&issue->fee_refund);
|
||||
&issue->fees.refund);
|
||||
if (0 !=
|
||||
TALER_amount_cmp (&fee_expected,
|
||||
fee_claimed))
|
||||
|
@ -1281,7 +1281,7 @@ refresh_session_cb (void *cls,
|
||||
TALER_denom_pub_hash (denom_pub,
|
||||
&h_denom_pub);
|
||||
TALER_amount_ntoh (&fee_refresh,
|
||||
&issue->fee_refresh);
|
||||
&issue->fees.refresh);
|
||||
if (GNUNET_OK !=
|
||||
TALER_wallet_melt_verify (amount_with_fee,
|
||||
&fee_refresh,
|
||||
@ -1375,7 +1375,7 @@ refresh_session_cb (void *cls,
|
||||
struct TALER_Amount value;
|
||||
|
||||
TALER_amount_ntoh (&fee,
|
||||
&reveal_ctx.new_issues[i]->fee_withdraw);
|
||||
&reveal_ctx.new_issues[i]->fees.withdraw);
|
||||
TALER_amount_ntoh (&value,
|
||||
&reveal_ctx.new_issues[i]->value);
|
||||
TALER_ARL_amount_add (&refresh_cost,
|
||||
@ -1391,7 +1391,7 @@ refresh_session_cb (void *cls,
|
||||
struct TALER_Amount melt_fee;
|
||||
|
||||
TALER_amount_ntoh (&melt_fee,
|
||||
&issue->fee_refresh);
|
||||
&issue->fees.refresh);
|
||||
if (TALER_ARL_SR_POSITIVE !=
|
||||
TALER_ARL_amount_subtract_neg (&amount_without_fee,
|
||||
amount_with_fee,
|
||||
@ -1528,7 +1528,7 @@ refresh_session_cb (void *cls,
|
||||
struct TALER_Amount rfee;
|
||||
|
||||
TALER_amount_ntoh (&rfee,
|
||||
&issue->fee_refresh);
|
||||
&issue->fees.refresh);
|
||||
TALER_ARL_amount_add (&total_melt_fee_income,
|
||||
&total_melt_fee_income,
|
||||
&rfee);
|
||||
@ -1621,7 +1621,7 @@ deposit_cb (void *cls,
|
||||
&deposit->wire_salt,
|
||||
&h_wire);
|
||||
TALER_amount_ntoh (&deposit_fee,
|
||||
&issue->fee_deposit);
|
||||
&issue->fees.deposit);
|
||||
/* NOTE: This is one of the operations we might eventually
|
||||
want to do in parallel in the background to improve
|
||||
auditor performance! */
|
||||
@ -1726,7 +1726,7 @@ deposit_cb (void *cls,
|
||||
struct TALER_Amount dfee;
|
||||
|
||||
TALER_amount_ntoh (&dfee,
|
||||
&issue->fee_deposit);
|
||||
&issue->fees.deposit);
|
||||
TALER_ARL_amount_add (&total_deposit_fee_income,
|
||||
&total_deposit_fee_income,
|
||||
&dfee);
|
||||
@ -1821,7 +1821,7 @@ refund_cb (void *cls,
|
||||
}
|
||||
|
||||
TALER_amount_ntoh (&refund_fee,
|
||||
&issue->fee_refund);
|
||||
&issue->fees.refund);
|
||||
if (TALER_ARL_SR_INVALID_NEGATIVE ==
|
||||
TALER_ARL_amount_subtract_neg (&amount_without_fee,
|
||||
amount_with_fee,
|
||||
@ -2178,10 +2178,7 @@ check_denomination (
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
struct TALER_AuditorSignatureP auditor_sig;
|
||||
struct TALER_Amount coin_value;
|
||||
struct TALER_Amount fee_withdraw;
|
||||
struct TALER_Amount fee_deposit;
|
||||
struct TALER_Amount fee_refresh;
|
||||
struct TALER_Amount fee_refund;
|
||||
struct TALER_DenomFeeSet fees;
|
||||
struct GNUNET_TIME_Timestamp start;
|
||||
struct GNUNET_TIME_Timestamp end;
|
||||
|
||||
@ -2189,14 +2186,8 @@ check_denomination (
|
||||
(void) denom_pub;
|
||||
TALER_amount_ntoh (&coin_value,
|
||||
&issue->value);
|
||||
TALER_amount_ntoh (&fee_withdraw,
|
||||
&issue->fee_withdraw);
|
||||
TALER_amount_ntoh (&fee_deposit,
|
||||
&issue->fee_deposit);
|
||||
TALER_amount_ntoh (&fee_refresh,
|
||||
&issue->fee_refresh);
|
||||
TALER_amount_ntoh (&fee_refund,
|
||||
&issue->fee_refund);
|
||||
TALER_denom_fee_set_ntoh (&fees,
|
||||
&issue->fees);
|
||||
start = GNUNET_TIME_timestamp_ntoh (issue->start);
|
||||
end = GNUNET_TIME_timestamp_ntoh (issue->expire_legal);
|
||||
qs = TALER_ARL_edb->select_auditor_denom_sig (TALER_ARL_edb->cls,
|
||||
@ -2224,10 +2215,7 @@ check_denomination (
|
||||
GNUNET_TIME_timestamp_ntoh (issue->expire_deposit),
|
||||
end,
|
||||
&coin_value,
|
||||
&fee_withdraw,
|
||||
&fee_deposit,
|
||||
&fee_refresh,
|
||||
&fee_refund,
|
||||
&fees,
|
||||
&TALER_ARL_auditor_pub,
|
||||
&auditor_sig))
|
||||
{
|
||||
|
@ -594,7 +594,7 @@ handle_reserve_out (void *cls,
|
||||
}
|
||||
|
||||
TALER_amount_ntoh (&withdraw_fee,
|
||||
&issue->fee_withdraw);
|
||||
&issue->fees.withdraw);
|
||||
TALER_amount_ntoh (&auditor_value,
|
||||
&issue->value);
|
||||
TALER_ARL_amount_add (&auditor_amount_with_fee,
|
||||
|
@ -505,10 +505,10 @@ run (void *cls,
|
||||
TALER_denom_pub_hash (&denom_pub,
|
||||
&h_denom_pub);
|
||||
make_amountN (2, 0, &issue.properties.value);
|
||||
make_amountN (0, 5, &issue.properties.fee_withdraw);
|
||||
make_amountN (0, 5, &issue.properties.fee_deposit);
|
||||
make_amountN (0, 5, &issue.properties.fee_refresh);
|
||||
make_amountN (0, 5, &issue.properties.fee_refund);
|
||||
make_amountN (0, 5, &issue.properties.fees.withdraw);
|
||||
make_amountN (0, 5, &issue.properties.fees.deposit);
|
||||
make_amountN (0, 5, &issue.properties.fees.refresh);
|
||||
make_amountN (0, 5, &issue.properties.fees.refund);
|
||||
issue.properties.denom_hash = h_denom_pub;
|
||||
if (0 >=
|
||||
plugin->insert_denomination_info (plugin->cls,
|
||||
|
@ -757,10 +757,7 @@ show_denomkeys (const json_t *denomkeys)
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_deposit;
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_legal;
|
||||
struct TALER_Amount coin_value;
|
||||
struct TALER_Amount fee_withdraw;
|
||||
struct TALER_Amount fee_deposit;
|
||||
struct TALER_Amount fee_refresh;
|
||||
struct TALER_Amount fee_refund;
|
||||
struct TALER_DenomFeeSet fees;
|
||||
struct TALER_MasterSignatureP master_sig;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
TALER_JSON_spec_denom_pub ("denom_pub",
|
||||
@ -768,18 +765,9 @@ show_denomkeys (const json_t *denomkeys)
|
||||
TALER_JSON_spec_amount ("value",
|
||||
currency,
|
||||
&coin_value),
|
||||
TALER_JSON_spec_amount ("fee_withdraw",
|
||||
TALER_JSON_SPEC_DENOM_FEES ("fee",
|
||||
currency,
|
||||
&fee_withdraw),
|
||||
TALER_JSON_spec_amount ("fee_deposit",
|
||||
currency,
|
||||
&fee_deposit),
|
||||
TALER_JSON_spec_amount ("fee_refresh",
|
||||
currency,
|
||||
&fee_refresh),
|
||||
TALER_JSON_spec_amount ("fee_refund",
|
||||
currency,
|
||||
&fee_refund),
|
||||
&fees),
|
||||
GNUNET_JSON_spec_timestamp ("stamp_start",
|
||||
&stamp_start),
|
||||
GNUNET_JSON_spec_timestamp ("stamp_expire_withdraw",
|
||||
@ -824,10 +812,7 @@ show_denomkeys (const json_t *denomkeys)
|
||||
stamp_expire_deposit,
|
||||
stamp_expire_legal,
|
||||
&coin_value,
|
||||
&fee_withdraw,
|
||||
&fee_deposit,
|
||||
&fee_refresh,
|
||||
&fee_refund,
|
||||
&fees,
|
||||
&master_pub,
|
||||
&master_sig))
|
||||
{
|
||||
@ -847,10 +832,10 @@ show_denomkeys (const json_t *denomkeys)
|
||||
char *deposit_s;
|
||||
char *legal_s;
|
||||
|
||||
withdraw_fee_s = TALER_amount_to_string (&fee_withdraw);
|
||||
deposit_fee_s = TALER_amount_to_string (&fee_deposit);
|
||||
refresh_fee_s = TALER_amount_to_string (&fee_refresh);
|
||||
refund_fee_s = TALER_amount_to_string (&fee_refund);
|
||||
withdraw_fee_s = TALER_amount_to_string (&fees.withdraw);
|
||||
deposit_fee_s = TALER_amount_to_string (&fees.deposit);
|
||||
refresh_fee_s = TALER_amount_to_string (&fees.refresh);
|
||||
refund_fee_s = TALER_amount_to_string (&fees.refund);
|
||||
deposit_s = GNUNET_strdup (
|
||||
GNUNET_TIME_timestamp2s (stamp_expire_deposit));
|
||||
legal_s = GNUNET_strdup (
|
||||
@ -1058,10 +1043,7 @@ sign_denomkeys (const json_t *denomkeys)
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_deposit;
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_legal;
|
||||
struct TALER_Amount coin_value;
|
||||
struct TALER_Amount fee_withdraw;
|
||||
struct TALER_Amount fee_deposit;
|
||||
struct TALER_Amount fee_refresh;
|
||||
struct TALER_Amount fee_refund;
|
||||
struct TALER_DenomFeeSet fees;
|
||||
struct TALER_MasterSignatureP master_sig;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
TALER_JSON_spec_denom_pub ("denom_pub",
|
||||
@ -1069,18 +1051,9 @@ sign_denomkeys (const json_t *denomkeys)
|
||||
TALER_JSON_spec_amount ("value",
|
||||
currency,
|
||||
&coin_value),
|
||||
TALER_JSON_spec_amount ("fee_withdraw",
|
||||
TALER_JSON_SPEC_DENOM_FEES ("fee",
|
||||
currency,
|
||||
&fee_withdraw),
|
||||
TALER_JSON_spec_amount ("fee_deposit",
|
||||
currency,
|
||||
&fee_deposit),
|
||||
TALER_JSON_spec_amount ("fee_refresh",
|
||||
currency,
|
||||
&fee_refresh),
|
||||
TALER_JSON_spec_amount ("fee_refund",
|
||||
currency,
|
||||
&fee_refund),
|
||||
&fees),
|
||||
GNUNET_JSON_spec_timestamp ("stamp_start",
|
||||
&stamp_start),
|
||||
GNUNET_JSON_spec_timestamp ("stamp_expire_withdraw",
|
||||
@ -1121,10 +1094,7 @@ sign_denomkeys (const json_t *denomkeys)
|
||||
stamp_expire_deposit,
|
||||
stamp_expire_legal,
|
||||
&coin_value,
|
||||
&fee_withdraw,
|
||||
&fee_deposit,
|
||||
&fee_refresh,
|
||||
&fee_refund,
|
||||
&fees,
|
||||
&master_pub,
|
||||
&master_sig))
|
||||
{
|
||||
@ -1147,10 +1117,7 @@ sign_denomkeys (const json_t *denomkeys)
|
||||
stamp_expire_deposit,
|
||||
stamp_expire_legal,
|
||||
&coin_value,
|
||||
&fee_withdraw,
|
||||
&fee_deposit,
|
||||
&fee_refresh,
|
||||
&fee_refund,
|
||||
&fees,
|
||||
&auditor_priv,
|
||||
&auditor_sig);
|
||||
output_operation (OP_SIGN_DENOMINATION,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2020, 2021 Taler Systems SA
|
||||
Copyright (C) 2020, 2021, 2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -2831,10 +2831,7 @@ show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_deposit;
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_legal;
|
||||
struct TALER_Amount coin_value;
|
||||
struct TALER_Amount fee_withdraw;
|
||||
struct TALER_Amount fee_deposit;
|
||||
struct TALER_Amount fee_refresh;
|
||||
struct TALER_Amount fee_refund;
|
||||
struct TALER_DenomFeeSet fees;
|
||||
struct TALER_SecurityModuleSignatureP secm_sig;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_string ("section_name",
|
||||
@ -2844,18 +2841,9 @@ show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
|
||||
TALER_JSON_spec_amount ("value",
|
||||
currency,
|
||||
&coin_value),
|
||||
TALER_JSON_spec_amount ("fee_withdraw",
|
||||
TALER_JSON_SPEC_DENOM_FEES ("fee",
|
||||
currency,
|
||||
&fee_withdraw),
|
||||
TALER_JSON_spec_amount ("fee_deposit",
|
||||
currency,
|
||||
&fee_deposit),
|
||||
TALER_JSON_spec_amount ("fee_refresh",
|
||||
currency,
|
||||
&fee_refresh),
|
||||
TALER_JSON_spec_amount ("fee_refund",
|
||||
currency,
|
||||
&fee_refund),
|
||||
&fees),
|
||||
GNUNET_JSON_spec_timestamp ("stamp_start",
|
||||
&stamp_start),
|
||||
GNUNET_JSON_spec_timestamp ("stamp_expire_withdraw",
|
||||
@ -2949,10 +2937,10 @@ show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
|
||||
char *deposit_s;
|
||||
char *legal_s;
|
||||
|
||||
withdraw_fee_s = TALER_amount_to_string (&fee_withdraw);
|
||||
deposit_fee_s = TALER_amount_to_string (&fee_deposit);
|
||||
refresh_fee_s = TALER_amount_to_string (&fee_refresh);
|
||||
refund_fee_s = TALER_amount_to_string (&fee_refund);
|
||||
withdraw_fee_s = TALER_amount_to_string (&fees.withdraw);
|
||||
deposit_fee_s = TALER_amount_to_string (&fees.deposit);
|
||||
refresh_fee_s = TALER_amount_to_string (&fees.refresh);
|
||||
refund_fee_s = TALER_amount_to_string (&fees.refund);
|
||||
deposit_s = GNUNET_strdup (
|
||||
GNUNET_TIME_timestamp2s (stamp_expire_deposit));
|
||||
legal_s = GNUNET_strdup (
|
||||
@ -3324,10 +3312,7 @@ sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_deposit;
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_legal;
|
||||
struct TALER_Amount coin_value;
|
||||
struct TALER_Amount fee_withdraw;
|
||||
struct TALER_Amount fee_deposit;
|
||||
struct TALER_Amount fee_refresh;
|
||||
struct TALER_Amount fee_refund;
|
||||
struct TALER_DenomFeeSet fees;
|
||||
struct TALER_SecurityModuleSignatureP secm_sig;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_string ("section_name",
|
||||
@ -3337,18 +3322,9 @@ sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
|
||||
TALER_JSON_spec_amount ("value",
|
||||
currency,
|
||||
&coin_value),
|
||||
TALER_JSON_spec_amount ("fee_withdraw",
|
||||
TALER_JSON_SPEC_DENOM_FEES ("fee",
|
||||
currency,
|
||||
&fee_withdraw),
|
||||
TALER_JSON_spec_amount ("fee_deposit",
|
||||
currency,
|
||||
&fee_deposit),
|
||||
TALER_JSON_spec_amount ("fee_refresh",
|
||||
currency,
|
||||
&fee_refresh),
|
||||
TALER_JSON_spec_amount ("fee_refund",
|
||||
currency,
|
||||
&fee_refund),
|
||||
&fees),
|
||||
GNUNET_JSON_spec_timestamp ("stamp_start",
|
||||
&stamp_start),
|
||||
GNUNET_JSON_spec_timestamp ("stamp_expire_withdraw",
|
||||
@ -3458,10 +3434,7 @@ sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
|
||||
stamp_expire_deposit,
|
||||
stamp_expire_legal,
|
||||
&coin_value,
|
||||
&fee_withdraw,
|
||||
&fee_deposit,
|
||||
&fee_refresh,
|
||||
&fee_refund,
|
||||
&fees,
|
||||
&master_priv,
|
||||
&master_sig);
|
||||
GNUNET_assert (0 ==
|
||||
|
@ -925,9 +925,15 @@ handle_mhd_request (void *cls,
|
||||
},
|
||||
/* request R, used in clause schnorr withdraw and refresh */
|
||||
{
|
||||
.url = "csr",
|
||||
.url = "csr-melt",
|
||||
.method = MHD_HTTP_METHOD_POST,
|
||||
.handler.post = &TEH_handler_csr,
|
||||
.handler.post = &TEH_handler_csr_melt,
|
||||
.nargs = 0
|
||||
},
|
||||
{
|
||||
.url = "csr-withdraw",
|
||||
.method = MHD_HTTP_METHOD_POST,
|
||||
.handler.post = &TEH_handler_csr_withdraw,
|
||||
.nargs = 0
|
||||
},
|
||||
/* Withdrawing coins / interaction with reserves */
|
||||
|
@ -150,10 +150,7 @@ add_auditor_denom_sig (void *cls,
|
||||
meta.expire_deposit,
|
||||
meta.expire_legal,
|
||||
&meta.value,
|
||||
&meta.fee_withdraw,
|
||||
&meta.fee_deposit,
|
||||
&meta.fee_refresh,
|
||||
&meta.fee_refund,
|
||||
&meta.fees,
|
||||
awc->auditor_pub,
|
||||
&awc->auditor_sig))
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2021 Taler Systems SA
|
||||
Copyright (C) 2014-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
@ -33,15 +33,16 @@
|
||||
|
||||
|
||||
MHD_RESULT
|
||||
TEH_handler_csr (struct TEH_RequestContext *rc,
|
||||
TEH_handler_csr_melt (struct TEH_RequestContext *rc,
|
||||
const json_t *root,
|
||||
const char *const args[])
|
||||
{
|
||||
struct TALER_RefreshMasterSecretP rms;
|
||||
unsigned int csr_requests_num;
|
||||
json_t *csr_requests;
|
||||
json_t *csr_response_ewvs;
|
||||
json_t *csr_response;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto ("rms",
|
||||
&rms),
|
||||
GNUNET_JSON_spec_json ("nks",
|
||||
&csr_requests),
|
||||
GNUNET_JSON_spec_end ()
|
||||
@ -50,8 +51,7 @@ TEH_handler_csr (struct TEH_RequestContext *rc,
|
||||
struct TEH_DenominationKey *dk;
|
||||
|
||||
(void) args;
|
||||
|
||||
// parse input
|
||||
/* parse input */
|
||||
{
|
||||
enum GNUNET_GenericReturnValue res;
|
||||
|
||||
@ -62,7 +62,8 @@ TEH_handler_csr (struct TEH_RequestContext *rc,
|
||||
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
|
||||
}
|
||||
csr_requests_num = json_array_size (csr_requests);
|
||||
if (TALER_MAX_FRESH_COINS <= csr_requests_num)
|
||||
if ( (TALER_MAX_FRESH_COINS <= csr_requests_num) ||
|
||||
(0 == csr_requests_num) )
|
||||
{
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TALER_MHD_reply_with_error (
|
||||
@ -71,19 +72,23 @@ TEH_handler_csr (struct TEH_RequestContext *rc,
|
||||
TALER_EC_EXCHANGE_GENERIC_NEW_DENOMS_ARRAY_SIZE_EXCESSIVE,
|
||||
NULL);
|
||||
}
|
||||
struct TALER_CsNonce nonces[GNUNET_NZL (csr_requests_num)];
|
||||
struct TALER_DenominationHash denom_pub_hashes[GNUNET_NZL (csr_requests_num)];
|
||||
|
||||
{
|
||||
struct TALER_ExchangeWithdrawValues ewvs[csr_requests_num];
|
||||
|
||||
{
|
||||
struct TALER_CsNonce nonces[csr_requests_num];
|
||||
struct TALER_DenominationHash denom_pub_hashes[csr_requests_num];
|
||||
|
||||
for (unsigned int i = 0; i < csr_requests_num; i++)
|
||||
{
|
||||
struct TALER_CsNonce *nonce = &nonces[i];
|
||||
uint32_t coin_off;
|
||||
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_uint32 ("coin_offset",
|
||||
&coin_off),
|
||||
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
|
||||
denom_pub_hash),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
enum GNUNET_GenericReturnValue res;
|
||||
@ -98,19 +103,22 @@ TEH_handler_csr (struct TEH_RequestContext *rc,
|
||||
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);
|
||||
|
||||
struct TALER_ExchangeWithdrawValues ewvs[GNUNET_NZL (csr_requests_num)];
|
||||
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];
|
||||
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
|
||||
/* check denomination referenced by denom_pub_hash */
|
||||
{
|
||||
struct TEH_KeyStateHandle *ksh;
|
||||
|
||||
@ -139,7 +147,7 @@ TEH_handler_csr (struct TEH_RequestContext *rc,
|
||||
rc->connection,
|
||||
denom_pub_hash,
|
||||
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
|
||||
"CSR");
|
||||
"csr-melt");
|
||||
}
|
||||
if (GNUNET_TIME_absolute_is_future (dk->meta.start.abs_time))
|
||||
{
|
||||
@ -149,7 +157,7 @@ TEH_handler_csr (struct TEH_RequestContext *rc,
|
||||
rc->connection,
|
||||
denom_pub_hash,
|
||||
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
|
||||
"CSR");
|
||||
"csr-melt");
|
||||
}
|
||||
if (dk->recoup_possible)
|
||||
{
|
||||
@ -158,18 +166,18 @@ TEH_handler_csr (struct TEH_RequestContext *rc,
|
||||
rc->connection,
|
||||
denom_pub_hash,
|
||||
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED,
|
||||
"CSR");
|
||||
"csr-melt");
|
||||
}
|
||||
if (TALER_DENOMINATION_CS != dk->denom_pub.cipher)
|
||||
{
|
||||
// denomination is valid but not CS
|
||||
/* 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,
|
||||
nonce,
|
||||
@ -182,8 +190,13 @@ TEH_handler_csr (struct TEH_RequestContext *rc,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* send response */
|
||||
{
|
||||
json_t *csr_response_ewvs;
|
||||
json_t *csr_response;
|
||||
|
||||
// send response
|
||||
csr_response_ewvs = json_array ();
|
||||
for (unsigned int i = 0; i < csr_requests_num; i++)
|
||||
{
|
||||
@ -204,6 +217,128 @@ TEH_handler_csr (struct TEH_RequestContext *rc,
|
||||
return TALER_MHD_reply_json_steal (rc->connection,
|
||||
csr_response,
|
||||
MHD_HTTP_OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
{
|
||||
enum GNUNET_GenericReturnValue res;
|
||||
|
||||
res = TALER_MHD_parse_json_data (rc->connection,
|
||||
root,
|
||||
spec);
|
||||
if (GNUNET_OK != res)
|
||||
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
|
||||
}
|
||||
|
||||
{
|
||||
struct TEH_KeyStateHandle *ksh;
|
||||
|
||||
ksh = TEH_keys_get_state ();
|
||||
if (NULL == ksh)
|
||||
{
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
|
||||
NULL);
|
||||
}
|
||||
dk = TEH_keys_denomination_by_hash2 (ksh,
|
||||
&denom_pub_hash,
|
||||
NULL,
|
||||
NULL);
|
||||
if (NULL == dk)
|
||||
{
|
||||
return TEH_RESPONSE_reply_unknown_denom_pub_hash (
|
||||
rc->connection,
|
||||
&denom_pub_hash);
|
||||
}
|
||||
if (GNUNET_TIME_absolute_is_past (dk->meta.expire_withdraw.abs_time))
|
||||
{
|
||||
/* This denomination is past the expiration time for withdraws/refreshes*/
|
||||
return TEH_RESPONSE_reply_expired_denom_pub_hash (
|
||||
rc->connection,
|
||||
&denom_pub_hash,
|
||||
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
|
||||
"csr-withdraw");
|
||||
}
|
||||
if (GNUNET_TIME_absolute_is_future (dk->meta.start.abs_time))
|
||||
{
|
||||
/* This denomination is not yet valid, no need to check
|
||||
for idempotency! */
|
||||
return TEH_RESPONSE_reply_expired_denom_pub_hash (
|
||||
rc->connection,
|
||||
&denom_pub_hash,
|
||||
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
|
||||
"csr-withdraw");
|
||||
}
|
||||
if (dk->recoup_possible)
|
||||
{
|
||||
/* This denomination has been revoked */
|
||||
return TEH_RESPONSE_reply_expired_denom_pub_hash (
|
||||
rc->connection,
|
||||
&denom_pub_hash,
|
||||
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED,
|
||||
"csr-withdraw");
|
||||
}
|
||||
if (TALER_DENOMINATION_CS != dk->denom_pub.cipher)
|
||||
{
|
||||
/* denomination is valid but not for CS */
|
||||
return TEH_RESPONSE_reply_invalid_denom_cipher_for_operation (
|
||||
rc->connection,
|
||||
&denom_pub_hash);
|
||||
}
|
||||
}
|
||||
|
||||
/* derive r_pub */
|
||||
{
|
||||
enum TALER_ErrorCode ec;
|
||||
|
||||
ec = TEH_keys_denomination_cs_r_pub (&denom_pub_hash,
|
||||
&nonce,
|
||||
&ewv.details.cs_values);
|
||||
if (TALER_EC_NONE != ec)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TALER_MHD_reply_with_ec (rc->connection,
|
||||
ec,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
json_t *csr_obj;
|
||||
|
||||
csr_obj = GNUNET_JSON_PACK (
|
||||
TALER_JSON_pack_exchange_withdraw_values ("ewv",
|
||||
&ewv));
|
||||
GNUNET_assert (NULL != csr_obj);
|
||||
return TALER_MHD_reply_json_steal (rc->connection,
|
||||
csr_obj,
|
||||
MHD_HTTP_OK);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
*/
|
||||
/**
|
||||
* @file taler-exchange-httpd_csr.h
|
||||
* @brief Handle /csr requests
|
||||
* @brief Handle /csr-* requests
|
||||
* @author Lucien Heuzeveldt
|
||||
* @author Gian Demarmles
|
||||
*/
|
||||
@ -27,8 +27,7 @@
|
||||
|
||||
|
||||
/**
|
||||
* Handle a "/csr" request. Parses the "nonce" and
|
||||
* the "denom_pub_hash" (identifying a denomination) used to derive the r_pub.
|
||||
* Handle a "/csr-melt" request.
|
||||
*
|
||||
* @param rc request context
|
||||
* @param root uploaded JSON data
|
||||
@ -36,7 +35,21 @@
|
||||
* @return MHD result code
|
||||
*/
|
||||
MHD_RESULT
|
||||
TEH_handler_csr (struct TEH_RequestContext *rc,
|
||||
TEH_handler_csr_melt (struct TEH_RequestContext *rc,
|
||||
const json_t *root,
|
||||
const char *const args[]);
|
||||
|
||||
|
||||
/**
|
||||
* Handle a "/csr-withdraw" request.
|
||||
*
|
||||
* @param rc request context
|
||||
* @param root uploaded JSON data
|
||||
* @param args empty array
|
||||
* @return MHD result code
|
||||
*/
|
||||
MHD_RESULT
|
||||
TEH_handler_csr_withdraw (struct TEH_RequestContext *rc,
|
||||
const json_t *root,
|
||||
const char *const args[]);
|
||||
|
||||
|
@ -370,7 +370,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
||||
NULL);
|
||||
}
|
||||
|
||||
deposit.deposit_fee = dk->meta.fee_deposit;
|
||||
deposit.deposit_fee = dk->meta.fees.deposit;
|
||||
/* check coin signature */
|
||||
if (GNUNET_YES !=
|
||||
TALER_test_coin_valid (&deposit.coin,
|
||||
|
@ -2113,14 +2113,8 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
|
||||
&dk->denom_pub),
|
||||
TALER_JSON_pack_amount ("value",
|
||||
&dk->meta.value),
|
||||
TALER_JSON_pack_amount ("fee_withdraw",
|
||||
&dk->meta.fee_withdraw),
|
||||
TALER_JSON_pack_amount ("fee_deposit",
|
||||
&dk->meta.fee_deposit),
|
||||
TALER_JSON_pack_amount ("fee_refresh",
|
||||
&dk->meta.fee_refresh),
|
||||
TALER_JSON_pack_amount ("fee_refund",
|
||||
&dk->meta.fee_refund));
|
||||
TALER_JSON_PACK_DENOM_FEES ("fee",
|
||||
&dk->meta.fees));
|
||||
|
||||
/* Put the denom into the correct array depending on the settings and
|
||||
* the properties of the denomination. Also, we build up the right
|
||||
@ -2810,74 +2804,22 @@ load_extension_data (const char *section_name,
|
||||
section_name);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_config_get_amount (TEH_cfg,
|
||||
section_name,
|
||||
"FEE_WITHDRAW",
|
||||
&meta->fee_withdraw))
|
||||
{
|
||||
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Need amount for option `%s' in section `%s'\n",
|
||||
"FEE_WITHDRAW",
|
||||
section_name);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_config_get_amount (TEH_cfg,
|
||||
section_name,
|
||||
"FEE_DEPOSIT",
|
||||
&meta->fee_deposit))
|
||||
{
|
||||
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Need amount for option `%s' in section `%s'\n",
|
||||
"FEE_DEPOSIT",
|
||||
section_name);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_config_get_amount (TEH_cfg,
|
||||
section_name,
|
||||
"FEE_REFRESH",
|
||||
&meta->fee_refresh))
|
||||
{
|
||||
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Need amount for option `%s' in section `%s'\n",
|
||||
"FEE_REFRESH",
|
||||
section_name);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_config_get_amount (TEH_cfg,
|
||||
section_name,
|
||||
"FEE_REFUND",
|
||||
&meta->fee_refund))
|
||||
{
|
||||
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Need amount for option `%s' in section `%s'\n",
|
||||
"FEE_REFUND",
|
||||
section_name);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if ( (0 != strcasecmp (TEH_currency,
|
||||
meta->value.currency)) ||
|
||||
(0 != strcasecmp (TEH_currency,
|
||||
meta->fee_withdraw.currency)) ||
|
||||
(0 != strcasecmp (TEH_currency,
|
||||
meta->fee_deposit.currency)) ||
|
||||
(0 != strcasecmp (TEH_currency,
|
||||
meta->fee_refresh.currency)) ||
|
||||
(0 != strcasecmp (TEH_currency,
|
||||
meta->fee_refund.currency)) )
|
||||
if (0 != strcasecmp (TEH_currency,
|
||||
meta->value.currency))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Need amounts in section `%s' to use currency `%s'\n",
|
||||
"Need denomination value in section `%s' to use currency `%s'\n",
|
||||
section_name,
|
||||
TEH_currency);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_config_get_denom_fees (TEH_cfg,
|
||||
TEH_currency,
|
||||
section_name,
|
||||
&meta->fees))
|
||||
return GNUNET_SYSERR;
|
||||
meta->age_mask = load_age_mask (section_name);
|
||||
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
@ -3040,14 +2982,8 @@ add_future_denomkey_cb (void *cls,
|
||||
meta.expire_legal),
|
||||
TALER_JSON_pack_denom_pub ("denom_pub",
|
||||
&hd->denom_pub),
|
||||
TALER_JSON_pack_amount ("fee_withdraw",
|
||||
&meta.fee_withdraw),
|
||||
TALER_JSON_pack_amount ("fee_deposit",
|
||||
&meta.fee_deposit),
|
||||
TALER_JSON_pack_amount ("fee_refresh",
|
||||
&meta.fee_refresh),
|
||||
TALER_JSON_pack_amount ("fee_refund",
|
||||
&meta.fee_refund),
|
||||
TALER_JSON_PACK_DENOM_FEES ("fee",
|
||||
&meta.fees),
|
||||
GNUNET_JSON_pack_data_auto ("denom_secmod_sig",
|
||||
&hd->sm_sig),
|
||||
GNUNET_JSON_pack_string ("section_name",
|
||||
|
@ -187,10 +187,7 @@ add_keys (void *cls,
|
||||
meta.expire_deposit,
|
||||
meta.expire_legal,
|
||||
&meta.value,
|
||||
&meta.fee_withdraw,
|
||||
&meta.fee_deposit,
|
||||
&meta.fee_refresh,
|
||||
&meta.fee_refund,
|
||||
&meta.fees,
|
||||
&TEH_master_public_key,
|
||||
&d->master_sig))
|
||||
{
|
||||
|
@ -104,6 +104,11 @@ struct MeltContext
|
||||
*/
|
||||
struct TALER_Amount coin_refresh_fee;
|
||||
|
||||
/**
|
||||
* Refresh master secret, if any of the fresh denominations use CS.
|
||||
*/
|
||||
struct TALER_RefreshMasterSecretP rms;
|
||||
|
||||
/**
|
||||
* Set to true if this coin's denomination was revoked and the operation
|
||||
* is thus only allowed for zombie coins where the transaction
|
||||
@ -117,6 +122,10 @@ struct MeltContext
|
||||
*/
|
||||
bool coin_is_dirty;
|
||||
|
||||
/**
|
||||
* True if @e rms is set.
|
||||
*/
|
||||
bool have_rms;
|
||||
};
|
||||
|
||||
|
||||
@ -155,6 +164,9 @@ melt_transaction (void *cls,
|
||||
|
||||
if (0 >
|
||||
(qs = TEH_plugin->do_melt (TEH_plugin->cls,
|
||||
rmc->have_rms
|
||||
? &rmc->rms
|
||||
: NULL,
|
||||
&rmc->refresh_session,
|
||||
rmc->known_coin_id,
|
||||
&rmc->zombie_required,
|
||||
@ -300,7 +312,7 @@ check_melt_valid (struct MHD_Connection *connection,
|
||||
"MELT");
|
||||
}
|
||||
|
||||
rmc->coin_refresh_fee = dk->meta.fee_refresh;
|
||||
rmc->coin_refresh_fee = dk->meta.fees.refresh;
|
||||
rmc->coin_value = dk->meta.value;
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
@ -422,6 +434,9 @@ TEH_handler_melt (struct MHD_Connection *connection,
|
||||
&rmc.refresh_session.amount_with_fee),
|
||||
GNUNET_JSON_spec_fixed_auto ("rc",
|
||||
&rmc.refresh_session.rc),
|
||||
GNUNET_JSON_spec_mark_optional (
|
||||
GNUNET_JSON_spec_fixed_auto ("rms",
|
||||
&rmc.rms)),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
@ -429,7 +444,6 @@ TEH_handler_melt (struct MHD_Connection *connection,
|
||||
0,
|
||||
sizeof (rmc));
|
||||
rmc.refresh_session.coin.coin_pub = *coin_pub;
|
||||
|
||||
{
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
ret = TALER_MHD_parse_json_data (connection,
|
||||
@ -438,7 +452,8 @@ TEH_handler_melt (struct MHD_Connection *connection,
|
||||
if (GNUNET_OK != ret)
|
||||
return (GNUNET_SYSERR == ret) ? MHD_NO : MHD_YES;
|
||||
}
|
||||
|
||||
rmc.have_rms = (NULL != json_object_get (root,
|
||||
"rms"));
|
||||
{
|
||||
MHD_RESULT res;
|
||||
|
||||
|
@ -42,7 +42,7 @@ struct RecoupContext
|
||||
/**
|
||||
* Hash identifying the withdraw request.
|
||||
*/
|
||||
struct TALER_WithdrawIdentificationHash wih;
|
||||
struct TALER_BlindedCoinHash h_coin_ev;
|
||||
|
||||
/**
|
||||
* Set by #recoup_transaction() to the reserve that will
|
||||
@ -273,9 +273,9 @@ verify_and_execute_recoup (
|
||||
blinded_planchet.details.cs_blinded_planchet.nonce
|
||||
= *nonce;
|
||||
if (GNUNET_OK !=
|
||||
TALER_withdraw_request_hash (&blinded_planchet,
|
||||
TALER_coin_ev_hash (&blinded_planchet,
|
||||
&coin->denom_pub_hash,
|
||||
&pc.wih))
|
||||
&pc.h_coin_ev))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TALER_MHD_reply_with_error (connection,
|
||||
@ -308,8 +308,8 @@ verify_and_execute_recoup (
|
||||
{
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
qs = TEH_plugin->get_reserve_by_wih (TEH_plugin->cls,
|
||||
&pc.wih,
|
||||
qs = TEH_plugin->get_reserve_by_h_blind (TEH_plugin->cls,
|
||||
&pc.h_coin_ev,
|
||||
&pc.reserve_pub,
|
||||
&pc.reserve_out_serial_id);
|
||||
if (0 > qs)
|
||||
@ -319,13 +319,13 @@ verify_and_execute_recoup (
|
||||
connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_GENERIC_DB_FETCH_FAILED,
|
||||
"get_reserve_by_wih");
|
||||
"get_reserve_by_h_blind");
|
||||
}
|
||||
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Recoup requested for unknown envelope %s\n",
|
||||
GNUNET_h2s (&pc.wih.hash));
|
||||
GNUNET_h2s (&pc.h_coin_ev.hash));
|
||||
return TALER_MHD_reply_with_error (
|
||||
connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
@ -412,9 +412,6 @@ TEH_handler_recoup (struct MHD_Connection *connection,
|
||||
return MHD_NO; /* hard failure */
|
||||
if (GNUNET_NO == ret)
|
||||
return MHD_YES; /* failure */
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Recoup coin with BKS=%s\n",
|
||||
TALER_B2S (&coin_bks));
|
||||
{
|
||||
MHD_RESULT res;
|
||||
|
||||
|
@ -121,11 +121,20 @@ struct RevealContext
|
||||
*/
|
||||
struct TALER_RefreshCoinData *rcds;
|
||||
|
||||
/**
|
||||
* Refresh master secret.
|
||||
*/
|
||||
struct TALER_RefreshMasterSecretP rms;
|
||||
|
||||
/**
|
||||
* Size of the @e dks, @e rcds and @e ev_sigs arrays (if non-NULL).
|
||||
*/
|
||||
unsigned int num_fresh_coins;
|
||||
|
||||
/**
|
||||
* True if @e rms was provided.
|
||||
*/
|
||||
bool have_rms;
|
||||
};
|
||||
|
||||
|
||||
@ -321,6 +330,9 @@ check_commitment (struct RevealContext *rctx,
|
||||
}
|
||||
TALER_refresh_get_commitment (&rc_expected,
|
||||
TALER_CNC_KAPPA,
|
||||
rctx->have_rms
|
||||
? &rctx->rms
|
||||
: NULL,
|
||||
rctx->num_fresh_coins,
|
||||
rcs,
|
||||
&rctx->melt.session.coin.coin_pub,
|
||||
@ -369,7 +381,7 @@ check_commitment (struct RevealContext *rctx,
|
||||
|
||||
if ( (0 >
|
||||
TALER_amount_add (&total,
|
||||
&rctx->dks[i]->meta.fee_withdraw,
|
||||
&rctx->dks[i]->meta.fees.withdraw,
|
||||
&rctx->dks[i]->meta.value)) ||
|
||||
(0 >
|
||||
TALER_amount_add (&refresh_cost,
|
||||
@ -464,7 +476,15 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
|
||||
&ret);
|
||||
if (NULL == dks[i])
|
||||
return ret;
|
||||
|
||||
if ( (TALER_DENOMINATION_CS == dks[i]->denom_pub.cipher) &&
|
||||
(! rctx->have_rms) )
|
||||
{
|
||||
return TALER_MHD_reply_with_error (
|
||||
connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_GENERIC_PARAMETER_MISSING,
|
||||
"rms");
|
||||
}
|
||||
if (GNUNET_TIME_absolute_is_past (dks[i]->meta.expire_withdraw.abs_time))
|
||||
{
|
||||
/* This denomination is past the expiration time for withdraws */
|
||||
@ -907,6 +927,9 @@ TEH_handler_reveal (struct TEH_RequestContext *rc,
|
||||
GNUNET_JSON_spec_mark_optional (
|
||||
GNUNET_JSON_spec_json ("old_age_commitment",
|
||||
&old_age_commitment)),
|
||||
GNUNET_JSON_spec_mark_optional (
|
||||
GNUNET_JSON_spec_fixed_auto ("rms",
|
||||
&rctx.rms)),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
@ -947,6 +970,8 @@ TEH_handler_reveal (struct TEH_RequestContext *rc,
|
||||
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
|
||||
}
|
||||
}
|
||||
rctx.have_rms = (NULL != json_object_get (root,
|
||||
"rms"));
|
||||
|
||||
/* Check we got enough transfer private keys */
|
||||
/* Note we do +1 as 1 row (cut-and-choose!) is missing! */
|
||||
|
@ -264,8 +264,8 @@ verify_and_execute_refund (struct MHD_Connection *connection,
|
||||
GNUNET_break (0);
|
||||
return mret;
|
||||
}
|
||||
refund->details.refund_fee = dk->meta.fee_refund;
|
||||
rctx.deposit_fee = dk->meta.fee_deposit;
|
||||
refund->details.refund_fee = dk->meta.fees.refund;
|
||||
rctx.deposit_fee = dk->meta.fees.deposit;
|
||||
}
|
||||
|
||||
/* Finally run the actual transaction logic */
|
||||
|
@ -91,11 +91,6 @@ reply_withdraw_insufficient_funds (
|
||||
struct WithdrawContext
|
||||
{
|
||||
|
||||
/**
|
||||
* Hash that uniquely identifies the withdraw request.
|
||||
*/
|
||||
struct TALER_WithdrawIdentificationHash wih;
|
||||
|
||||
/**
|
||||
* Hash of the (blinded) message to be signed by the Exchange.
|
||||
*/
|
||||
@ -157,10 +152,17 @@ withdraw_transaction (void *cls,
|
||||
bool balance_ok = false;
|
||||
struct GNUNET_TIME_Timestamp now;
|
||||
uint64_t ruuid;
|
||||
const struct TALER_CsNonce *nonce;
|
||||
const struct TALER_BlindedPlanchet *bp;
|
||||
|
||||
now = GNUNET_TIME_timestamp_get ();
|
||||
bp = &wc->blinded_planchet;
|
||||
nonce =
|
||||
(TALER_DENOMINATION_CS == bp->cipher)
|
||||
? &bp->details.cs_blinded_planchet.nonce
|
||||
: NULL;
|
||||
qs = TEH_plugin->do_withdraw (TEH_plugin->cls,
|
||||
&wc->wih,
|
||||
nonce,
|
||||
&wc->collectable,
|
||||
now,
|
||||
&found,
|
||||
@ -300,7 +302,7 @@ check_request_idempotent (struct TEH_RequestContext *rc,
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
qs = TEH_plugin->get_withdraw_info (TEH_plugin->cls,
|
||||
&wc->wih,
|
||||
&wc->h_coin_envelope,
|
||||
&wc->collectable);
|
||||
if (0 > qs)
|
||||
{
|
||||
@ -465,7 +467,7 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
|
||||
if (0 >
|
||||
TALER_amount_add (&wc.collectable.amount_with_fee,
|
||||
&dk->meta.value,
|
||||
&dk->meta.fee_withdraw))
|
||||
&dk->meta.fees.withdraw))
|
||||
{
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
@ -502,19 +504,6 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_withdraw_request_hash (&wc.blinded_planchet,
|
||||
&wc.collectable.denom_pub_hash,
|
||||
&wc.wih))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* Sign before transaction! */
|
||||
ec = TEH_keys_denomination_sign (
|
||||
&wc.collectable.denom_pub_hash,
|
||||
|
@ -1,6 +1,6 @@
|
||||
--
|
||||
-- This file is part of TALER
|
||||
-- Copyright (C) 2014--2021 Taler Systems SA
|
||||
-- Copyright (C) 2014--2022 Taler Systems SA
|
||||
--
|
||||
-- TALER is free software; you can redistribute it and/or modify it under the
|
||||
-- terms of the GNU General Public License as published by the Free Software
|
||||
@ -22,7 +22,7 @@ SELECT _v.register_patch('exchange-0001', NULL, NULL);
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS denominations
|
||||
(denominations_serial BIGSERIAL UNIQUE
|
||||
(denominations_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
|
||||
,denom_pub_hash BYTEA PRIMARY KEY CHECK (LENGTH(denom_pub_hash)=64)
|
||||
,denom_type INT4 NOT NULL DEFAULT (1) -- 1 == RSA (for now, remove default later!)
|
||||
,age_mask INT4 NOT NULL DEFAULT (0)
|
||||
@ -58,7 +58,7 @@ CREATE INDEX IF NOT EXISTS denominations_by_expire_legal_index
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS denomination_revocations
|
||||
(denom_revocations_serial_id BIGSERIAL UNIQUE
|
||||
(denom_revocations_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
|
||||
,denominations_serial INT8 PRIMARY KEY REFERENCES denominations (denominations_serial) ON DELETE CASCADE
|
||||
,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
|
||||
);
|
||||
@ -67,7 +67,7 @@ COMMENT ON TABLE denomination_revocations
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS wire_targets
|
||||
(wire_target_serial_id BIGSERIAL -- UNIQUE
|
||||
(wire_target_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
|
||||
,h_payto BYTEA PRIMARY KEY CHECK (LENGTH(h_payto)=64)
|
||||
,payto_uri VARCHAR NOT NULL
|
||||
,kyc_ok BOOLEAN NOT NULL DEFAULT (FALSE)
|
||||
@ -89,7 +89,7 @@ CREATE TABLE IF NOT EXISTS wire_targets_default
|
||||
FOR VALUES WITH (MODULUS 1, REMAINDER 0);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS reserves
|
||||
(reserve_uuid BIGSERIAL
|
||||
(reserve_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY
|
||||
,reserve_pub BYTEA PRIMARY KEY CHECK(LENGTH(reserve_pub)=32)
|
||||
,current_balance_val INT8 NOT NULL
|
||||
,current_balance_frac INT4 NOT NULL
|
||||
@ -130,7 +130,7 @@ COMMENT ON INDEX reserves_by_gc_date_index
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS reserves_in
|
||||
(reserve_in_serial_id BIGSERIAL -- UNIQUE
|
||||
(reserve_in_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
|
||||
,reserve_pub BYTEA PRIMARY KEY REFERENCES reserves (reserve_pub) ON DELETE CASCADE
|
||||
,wire_reference INT8 NOT NULL
|
||||
,credit_val INT8 NOT NULL
|
||||
@ -168,7 +168,7 @@ CREATE INDEX IF NOT EXISTS reserves_in_by_exchange_account_reserve_in_serial_id_
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS reserves_close
|
||||
(close_uuid BIGSERIAL -- UNIQUE / PRIMARY KEY
|
||||
(close_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE / PRIMARY KEY
|
||||
,reserve_pub BYTEA NOT NULL REFERENCES reserves (reserve_pub) ON DELETE CASCADE
|
||||
,execution_date INT8 NOT NULL
|
||||
,wtid BYTEA NOT NULL CHECK (LENGTH(wtid)=32)
|
||||
@ -195,8 +195,7 @@ CREATE INDEX IF NOT EXISTS reserves_close_by_reserve_pub_index
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS reserves_out
|
||||
(reserve_out_serial_id BIGSERIAL -- UNIQUE
|
||||
,wih BYTEA PRIMARY KEY CHECK (LENGTH(wih)=64)
|
||||
(reserve_out_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
|
||||
,h_blind_ev BYTEA CHECK (LENGTH(h_blind_ev)=64) -- UNIQUE
|
||||
,denominations_serial INT8 NOT NULL REFERENCES denominations (denominations_serial)
|
||||
,denom_sig BYTEA NOT NULL
|
||||
@ -206,11 +205,9 @@ CREATE TABLE IF NOT EXISTS reserves_out
|
||||
,amount_with_fee_val INT8 NOT NULL
|
||||
,amount_with_fee_frac INT4 NOT NULL
|
||||
)
|
||||
PARTITION BY HASH (wih);
|
||||
PARTITION BY HASH (h_blind_ev);
|
||||
COMMENT ON TABLE reserves_out
|
||||
IS 'Withdraw operations performed on reserves.';
|
||||
COMMENT ON COLUMN reserves_out.wih
|
||||
IS 'Hash that uniquely identifies the withdraw request. Used to detect request replays (crucial for CS) and to check the withdraw existed during recoup.';
|
||||
COMMENT ON COLUMN reserves_out.h_blind_ev
|
||||
IS 'Hash of the blinded coin, used as primary key here so that broken clients that use a non-random coin or blinding factor fail to withdraw (otherwise they would fail on deposit when the coin is not unique there).';
|
||||
COMMENT ON COLUMN reserves_out.denominations_serial
|
||||
@ -230,7 +227,7 @@ COMMENT ON INDEX reserves_out_by_reserve_uuid_and_execution_date_index
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS auditors
|
||||
(auditor_uuid BIGSERIAL UNIQUE
|
||||
(auditor_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
|
||||
,auditor_pub BYTEA PRIMARY KEY CHECK (LENGTH(auditor_pub)=32)
|
||||
,auditor_name VARCHAR NOT NULL
|
||||
,auditor_url VARCHAR NOT NULL
|
||||
@ -250,7 +247,7 @@ COMMENT ON COLUMN auditors.last_change
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS auditor_denom_sigs
|
||||
(auditor_denom_serial BIGSERIAL UNIQUE
|
||||
(auditor_denom_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
|
||||
,auditor_uuid INT8 NOT NULL REFERENCES auditors (auditor_uuid) ON DELETE CASCADE
|
||||
,denominations_serial INT8 NOT NULL REFERENCES denominations (denominations_serial) ON DELETE CASCADE
|
||||
,auditor_sig BYTEA CHECK (LENGTH(auditor_sig)=64)
|
||||
@ -267,7 +264,7 @@ COMMENT ON COLUMN auditor_denom_sigs.auditor_sig
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS exchange_sign_keys
|
||||
(esk_serial BIGSERIAL UNIQUE
|
||||
(esk_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
|
||||
,exchange_pub BYTEA PRIMARY KEY CHECK (LENGTH(exchange_pub)=32)
|
||||
,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
|
||||
,valid_from INT8 NOT NULL
|
||||
@ -289,7 +286,7 @@ COMMENT ON COLUMN exchange_sign_keys.expire_legal
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS signkey_revocations
|
||||
(signkey_revocations_serial_id BIGSERIAL UNIQUE
|
||||
(signkey_revocations_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
|
||||
,esk_serial INT8 PRIMARY KEY REFERENCES exchange_sign_keys (esk_serial) ON DELETE CASCADE
|
||||
,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
|
||||
);
|
||||
@ -298,7 +295,7 @@ COMMENT ON TABLE signkey_revocations
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS extensions
|
||||
(extension_id BIGSERIAL UNIQUE
|
||||
(extension_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
|
||||
,name VARCHAR NOT NULL UNIQUE
|
||||
,config BYTEA
|
||||
);
|
||||
@ -311,7 +308,7 @@ COMMENT ON COLUMN extensions.config
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS known_coins
|
||||
(known_coin_id BIGSERIAL -- UNIQUE
|
||||
(known_coin_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
|
||||
,denominations_serial INT8 NOT NULL REFERENCES denominations (denominations_serial) ON DELETE CASCADE
|
||||
,coin_pub BYTEA NOT NULL PRIMARY KEY CHECK (LENGTH(coin_pub)=32)
|
||||
,age_hash BYTEA CHECK (LENGTH(age_hash)=32)
|
||||
@ -342,7 +339,7 @@ CREATE INDEX IF NOT EXISTS known_coins_by_known_coin_id_index
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS refresh_commitments
|
||||
(melt_serial_id BIGSERIAL -- UNIQUE
|
||||
(melt_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
|
||||
,rc BYTEA PRIMARY KEY CHECK (LENGTH(rc)=64)
|
||||
,old_coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) ON DELETE CASCADE
|
||||
,h_age_commitment BYTEA CHECK(LENGTH(h_age_commitment)=32)
|
||||
@ -375,7 +372,7 @@ CREATE INDEX IF NOT EXISTS refresh_commitments_by_old_coin_pub_index
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS refresh_revealed_coins
|
||||
(rrc_serial BIGSERIAL -- UNIQUE
|
||||
(rrc_serial BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
|
||||
,melt_serial_id INT8 NOT NULL -- REFERENCES refresh_commitments (melt_serial_id) ON DELETE CASCADE
|
||||
,freshcoin_index INT4 NOT NULL
|
||||
,link_sig BYTEA NOT NULL CHECK(LENGTH(link_sig)=64)
|
||||
@ -419,7 +416,7 @@ CREATE INDEX IF NOT EXISTS refresh_revealed_coins_by_melt_serial_id_index
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS refresh_transfer_keys
|
||||
(rtc_serial BIGSERIAL -- UNIQUE
|
||||
(rtc_serial BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
|
||||
,melt_serial_id INT8 PRIMARY KEY -- REFERENCES refresh_commitments (melt_serial_id) ON DELETE CASCADE
|
||||
,transfer_pub BYTEA NOT NULL CHECK(LENGTH(transfer_pub)=32)
|
||||
,transfer_privs BYTEA NOT NULL
|
||||
@ -445,7 +442,7 @@ CREATE INDEX IF NOT EXISTS refresh_transfer_keys_by_rtc_serial_index
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS extension_details
|
||||
(extension_details_serial_id BIGSERIAL PRIMARY KEY
|
||||
(extension_details_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
|
||||
,extension_options VARCHAR);
|
||||
COMMENT ON TABLE extension_details
|
||||
IS 'Extensions that were provided with deposits (not yet used).';
|
||||
@ -454,7 +451,7 @@ COMMENT ON COLUMN extension_details.extension_options
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS deposits
|
||||
(deposit_serial_id BIGSERIAL -- PRIMARY KEY
|
||||
(deposit_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- PRIMARY KEY
|
||||
,shard INT8 NOT NULL
|
||||
,known_coin_id INT8 NOT NULL -- REFERENCES known_coins (known_coin_id) ON DELETE CASCADE
|
||||
,amount_with_fee_val INT8 NOT NULL
|
||||
@ -526,7 +523,7 @@ COMMENT ON INDEX deposits_for_iterate_matching_index
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS refunds
|
||||
(refund_serial_id BIGSERIAL -- UNIQUE
|
||||
(refund_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
|
||||
,deposit_serial_id INT8 NOT NULL -- REFERENCES deposits (deposit_serial_id) ON DELETE CASCADE
|
||||
,merchant_sig BYTEA NOT NULL CHECK(LENGTH(merchant_sig)=64)
|
||||
,rtransaction_id INT8 NOT NULL
|
||||
@ -553,7 +550,7 @@ CREATE INDEX IF NOT EXISTS refunds_by_refund_serial_id_index
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS wire_out
|
||||
(wireout_uuid BIGSERIAL -- PRIMARY KEY
|
||||
(wireout_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY -- PRIMARY KEY
|
||||
,execution_date INT8 NOT NULL
|
||||
,wtid_raw BYTEA UNIQUE NOT NULL CHECK (LENGTH(wtid_raw)=32)
|
||||
,wire_target_serial_id INT8 NOT NULL -- REFERENCES wire_targets (wire_target_serial_id)
|
||||
@ -582,7 +579,7 @@ CREATE INDEX IF NOT EXISTS wire_out_by_wire_target_serial_id_index
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS aggregation_tracking
|
||||
(aggregation_serial_id BIGSERIAL -- UNIQUE
|
||||
(aggregation_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
|
||||
,deposit_serial_id INT8 PRIMARY KEY -- REFERENCES deposits (deposit_serial_id) ON DELETE CASCADE
|
||||
,wtid_raw BYTEA CONSTRAINT wire_out_ref REFERENCES wire_out(wtid_raw) ON DELETE CASCADE DEFERRABLE
|
||||
)
|
||||
@ -606,7 +603,7 @@ COMMENT ON INDEX aggregation_tracking_by_wtid_raw_index
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS wire_fee
|
||||
(wire_fee_serial BIGSERIAL UNIQUE
|
||||
(wire_fee_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
|
||||
,wire_method VARCHAR NOT NULL
|
||||
,start_date INT8 NOT NULL
|
||||
,end_date INT8 NOT NULL
|
||||
@ -628,7 +625,7 @@ CREATE INDEX IF NOT EXISTS wire_fee_by_end_date_index
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS recoup
|
||||
(recoup_uuid BIGSERIAL -- UNIQUE
|
||||
(recoup_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
|
||||
,known_coin_id INT8 NOT NULL -- REFERENCES known_coins (known_coin_id)
|
||||
,coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64)
|
||||
,coin_blind BYTEA NOT NULL CHECK(LENGTH(coin_blind)=32)
|
||||
@ -643,7 +640,7 @@ COMMENT ON TABLE recoup
|
||||
COMMENT ON COLUMN recoup.known_coin_id
|
||||
IS 'Coin that is being debited in the recoup. Do not CASCADE ON DROP on the coin_pub, as we may keep the coin alive!';
|
||||
COMMENT ON COLUMN recoup.reserve_out_serial_id
|
||||
IS 'Identifies the wih of the recouped coin and provides the link to the credited reserve.';
|
||||
IS 'Identifies the h_blind_ev of the recouped coin and provides the link to the credited reserve.';
|
||||
COMMENT ON COLUMN recoup.coin_sig
|
||||
IS 'Signature by the coin affirming the recoup, of type TALER_SIGNATURE_WALLET_COIN_RECOUP';
|
||||
COMMENT ON COLUMN recoup.coin_blind
|
||||
@ -664,7 +661,7 @@ CREATE INDEX IF NOT EXISTS recoup_by_known_coin_id_index
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS recoup_refresh
|
||||
(recoup_refresh_uuid BIGSERIAL -- UNIQUE
|
||||
(recoup_refresh_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
|
||||
,known_coin_id INT8 NOT NULL -- REFERENCES known_coins (known_coin_id)
|
||||
,coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64)
|
||||
,coin_blind BYTEA NOT NULL CHECK(LENGTH(coin_blind)=32)
|
||||
@ -698,7 +695,7 @@ CREATE INDEX IF NOT EXISTS recoup_refresh_by_known_coin_id_index
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS prewire
|
||||
(prewire_uuid BIGSERIAL PRIMARY KEY
|
||||
(prewire_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
|
||||
,wire_method TEXT NOT NULL
|
||||
,finished BOOLEAN NOT NULL DEFAULT false
|
||||
,failed BOOLEAN NOT NULL DEFAULT false
|
||||
@ -746,12 +743,29 @@ COMMENT ON COLUMN wire_accounts.is_active
|
||||
IS 'true if we are currently supporting the use of this account.';
|
||||
COMMENT ON COLUMN wire_accounts.last_change
|
||||
IS 'Latest time when active status changed. Used to detect replays of old messages.';
|
||||
-- "wire_accounts" has no BIGSERIAL because it is a 'mutable' table
|
||||
-- "wire_accounts" has no sequence because it is a 'mutable' table
|
||||
-- and is of no concern to the auditor
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS cs_nonce_locks
|
||||
(cs_nonce_lock_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE
|
||||
,nonce BYTEA PRIMARY KEY CHECK (LENGTH(nonce)=32)
|
||||
,op_hash BYTEA NOT NULL CHECK (LENGTH(op_hash)=64)
|
||||
,max_denomination_serial INT8 NOT NULL
|
||||
)
|
||||
PARTITION BY HASH (nonce);
|
||||
COMMENT ON TABLE cs_nonce_locks
|
||||
IS 'ensures a Clause Schnorr client nonce is locked for use with an operation identified by a hash';
|
||||
COMMENT ON COLUMN cs_nonce_locks.nonce
|
||||
IS 'actual nonce submitted by the client';
|
||||
COMMENT ON COLUMN cs_nonce_locks.op_hash
|
||||
IS 'hash (RC for refresh, blind coin hash for withdraw) the nonce may be used with';
|
||||
COMMENT ON COLUMN cs_nonce_locks.max_denomination_serial
|
||||
IS 'Maximum number of a CS denomination serial the nonce could be used with, for GC';
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS work_shards
|
||||
(shard_serial_id BIGSERIAL UNIQUE
|
||||
(shard_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
|
||||
,last_attempt INT8 NOT NULL
|
||||
,start_row INT8 NOT NULL
|
||||
,end_row INT8 NOT NULL
|
||||
@ -783,7 +797,7 @@ CREATE INDEX IF NOT EXISTS work_shards_by_job_name_completed_last_attempt_index
|
||||
|
||||
|
||||
CREATE UNLOGGED TABLE IF NOT EXISTS revolving_work_shards
|
||||
(shard_serial_id BIGSERIAL UNIQUE
|
||||
(shard_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
|
||||
,last_attempt INT8 NOT NULL
|
||||
,start_row INT4 NOT NULL
|
||||
,end_row INT4 NOT NULL
|
||||
@ -818,7 +832,7 @@ CREATE INDEX IF NOT EXISTS revolving_work_shards_by_job_name_active_last_attempt
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION exchange_do_withdraw(
|
||||
IN in_wih BYTEA,
|
||||
IN cs_nonce BYTEA,
|
||||
IN amount_val INT8,
|
||||
IN amount_frac INT4,
|
||||
IN h_denom_pub BYTEA,
|
||||
@ -832,8 +846,7 @@ CREATE OR REPLACE FUNCTION exchange_do_withdraw(
|
||||
OUT balance_ok BOOLEAN,
|
||||
OUT kycok BOOLEAN,
|
||||
OUT account_uuid INT8,
|
||||
OUT ruuid INT8,
|
||||
OUT out_denom_sig BYTEA)
|
||||
OUT ruuid INT8)
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
@ -851,7 +864,8 @@ BEGIN
|
||||
-- reserves_in by reserve_pub (SELECT)
|
||||
-- wire_targets by wire_target_serial_id
|
||||
|
||||
SELECT denominations_serial INTO denom_serial
|
||||
SELECT denominations_serial
|
||||
INTO denom_serial
|
||||
FROM denominations
|
||||
WHERE denom_pub_hash=h_denom_pub;
|
||||
|
||||
@ -867,6 +881,7 @@ THEN
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
|
||||
SELECT
|
||||
current_balance_val
|
||||
,current_balance_frac
|
||||
@ -887,7 +902,7 @@ THEN
|
||||
balance_ok=FALSE;
|
||||
kycok=FALSE;
|
||||
account_uuid=0;
|
||||
ruuid=0;
|
||||
ruuid=2;
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
@ -895,7 +910,6 @@ END IF;
|
||||
-- the query successful due to idempotency.
|
||||
INSERT INTO reserves_out
|
||||
(h_blind_ev
|
||||
,wih
|
||||
,denominations_serial
|
||||
,denom_sig
|
||||
,reserve_uuid
|
||||
@ -905,7 +919,6 @@ INSERT INTO reserves_out
|
||||
,amount_with_fee_frac)
|
||||
VALUES
|
||||
(h_coin_envelope
|
||||
,in_wih
|
||||
,denom_serial
|
||||
,denom_sig
|
||||
,ruuid
|
||||
@ -918,25 +931,6 @@ ON CONFLICT DO NOTHING;
|
||||
IF NOT FOUND
|
||||
THEN
|
||||
-- idempotent query, all constraints must be satisfied
|
||||
|
||||
SELECT
|
||||
denom_sig
|
||||
INTO
|
||||
out_denom_sig
|
||||
FROM reserves_in
|
||||
WHERE wih=in_wih
|
||||
LIMIT 1; -- limit 1 should not be required (without p2p transfers)
|
||||
|
||||
IF NOT FOUND
|
||||
THEN
|
||||
reserve_found=FALSE;
|
||||
balance_ok=FALSE;
|
||||
kycok=FALSE;
|
||||
account_uuid=0;
|
||||
ruuid=0;
|
||||
ASSERT false, 'internal logic error';
|
||||
END IF;
|
||||
|
||||
reserve_found=TRUE;
|
||||
balance_ok=TRUE;
|
||||
kycok=TRUE;
|
||||
@ -983,6 +977,44 @@ WHERE
|
||||
reserve_found=TRUE;
|
||||
balance_ok=TRUE;
|
||||
|
||||
|
||||
|
||||
-- Special actions needed for a CS withdraw?
|
||||
IF NOT NULL cs_nonce
|
||||
THEN
|
||||
-- Cache CS signature to prevent replays in the future
|
||||
-- (and check if cached signature exists at the same time).
|
||||
INSERT INTO cs_nonce_locks
|
||||
(nonce
|
||||
,max_denomination_serial
|
||||
,op_hash)
|
||||
VALUES
|
||||
(cs_nonce
|
||||
,denom_serial
|
||||
,h_coin_envelope)
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
IF NOT FOUND
|
||||
THEN
|
||||
-- See if the existing entry is identical.
|
||||
SELECT 1
|
||||
FROM cs_nonce_locks
|
||||
WHERE nonce=cs_nonce
|
||||
AND op_hash=h_coin_envelope;
|
||||
IF NOT FOUND
|
||||
THEN
|
||||
reserve_found=FALSE;
|
||||
balance_ok=FALSE;
|
||||
kycok=FALSE;
|
||||
account_uuid=0;
|
||||
ruuid=1; -- FIXME: return error message more nicely!
|
||||
ASSERT false, 'nonce reuse attempted by client';
|
||||
END IF;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
|
||||
|
||||
-- Obtain KYC status based on the last wire transfer into
|
||||
-- this reserve. FIXME: likely not adequate for reserves that got P2P transfers!
|
||||
SELECT
|
||||
@ -996,9 +1028,6 @@ SELECT
|
||||
WHERE reserve_pub=rpub
|
||||
LIMIT 1; -- limit 1 should not be required (without p2p transfers)
|
||||
|
||||
-- Return denomination signature as result that
|
||||
-- was given as the argument.
|
||||
out_denom_sig=denom_sig;
|
||||
|
||||
END $$;
|
||||
|
||||
@ -1223,6 +1252,7 @@ END $$;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION exchange_do_melt(
|
||||
IN in_cs_rms BYTEA,
|
||||
IN in_amount_with_fee_val INT8,
|
||||
IN in_amount_with_fee_frac INT4,
|
||||
IN in_rc BYTEA,
|
||||
@ -1236,6 +1266,8 @@ CREATE OR REPLACE FUNCTION exchange_do_melt(
|
||||
OUT out_noreveal_index INT4)
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
denom_max INT8;
|
||||
BEGIN
|
||||
-- Shards: INSERT refresh_commitments (by rc)
|
||||
-- (rare:) SELECT refresh_commitments (by old_coin_pub) -- crosses shards!
|
||||
@ -1333,6 +1365,56 @@ THEN
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
|
||||
|
||||
-- Special actions needed for a CS melt?
|
||||
IF NOT NULL in_cs_rms
|
||||
THEN
|
||||
-- Get maximum denominations serial value in
|
||||
-- existence, this will determine how long the
|
||||
-- nonce will be locked.
|
||||
SELECT
|
||||
denominations_serial
|
||||
INTO
|
||||
denom_max
|
||||
FROM denominations
|
||||
ORDER BY denominations_serial DESC
|
||||
LIMIT 1;
|
||||
|
||||
-- Cache CS signature to prevent replays in the future
|
||||
-- (and check if cached signature exists at the same time).
|
||||
INSERT INTO cs_nonce_locks
|
||||
(nonce
|
||||
,max_denomination_serial
|
||||
,op_hash)
|
||||
VALUES
|
||||
(cs_rms
|
||||
,denom_serial
|
||||
,in_rc)
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
IF NOT FOUND
|
||||
THEN
|
||||
-- Record exists, make sure it is the same
|
||||
SELECT 1
|
||||
FROM cs_nonce_locks
|
||||
WHERE nonce=cs_rms
|
||||
AND op_hash=in_rc;
|
||||
|
||||
IF NOT FOUND
|
||||
THEN
|
||||
-- Nonce reuse detected
|
||||
out_balance_ok=FALSE;
|
||||
out_zombie_bad=FALSE;
|
||||
out_noreveal_index=42; -- FIXME: return error message more nicely!
|
||||
ASSERT false, 'nonce reuse attempted by client';
|
||||
END IF;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
|
||||
|
||||
|
||||
-- Everything fine, return success!
|
||||
out_balance_ok=TRUE;
|
||||
out_noreveal_index=in_noreveal_index;
|
||||
@ -1806,6 +1888,8 @@ DECLARE
|
||||
deposit_min INT8; -- minimum deposit still alive
|
||||
DECLARE
|
||||
reserve_out_min INT8; -- minimum reserve_out still alive
|
||||
DECLARE
|
||||
denom_min INT8; -- minimum denomination still alive
|
||||
BEGIN
|
||||
|
||||
DELETE FROM prewire
|
||||
@ -1901,6 +1985,16 @@ DELETE FROM refunds
|
||||
DELETE FROM aggregation_tracking
|
||||
WHERE deposit_serial_id < deposit_min;
|
||||
|
||||
SELECT
|
||||
denominations_serial
|
||||
INTO
|
||||
denom_min
|
||||
FROM denominations
|
||||
ORDER BY denominations_serial ASC
|
||||
LIMIT 1;
|
||||
|
||||
DELETE FROM cs_nonce_locks
|
||||
WHERE max_denomination_serial <= denom_min;
|
||||
|
||||
END $$;
|
||||
|
||||
|
@ -53,13 +53,13 @@ irbt_cb_table_denominations (struct PostgresClosure *pg,
|
||||
&td->details.denominations.expire_legal),
|
||||
TALER_PQ_query_param_amount (&td->details.denominations.coin),
|
||||
TALER_PQ_query_param_amount (
|
||||
&td->details.denominations.fee_withdraw),
|
||||
&td->details.denominations.fees.withdraw),
|
||||
TALER_PQ_query_param_amount (
|
||||
&td->details.denominations.fee_deposit),
|
||||
&td->details.denominations.fees.deposit),
|
||||
TALER_PQ_query_param_amount (
|
||||
&td->details.denominations.fee_refresh),
|
||||
&td->details.denominations.fees.refresh),
|
||||
TALER_PQ_query_param_amount (
|
||||
&td->details.denominations.fee_refund),
|
||||
&td->details.denominations.fees.refund),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
|
||||
|
@ -80,16 +80,16 @@ lrbt_cb_table_denominations (void *cls,
|
||||
&td.details.denominations.coin),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT (
|
||||
"fee_withdraw",
|
||||
&td.details.denominations.fee_withdraw),
|
||||
&td.details.denominations.fees.withdraw),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT (
|
||||
"fee_deposit",
|
||||
&td.details.denominations.fee_deposit),
|
||||
&td.details.denominations.fees.deposit),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT (
|
||||
"fee_refresh",
|
||||
&td.details.denominations.fee_refresh),
|
||||
&td.details.denominations.fees.refresh),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT (
|
||||
"fee_refund",
|
||||
&td.details.denominations.fee_refund),
|
||||
&td.details.denominations.fees.refund),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014--2021 Taler Systems SA
|
||||
Copyright (C) 2014--2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -579,7 +579,6 @@ prepare_statements (struct PostgresClosure *pg)
|
||||
",kycok AS kyc_ok"
|
||||
",account_uuid AS payment_target_uuid"
|
||||
",ruuid"
|
||||
",out_denom_sig"
|
||||
" FROM exchange_do_withdraw"
|
||||
" ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);",
|
||||
10),
|
||||
@ -612,8 +611,8 @@ prepare_statements (struct PostgresClosure *pg)
|
||||
",out_zombie_bad AS zombie_required"
|
||||
",out_noreveal_index AS noreveal_index"
|
||||
" FROM exchange_do_melt"
|
||||
" ($1,$2,$3,$4,$5,$6,$7,$8);",
|
||||
8),
|
||||
" ($1,$2,$3,$4,$5,$6,$7,$8,$9);",
|
||||
9),
|
||||
/* Used in #postgres_do_refund() to refund a deposit. */
|
||||
GNUNET_PQ_make_prepare (
|
||||
"call_refund",
|
||||
@ -667,7 +666,7 @@ prepare_statements (struct PostgresClosure *pg)
|
||||
" USING (reserve_uuid)"
|
||||
" JOIN denominations denom"
|
||||
" USING (denominations_serial)"
|
||||
" WHERE wih=$1;",
|
||||
" WHERE h_blind_ev=$1;",
|
||||
1),
|
||||
/* Used during #postgres_get_reserve_history() to
|
||||
obtain all of the /reserve/withdraw operations that
|
||||
@ -1672,16 +1671,16 @@ prepare_statements (struct PostgresClosure *pg)
|
||||
" ON (denoms.denominations_serial = coins.denominations_serial)"
|
||||
" WHERE coins.coin_pub=$1;",
|
||||
1),
|
||||
/* Used in #postgres_get_reserve_by_wih() */
|
||||
/* Used in #postgres_get_reserve_by_h_blind() */
|
||||
GNUNET_PQ_make_prepare (
|
||||
"reserve_by_wih",
|
||||
"reserve_by_h_blind",
|
||||
"SELECT"
|
||||
" reserves.reserve_pub"
|
||||
",reserve_out_serial_id"
|
||||
" FROM reserves_out"
|
||||
" JOIN reserves"
|
||||
" USING (reserve_uuid)"
|
||||
" WHERE wih=$1"
|
||||
" WHERE h_blind_ev=$1"
|
||||
" LIMIT 1;",
|
||||
1),
|
||||
/* Used in #postgres_get_old_coin_by_h_blind() */
|
||||
@ -3091,6 +3090,7 @@ postgres_insert_denomination_info (
|
||||
const struct TALER_EXCHANGEDB_DenominationKeyInformationP *issue)
|
||||
{
|
||||
struct PostgresClosure *pg = cls;
|
||||
uint32_t age_mask = 0; /* FIXME-OEC */
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_auto_from_type (&issue->properties.denom_hash),
|
||||
TALER_PQ_query_param_denom_pub (denom_pub),
|
||||
@ -3100,13 +3100,14 @@ postgres_insert_denomination_info (
|
||||
GNUNET_PQ_query_param_timestamp_nbo (&issue->properties.expire_deposit),
|
||||
GNUNET_PQ_query_param_timestamp_nbo (&issue->properties.expire_legal),
|
||||
TALER_PQ_query_param_amount_nbo (&issue->properties.value),
|
||||
TALER_PQ_query_param_amount_nbo (&issue->properties.fee_withdraw),
|
||||
TALER_PQ_query_param_amount_nbo (&issue->properties.fee_deposit),
|
||||
TALER_PQ_query_param_amount_nbo (&issue->properties.fee_refresh),
|
||||
TALER_PQ_query_param_amount_nbo (&issue->properties.fee_refund),
|
||||
GNUNET_PQ_query_param_uint32 (&denom_pub->age_mask.mask),
|
||||
TALER_PQ_query_param_amount_nbo (&issue->properties.fees.withdraw),
|
||||
TALER_PQ_query_param_amount_nbo (&issue->properties.fees.deposit),
|
||||
TALER_PQ_query_param_amount_nbo (&issue->properties.fees.refresh),
|
||||
TALER_PQ_query_param_amount_nbo (&issue->properties.fees.refund),
|
||||
GNUNET_PQ_query_param_uint32 (&age_mask),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
struct TALER_DenomFeeSet fees;
|
||||
|
||||
GNUNET_assert (denom_pub->age_mask.mask == issue->age_mask.mask);
|
||||
|
||||
@ -3122,20 +3123,13 @@ postgres_insert_denomination_info (
|
||||
GNUNET_assert (! GNUNET_TIME_absolute_is_zero (
|
||||
GNUNET_TIME_timestamp_ntoh (
|
||||
issue->properties.expire_legal).abs_time));
|
||||
/* check fees match coin currency */
|
||||
/* check fees match denomination currency */
|
||||
TALER_denom_fee_set_ntoh (&fees,
|
||||
&issue->properties.fees);
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
TALER_amount_cmp_currency_nbo (&issue->properties.value,
|
||||
&issue->properties.fee_withdraw));
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
TALER_amount_cmp_currency_nbo (&issue->properties.value,
|
||||
&issue->properties.fee_deposit));
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
TALER_amount_cmp_currency_nbo (&issue->properties.value,
|
||||
&issue->properties.fee_refresh));
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
TALER_amount_cmp_currency_nbo (&issue->properties.value,
|
||||
&issue->properties.fee_refund));
|
||||
|
||||
TALER_denom_fee_check_currency (
|
||||
issue->properties.value.currency,
|
||||
&fees));
|
||||
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
|
||||
"denomination_insert",
|
||||
params);
|
||||
@ -3176,13 +3170,13 @@ postgres_get_denomination_info (
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("coin",
|
||||
&issue->properties.value),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_withdraw",
|
||||
&issue->properties.fee_withdraw),
|
||||
&issue->properties.fees.withdraw),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_deposit",
|
||||
&issue->properties.fee_deposit),
|
||||
&issue->properties.fees.deposit),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refresh",
|
||||
&issue->properties.fee_refresh),
|
||||
&issue->properties.fees.refresh),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refund",
|
||||
&issue->properties.fee_refund),
|
||||
&issue->properties.fees.refund),
|
||||
GNUNET_PQ_result_spec_uint32 ("age_mask",
|
||||
&issue->age_mask.mask),
|
||||
GNUNET_PQ_result_spec_end
|
||||
@ -3262,13 +3256,13 @@ domination_cb_helper (void *cls,
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("coin",
|
||||
&issue.properties.value),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_withdraw",
|
||||
&issue.properties.fee_withdraw),
|
||||
&issue.properties.fees.withdraw),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_deposit",
|
||||
&issue.properties.fee_deposit),
|
||||
&issue.properties.fees.deposit),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refresh",
|
||||
&issue.properties.fee_refresh),
|
||||
&issue.properties.fees.refresh),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refund",
|
||||
&issue.properties.fee_refund),
|
||||
&issue.properties.fees.refund),
|
||||
TALER_PQ_result_spec_denom_pub ("denom_pub",
|
||||
&denom_pub),
|
||||
GNUNET_PQ_result_spec_uint32 ("age_mask",
|
||||
@ -3401,13 +3395,13 @@ dominations_cb_helper (void *cls,
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
|
||||
&meta.value),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
|
||||
&meta.fee_withdraw),
|
||||
&meta.fees.withdraw),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
|
||||
&meta.fee_deposit),
|
||||
&meta.fees.deposit),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
|
||||
&meta.fee_refresh),
|
||||
&meta.fees.refresh),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
|
||||
&meta.fee_refund),
|
||||
&meta.fees.refund),
|
||||
TALER_PQ_result_spec_denom_pub ("denom_pub",
|
||||
&denom_pub),
|
||||
GNUNET_PQ_result_spec_uint32 ("age_mask",
|
||||
@ -4328,7 +4322,7 @@ postgres_reserves_in_insert (void *cls,
|
||||
* key of the hash of the blinded message.
|
||||
*
|
||||
* @param cls the `struct PostgresClosure` with the plugin-specific state
|
||||
* @param wih hash that uniquely identifies the withdraw operation
|
||||
* @param bch hash that uniquely identifies the withdraw operation
|
||||
* @param collectable corresponding collectable coin (blind signature)
|
||||
* if a coin is found
|
||||
* @return statement execution status
|
||||
@ -4336,12 +4330,12 @@ postgres_reserves_in_insert (void *cls,
|
||||
static enum GNUNET_DB_QueryStatus
|
||||
postgres_get_withdraw_info (
|
||||
void *cls,
|
||||
const struct TALER_WithdrawIdentificationHash *wih,
|
||||
const struct TALER_BlindedCoinHash *bch,
|
||||
struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable)
|
||||
{
|
||||
struct PostgresClosure *pg = cls;
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_auto_from_type (wih),
|
||||
GNUNET_PQ_query_param_auto_from_type (bch),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
@ -4374,7 +4368,7 @@ postgres_get_withdraw_info (
|
||||
* and possibly persisting the withdrawal details.
|
||||
*
|
||||
* @param cls the `struct PostgresClosure` with the plugin-specific state
|
||||
* @param wih hash that uniquely identifies the withdraw operation
|
||||
* @param nonce client-contributed input for CS denominations that must be checked for idempotency, or NULL for non-CS withdrawals
|
||||
* @param[in,out] collectable corresponding collectable coin (blind signature) if a coin is found; possibly updated if a (different) signature exists already
|
||||
* @param now current time (rounded)
|
||||
* @param[out] found set to true if the reserve was found
|
||||
@ -4386,8 +4380,8 @@ postgres_get_withdraw_info (
|
||||
static enum GNUNET_DB_QueryStatus
|
||||
postgres_do_withdraw (
|
||||
void *cls,
|
||||
const struct TALER_WithdrawIdentificationHash *wih,
|
||||
struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable,
|
||||
const struct TALER_CsNonce *nonce,
|
||||
const struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable,
|
||||
struct GNUNET_TIME_Timestamp now,
|
||||
bool *found,
|
||||
bool *balance_ok,
|
||||
@ -4397,7 +4391,9 @@ postgres_do_withdraw (
|
||||
struct PostgresClosure *pg = cls;
|
||||
struct GNUNET_TIME_Timestamp gc;
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_auto_from_type (wih),
|
||||
NULL == nonce
|
||||
? GNUNET_PQ_query_param_null ()
|
||||
: GNUNET_PQ_query_param_auto_from_type (nonce),
|
||||
TALER_PQ_query_param_amount (&collectable->amount_with_fee),
|
||||
GNUNET_PQ_query_param_auto_from_type (&collectable->denom_pub_hash),
|
||||
GNUNET_PQ_query_param_auto_from_type (&collectable->reserve_pub),
|
||||
@ -4408,9 +4404,6 @@ postgres_do_withdraw (
|
||||
GNUNET_PQ_query_param_timestamp (&gc),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
bool no_out_sig;
|
||||
struct TALER_BlindedDenominationSignature out_sig;
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
GNUNET_PQ_result_spec_bool ("reserve_found",
|
||||
found),
|
||||
@ -4422,33 +4415,17 @@ postgres_do_withdraw (
|
||||
&kyc->payment_target_uuid),
|
||||
GNUNET_PQ_result_spec_uint64 ("ruuid",
|
||||
ruuid),
|
||||
GNUNET_PQ_result_spec_allow_null (
|
||||
TALER_PQ_result_spec_blinded_denom_sig ("out_denom_sig",
|
||||
&out_sig),
|
||||
&no_out_sig),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
|
||||
#if 0
|
||||
memset (&out_sig,
|
||||
0,
|
||||
sizeof (out_sig));
|
||||
#endif
|
||||
gc = GNUNET_TIME_absolute_to_timestamp (
|
||||
GNUNET_TIME_absolute_add (now.abs_time,
|
||||
pg->legal_reserve_expiration_time));
|
||||
kyc->type = TALER_EXCHANGEDB_KYC_WITHDRAW;
|
||||
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
|
||||
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
|
||||
"call_withdraw",
|
||||
params,
|
||||
rs);
|
||||
if ( (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) &&
|
||||
(! no_out_sig) )
|
||||
{
|
||||
TALER_blinded_denom_sig_free (&collectable->sig);
|
||||
collectable->sig = out_sig;
|
||||
}
|
||||
return qs;
|
||||
}
|
||||
|
||||
|
||||
@ -4600,6 +4577,7 @@ postgres_do_deposit (
|
||||
static enum GNUNET_DB_QueryStatus
|
||||
postgres_do_melt (
|
||||
void *cls,
|
||||
const struct TALER_RefreshMasterSecretP *rms,
|
||||
struct TALER_EXCHANGEDB_Refresh *refresh,
|
||||
uint64_t known_coin_id,
|
||||
bool *zombie_required,
|
||||
@ -4607,6 +4585,9 @@ postgres_do_melt (
|
||||
{
|
||||
struct PostgresClosure *pg = cls;
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
NULL == rms
|
||||
? GNUNET_PQ_query_param_null ()
|
||||
: GNUNET_PQ_query_param_auto_from_type (rms),
|
||||
TALER_PQ_query_param_amount (&refresh->amount_with_fee),
|
||||
GNUNET_PQ_query_param_auto_from_type (&refresh->rc),
|
||||
GNUNET_PQ_query_param_auto_from_type (&refresh->coin.coin_pub),
|
||||
@ -9428,21 +9409,21 @@ postgres_select_reserve_closed_above_serial_id (
|
||||
* from given the hash of the blinded coin.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param wih hash that uniquely identifies the withdraw request
|
||||
* @param bch hash that uniquely identifies the withdraw request
|
||||
* @param[out] reserve_pub set to information about the reserve (on success only)
|
||||
* @param[out] reserve_out_serial_id set to row of the @a h_blind_ev in reserves_out
|
||||
* @return transaction status code
|
||||
*/
|
||||
static enum GNUNET_DB_QueryStatus
|
||||
postgres_get_reserve_by_wih (
|
||||
postgres_get_reserve_by_h_blind (
|
||||
void *cls,
|
||||
const struct TALER_WithdrawIdentificationHash *wih,
|
||||
const struct TALER_BlindedCoinHash *bch,
|
||||
struct TALER_ReservePublicKeyP *reserve_pub,
|
||||
uint64_t *reserve_out_serial_id)
|
||||
{
|
||||
struct PostgresClosure *pg = cls;
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_auto_from_type (wih),
|
||||
GNUNET_PQ_query_param_auto_from_type (bch),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
@ -9454,7 +9435,7 @@ postgres_get_reserve_by_wih (
|
||||
};
|
||||
|
||||
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
|
||||
"reserve_by_wih",
|
||||
"reserve_by_h_blind",
|
||||
params,
|
||||
rs);
|
||||
}
|
||||
@ -10241,13 +10222,13 @@ postgres_lookup_denomination_key (
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
|
||||
&meta->value),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
|
||||
&meta->fee_withdraw),
|
||||
&meta->fees.withdraw),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
|
||||
&meta->fee_deposit),
|
||||
&meta->fees.deposit),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
|
||||
&meta->fee_refresh),
|
||||
&meta->fees.refresh),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
|
||||
&meta->fee_refund),
|
||||
&meta->fees.refund),
|
||||
GNUNET_PQ_result_spec_uint32 ("age_mask",
|
||||
&meta->age_mask.mask),
|
||||
GNUNET_PQ_result_spec_end
|
||||
@ -10289,27 +10270,18 @@ postgres_add_denomination_key (
|
||||
GNUNET_PQ_query_param_timestamp (&meta->expire_deposit),
|
||||
GNUNET_PQ_query_param_timestamp (&meta->expire_legal),
|
||||
TALER_PQ_query_param_amount (&meta->value),
|
||||
TALER_PQ_query_param_amount (&meta->fee_withdraw),
|
||||
TALER_PQ_query_param_amount (&meta->fee_deposit),
|
||||
TALER_PQ_query_param_amount (&meta->fee_refresh),
|
||||
TALER_PQ_query_param_amount (&meta->fee_refund),
|
||||
TALER_PQ_query_param_amount (&meta->fees.withdraw),
|
||||
TALER_PQ_query_param_amount (&meta->fees.deposit),
|
||||
TALER_PQ_query_param_amount (&meta->fees.refresh),
|
||||
TALER_PQ_query_param_amount (&meta->fees.refund),
|
||||
GNUNET_PQ_query_param_uint32 (&meta->age_mask.mask),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
|
||||
/* Sanity check: ensure fees match coin currency */
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
TALER_amount_cmp_currency (&meta->value,
|
||||
&meta->fee_withdraw));
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
TALER_amount_cmp_currency (&meta->value,
|
||||
&meta->fee_deposit));
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
TALER_amount_cmp_currency (&meta->value,
|
||||
&meta->fee_refresh));
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
TALER_amount_cmp_currency (&meta->value,
|
||||
&meta->fee_refund));
|
||||
TALER_denom_fee_check_currency (meta->value.currency,
|
||||
&meta->fees));
|
||||
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
|
||||
"denomination_insert",
|
||||
iparams);
|
||||
@ -11722,8 +11694,8 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
|
||||
= &postgres_select_recoup_refresh_above_serial_id;
|
||||
plugin->select_reserve_closed_above_serial_id
|
||||
= &postgres_select_reserve_closed_above_serial_id;
|
||||
plugin->get_reserve_by_wih
|
||||
= &postgres_get_reserve_by_wih;
|
||||
plugin->get_reserve_by_h_blind
|
||||
= &postgres_get_reserve_by_h_blind;
|
||||
plugin->get_old_coin_by_h_blind
|
||||
= &postgres_get_old_coin_by_h_blind;
|
||||
plugin->insert_denomination_revocation
|
||||
|
@ -263,20 +263,14 @@ destroy_denom_key_pair (struct DenomKeyPair *dkp)
|
||||
*
|
||||
* @param size the size of the denomination key
|
||||
* @param now time to use for key generation, legal expiration will be 3h later.
|
||||
* @param fee_withdraw withdraw fee to use
|
||||
* @param fee_deposit deposit fee to use
|
||||
* @param fee_refresh refresh fee to use
|
||||
* @param fee_refund refund fee to use
|
||||
* @param fees fees to use
|
||||
* @return the denominaiton key pair; NULL upon error
|
||||
*/
|
||||
static struct DenomKeyPair *
|
||||
create_denom_key_pair (unsigned int size,
|
||||
struct GNUNET_TIME_Timestamp now,
|
||||
const struct TALER_Amount *value,
|
||||
const struct TALER_Amount *fee_withdraw,
|
||||
const struct TALER_Amount *fee_deposit,
|
||||
const struct TALER_Amount *fee_refresh,
|
||||
const struct TALER_Amount *fee_refund)
|
||||
const struct TALER_DenomFeeSet *fees)
|
||||
{
|
||||
struct DenomKeyPair *dkp;
|
||||
struct TALER_EXCHANGEDB_DenominationKey dki;
|
||||
@ -315,11 +309,10 @@ create_denom_key_pair (unsigned int size,
|
||||
(now.abs_time,
|
||||
GNUNET_TIME_relative_multiply (
|
||||
GNUNET_TIME_UNIT_HOURS, 3))));
|
||||
TALER_amount_hton (&dki.issue.properties.value, value);
|
||||
TALER_amount_hton (&dki.issue.properties.fee_withdraw, fee_withdraw);
|
||||
TALER_amount_hton (&dki.issue.properties.fee_deposit, fee_deposit);
|
||||
TALER_amount_hton (&dki.issue.properties.fee_refresh, fee_refresh);
|
||||
TALER_amount_hton (&dki.issue.properties.fee_refund, fee_refund);
|
||||
TALER_amount_hton (&dki.issue.properties.value,
|
||||
value);
|
||||
TALER_denom_fee_set_hton (&dki.issue.properties.fees,
|
||||
fees);
|
||||
TALER_denom_pub_hash (&dkp->pub,
|
||||
&dki.issue.properties.denom_hash);
|
||||
|
||||
@ -359,10 +352,7 @@ create_denom_key_pair (unsigned int size,
|
||||
|
||||
|
||||
static struct TALER_Amount value;
|
||||
static struct TALER_Amount fee_withdraw;
|
||||
static struct TALER_Amount fee_deposit;
|
||||
static struct TALER_Amount fee_refresh;
|
||||
static struct TALER_Amount fee_refund;
|
||||
static struct TALER_DenomFeeSet fees;
|
||||
static struct TALER_Amount fee_closing;
|
||||
static struct TALER_Amount amount_with_fee;
|
||||
|
||||
@ -881,10 +871,7 @@ test_gc (void)
|
||||
dkp = create_denom_key_pair (RSA_KEY_SIZE,
|
||||
past,
|
||||
&value,
|
||||
&fee_withdraw,
|
||||
&fee_deposit,
|
||||
&fee_refresh,
|
||||
&fee_refund);
|
||||
&fees);
|
||||
GNUNET_assert (NULL != dkp);
|
||||
if (GNUNET_OK !=
|
||||
plugin->gc (plugin->cls))
|
||||
@ -1080,7 +1067,7 @@ test_wire_out (const struct TALER_EXCHANGEDB_Deposit *deposit)
|
||||
coin_pub_wt = deposit->coin.coin_pub;
|
||||
|
||||
coin_value_wt = deposit->amount_with_fee;
|
||||
coin_fee_wt = fee_deposit;
|
||||
coin_fee_wt = fees.deposit;
|
||||
GNUNET_assert (0 <
|
||||
TALER_amount_subtract (&transfer_value_wt,
|
||||
&coin_value_wt,
|
||||
@ -1349,7 +1336,6 @@ run (void *cls)
|
||||
struct GNUNET_TIME_Timestamp now;
|
||||
struct TALER_WireSaltP salt;
|
||||
struct TALER_CoinPubHash c_hash;
|
||||
struct TALER_WithdrawIdentificationHash wih;
|
||||
uint64_t known_coin_id;
|
||||
uint64_t rrc_serial;
|
||||
struct TALER_EXCHANGEDB_Refresh refresh;
|
||||
@ -1410,17 +1396,17 @@ run (void *cls)
|
||||
&value));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":0.000010",
|
||||
&fee_withdraw));
|
||||
&fees.withdraw));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":0.000010",
|
||||
&fee_deposit));
|
||||
deposit.deposit_fee = fee_deposit;
|
||||
&fees.deposit));
|
||||
deposit.deposit_fee = fees.deposit;
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":0.000010",
|
||||
&fee_refresh));
|
||||
&fees.refresh));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":0.000010",
|
||||
&fee_refund));
|
||||
&fees.refund));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":1.000010",
|
||||
&amount_with_fee));
|
||||
@ -1464,10 +1450,7 @@ run (void *cls)
|
||||
dkp = create_denom_key_pair (RSA_KEY_SIZE,
|
||||
now,
|
||||
&value,
|
||||
&fee_withdraw,
|
||||
&fee_deposit,
|
||||
&fee_refresh,
|
||||
&fee_refund);
|
||||
&fees);
|
||||
GNUNET_assert (NULL != dkp);
|
||||
TALER_denom_pub_hash (&dkp->pub,
|
||||
&cbc.denom_pub_hash);
|
||||
@ -1502,10 +1485,7 @@ run (void *cls)
|
||||
TALER_coin_ev_hash (&pd.blinded_planchet,
|
||||
&cbc.denom_pub_hash,
|
||||
&cbc.h_coin_envelope));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_withdraw_request_hash (&pd.blinded_planchet,
|
||||
&cbc.denom_pub_hash,
|
||||
&wih)); GNUNET_assert (
|
||||
GNUNET_assert (
|
||||
GNUNET_OK ==
|
||||
TALER_denom_sign_blinded (
|
||||
&cbc.sig,
|
||||
@ -1529,7 +1509,7 @@ run (void *cls)
|
||||
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->do_withdraw (plugin->cls,
|
||||
&wih,
|
||||
NULL,
|
||||
&cbc,
|
||||
now,
|
||||
&found,
|
||||
@ -1551,8 +1531,8 @@ run (void *cls)
|
||||
value.fraction,
|
||||
value.currency));
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->get_reserve_by_wih (plugin->cls,
|
||||
&wih,
|
||||
plugin->get_reserve_by_h_blind (plugin->cls,
|
||||
&cbc.h_coin_envelope,
|
||||
&reserve_pub3,
|
||||
&reserve_out_serial_id));
|
||||
FAILIF (0 != GNUNET_memcmp (&reserve_pub,
|
||||
@ -1560,7 +1540,7 @@ run (void *cls)
|
||||
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->get_withdraw_info (plugin->cls,
|
||||
&wih,
|
||||
&cbc.h_coin_envelope,
|
||||
&cbc2));
|
||||
FAILIF (0 != GNUNET_memcmp (&cbc2.reserve_sig,
|
||||
&cbc.reserve_sig));
|
||||
@ -1649,12 +1629,12 @@ run (void *cls)
|
||||
refund.details.h_contract_terms = deposit.h_contract_terms;
|
||||
refund.details.rtransaction_id = 1;
|
||||
refund.details.refund_amount = value;
|
||||
refund.details.refund_fee = fee_refund;
|
||||
refund.details.refund_fee = fees.refund;
|
||||
RND_BLK (&refund.details.merchant_sig);
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->do_refund (plugin->cls,
|
||||
&refund,
|
||||
&fee_deposit,
|
||||
&fees.deposit,
|
||||
known_coin_id,
|
||||
¬_found,
|
||||
&refund_ok,
|
||||
@ -1686,6 +1666,7 @@ run (void *cls)
|
||||
refresh.noreveal_index = MELT_NOREVEAL_INDEX;
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->do_melt (plugin->cls,
|
||||
NULL,
|
||||
&refresh,
|
||||
known_coin_id,
|
||||
&zombie_required,
|
||||
@ -1709,7 +1690,7 @@ run (void *cls)
|
||||
TALER_amount_cmp (&refresh.amount_with_fee,
|
||||
&ret_refresh_session.session.amount_with_fee));
|
||||
FAILIF (0 !=
|
||||
TALER_amount_cmp (&fee_refresh,
|
||||
TALER_amount_cmp (&fees.refresh,
|
||||
&ret_refresh_session.melt_fee));
|
||||
FAILIF (0 !=
|
||||
GNUNET_memcmp (&refresh.rc,
|
||||
@ -1755,10 +1736,7 @@ run (void *cls)
|
||||
new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
|
||||
now,
|
||||
&value,
|
||||
&fee_withdraw,
|
||||
&fee_deposit,
|
||||
&fee_refresh,
|
||||
&fee_refund);
|
||||
&fees);
|
||||
GNUNET_assert (NULL != new_dkp[cnt]);
|
||||
new_denom_pubs[cnt] = new_dkp[cnt]->pub;
|
||||
ccoin = &revealed_coins[cnt];
|
||||
@ -2174,7 +2152,7 @@ run (void *cls)
|
||||
memset (&deposit,
|
||||
0,
|
||||
sizeof (deposit));
|
||||
deposit.deposit_fee = fee_deposit;
|
||||
deposit.deposit_fee = fees.deposit;
|
||||
RND_BLK (&deposit.coin.coin_pub);
|
||||
TALER_denom_pub_hash (&dkp->pub,
|
||||
&deposit.coin.denom_pub_hash);
|
||||
@ -2196,7 +2174,7 @@ run (void *cls)
|
||||
&deposit.wire_salt,
|
||||
&h_wire_wt);
|
||||
deposit.amount_with_fee = value;
|
||||
deposit.deposit_fee = fee_deposit;
|
||||
deposit.deposit_fee = fees.deposit;
|
||||
|
||||
deposit.refund_deadline = deadline;
|
||||
deposit.wire_deadline = deadline;
|
||||
|
@ -184,6 +184,18 @@ enum GNUNET_GenericReturnValue
|
||||
TALER_amount_is_valid (const struct TALER_Amount *amount);
|
||||
|
||||
|
||||
/**
|
||||
* Test if the given amount is in the given currency
|
||||
*
|
||||
* @param amount amount to check
|
||||
* @param currency currency to check for
|
||||
* @return #GNUNET_OK if @a amount is in @a currency
|
||||
*/
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_amount_is_currency (const struct TALER_Amount *amount,
|
||||
const char *currency);
|
||||
|
||||
|
||||
/**
|
||||
* Convert amount from host to network representation.
|
||||
*
|
||||
|
@ -563,22 +563,6 @@ struct TALER_BlindedCoinHash
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Hash used to uniquely represent a withdraw process so as to perform
|
||||
* idempotency checks (and prevent clients from harmfully replaying withdraw
|
||||
* operations with problematic variations on the inputs). In the CS case,
|
||||
* this is a hash over the DK and nonce, while in the RSA case, it is simply a
|
||||
* hash over the DK and the blinded coin.
|
||||
*/
|
||||
struct TALER_WithdrawIdentificationHash
|
||||
{
|
||||
/**
|
||||
* Actual hash value.
|
||||
*/
|
||||
struct GNUNET_HashCode hash;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Hash used to represent the hash of the public
|
||||
* key of a coin (without blinding).
|
||||
@ -629,9 +613,99 @@ struct TALER_ExtensionConfigHash
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set of the fees applying to a denomination.
|
||||
*/
|
||||
struct TALER_DenomFeeSetNBOP
|
||||
{
|
||||
|
||||
/**
|
||||
* The fee the exchange charges when a coin of this type is withdrawn.
|
||||
* (can be zero).
|
||||
*/
|
||||
struct TALER_AmountNBO withdraw;
|
||||
|
||||
/**
|
||||
* The fee the exchange charges when a coin of this type is deposited.
|
||||
* (can be zero).
|
||||
*/
|
||||
struct TALER_AmountNBO deposit;
|
||||
|
||||
/**
|
||||
* The fee the exchange charges when a coin of this type is refreshed.
|
||||
* (can be zero).
|
||||
*/
|
||||
struct TALER_AmountNBO refresh;
|
||||
|
||||
/**
|
||||
* The fee the exchange charges when a coin of this type is refunded.
|
||||
* (can be zero). Note that refund fees are charged to the customer;
|
||||
* if a refund is given, the deposit fee is also refunded.
|
||||
*/
|
||||
struct TALER_AmountNBO refund;
|
||||
|
||||
};
|
||||
|
||||
|
||||
GNUNET_NETWORK_STRUCT_END
|
||||
|
||||
|
||||
/**
|
||||
* Set of the fees applying to a denomination.
|
||||
*/
|
||||
struct TALER_DenomFeeSet
|
||||
{
|
||||
|
||||
/**
|
||||
* The fee the exchange charges when a coin of this type is withdrawn.
|
||||
* (can be zero).
|
||||
*/
|
||||
struct TALER_Amount withdraw;
|
||||
|
||||
/**
|
||||
* The fee the exchange charges when a coin of this type is deposited.
|
||||
* (can be zero).
|
||||
*/
|
||||
struct TALER_Amount deposit;
|
||||
|
||||
/**
|
||||
* The fee the exchange charges when a coin of this type is refreshed.
|
||||
* (can be zero).
|
||||
*/
|
||||
struct TALER_Amount refresh;
|
||||
|
||||
/**
|
||||
* The fee the exchange charges when a coin of this type is refunded.
|
||||
* (can be zero). Note that refund fees are charged to the customer;
|
||||
* if a refund is given, the deposit fee is also refunded.
|
||||
*/
|
||||
struct TALER_Amount refund;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Convert fee set from host to network byte order.
|
||||
*
|
||||
* @param[out] nbo where to write the result
|
||||
* @param fees fee set to convert
|
||||
*/
|
||||
void
|
||||
TALER_denom_fee_set_hton (struct TALER_DenomFeeSetNBOP *nbo,
|
||||
const struct TALER_DenomFeeSet *fees);
|
||||
|
||||
|
||||
/**
|
||||
* Convert fee set from network to host network byte order.
|
||||
*
|
||||
* @param[out] fees where to write the result
|
||||
* @param nbo fee set to convert
|
||||
*/
|
||||
void
|
||||
TALER_denom_fee_set_ntoh (struct TALER_DenomFeeSet *fees,
|
||||
const struct TALER_DenomFeeSetNBOP *nbo);
|
||||
|
||||
|
||||
/**
|
||||
* Hash @a rsa.
|
||||
*
|
||||
@ -1357,22 +1431,6 @@ TALER_coin_ev_hash (const struct TALER_BlindedPlanchet *blinded_planchet,
|
||||
struct TALER_BlindedCoinHash *bch);
|
||||
|
||||
|
||||
/**
|
||||
* Compute the hash to uniquely identify a withdraw
|
||||
* request.
|
||||
*
|
||||
* @param blinded_planchet blinded planchet
|
||||
* @param denom_hash hash of the denomination publick key
|
||||
* @param[out] wih where to write the hash
|
||||
* @return #GNUNET_OK when successful, #GNUNET_SYSERR if an internal error occured
|
||||
*/
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_withdraw_request_hash (
|
||||
const struct TALER_BlindedPlanchet *blinded_planchet,
|
||||
const struct TALER_DenominationHash *denom_hash,
|
||||
struct TALER_WithdrawIdentificationHash *wih);
|
||||
|
||||
|
||||
/**
|
||||
* Compute the hash of a coin.
|
||||
*
|
||||
@ -1548,16 +1606,19 @@ TALER_transfer_secret_to_planchet_secret (
|
||||
|
||||
/**
|
||||
* Derive the @a coin_num transfer private key @a tpriv from a refresh from
|
||||
* the @a rms seed of the refresh operation. The transfer private key
|
||||
* derivation is based on the @a ps with a KDF salted by the @a coin_num.
|
||||
* the @a rms seed and the @a old_coin_pub of the refresh operation. The
|
||||
* transfer private key derivation is based on the @a ps with a KDF salted by
|
||||
* the @a coin_num.
|
||||
*
|
||||
* @param rms seed to use for KDF to derive transfer keys
|
||||
* @param old_coin_priv private key of the old coin
|
||||
* @param cnc_num cut and choose number to include in KDF
|
||||
* @param[out] tpriv value to initialize
|
||||
*/
|
||||
void
|
||||
TALER_planchet_secret_to_transfer_priv (
|
||||
const struct TALER_RefreshMasterSecretP *rms,
|
||||
const struct TALER_CoinSpendPrivateKeyP *old_coin_priv,
|
||||
uint32_t cnc_num,
|
||||
struct TALER_TransferPrivateKeyP *tpriv);
|
||||
|
||||
@ -1675,7 +1736,7 @@ TALER_planchet_to_coin (
|
||||
* @param[in,out] hash_context hash context to use
|
||||
*/
|
||||
void
|
||||
TALER_blinded_planchet_hash (const struct TALER_BlindedPlanchet *bp,
|
||||
TALER_blinded_planchet_hash_ (const struct TALER_BlindedPlanchet *bp,
|
||||
struct GNUNET_HashContext *hash_context);
|
||||
|
||||
|
||||
@ -1769,6 +1830,7 @@ struct TALER_RefreshCommitmentEntry
|
||||
*
|
||||
* @param[out] rc set to the value the wallet must commit to
|
||||
* @param kappa number of transfer public keys involved (must be #TALER_CNC_KAPPA)
|
||||
* @param rms refresh master secret to include, can be NULL!
|
||||
* @param num_new_coins number of new coins to be created
|
||||
* @param rcs array of @a kappa commitments
|
||||
* @param coin_pub public key of the coin to be melted
|
||||
@ -1777,6 +1839,7 @@ struct TALER_RefreshCommitmentEntry
|
||||
void
|
||||
TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc,
|
||||
uint32_t kappa,
|
||||
const struct TALER_RefreshMasterSecretP *rms,
|
||||
uint32_t num_new_coins,
|
||||
const struct TALER_RefreshCommitmentEntry *rcs,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
@ -2723,10 +2786,7 @@ TALER_exchange_offline_signkey_validity_verify (
|
||||
* @param stamp_expire_deposit how long does the exchange accept the deposit of coins with this key
|
||||
* @param stamp_expire_legal how long does the exchange preserve information for legal disputes with this key
|
||||
* @param coin_value what is the value of coins signed with this key
|
||||
* @param fee_withdraw what withdraw fee does the exchange charge for this denomination
|
||||
* @param fee_deposit what deposit fee does the exchange charge for this denomination
|
||||
* @param fee_refresh what refresh fee does the exchange charge for this denomination
|
||||
* @param fee_refund what refund fee does the exchange charge for this denomination
|
||||
* @param fees fees for this denomination
|
||||
* @param master_priv private key to sign with
|
||||
* @param[out] master_sig where to write the signature
|
||||
*/
|
||||
@ -2738,10 +2798,7 @@ TALER_exchange_offline_denom_validity_sign (
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_deposit,
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_legal,
|
||||
const struct TALER_Amount *coin_value,
|
||||
const struct TALER_Amount *fee_withdraw,
|
||||
const struct TALER_Amount *fee_deposit,
|
||||
const struct TALER_Amount *fee_refresh,
|
||||
const struct TALER_Amount *fee_refund,
|
||||
const struct TALER_DenomFeeSet *fees,
|
||||
const struct TALER_MasterPrivateKeyP *master_priv,
|
||||
struct TALER_MasterSignatureP *master_sig);
|
||||
|
||||
@ -2755,10 +2812,7 @@ TALER_exchange_offline_denom_validity_sign (
|
||||
* @param stamp_expire_deposit how long does the exchange accept the deposit of coins with this key
|
||||
* @param stamp_expire_legal how long does the exchange preserve information for legal disputes with this key
|
||||
* @param coin_value what is the value of coins signed with this key
|
||||
* @param fee_withdraw what withdraw fee does the exchange charge for this denomination
|
||||
* @param fee_deposit what deposit fee does the exchange charge for this denomination
|
||||
* @param fee_refresh what refresh fee does the exchange charge for this denomination
|
||||
* @param fee_refund what refund fee does the exchange charge for this denomination
|
||||
* @param fees fees for this denomination
|
||||
* @param master_pub public key to verify against
|
||||
* @param master_sig the signature the signature
|
||||
* @return #GNUNET_OK if the signature is valid
|
||||
@ -2771,10 +2825,7 @@ TALER_exchange_offline_denom_validity_verify (
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_deposit,
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_legal,
|
||||
const struct TALER_Amount *coin_value,
|
||||
const struct TALER_Amount *fee_withdraw,
|
||||
const struct TALER_Amount *fee_deposit,
|
||||
const struct TALER_Amount *fee_refresh,
|
||||
const struct TALER_Amount *fee_refund,
|
||||
const struct TALER_DenomFeeSet *fees,
|
||||
const struct TALER_MasterPublicKeyP *master_pub,
|
||||
const struct TALER_MasterSignatureP *master_sig);
|
||||
|
||||
@ -2909,10 +2960,7 @@ TALER_exchange_secmod_cs_verify (
|
||||
* @param stamp_expire_deposit how long does the exchange accept the deposit of coins with this key
|
||||
* @param stamp_expire_legal how long does the exchange preserve information for legal disputes with this key
|
||||
* @param coin_value what is the value of coins signed with this key
|
||||
* @param fee_withdraw what withdraw fee does the exchange charge for this denomination
|
||||
* @param fee_deposit what deposit fee does the exchange charge for this denomination
|
||||
* @param fee_refresh what refresh fee does the exchange charge for this denomination
|
||||
* @param fee_refund what refund fee does the exchange charge for this denomination
|
||||
* @param fees fees the exchange charges for this denomination
|
||||
* @param auditor_priv private key to sign with
|
||||
* @param[out] auditor_sig where to write the signature
|
||||
*/
|
||||
@ -2926,10 +2974,7 @@ TALER_auditor_denom_validity_sign (
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_deposit,
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_legal,
|
||||
const struct TALER_Amount *coin_value,
|
||||
const struct TALER_Amount *fee_withdraw,
|
||||
const struct TALER_Amount *fee_deposit,
|
||||
const struct TALER_Amount *fee_refresh,
|
||||
const struct TALER_Amount *fee_refund,
|
||||
const struct TALER_DenomFeeSet *fees,
|
||||
const struct TALER_AuditorPrivateKeyP *auditor_priv,
|
||||
struct TALER_AuditorSignatureP *auditor_sig);
|
||||
|
||||
@ -2945,10 +2990,7 @@ TALER_auditor_denom_validity_sign (
|
||||
* @param stamp_expire_deposit how long does the exchange accept the deposit of coins with this key
|
||||
* @param stamp_expire_legal how long does the exchange preserve information for legal disputes with this key
|
||||
* @param coin_value what is the value of coins signed with this key
|
||||
* @param fee_withdraw what withdraw fee does the exchange charge for this denomination
|
||||
* @param fee_deposit what deposit fee does the exchange charge for this denomination
|
||||
* @param fee_refresh what refresh fee does the exchange charge for this denomination
|
||||
* @param fee_refund what refund fee does the exchange charge for this denomination
|
||||
* @param fees fees the exchange charges for this denomination
|
||||
* @param auditor_pub public key to verify against
|
||||
* @param auditor_sig the signature the signature
|
||||
* @return #GNUNET_OK if the signature is valid
|
||||
@ -2963,10 +3005,7 @@ TALER_auditor_denom_validity_verify (
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_deposit,
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_legal,
|
||||
const struct TALER_Amount *coin_value,
|
||||
const struct TALER_Amount *fee_withdraw,
|
||||
const struct TALER_Amount *fee_deposit,
|
||||
const struct TALER_Amount *fee_refresh,
|
||||
const struct TALER_Amount *fee_refund,
|
||||
const struct TALER_DenomFeeSet *fees,
|
||||
const struct TALER_AuditorPublicKeyP *auditor_pub,
|
||||
const struct TALER_AuditorSignatureP *auditor_sig);
|
||||
|
||||
|
@ -135,24 +135,9 @@ struct TALER_EXCHANGE_DenomPublicKey
|
||||
struct TALER_Amount value;
|
||||
|
||||
/**
|
||||
* The applicable fee for withdrawing a coin of this denomination
|
||||
* The applicable fees for this denomination
|
||||
*/
|
||||
struct TALER_Amount fee_withdraw;
|
||||
|
||||
/**
|
||||
* The applicable fee to spend a coin of this denomination
|
||||
*/
|
||||
struct TALER_Amount fee_deposit;
|
||||
|
||||
/**
|
||||
* The applicable fee to melt/refresh a coin of this denomination
|
||||
*/
|
||||
struct TALER_Amount fee_refresh;
|
||||
|
||||
/**
|
||||
* The applicable fee to refund a coin of this denomination
|
||||
*/
|
||||
struct TALER_Amount fee_refund;
|
||||
struct TALER_DenomFeeSet fees;
|
||||
|
||||
/**
|
||||
* Set to true if this denomination key has been
|
||||
@ -1031,19 +1016,19 @@ void
|
||||
TALER_EXCHANGE_refund_cancel (struct TALER_EXCHANGE_RefundHandle *refund);
|
||||
|
||||
|
||||
/* ********************* POST /csr *********************** */
|
||||
/* ********************* POST /csr-melt *********************** */
|
||||
|
||||
|
||||
/**
|
||||
* @brief A /csr Handle
|
||||
* @brief A /csr-melt Handle
|
||||
*/
|
||||
struct TALER_EXCHANGE_CsRHandle;
|
||||
struct TALER_EXCHANGE_CsRMeltHandle;
|
||||
|
||||
|
||||
/**
|
||||
* Details about a response for a CS R request.
|
||||
*/
|
||||
struct TALER_EXCHANGE_CsRResponse
|
||||
struct TALER_EXCHANGE_CsRMeltResponse
|
||||
{
|
||||
/**
|
||||
* HTTP response data.
|
||||
@ -1092,29 +1077,31 @@ struct TALER_EXCHANGE_CsRResponse
|
||||
* @param csrr response details
|
||||
*/
|
||||
typedef void
|
||||
(*TALER_EXCHANGE_CsRCallback) (void *cls,
|
||||
const struct TALER_EXCHANGE_CsRResponse *csrr);
|
||||
(*TALER_EXCHANGE_CsRMeltCallback) (
|
||||
void *cls,
|
||||
const struct TALER_EXCHANGE_CsRMeltResponse *csrr);
|
||||
|
||||
|
||||
/**
|
||||
* Information we pass per coin to a /csr request.
|
||||
* Information we pass per coin to a /csr-melt request.
|
||||
*/
|
||||
struct TALER_EXCHANGE_NonceKey
|
||||
{
|
||||
/**
|
||||
* Which denomination key is the /csr request for?
|
||||
* Which denomination key is the /csr-melt request for?
|
||||
*/
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *pk;
|
||||
|
||||
/**
|
||||
* What is the client nonce for the request?
|
||||
* What is number to derive the client nonce for the
|
||||
* fresh coin?
|
||||
*/
|
||||
struct TALER_CsNonce nonce;
|
||||
uint32_t cnc_num;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get a CS R using a /csr request.
|
||||
* Get a set of CS R values using a /csr-melt request.
|
||||
*
|
||||
* @param exchange the exchange handle; the exchange must be ready to operate
|
||||
* @param nks_len length of the @a nks array
|
||||
@ -1125,23 +1112,117 @@ struct TALER_EXCHANGE_NonceKey
|
||||
* if the inputs are invalid (i.e. denomination key not with this exchange).
|
||||
* In this case, the callback is not called.
|
||||
*/
|
||||
struct TALER_EXCHANGE_CsRHandle *
|
||||
TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange,
|
||||
struct TALER_EXCHANGE_CsRMeltHandle *
|
||||
TALER_EXCHANGE_csr_melt (struct TALER_EXCHANGE_Handle *exchange,
|
||||
const struct TALER_RefreshMasterSecretP *rms,
|
||||
unsigned int nks_len,
|
||||
struct TALER_EXCHANGE_NonceKey *nks,
|
||||
TALER_EXCHANGE_CsRCallback res_cb,
|
||||
TALER_EXCHANGE_CsRMeltCallback res_cb,
|
||||
void *res_cb_cls);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Cancel a CS R request. This function cannot be used
|
||||
* Cancel a CS R melt request. This function cannot be used
|
||||
* on a request handle if a response is already served for it.
|
||||
*
|
||||
* @param csrh the withdraw handle
|
||||
*/
|
||||
void
|
||||
TALER_EXCHANGE_csr_cancel (struct TALER_EXCHANGE_CsRHandle *csrh);
|
||||
TALER_EXCHANGE_csr_melt_cancel (struct TALER_EXCHANGE_CsRMeltHandle *csrh);
|
||||
|
||||
|
||||
/* ********************* POST /csr-withdraw *********************** */
|
||||
|
||||
|
||||
/**
|
||||
* @brief A /csr-withdraw Handle
|
||||
*/
|
||||
struct TALER_EXCHANGE_CsRWithdrawHandle;
|
||||
|
||||
|
||||
/**
|
||||
* Details about a response for a CS R request.
|
||||
*/
|
||||
struct TALER_EXCHANGE_CsRWithdrawResponse
|
||||
{
|
||||
/**
|
||||
* HTTP response data.
|
||||
*/
|
||||
struct TALER_EXCHANGE_HttpResponse hr;
|
||||
|
||||
/**
|
||||
* Details about the response.
|
||||
*/
|
||||
union
|
||||
{
|
||||
/**
|
||||
* Details if the status is #MHD_HTTP_OK.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
/**
|
||||
* Values contributed by the exchange for the
|
||||
* respective coin's withdraw operation.
|
||||
*/
|
||||
struct TALER_ExchangeWithdrawValues alg_values;
|
||||
} success;
|
||||
|
||||
/**
|
||||
* Details if the status is #MHD_HTTP_GONE.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
/* TODO: returning full details is not implemented */
|
||||
} gone;
|
||||
|
||||
} details;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Callbacks of this type are used to serve the result of submitting a
|
||||
* CS R withdraw request to a exchange.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param csrr response details
|
||||
*/
|
||||
typedef void
|
||||
(*TALER_EXCHANGE_CsRWithdrawCallback) (
|
||||
void *cls,
|
||||
const struct TALER_EXCHANGE_CsRWithdrawResponse *csrr);
|
||||
|
||||
|
||||
/**
|
||||
* Get a CS R using a /csr-withdraw request.
|
||||
*
|
||||
* @param exchange the exchange handle; the exchange must be ready to operate
|
||||
* @param dk Which denomination key is the /csr request for
|
||||
* @param nonce client nonce for the request
|
||||
* @param res_cb the callback to call when the final result for this request is available
|
||||
* @param res_cb_cls closure for the above callback
|
||||
* @return handle for the operation on success, NULL on error, i.e.
|
||||
* if the inputs are invalid (i.e. denomination key not with this exchange).
|
||||
* In this case, the callback is not called.
|
||||
*/
|
||||
struct TALER_EXCHANGE_CsRWithdrawHandle *
|
||||
TALER_EXCHANGE_csr_withdraw (struct TALER_EXCHANGE_Handle *exchange,
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *pk,
|
||||
const struct TALER_CsNonce *nonce,
|
||||
TALER_EXCHANGE_CsRWithdrawCallback res_cb,
|
||||
void *res_cb_cls);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Cancel a CS R withdraw request. This function cannot be used
|
||||
* on a request handle if a response is already served for it.
|
||||
*
|
||||
* @param csrh the withdraw handle
|
||||
*/
|
||||
void
|
||||
TALER_EXCHANGE_csr_withdraw_cancel (
|
||||
struct TALER_EXCHANGE_CsRWithdrawHandle *csrh);
|
||||
|
||||
|
||||
/* ********************* GET /reserves/$RESERVE_PUB *********************** */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2021 Taler Systems SA
|
||||
Copyright (C) 2014-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -208,10 +208,7 @@ struct TALER_EXCHANGEDB_TableData
|
||||
struct GNUNET_TIME_Timestamp expire_deposit;
|
||||
struct GNUNET_TIME_Timestamp expire_legal;
|
||||
struct TALER_Amount coin;
|
||||
struct TALER_Amount fee_withdraw;
|
||||
struct TALER_Amount fee_deposit;
|
||||
struct TALER_Amount fee_refresh;
|
||||
struct TALER_Amount fee_refund;
|
||||
struct TALER_DenomFeeSet fees;
|
||||
} denominations;
|
||||
|
||||
struct
|
||||
@ -612,29 +609,10 @@ struct TALER_EXCHANGEDB_DenominationKeyMetaData
|
||||
struct TALER_Amount value;
|
||||
|
||||
/**
|
||||
* The fee the exchange charges when a coin of this type is withdrawn.
|
||||
* (can be zero).
|
||||
* The fees the exchange charges for operations with
|
||||
* coins of this denomination.
|
||||
*/
|
||||
struct TALER_Amount fee_withdraw;
|
||||
|
||||
/**
|
||||
* The fee the exchange charges when a coin of this type is deposited.
|
||||
* (can be zero).
|
||||
*/
|
||||
struct TALER_Amount fee_deposit;
|
||||
|
||||
/**
|
||||
* The fee the exchange charges when a coin of this type is refreshed.
|
||||
* (can be zero).
|
||||
*/
|
||||
struct TALER_Amount fee_refresh;
|
||||
|
||||
/**
|
||||
* The fee the exchange charges when a coin of this type is refunded.
|
||||
* (can be zero). Note that refund fees are charged to the customer;
|
||||
* if a refund is given, the deposit fee is also refunded.
|
||||
*/
|
||||
struct TALER_Amount fee_refund;
|
||||
struct TALER_DenomFeeSet fees;
|
||||
|
||||
/**
|
||||
* Age restriction for the denomination. (can be zero). If not zero, the bits
|
||||
@ -827,6 +805,23 @@ struct TALER_EXCHANGEDB_Recoup
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Public key to which a nonce is locked.
|
||||
*/
|
||||
union TALER_EXCHANGEDB_NonceLockTargetP
|
||||
{
|
||||
/**
|
||||
* Nonce is locked to this coin key.
|
||||
*/
|
||||
struct TALER_CoinSpendPublicKeyP coin;
|
||||
|
||||
/**
|
||||
* Nonce is locked to this reserve key.
|
||||
*/
|
||||
struct TALER_ReservePublicKeyP reserve;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Information the exchange records about a recoup request
|
||||
* in a coin history.
|
||||
@ -1702,6 +1697,33 @@ struct TALER_EXCHANGEDB_RefreshRevealedCoin
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Information per Clause-Schnorr (CS) fresh coin to
|
||||
* be persisted for idempotency during refreshes-reveal.
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_CsRevealFreshCoinData
|
||||
{
|
||||
/**
|
||||
* Denomination of the fresh coin.
|
||||
*/
|
||||
struct TALER_DenominationHash new_denom_pub_hash;
|
||||
|
||||
/**
|
||||
* Blind signature of the fresh coin (possibly updated
|
||||
* in case if a replay!).
|
||||
*/
|
||||
struct TALER_BlindedDenominationSignature bsig;
|
||||
|
||||
/**
|
||||
* Offset of the fresh coin in the reveal operation.
|
||||
* (May not match the array offset as we may have
|
||||
* a mixture of RSA and CS coins being created, and
|
||||
* this request is only made for the CS subset).
|
||||
*/
|
||||
uint32_t coin_off;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Types of operations that require KYC checks.
|
||||
*/
|
||||
@ -2497,20 +2519,36 @@ struct TALER_EXCHANGEDB_Plugin
|
||||
uint64_t wire_reference);
|
||||
|
||||
|
||||
/**
|
||||
* Locate a nonce for use with a particular public key.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param nonce the nonce to be locked
|
||||
* @param denom_pub_hash hash of the public key of the denomination
|
||||
* @param target public key the nonce is to be locked to
|
||||
* @return statement execution status
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*lock_nonce)(void *cls,
|
||||
const struct TALER_CsNonce *nonce,
|
||||
const struct TALER_DenominationHash *denom_pub_hash,
|
||||
const union TALER_EXCHANGEDB_NonceLockTargetP *target);
|
||||
|
||||
|
||||
/**
|
||||
* Locate the response for a withdraw request under a hash that uniquely
|
||||
* identifies the withdraw operation. Used to ensure idempotency of the
|
||||
* request.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param wih hash that uniquely identifies the withdraw operation
|
||||
* @param bch hash that uniquely identifies the withdraw operation
|
||||
* @param[out] collectable corresponding collectable coin (blind signature)
|
||||
* if a coin is found
|
||||
* @return statement execution status
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*get_withdraw_info)(void *cls,
|
||||
const struct TALER_WithdrawIdentificationHash *wih,
|
||||
const struct TALER_BlindedCoinHash *bch,
|
||||
struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable);
|
||||
|
||||
|
||||
@ -2519,9 +2557,8 @@ struct TALER_EXCHANGEDB_Plugin
|
||||
* and possibly persisting the withdrawal details.
|
||||
*
|
||||
* @param cls the `struct PostgresClosure` with the plugin-specific state
|
||||
* @param wih hash that uniquely identifies the withdraw operation
|
||||
* @param[in,out] collectable corresponding collectable coin (blind signature)
|
||||
* if a coin is found
|
||||
* @param nonce client-contributed input for CS denominations that must be checked for idempotency, or NULL for non-CS withdrawals
|
||||
* @param collectable corresponding collectable coin (blind signature)
|
||||
* @param now current time (rounded)
|
||||
* @param[out] found set to true if the reserve was found
|
||||
* @param[out] balance_ok set to true if the balance was sufficient
|
||||
@ -2532,8 +2569,8 @@ struct TALER_EXCHANGEDB_Plugin
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*do_withdraw)(
|
||||
void *cls,
|
||||
const struct TALER_WithdrawIdentificationHash *wih,
|
||||
struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable,
|
||||
const struct TALER_CsNonce *nonce,
|
||||
const struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable,
|
||||
struct GNUNET_TIME_Timestamp now,
|
||||
bool *found,
|
||||
bool *balance_ok,
|
||||
@ -2591,7 +2628,8 @@ struct TALER_EXCHANGEDB_Plugin
|
||||
* Perform melt operation, checking for sufficient balance
|
||||
* of the coin and possibly persisting the melt details.
|
||||
*
|
||||
* @param cls the `struct PostgresClosure` with the plugin-specific state
|
||||
* @param cls the plugin-specific state
|
||||
* @param rms client-contributed input for CS denominations that must be checked for idempotency, or NULL for non-CS withdrawals
|
||||
* @param[in,out] refresh refresh operation details; the noreveal_index
|
||||
* is set in case the coin was already melted before
|
||||
* @param known_coin_id row of the coin in the known_coins table
|
||||
@ -2602,12 +2640,35 @@ struct TALER_EXCHANGEDB_Plugin
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*do_melt)(
|
||||
void *cls,
|
||||
const struct TALER_RefreshMasterSecretP *rms,
|
||||
struct TALER_EXCHANGEDB_Refresh *refresh,
|
||||
uint64_t known_coin_id,
|
||||
bool *zombie_required,
|
||||
bool *balance_ok);
|
||||
|
||||
|
||||
/**
|
||||
* Check if the given @a nonce was properly locked to the given @a old_coin_pub. If so, check if we already
|
||||
* created CS signatures for the given @a nonce and @a new_denom_pub_hashes,
|
||||
* and if so, return them in @a s_scalars. Otherwise, persist the
|
||||
* signatures from @a s_scalars in the database.
|
||||
*
|
||||
* @param cls the plugin-specific state
|
||||
* @param nonce the client-provided nonce where we must prevent reuse
|
||||
* @param old_coin_pub public key the nonce was locked to
|
||||
* @param num_fresh_coins array length, number of fresh coins revealed
|
||||
* @param[in,out] crfcds array of data about the fresh coins, of length @a num_fresh_coins
|
||||
* @return query execution status
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*cs_refreshes_reveal)(
|
||||
void *cls,
|
||||
const struct TALER_CsNonce *nonce,
|
||||
const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
|
||||
unsigned int num_fresh_coins,
|
||||
struct TALER_EXCHANGEDB_CsRevealFreshCoinData *crfcds);
|
||||
|
||||
|
||||
/**
|
||||
* Perform refund operation, checking for sufficient deposits
|
||||
* of the coin and possibly persisting the refund details.
|
||||
@ -3540,14 +3601,14 @@ struct TALER_EXCHANGEDB_Plugin
|
||||
* from given the hash of the blinded coin.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param wih hash identifying the withdraw operation
|
||||
* @param bch hash identifying the withdraw operation
|
||||
* @param[out] reserve_pub set to information about the reserve (on success only)
|
||||
* @param[out] reserve_out_serial_id set to row of the @a h_blind_ev in reserves_out
|
||||
* @return transaction status code
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*get_reserve_by_wih)(void *cls,
|
||||
const struct TALER_WithdrawIdentificationHash *wih,
|
||||
(*get_reserve_by_h_blind)(void *cls,
|
||||
const struct TALER_BlindedCoinHash *bch,
|
||||
struct TALER_ReservePublicKeyP *reserve_pub,
|
||||
uint64_t *reserve_out_serial_id);
|
||||
|
||||
|
@ -250,6 +250,35 @@ TALER_JSON_spec_amount_any_nbo (const char *name,
|
||||
struct TALER_AmountNBO *r_amount);
|
||||
|
||||
|
||||
/**
|
||||
* Generate specification to parse all fees for
|
||||
* a denomination under a prefix @a pfx.
|
||||
*
|
||||
* @param pfx string prefix to use
|
||||
* @param currency which currency to expect
|
||||
* @param[out] dfs a `struct TALER_DenomFeeSet` to initialize
|
||||
*/
|
||||
#define TALER_JSON_SPEC_DENOM_FEES(pfx,currency,dfs) \
|
||||
TALER_JSON_spec_amount (pfx "_withdraw", (currency), &(dfs)->withdraw), \
|
||||
TALER_JSON_spec_amount (pfx "_deposit", (currency), &(dfs)->deposit), \
|
||||
TALER_JSON_spec_amount (pfx "_refresh", (currency), &(dfs)->refresh), \
|
||||
TALER_JSON_spec_amount (pfx "_refund", (currency), &(dfs)->refund)
|
||||
|
||||
|
||||
/**
|
||||
* Macro to pack all of a denominations' fees under
|
||||
* a given @a pfx.
|
||||
*
|
||||
* @param pfx string prefix to use
|
||||
* @param dfs a `struct TALER_DenomFeeSet` to pack
|
||||
*/
|
||||
#define TALER_JSON_PACK_DENOM_FEES(pfx, dfs) \
|
||||
TALER_JSON_pack_amount (pfx "_withdraw", &(dfs)->withdraw), \
|
||||
TALER_JSON_pack_amount (pfx "_deposit", &(dfs)->deposit), \
|
||||
TALER_JSON_pack_amount (pfx "_refresh", &(dfs)->refresh), \
|
||||
TALER_JSON_pack_amount (pfx "_refund", &(dfs)->refund)
|
||||
|
||||
|
||||
/**
|
||||
* Generate line in parser specification for denomination public key.
|
||||
*
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2021 Taler Systems SA
|
||||
Copyright (C) 2014-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -395,6 +395,7 @@ struct TALER_SigningKeyAnnouncementPS
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Format used for to allow the wallet to authenticate
|
||||
* link data provided by the exchange.
|
||||
@ -999,6 +1000,7 @@ struct TALER_MasterExtensionConfigurationPS
|
||||
struct TALER_ExtensionConfigHash h_config GNUNET_PACKED;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Information about a denomination key. Denomination keys
|
||||
* are used to sign coins of a certain value into existence.
|
||||
@ -1063,29 +1065,9 @@ struct TALER_DenominationKeyValidityPS
|
||||
struct TALER_AmountNBO value;
|
||||
|
||||
/**
|
||||
* The fee the exchange charges when a coin of this type is withdrawn.
|
||||
* (can be zero).
|
||||
* Fees for the coin.
|
||||
*/
|
||||
struct TALER_AmountNBO fee_withdraw;
|
||||
|
||||
/**
|
||||
* The fee the exchange charges when a coin of this type is deposited.
|
||||
* (can be zero).
|
||||
*/
|
||||
struct TALER_AmountNBO fee_deposit;
|
||||
|
||||
/**
|
||||
* The fee the exchange charges when a coin of this type is refreshed.
|
||||
* (can be zero).
|
||||
*/
|
||||
struct TALER_AmountNBO fee_refresh;
|
||||
|
||||
/**
|
||||
* The fee the exchange charges when a coin of this type is refunded.
|
||||
* (can be zero). Note that refund fees are charged to the customer;
|
||||
* if a refund is given, the deposit fee is also refunded.
|
||||
*/
|
||||
struct TALER_AmountNBO fee_refund;
|
||||
struct TALER_DenomFeeSetNBOP fees;
|
||||
|
||||
/**
|
||||
* Hash code of the denomination public key. (Used to avoid having
|
||||
@ -1166,28 +1148,9 @@ struct TALER_ExchangeKeyValidityPS
|
||||
struct TALER_AmountNBO value;
|
||||
|
||||
/**
|
||||
* The fee the exchange charges when a coin of this type is withdrawn.
|
||||
* (can be zero).
|
||||
* Fees for the coin.
|
||||
*/
|
||||
struct TALER_AmountNBO fee_withdraw;
|
||||
|
||||
/**
|
||||
* The fee the exchange charges when a coin of this type is deposited.
|
||||
* (can be zero).
|
||||
*/
|
||||
struct TALER_AmountNBO fee_deposit;
|
||||
|
||||
/**
|
||||
* The fee the exchange charges when a coin of this type is refreshed.
|
||||
* (can be zero).
|
||||
*/
|
||||
struct TALER_AmountNBO fee_refresh;
|
||||
|
||||
/**
|
||||
* The fee the exchange charges when a coin of this type is refreshed.
|
||||
* (can be zero).
|
||||
*/
|
||||
struct TALER_AmountNBO fee_refund;
|
||||
struct TALER_DenomFeeSetNBOP fees;
|
||||
|
||||
/**
|
||||
* Hash code of the denomination public key. (Used to avoid having
|
||||
|
@ -144,6 +144,39 @@ TALER_config_get_amount (const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||
struct TALER_Amount *denom);
|
||||
|
||||
|
||||
/**
|
||||
* Obtain denomination fee structure of a
|
||||
* denomination from configuration file. All
|
||||
* fee options must start with "fee_" and have
|
||||
* names typical for the respective fees.
|
||||
*
|
||||
* @param cfg configuration to extract data from
|
||||
* @param currency expected currency
|
||||
* @param section section of the configuration to access
|
||||
* @param[out] fees set to the denomination fees
|
||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
|
||||
*/
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_config_get_denom_fees (const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||
const char *currency,
|
||||
const char *section,
|
||||
struct TALER_DenomFeeSet *fees);
|
||||
|
||||
|
||||
/**
|
||||
* Check that all denominations in @a fees use
|
||||
* @a currency
|
||||
*
|
||||
* @param currency desired currency
|
||||
* @param fees fee set to check
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_denom_fee_check_currency (
|
||||
const char *currency,
|
||||
const struct TALER_DenomFeeSet *fees);
|
||||
|
||||
|
||||
/**
|
||||
* Load our currency from the @a cfg (in section [taler]
|
||||
* the option "CURRENCY").
|
||||
|
@ -24,7 +24,8 @@ libtalerexchange_la_SOURCES = \
|
||||
exchange_api_auditor_add_denomination.c \
|
||||
exchange_api_curl_defaults.c exchange_api_curl_defaults.h \
|
||||
exchange_api_common.c \
|
||||
exchange_api_csr.c \
|
||||
exchange_api_csr_melt.c \
|
||||
exchange_api_csr_withdraw.c \
|
||||
exchange_api_handle.c exchange_api_handle.h \
|
||||
exchange_api_deposit.c \
|
||||
exchange_api_deposits_get.c \
|
||||
|
@ -171,10 +171,10 @@ TALER_EXCHANGE_parse_reserve_history (
|
||||
&h_denom_pub);
|
||||
if ( (GNUNET_YES !=
|
||||
TALER_amount_cmp_currency (&withdraw_fee,
|
||||
&dki->fee_withdraw)) ||
|
||||
&dki->fees.withdraw)) ||
|
||||
(0 !=
|
||||
TALER_amount_cmp (&withdraw_fee,
|
||||
&dki->fee_withdraw)) )
|
||||
&dki->fees.withdraw)) )
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_JSON_parse_free (withdraw_spec);
|
||||
@ -529,10 +529,10 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
/* check that deposit fee matches our expectations from /keys! */
|
||||
if ( (GNUNET_YES !=
|
||||
TALER_amount_cmp_currency (&fee,
|
||||
&dk->fee_deposit)) ||
|
||||
&dk->fees.deposit)) ||
|
||||
(0 !=
|
||||
TALER_amount_cmp (&fee,
|
||||
&dk->fee_deposit)) )
|
||||
&dk->fees.deposit)) )
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
@ -575,10 +575,10 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
/* check that melt fee matches our expectations from /keys! */
|
||||
if ( (GNUNET_YES !=
|
||||
TALER_amount_cmp_currency (&fee,
|
||||
&dk->fee_refresh)) ||
|
||||
&dk->fees.refresh)) ||
|
||||
(0 !=
|
||||
TALER_amount_cmp (&fee,
|
||||
&dk->fee_refresh)) )
|
||||
&dk->fees.refresh)) )
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
@ -669,10 +669,10 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
{
|
||||
if ( (GNUNET_YES !=
|
||||
TALER_amount_cmp_currency (&refund_fee,
|
||||
&dk->fee_refund)) ||
|
||||
&dk->fees.refund)) ||
|
||||
(0 !=
|
||||
TALER_amount_cmp (&refund_fee,
|
||||
&dk->fee_refund)) )
|
||||
&dk->fees.refund)) )
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
@ -863,6 +863,11 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
}
|
||||
add = GNUNET_NO;
|
||||
}
|
||||
else if (0 == strcasecmp (type,
|
||||
"LOCK_NONCE"))
|
||||
{
|
||||
GNUNET_break (0); // FIXME: implement!
|
||||
}
|
||||
else
|
||||
{
|
||||
/* signature not supported, new version on server? */
|
||||
|
@ -15,8 +15,8 @@
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file lib/exchange_api_csr.c
|
||||
* @brief Implementation of /csr requests (get R in exchange used for Clause Schnorr withdraw and refresh)
|
||||
* @file lib/exchange_api_csr_melt.c
|
||||
* @brief Implementation of /csr-melt requests (get R in exchange used for Clause Schnorr refresh)
|
||||
* @author Lucien Heuzeveldt
|
||||
* @author Gian Demarmels
|
||||
*/
|
||||
@ -36,7 +36,7 @@
|
||||
/**
|
||||
* @brief A Clause Schnorr R Handle
|
||||
*/
|
||||
struct TALER_EXCHANGE_CsRHandle
|
||||
struct TALER_EXCHANGE_CsRMeltHandle
|
||||
{
|
||||
/**
|
||||
* The connection to exchange this request handle will use
|
||||
@ -46,7 +46,7 @@ struct TALER_EXCHANGE_CsRHandle
|
||||
/**
|
||||
* Function to call with the result.
|
||||
*/
|
||||
TALER_EXCHANGE_CsRCallback cb;
|
||||
TALER_EXCHANGE_CsRMeltCallback cb;
|
||||
|
||||
/**
|
||||
* Closure for @a cb.
|
||||
@ -86,13 +86,13 @@ struct TALER_EXCHANGE_CsRHandle
|
||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
csr_ok (struct TALER_EXCHANGE_CsRHandle *csrh,
|
||||
json_t *arr,
|
||||
csr_ok (struct TALER_EXCHANGE_CsRMeltHandle *csrh,
|
||||
const json_t *arr,
|
||||
struct TALER_EXCHANGE_HttpResponse *hr)
|
||||
{
|
||||
unsigned int alen = json_array_size (arr);
|
||||
struct TALER_ExchangeWithdrawValues alg_values[GNUNET_NZL (alen)];
|
||||
struct TALER_EXCHANGE_CsRResponse csrr = {
|
||||
struct TALER_EXCHANGE_CsRMeltResponse csrr = {
|
||||
.hr = *hr,
|
||||
.details.success.alg_values_len = alen,
|
||||
.details.success.alg_values = alg_values
|
||||
@ -127,7 +127,7 @@ csr_ok (struct TALER_EXCHANGE_CsRHandle *csrh,
|
||||
/**
|
||||
* Function called when we're done processing the HTTP /csr request.
|
||||
*
|
||||
* @param cls the `struct TALER_EXCHANGE_CsRHandle`
|
||||
* @param cls the `struct TALER_EXCHANGE_CsRMeltHandle`
|
||||
* @param response_code HTTP response code, 0 on error
|
||||
* @param response parsed JSON result, NULL on error
|
||||
*/
|
||||
@ -136,13 +136,13 @@ handle_csr_finished (void *cls,
|
||||
long response_code,
|
||||
const void *response)
|
||||
{
|
||||
struct TALER_EXCHANGE_CsRHandle *csrh = cls;
|
||||
struct TALER_EXCHANGE_CsRMeltHandle *csrh = cls;
|
||||
const json_t *j = response;
|
||||
struct TALER_EXCHANGE_HttpResponse hr = {
|
||||
.reply = j,
|
||||
.http_status = (unsigned int) response_code
|
||||
};
|
||||
struct TALER_EXCHANGE_CsRResponse csrr = {
|
||||
struct TALER_EXCHANGE_CsRMeltResponse csrr = {
|
||||
.hr = hr
|
||||
};
|
||||
|
||||
@ -171,7 +171,7 @@ handle_csr_finished (void *cls,
|
||||
break;
|
||||
}
|
||||
}
|
||||
TALER_EXCHANGE_csr_cancel (csrh);
|
||||
TALER_EXCHANGE_csr_melt_cancel (csrh);
|
||||
return;
|
||||
case MHD_HTTP_BAD_REQUEST:
|
||||
/* This should never happen, either us or the exchange is buggy
|
||||
@ -215,18 +215,19 @@ handle_csr_finished (void *cls,
|
||||
csrh->cb (csrh->cb_cls,
|
||||
&csrr);
|
||||
csrh->cb = NULL;
|
||||
TALER_EXCHANGE_csr_cancel (csrh);
|
||||
TALER_EXCHANGE_csr_melt_cancel (csrh);
|
||||
}
|
||||
|
||||
|
||||
struct TALER_EXCHANGE_CsRHandle *
|
||||
TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange,
|
||||
struct TALER_EXCHANGE_CsRMeltHandle *
|
||||
TALER_EXCHANGE_csr_melt (struct TALER_EXCHANGE_Handle *exchange,
|
||||
const struct TALER_RefreshMasterSecretP *rms,
|
||||
unsigned int nks_len,
|
||||
struct TALER_EXCHANGE_NonceKey *nks,
|
||||
TALER_EXCHANGE_CsRCallback res_cb,
|
||||
TALER_EXCHANGE_CsRMeltCallback res_cb,
|
||||
void *res_cb_cls)
|
||||
{
|
||||
struct TALER_EXCHANGE_CsRHandle *csrh;
|
||||
struct TALER_EXCHANGE_CsRMeltHandle *csrh;
|
||||
json_t *csr_arr;
|
||||
|
||||
if (0 == nks_len)
|
||||
@ -240,12 +241,10 @@ TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange,
|
||||
GNUNET_break (0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
csrh = GNUNET_new (struct TALER_EXCHANGE_CsRHandle);
|
||||
csrh = GNUNET_new (struct TALER_EXCHANGE_CsRMeltHandle);
|
||||
csrh->exchange = exchange;
|
||||
csrh->cb = res_cb;
|
||||
csrh->cb_cls = res_cb_cls;
|
||||
|
||||
csr_arr = json_array ();
|
||||
GNUNET_assert (NULL != csr_arr);
|
||||
for (unsigned int i = 0; i<nks_len; i++)
|
||||
@ -254,19 +253,17 @@ TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange,
|
||||
json_t *csr_obj;
|
||||
|
||||
csr_obj = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_varsize ("nonce",
|
||||
&nk->nonce,
|
||||
sizeof(struct TALER_CsNonce)),
|
||||
GNUNET_JSON_pack_data_varsize ("denom_pub_hash",
|
||||
&nk->pk->h_key,
|
||||
sizeof(struct TALER_DenominationHash)));
|
||||
GNUNET_JSON_pack_uint64 ("coin_offset",
|
||||
nk->cnc_num),
|
||||
GNUNET_JSON_pack_data_auto ("denom_pub_hash",
|
||||
&nk->pk->h_key));
|
||||
GNUNET_assert (NULL != csr_obj);
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (csr_arr,
|
||||
csr_obj));
|
||||
}
|
||||
csrh->url = TEAH_path_to_url (exchange,
|
||||
"/csr");
|
||||
"/csr-melt");
|
||||
if (NULL == csrh->url)
|
||||
{
|
||||
json_decref (csr_arr);
|
||||
@ -279,6 +276,8 @@ TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange,
|
||||
json_t *req;
|
||||
|
||||
req = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto ("rms",
|
||||
rms),
|
||||
GNUNET_JSON_pack_array_steal ("nks",
|
||||
csr_arr));
|
||||
ctx = TEAH_handle_to_context (exchange);
|
||||
@ -309,7 +308,7 @@ TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange,
|
||||
|
||||
|
||||
void
|
||||
TALER_EXCHANGE_csr_cancel (struct TALER_EXCHANGE_CsRHandle *csrh)
|
||||
TALER_EXCHANGE_csr_melt_cancel (struct TALER_EXCHANGE_CsRMeltHandle *csrh)
|
||||
{
|
||||
if (NULL != csrh->job)
|
||||
{
|
284
src/lib/exchange_api_csr_withdraw.c
Normal file
284
src/lib/exchange_api_csr_withdraw.c
Normal 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);
|
||||
}
|
@ -491,7 +491,7 @@ verify_signatures (const struct TALER_EXCHANGE_DenomPublicKey *dki,
|
||||
{
|
||||
if (GNUNET_OK !=
|
||||
TALER_wallet_deposit_verify (amount,
|
||||
&dki->fee_deposit,
|
||||
&dki->fees.deposit,
|
||||
h_wire,
|
||||
h_contract_terms,
|
||||
h_age_commitment,
|
||||
@ -508,7 +508,7 @@ verify_signatures (const struct TALER_EXCHANGE_DenomPublicKey *dki,
|
||||
TALER_LOG_DEBUG ("... amount_with_fee was %s\n",
|
||||
TALER_amount2s (amount));
|
||||
TALER_LOG_DEBUG ("... deposit_fee was %s\n",
|
||||
TALER_amount2s (&dki->fee_deposit));
|
||||
TALER_amount2s (&dki->fees.deposit));
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
@ -536,7 +536,7 @@ verify_signatures (const struct TALER_EXCHANGE_DenomPublicKey *dki,
|
||||
}
|
||||
|
||||
/* Check coin does make a contribution */
|
||||
if (0 < TALER_amount_cmp (&dki->fee_deposit,
|
||||
if (0 < TALER_amount_cmp (&dki->fees.deposit,
|
||||
amount))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
@ -628,7 +628,7 @@ TALER_EXCHANGE_deposit (
|
||||
if (0 >
|
||||
TALER_amount_subtract (&amount_without_fee,
|
||||
amount,
|
||||
&dki->fee_deposit))
|
||||
&dki->fees.deposit))
|
||||
{
|
||||
*ec = TALER_EC_EXCHANGE_DEPOSIT_FEE_ABOVE_AMOUNT;
|
||||
GNUNET_break_op (0);
|
||||
|
@ -305,6 +305,7 @@ parse_json_signkey (struct TALER_EXCHANGE_SigningPublicKey *sign_key,
|
||||
/**
|
||||
* Parse a exchange's denomination key encoded in JSON.
|
||||
*
|
||||
* @param currency expected currency of all fees
|
||||
* @param[out] denom_key where to return the result
|
||||
* @param check_sigs should we check signatures?
|
||||
* @param[in] denom_key_obj json to parse
|
||||
@ -314,7 +315,8 @@ parse_json_signkey (struct TALER_EXCHANGE_SigningPublicKey *sign_key,
|
||||
* invalid or the json malformed.
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key,
|
||||
parse_json_denomkey (const char *currency,
|
||||
struct TALER_EXCHANGE_DenomPublicKey *denom_key,
|
||||
int check_sigs,
|
||||
json_t *denom_key_obj,
|
||||
struct TALER_MasterPublicKeyP *master_key,
|
||||
@ -331,16 +333,12 @@ parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key,
|
||||
&denom_key->valid_from),
|
||||
GNUNET_JSON_spec_timestamp ("stamp_expire_legal",
|
||||
&denom_key->expire_legal),
|
||||
TALER_JSON_spec_amount_any ("value",
|
||||
TALER_JSON_spec_amount ("value",
|
||||
currency,
|
||||
&denom_key->value),
|
||||
TALER_JSON_spec_amount_any ("fee_withdraw",
|
||||
&denom_key->fee_withdraw),
|
||||
TALER_JSON_spec_amount_any ("fee_deposit",
|
||||
&denom_key->fee_deposit),
|
||||
TALER_JSON_spec_amount_any ("fee_refresh",
|
||||
&denom_key->fee_refresh),
|
||||
TALER_JSON_spec_amount_any ("fee_refund",
|
||||
&denom_key->fee_refund),
|
||||
TALER_JSON_SPEC_DENOM_FEES ("fee",
|
||||
currency,
|
||||
&denom_key->fees),
|
||||
TALER_JSON_spec_denom_pub ("denom_pub",
|
||||
&denom_key->key),
|
||||
GNUNET_JSON_spec_end ()
|
||||
@ -372,10 +370,7 @@ parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key,
|
||||
denom_key->expire_deposit,
|
||||
denom_key->expire_legal,
|
||||
&denom_key->value,
|
||||
&denom_key->fee_withdraw,
|
||||
&denom_key->fee_deposit,
|
||||
&denom_key->fee_refresh,
|
||||
&denom_key->fee_refund,
|
||||
&denom_key->fees,
|
||||
master_key,
|
||||
&denom_key->master_sig));
|
||||
return GNUNET_OK;
|
||||
@ -492,10 +487,7 @@ parse_json_auditor (struct TALER_EXCHANGE_AuditorInformation *auditor,
|
||||
dk->expire_deposit,
|
||||
dk->expire_legal,
|
||||
&dk->value,
|
||||
&dk->fee_withdraw,
|
||||
&dk->fee_deposit,
|
||||
&dk->fee_refresh,
|
||||
&dk->fee_refund,
|
||||
&dk->fees,
|
||||
&auditor->auditor_pub,
|
||||
&auditor_sig))
|
||||
{
|
||||
@ -883,7 +875,8 @@ decode_keys_json (const json_t *resp_obj,
|
||||
0,
|
||||
sizeof (dk));
|
||||
EXITIF (GNUNET_SYSERR ==
|
||||
parse_json_denomkey (&dk,
|
||||
parse_json_denomkey (key_data->currency,
|
||||
&dk,
|
||||
check_sig,
|
||||
denom_key_obj,
|
||||
&key_data->master_pub,
|
||||
@ -1728,14 +1721,8 @@ TALER_EXCHANGE_serialize_data (struct TALER_EXCHANGE_Handle *exchange)
|
||||
dk->expire_legal),
|
||||
TALER_JSON_pack_amount ("value",
|
||||
&dk->value),
|
||||
TALER_JSON_pack_amount ("fee_withdraw",
|
||||
&dk->fee_withdraw),
|
||||
TALER_JSON_pack_amount ("fee_deposit",
|
||||
&dk->fee_deposit),
|
||||
TALER_JSON_pack_amount ("fee_refresh",
|
||||
&dk->fee_refresh),
|
||||
TALER_JSON_pack_amount ("fee_refund",
|
||||
&dk->fee_refund),
|
||||
TALER_JSON_PACK_DENOM_FEES ("fee",
|
||||
&dk->fees),
|
||||
GNUNET_JSON_pack_data_auto ("master_sig",
|
||||
&dk->master_sig),
|
||||
TALER_JSON_pack_denom_pub ("denom_pub",
|
||||
|
@ -94,7 +94,7 @@ struct TALER_EXCHANGE_MeltHandle
|
||||
/**
|
||||
* Handle for the preflight request, or NULL.
|
||||
*/
|
||||
struct TALER_EXCHANGE_CsRHandle *csr;
|
||||
struct TALER_EXCHANGE_CsRMeltHandle *csr;
|
||||
|
||||
/**
|
||||
* Public key of the coin being melted.
|
||||
@ -111,6 +111,10 @@ struct TALER_EXCHANGE_MeltHandle
|
||||
*/
|
||||
uint32_t noreveal_index;
|
||||
|
||||
/**
|
||||
* True if we need to include @e rms in our melt request.
|
||||
*/
|
||||
bool send_rms;
|
||||
};
|
||||
|
||||
|
||||
@ -488,7 +492,13 @@ start_melt (struct TALER_EXCHANGE_MeltHandle *mh)
|
||||
TALER_JSON_pack_amount ("value_with_fee",
|
||||
&mh->md.melted_coin.melt_amount_with_fee),
|
||||
GNUNET_JSON_pack_data_auto ("rc",
|
||||
&mh->md.rc));
|
||||
&mh->md.rc),
|
||||
GNUNET_JSON_pack_allow_null (
|
||||
mh->send_rms
|
||||
? GNUNET_JSON_pack_data_auto ("rms",
|
||||
&mh->rms)
|
||||
: GNUNET_JSON_pack_string ("rms",
|
||||
NULL)));
|
||||
{
|
||||
char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2];
|
||||
char *end;
|
||||
@ -571,7 +581,7 @@ fail_mh (struct TALER_EXCHANGE_MeltHandle *mh,
|
||||
*/
|
||||
static void
|
||||
csr_cb (void *cls,
|
||||
const struct TALER_EXCHANGE_CsRResponse *csrr)
|
||||
const struct TALER_EXCHANGE_CsRMeltResponse *csrr)
|
||||
{
|
||||
struct TALER_EXCHANGE_MeltHandle *mh = cls;
|
||||
unsigned int nks_off = 0;
|
||||
@ -583,7 +593,7 @@ csr_cb (void *cls,
|
||||
.hr = csrr->hr
|
||||
};
|
||||
|
||||
mr.hr.hint = "/csr failed";
|
||||
mr.hr.hint = "/csr-melt failed";
|
||||
mh->melt_cb (mh->melt_cb_cls,
|
||||
&mr);
|
||||
TALER_EXCHANGE_melt_cancel (mh);
|
||||
@ -612,6 +622,7 @@ csr_cb (void *cls,
|
||||
break;
|
||||
}
|
||||
}
|
||||
mh->send_rms = true;
|
||||
if (GNUNET_OK !=
|
||||
start_melt (mh))
|
||||
{
|
||||
@ -668,16 +679,15 @@ TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
|
||||
case TALER_DENOMINATION_CS:
|
||||
wv->cipher = TALER_DENOMINATION_CS;
|
||||
nks[nks_off].pk = fresh_pk;
|
||||
TALER_cs_refresh_nonce_derive (rms,
|
||||
i,
|
||||
&nks[nks_off].nonce);
|
||||
nks[nks_off].cnc_num = nks_off;
|
||||
nks_off++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (0 != nks_off)
|
||||
{
|
||||
mh->csr = TALER_EXCHANGE_csr (exchange,
|
||||
mh->csr = TALER_EXCHANGE_csr_melt (exchange,
|
||||
rms,
|
||||
nks_off,
|
||||
nks,
|
||||
&csr_cb,
|
||||
@ -711,7 +721,7 @@ TALER_EXCHANGE_melt_cancel (struct TALER_EXCHANGE_MeltHandle *mh)
|
||||
}
|
||||
if (NULL != mh->csr)
|
||||
{
|
||||
TALER_EXCHANGE_csr_cancel (mh->csr);
|
||||
TALER_EXCHANGE_csr_melt_cancel (mh->csr);
|
||||
mh->csr = NULL;
|
||||
}
|
||||
TALER_EXCHANGE_free_melt_data_ (&mh->md); /* does not free 'md' itself */
|
||||
|
@ -178,7 +178,7 @@ handle_recoup_finished (void *cls,
|
||||
"history");
|
||||
if (GNUNET_OK !=
|
||||
TALER_EXCHANGE_verify_coin_history (dki,
|
||||
dki->fee_deposit.currency,
|
||||
dki->fees.deposit.currency,
|
||||
&ph->coin_pub,
|
||||
history,
|
||||
&h_denom_pub,
|
||||
|
@ -192,7 +192,7 @@ handle_recoup_refresh_finished (void *cls,
|
||||
"history");
|
||||
if (GNUNET_OK !=
|
||||
TALER_EXCHANGE_verify_coin_history (dki,
|
||||
dki->fee_deposit.currency,
|
||||
dki->fees.deposit.currency,
|
||||
&ph->coin_pub,
|
||||
history,
|
||||
&h_denom_pub,
|
||||
|
@ -64,6 +64,7 @@ TALER_EXCHANGE_get_melt_data_ (
|
||||
struct TALER_Amount total;
|
||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||
struct TALER_CsNonce nonces[rd->fresh_pks_len];
|
||||
bool uses_cs = false;
|
||||
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&rd->melt_priv.eddsa_priv,
|
||||
&coin_pub.eddsa_pub);
|
||||
@ -74,7 +75,7 @@ TALER_EXCHANGE_get_melt_data_ (
|
||||
md->num_fresh_coins = rd->fresh_pks_len;
|
||||
md->melted_coin.coin_priv = rd->melt_priv;
|
||||
md->melted_coin.melt_amount_with_fee = rd->melt_amount;
|
||||
md->melted_coin.fee_melt = rd->melt_pk.fee_refresh;
|
||||
md->melted_coin.fee_melt = rd->melt_pk.fees.refresh;
|
||||
md->melted_coin.original_value = rd->melt_pk.value;
|
||||
md->melted_coin.expire_deposit = rd->melt_pk.expire_deposit;
|
||||
md->melted_coin.age_commitment = rd->age_commitment;
|
||||
@ -100,6 +101,7 @@ TALER_EXCHANGE_get_melt_data_ (
|
||||
}
|
||||
if (TALER_DENOMINATION_CS == alg_values[j].cipher)
|
||||
{
|
||||
uses_cs = true;
|
||||
TALER_cs_refresh_nonce_derive (
|
||||
rms,
|
||||
j,
|
||||
@ -114,7 +116,7 @@ TALER_EXCHANGE_get_melt_data_ (
|
||||
(0 >
|
||||
TALER_amount_add (&total,
|
||||
&total,
|
||||
&rd->fresh_pks[j].fee_withdraw)) )
|
||||
&rd->fresh_pks[j].fees.withdraw)) )
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_EXCHANGE_free_melt_data_ (md);
|
||||
@ -141,6 +143,7 @@ TALER_EXCHANGE_get_melt_data_ (
|
||||
|
||||
TALER_planchet_secret_to_transfer_priv (
|
||||
rms,
|
||||
&rd->melt_priv,
|
||||
i,
|
||||
&md->transfer_priv[i]);
|
||||
|
||||
@ -239,6 +242,9 @@ TALER_EXCHANGE_get_melt_data_ (
|
||||
}
|
||||
TALER_refresh_get_commitment (&md->rc,
|
||||
TALER_CNC_KAPPA,
|
||||
uses_cs
|
||||
? rms
|
||||
: NULL,
|
||||
rd->fresh_pks_len,
|
||||
rce,
|
||||
&coin_pub,
|
||||
|
@ -340,6 +340,7 @@ TALER_EXCHANGE_refreshes_reveal (
|
||||
struct GNUNET_CURL_Context *ctx;
|
||||
struct MeltData md;
|
||||
char arg_str[sizeof (struct TALER_RefreshCommitmentP) * 2 + 32];
|
||||
bool send_rms = false;
|
||||
|
||||
GNUNET_assert (num_coins == rd->fresh_pks_len);
|
||||
if (noreveal_index >= TALER_CNC_KAPPA)
|
||||
@ -376,6 +377,8 @@ TALER_EXCHANGE_refreshes_reveal (
|
||||
const struct TALER_RefreshCoinData *rcd = &md.rcd[noreveal_index][i];
|
||||
struct TALER_DenominationHash denom_hash;
|
||||
|
||||
if (TALER_DENOMINATION_CS == md.fcds[i].fresh_pk.cipher)
|
||||
send_rms = true;
|
||||
TALER_denom_pub_hash (&md.fcds[i].fresh_pk,
|
||||
&denom_hash);
|
||||
GNUNET_assert (0 ==
|
||||
@ -428,6 +431,12 @@ TALER_EXCHANGE_refreshes_reveal (
|
||||
reveal_obj = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto ("transfer_pub",
|
||||
&md.transfer_pub[noreveal_index]),
|
||||
GNUNET_JSON_pack_allow_null (
|
||||
send_rms
|
||||
? GNUNET_JSON_pack_data_auto ("rms",
|
||||
rms)
|
||||
: GNUNET_JSON_pack_string ("rms",
|
||||
NULL)),
|
||||
GNUNET_JSON_pack_array_steal ("transfer_privs",
|
||||
transfer_privs),
|
||||
GNUNET_JSON_pack_array_steal ("link_sigs",
|
||||
|
@ -106,7 +106,7 @@ struct TALER_EXCHANGE_WithdrawHandle
|
||||
/**
|
||||
* Handler for the CS R request (only used for TALER_DENOMINATION_CS denominations)
|
||||
*/
|
||||
struct TALER_EXCHANGE_CsRHandle *csrh;
|
||||
struct TALER_EXCHANGE_CsRWithdrawHandle *csrh;
|
||||
|
||||
};
|
||||
|
||||
@ -192,11 +192,12 @@ handle_reserve_withdraw_finished (
|
||||
* Function called when stage 1 of CS withdraw is finished (request r_pub's)
|
||||
*
|
||||
* @param cls the `struct TALER_EXCHANGE_WithdrawHandle`
|
||||
* @param csrr replies from the /csr request
|
||||
* @param csrr replies from the /csr-withdraw request
|
||||
*/
|
||||
static void
|
||||
withdraw_cs_stage_two_callback (void *cls,
|
||||
const struct TALER_EXCHANGE_CsRResponse *csrr)
|
||||
withdraw_cs_stage_two_callback (
|
||||
void *cls,
|
||||
const struct TALER_EXCHANGE_CsRWithdrawResponse *csrr)
|
||||
{
|
||||
struct TALER_EXCHANGE_WithdrawHandle *wh = cls;
|
||||
struct TALER_EXCHANGE_WithdrawResponse wr = {
|
||||
@ -208,13 +209,7 @@ withdraw_cs_stage_two_callback (void *cls,
|
||||
switch (csrr->hr.http_status)
|
||||
{
|
||||
case MHD_HTTP_OK:
|
||||
if (1 != csrr->details.success.alg_values_len)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
wr.hr.http_status = 0;
|
||||
break;
|
||||
}
|
||||
wh->alg_values = csrr->details.success.alg_values[0];
|
||||
wh->alg_values = csrr->details.success.alg_values;
|
||||
TALER_planchet_setup_coin_priv (&wh->ps,
|
||||
&wh->alg_values,
|
||||
&wh->priv);
|
||||
@ -306,20 +301,17 @@ TALER_EXCHANGE_withdraw (
|
||||
}
|
||||
case TALER_DENOMINATION_CS:
|
||||
{
|
||||
struct TALER_EXCHANGE_NonceKey nk = {
|
||||
.pk = pk,
|
||||
};
|
||||
|
||||
TALER_cs_withdraw_nonce_derive (ps,
|
||||
&nk.nonce);
|
||||
TALER_cs_withdraw_nonce_derive (
|
||||
ps,
|
||||
&wh->pd.blinded_planchet.details.cs_blinded_planchet.nonce);
|
||||
/* Note that we only initialize the first half
|
||||
of the blinded_planchet here; the other part
|
||||
will be done after the /csr request! */
|
||||
will be done after the /csr-withdraw request! */
|
||||
wh->pd.blinded_planchet.cipher = TALER_DENOMINATION_CS;
|
||||
wh->pd.blinded_planchet.details.cs_blinded_planchet.nonce = nk.nonce;
|
||||
wh->csrh = TALER_EXCHANGE_csr (exchange,
|
||||
1, /* "array" length */
|
||||
&nk,
|
||||
wh->csrh = TALER_EXCHANGE_csr_withdraw (
|
||||
exchange,
|
||||
pk,
|
||||
&wh->pd.blinded_planchet.details.cs_blinded_planchet.nonce,
|
||||
&withdraw_cs_stage_two_callback,
|
||||
wh);
|
||||
break;
|
||||
@ -339,7 +331,7 @@ TALER_EXCHANGE_withdraw_cancel (struct TALER_EXCHANGE_WithdrawHandle *wh)
|
||||
TALER_blinded_planchet_free (&wh->pd.blinded_planchet);
|
||||
if (NULL != wh->csrh)
|
||||
{
|
||||
TALER_EXCHANGE_csr_cancel (wh->csrh);
|
||||
TALER_EXCHANGE_csr_withdraw_cancel (wh->csrh);
|
||||
wh->csrh = NULL;
|
||||
}
|
||||
if (NULL != wh->wh2)
|
||||
|
@ -403,7 +403,7 @@ TALER_EXCHANGE_withdraw2 (
|
||||
if (0 >
|
||||
TALER_amount_add (&wh->requested_amount,
|
||||
&dk->value,
|
||||
&dk->fee_withdraw))
|
||||
&dk->fees.withdraw))
|
||||
{
|
||||
/* Overflow here? Very strange, our CPU must be fried... */
|
||||
GNUNET_break (0);
|
||||
|
@ -152,10 +152,7 @@ auditor_add_run (void *cls,
|
||||
dk->expire_deposit,
|
||||
dk->expire_legal,
|
||||
&dk->value,
|
||||
&dk->fee_withdraw,
|
||||
&dk->fee_deposit,
|
||||
&dk->fee_refresh,
|
||||
&dk->fee_refund,
|
||||
&dk->fees,
|
||||
&is->auditor_priv,
|
||||
&auditor_sig);
|
||||
}
|
||||
|
@ -409,8 +409,7 @@ deposit_run (void *cls,
|
||||
{
|
||||
TALER_age_commitment_hash (age_commitment, &h_age_commitment);
|
||||
}
|
||||
|
||||
ds->deposit_fee = denom_pub->fee_deposit;
|
||||
ds->deposit_fee = denom_pub->fees.deposit;
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
|
||||
&coin_pub.eddsa_pub);
|
||||
|
||||
@ -440,7 +439,7 @@ deposit_run (void *cls,
|
||||
TALER_JSON_merchant_wire_signature_hash (ds->wire_details,
|
||||
&h_wire));
|
||||
TALER_wallet_deposit_sign (&ds->amount,
|
||||
&denom_pub->fee_deposit,
|
||||
&denom_pub->fees.deposit,
|
||||
&h_wire,
|
||||
&h_contract_terms,
|
||||
&h_age_commitment,
|
||||
|
@ -103,16 +103,16 @@ fake_issue (struct TALER_EXCHANGEDB_DenominationKeyInformationP *issue)
|
||||
&issue->properties.value));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount_nbo ("EUR:0.1",
|
||||
&issue->properties.fee_withdraw));
|
||||
&issue->properties.fees.withdraw));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount_nbo ("EUR:0.1",
|
||||
&issue->properties.fee_deposit));
|
||||
&issue->properties.fees.deposit));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount_nbo ("EUR:0.1",
|
||||
&issue->properties.fee_refresh));
|
||||
&issue->properties.fees.refresh));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount_nbo ("EUR:0.1",
|
||||
&issue->properties.fee_refund));
|
||||
&issue->properties.fees.refund));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1102,7 +1102,7 @@ melt_run (void *cls,
|
||||
|
||||
/* Melt amount starts with the melt fee of the old coin; we'll add the
|
||||
values and withdraw fees of the fresh coins next */
|
||||
melt_amount = melt_denom_pub->fee_refresh;
|
||||
melt_amount = melt_denom_pub->fees.refresh;
|
||||
age_restricted = melt_denom_pub->key.age_mask.mask != 0;
|
||||
for (unsigned int i = 0; i<num_fresh_coins; i++)
|
||||
{
|
||||
@ -1137,7 +1137,7 @@ melt_run (void *cls,
|
||||
GNUNET_assert (0 <=
|
||||
TALER_amount_add (&melt_amount,
|
||||
&melt_amount,
|
||||
&fresh_pk->fee_withdraw));
|
||||
&fresh_pk->fees.withdraw));
|
||||
rms->fresh_pks[i] = *fresh_pk;
|
||||
/* Make a deep copy of the RSA key */
|
||||
TALER_denom_pub_deep_copy (&rms->fresh_pks[i].key,
|
||||
|
@ -474,11 +474,8 @@ withdraw_run (void *cls,
|
||||
GNUNET_assert (0 <=
|
||||
TALER_amount_add (&ws->reserve_history.amount,
|
||||
&ws->amount,
|
||||
&ws->pk->fee_withdraw));
|
||||
ws->reserve_history.details.withdraw.fee = ws->pk->fee_withdraw;
|
||||
|
||||
{
|
||||
|
||||
&ws->pk->fees.withdraw));
|
||||
ws->reserve_history.details.withdraw.fee = ws->pk->fees.withdraw;
|
||||
ws->wsh = TALER_EXCHANGE_withdraw (is->exchange,
|
||||
ws->pk,
|
||||
rp,
|
||||
@ -486,7 +483,6 @@ withdraw_run (void *cls,
|
||||
ws->h_age_commitment,
|
||||
&reserve_withdraw_cb,
|
||||
ws);
|
||||
}
|
||||
if (NULL == ws->wsh)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2020 Taler Systems SA
|
||||
Copyright (C) 2020, 2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -33,10 +33,7 @@ TALER_auditor_denom_validity_sign (
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_deposit,
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_legal,
|
||||
const struct TALER_Amount *coin_value,
|
||||
const struct TALER_Amount *fee_withdraw,
|
||||
const struct TALER_Amount *fee_deposit,
|
||||
const struct TALER_Amount *fee_refresh,
|
||||
const struct TALER_Amount *fee_refund,
|
||||
const struct TALER_DenomFeeSet *fees,
|
||||
const struct TALER_AuditorPrivateKeyP *auditor_priv,
|
||||
struct TALER_AuditorSignatureP *auditor_sig)
|
||||
{
|
||||
@ -53,14 +50,8 @@ TALER_auditor_denom_validity_sign (
|
||||
|
||||
TALER_amount_hton (&kv.value,
|
||||
coin_value);
|
||||
TALER_amount_hton (&kv.fee_withdraw,
|
||||
fee_withdraw);
|
||||
TALER_amount_hton (&kv.fee_deposit,
|
||||
fee_deposit);
|
||||
TALER_amount_hton (&kv.fee_refresh,
|
||||
fee_refresh);
|
||||
TALER_amount_hton (&kv.fee_refund,
|
||||
fee_refund);
|
||||
TALER_denom_fee_set_hton (&kv.fees,
|
||||
fees);
|
||||
GNUNET_CRYPTO_hash (auditor_url,
|
||||
strlen (auditor_url) + 1,
|
||||
&kv.auditor_url_hash);
|
||||
@ -80,10 +71,7 @@ TALER_auditor_denom_validity_verify (
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_deposit,
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_legal,
|
||||
const struct TALER_Amount *coin_value,
|
||||
const struct TALER_Amount *fee_withdraw,
|
||||
const struct TALER_Amount *fee_deposit,
|
||||
const struct TALER_Amount *fee_refresh,
|
||||
const struct TALER_Amount *fee_refund,
|
||||
const struct TALER_DenomFeeSet *fees,
|
||||
const struct TALER_AuditorPublicKeyP *auditor_pub,
|
||||
const struct TALER_AuditorSignatureP *auditor_sig)
|
||||
{
|
||||
@ -100,14 +88,8 @@ TALER_auditor_denom_validity_verify (
|
||||
|
||||
TALER_amount_hton (&kv.value,
|
||||
coin_value);
|
||||
TALER_amount_hton (&kv.fee_withdraw,
|
||||
fee_withdraw);
|
||||
TALER_amount_hton (&kv.fee_deposit,
|
||||
fee_deposit);
|
||||
TALER_amount_hton (&kv.fee_refresh,
|
||||
fee_refresh);
|
||||
TALER_amount_hton (&kv.fee_refund,
|
||||
fee_refund);
|
||||
TALER_denom_fee_set_hton (&kv.fees,
|
||||
fees);
|
||||
GNUNET_CRYPTO_hash (auditor_url,
|
||||
strlen (auditor_url) + 1,
|
||||
&kv.auditor_url_hash);
|
||||
|
@ -58,6 +58,74 @@ TALER_config_get_amount (const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||
}
|
||||
|
||||
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_config_get_denom_fees (const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||
const char *currency,
|
||||
const char *section,
|
||||
struct TALER_DenomFeeSet *fees)
|
||||
{
|
||||
if (GNUNET_OK !=
|
||||
TALER_config_get_amount (cfg,
|
||||
section,
|
||||
"FEE_WITHDRAW",
|
||||
&fees->withdraw))
|
||||
{
|
||||
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Need amount for option `%s' in section `%s'\n",
|
||||
"FEE_WITHDRAW",
|
||||
section);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_config_get_amount (cfg,
|
||||
section,
|
||||
"FEE_DEPOSIT",
|
||||
&fees->deposit))
|
||||
{
|
||||
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Need amount for option `%s' in section `%s'\n",
|
||||
"FEE_DEPOSIT",
|
||||
section);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_config_get_amount (cfg,
|
||||
section,
|
||||
"FEE_REFRESH",
|
||||
&fees->refresh))
|
||||
{
|
||||
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Need amount for option `%s' in section `%s'\n",
|
||||
"FEE_REFRESH",
|
||||
section);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_config_get_amount (cfg,
|
||||
section,
|
||||
"FEE_REFUND",
|
||||
&fees->refund))
|
||||
{
|
||||
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Need amount for option `%s' in section `%s'\n",
|
||||
"FEE_REFUND",
|
||||
section);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_denom_fee_check_currency (currency,
|
||||
fees))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Need fee amounts in section `%s' to use currency `%s'\n",
|
||||
section,
|
||||
currency);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_config_get_currency (const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||
char **currency)
|
||||
|
@ -193,6 +193,7 @@ TALER_transfer_secret_to_planchet_secret (
|
||||
void
|
||||
TALER_planchet_secret_to_transfer_priv (
|
||||
const struct TALER_RefreshMasterSecretP *rms,
|
||||
const struct TALER_CoinSpendPrivateKeyP *old_coin_priv,
|
||||
uint32_t cnc_num,
|
||||
struct TALER_TransferPrivateKeyP *tpriv)
|
||||
{
|
||||
@ -203,6 +204,8 @@ TALER_planchet_secret_to_transfer_priv (
|
||||
sizeof (*tpriv),
|
||||
&be_salt,
|
||||
sizeof (be_salt),
|
||||
old_coin_priv,
|
||||
sizeof (*old_coin_priv),
|
||||
rms,
|
||||
sizeof (*rms),
|
||||
"taler-transfer-priv-derivation",
|
||||
@ -337,6 +340,7 @@ TALER_planchet_to_coin (
|
||||
void
|
||||
TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc,
|
||||
uint32_t kappa,
|
||||
const struct TALER_RefreshMasterSecretP *rms,
|
||||
uint32_t num_new_coins,
|
||||
const struct TALER_RefreshCommitmentEntry *rcs,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
@ -345,6 +349,10 @@ TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc,
|
||||
struct GNUNET_HashContext *hash_context;
|
||||
|
||||
hash_context = GNUNET_CRYPTO_hash_context_start ();
|
||||
if (NULL != rms)
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
rms,
|
||||
sizeof (*rms));
|
||||
/* first, iterate over transfer public keys for hash_context */
|
||||
for (unsigned int i = 0; i<kappa; i++)
|
||||
{
|
||||
@ -391,7 +399,7 @@ TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc,
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -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 */
|
||||
|
@ -652,7 +652,7 @@ TALER_blinded_denom_sig_cmp (
|
||||
|
||||
|
||||
void
|
||||
TALER_blinded_planchet_hash (const struct TALER_BlindedPlanchet *bp,
|
||||
TALER_blinded_planchet_hash_ (const struct TALER_BlindedPlanchet *bp,
|
||||
struct GNUNET_HashContext *hash_context)
|
||||
{
|
||||
uint32_t cipher = htonl (bp->cipher);
|
||||
@ -771,97 +771,20 @@ TALER_blinded_planchet_free (struct TALER_BlindedPlanchet *blinded_planchet)
|
||||
{
|
||||
switch (blinded_planchet->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_INVALID:
|
||||
GNUNET_break (0);
|
||||
return;
|
||||
case TALER_DENOMINATION_RSA:
|
||||
GNUNET_free (blinded_planchet->details.rsa_blinded_planchet.blinded_msg);
|
||||
break;
|
||||
return;
|
||||
case TALER_DENOMINATION_CS:
|
||||
memset (blinded_planchet,
|
||||
0,
|
||||
sizeof (*blinded_planchet));
|
||||
/* nothing to do for CS */
|
||||
break;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_coin_ev_hash (const struct TALER_BlindedPlanchet *blinded_planchet,
|
||||
const struct TALER_DenominationHash *denom_hash,
|
||||
struct TALER_BlindedCoinHash *bch)
|
||||
{
|
||||
struct GNUNET_HashContext *hash_context;
|
||||
|
||||
hash_context = GNUNET_CRYPTO_hash_context_start ();
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
denom_hash,
|
||||
sizeof(*denom_hash));
|
||||
switch (blinded_planchet->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
GNUNET_CRYPTO_hash_context_read (
|
||||
hash_context,
|
||||
blinded_planchet->details.rsa_blinded_planchet.blinded_msg,
|
||||
blinded_planchet->details.rsa_blinded_planchet.blinded_msg_size);
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
// FIXME: c-values MUST NOT be included in idempotency check
|
||||
// during withdraw (or recoup), but right now they are!!!
|
||||
GNUNET_CRYPTO_hash_context_read (
|
||||
hash_context,
|
||||
&blinded_planchet->details.cs_blinded_planchet.c[0],
|
||||
sizeof (struct GNUNET_CRYPTO_CsC) * 2);
|
||||
GNUNET_CRYPTO_hash_context_read (
|
||||
hash_context,
|
||||
&blinded_planchet->details.cs_blinded_planchet.nonce,
|
||||
sizeof (struct TALER_CsNonce));
|
||||
break;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
GNUNET_CRYPTO_hash_context_abort (hash_context);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
GNUNET_CRYPTO_hash_context_finish (hash_context,
|
||||
&bch->hash);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_withdraw_request_hash (
|
||||
const struct TALER_BlindedPlanchet *blinded_planchet,
|
||||
const struct TALER_DenominationHash *denom_hash,
|
||||
struct TALER_WithdrawIdentificationHash *wih)
|
||||
{
|
||||
struct GNUNET_HashContext *hash_context;
|
||||
|
||||
hash_context = GNUNET_CRYPTO_hash_context_start ();
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
denom_hash,
|
||||
sizeof(*denom_hash));
|
||||
switch (blinded_planchet->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
GNUNET_CRYPTO_hash_context_read (
|
||||
hash_context,
|
||||
blinded_planchet->details.rsa_blinded_planchet.blinded_msg,
|
||||
blinded_planchet->details.rsa_blinded_planchet.blinded_msg_size);
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
GNUNET_CRYPTO_hash_context_read (
|
||||
hash_context,
|
||||
&blinded_planchet->details.cs_blinded_planchet.nonce,
|
||||
sizeof (struct TALER_CsNonce));
|
||||
break;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
GNUNET_CRYPTO_hash_context_abort (hash_context);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
GNUNET_CRYPTO_hash_context_finish (hash_context,
|
||||
&wih->hash);
|
||||
return GNUNET_OK;
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -255,10 +255,7 @@ TALER_exchange_offline_denom_validity_sign (
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_deposit,
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_legal,
|
||||
const struct TALER_Amount *coin_value,
|
||||
const struct TALER_Amount *fee_withdraw,
|
||||
const struct TALER_Amount *fee_deposit,
|
||||
const struct TALER_Amount *fee_refresh,
|
||||
const struct TALER_Amount *fee_refund,
|
||||
const struct TALER_DenomFeeSet *fees,
|
||||
const struct TALER_MasterPrivateKeyP *master_priv,
|
||||
struct TALER_MasterSignatureP *master_sig)
|
||||
{
|
||||
@ -278,14 +275,8 @@ TALER_exchange_offline_denom_validity_sign (
|
||||
&issue.master.eddsa_pub);
|
||||
TALER_amount_hton (&issue.value,
|
||||
coin_value);
|
||||
TALER_amount_hton (&issue.fee_withdraw,
|
||||
fee_withdraw);
|
||||
TALER_amount_hton (&issue.fee_deposit,
|
||||
fee_deposit);
|
||||
TALER_amount_hton (&issue.fee_refresh,
|
||||
fee_refresh);
|
||||
TALER_amount_hton (&issue.fee_refund,
|
||||
fee_refund);
|
||||
TALER_denom_fee_set_hton (&issue.fees,
|
||||
fees);
|
||||
GNUNET_CRYPTO_eddsa_sign (&master_priv->eddsa_priv,
|
||||
&issue,
|
||||
&master_sig->eddsa_signature);
|
||||
@ -300,10 +291,7 @@ TALER_exchange_offline_denom_validity_verify (
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_deposit,
|
||||
struct GNUNET_TIME_Timestamp stamp_expire_legal,
|
||||
const struct TALER_Amount *coin_value,
|
||||
const struct TALER_Amount *fee_withdraw,
|
||||
const struct TALER_Amount *fee_deposit,
|
||||
const struct TALER_Amount *fee_refresh,
|
||||
const struct TALER_Amount *fee_refund,
|
||||
const struct TALER_DenomFeeSet *fees,
|
||||
const struct TALER_MasterPublicKeyP *master_pub,
|
||||
const struct TALER_MasterSignatureP *master_sig)
|
||||
{
|
||||
@ -321,14 +309,8 @@ TALER_exchange_offline_denom_validity_verify (
|
||||
|
||||
TALER_amount_hton (&dkv.value,
|
||||
coin_value);
|
||||
TALER_amount_hton (&dkv.fee_withdraw,
|
||||
fee_withdraw);
|
||||
TALER_amount_hton (&dkv.fee_deposit,
|
||||
fee_deposit);
|
||||
TALER_amount_hton (&dkv.fee_refresh,
|
||||
fee_refresh);
|
||||
TALER_amount_hton (&dkv.fee_refund,
|
||||
fee_refund);
|
||||
TALER_denom_fee_set_hton (&dkv.fees,
|
||||
fees);
|
||||
return
|
||||
GNUNET_CRYPTO_eddsa_verify (
|
||||
TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY,
|
||||
|
@ -258,6 +258,7 @@ test_planchets_cs (void)
|
||||
&alg_values,
|
||||
&bks,
|
||||
&coin_priv,
|
||||
NULL,
|
||||
&c_hash,
|
||||
&pd));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
@ -270,6 +271,7 @@ test_planchets_cs (void)
|
||||
&blind_sig,
|
||||
&bks,
|
||||
&coin_priv,
|
||||
NULL,
|
||||
&c_hash,
|
||||
&alg_values,
|
||||
&coin));
|
||||
@ -396,8 +398,10 @@ main (int argc,
|
||||
return 1;
|
||||
if (0 != test_planchets ())
|
||||
return 2;
|
||||
#if FIXME_OEC
|
||||
if (0 != test_planchets_with_age_commitment ())
|
||||
return 3;
|
||||
#endif
|
||||
if (0 != test_exchange_sigs ())
|
||||
return 4;
|
||||
if (0 != test_merchant_sigs ())
|
||||
|
@ -330,6 +330,7 @@ test_r_derive (struct TALER_CRYPTO_CsDenominationHelper *dh)
|
||||
&alg_values,
|
||||
&bks,
|
||||
&coin_priv,
|
||||
NULL, /* no age commitment */
|
||||
&c_hash,
|
||||
&pd));
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
@ -450,6 +451,7 @@ test_signing (struct TALER_CRYPTO_CsDenominationHelper *dh)
|
||||
&alg_values,
|
||||
&bks,
|
||||
&coin_priv,
|
||||
NULL, /* no age commitment */
|
||||
&c_hash,
|
||||
&pd));
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
@ -484,11 +486,13 @@ test_signing (struct TALER_CRYPTO_CsDenominationHelper *dh)
|
||||
}
|
||||
{
|
||||
struct TALER_FreshCoin coin;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_planchet_to_coin (&keys[i].denom_pub,
|
||||
&ds,
|
||||
&bks,
|
||||
&coin_priv,
|
||||
NULL, /* no age commitment */
|
||||
&c_hash,
|
||||
&alg_values,
|
||||
&coin))
|
||||
@ -548,6 +552,7 @@ test_signing (struct TALER_CRYPTO_CsDenominationHelper *dh)
|
||||
&alg_values,
|
||||
&bks,
|
||||
&coin_priv,
|
||||
NULL, /* no age commitment */
|
||||
&c_hash,
|
||||
&pd));
|
||||
|
||||
@ -636,6 +641,7 @@ perf_signing (struct TALER_CRYPTO_CsDenominationHelper *dh,
|
||||
&alg_values,
|
||||
&bks,
|
||||
&coin_priv,
|
||||
NULL, /* no age commitment */
|
||||
&c_hash,
|
||||
&pd));
|
||||
/* use this key as long as it works */
|
||||
|
@ -46,6 +46,73 @@ TALER_b2s (const void *buf,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_denom_fee_set_hton (struct TALER_DenomFeeSetNBOP *nbo,
|
||||
const struct TALER_DenomFeeSet *fees)
|
||||
{
|
||||
TALER_amount_hton (&nbo->withdraw,
|
||||
&fees->withdraw);
|
||||
TALER_amount_hton (&nbo->deposit,
|
||||
&fees->deposit);
|
||||
TALER_amount_hton (&nbo->refresh,
|
||||
&fees->refresh);
|
||||
TALER_amount_hton (&nbo->refund,
|
||||
&fees->refund);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_denom_fee_set_ntoh (struct TALER_DenomFeeSet *fees,
|
||||
const struct TALER_DenomFeeSetNBOP *nbo)
|
||||
{
|
||||
TALER_amount_ntoh (&fees->withdraw,
|
||||
&nbo->withdraw);
|
||||
TALER_amount_ntoh (&fees->deposit,
|
||||
&nbo->deposit);
|
||||
TALER_amount_ntoh (&fees->refresh,
|
||||
&nbo->refresh);
|
||||
TALER_amount_ntoh (&fees->refund,
|
||||
&nbo->refund);
|
||||
}
|
||||
|
||||
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_denom_fee_check_currency (
|
||||
const char *currency,
|
||||
const struct TALER_DenomFeeSet *fees)
|
||||
{
|
||||
if (GNUNET_YES !=
|
||||
TALER_amount_is_currency (&fees->withdraw,
|
||||
currency))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
if (GNUNET_YES !=
|
||||
TALER_amount_is_currency (&fees->deposit,
|
||||
currency))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
if (GNUNET_YES !=
|
||||
TALER_amount_is_currency (&fees->refresh,
|
||||
currency))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
if (GNUNET_YES !=
|
||||
TALER_amount_is_currency (&fees->refund,
|
||||
currency))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
char *
|
||||
strchrnul (const char *s,
|
||||
|
Loading…
Reference in New Issue
Block a user