summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorÖzgür Kesim <oec-taler@kesim.org>2022-02-16 22:01:05 +0100
committerÖzgür Kesim <oec-taler@kesim.org>2022-02-16 22:01:05 +0100
commit8bdf6ab19df70c16d335ecf82f2c3b2117eeb70e (patch)
treefe38fc98807feb6892052ee091b2b5f0a70ab17a /src/lib
parentb73be40ccd9ad0ef4a985f252099c867f698896d (diff)
downloadexchange-8bdf6ab19df70c16d335ecf82f2c3b2117eeb70e.tar.gz
exchange-8bdf6ab19df70c16d335ecf82f2c3b2117eeb70e.tar.bz2
exchange-8bdf6ab19df70c16d335ecf82f2c3b2117eeb70e.zip
[age restriction] progress 14/n - withdraw and deposit
Age restriction support for - withdraw is done and tested - deposit is done and tested TODOs: - melt/refresh/reveal - link ------ Added functions - TALER_age_restriction_commit - TALER_age_commitment_derive - TALER_age_commitment_hash - TALER_age_restriction_commitment_free_inside - Hash of age commitment passed around API boundaries Exchangedb adjustments for denominations - all prepared statements re: denominations now handle age_mask - signature parameters adjusted Hash and signature verification of /keys adjusted - Hashes of (normal) denominations and age-restricted denominations are calculated seperately - The hash of the age-restricted ones will then be added to the other hash - The total hash is signed/verified Tests for withdraw with age restriction added - TALER_EXCHANGE_DenomPublickey now carries age_mask - TALER_TESTING_cmd_withdraw_amount* takes age parameter - TALER_TESTING_find_pk takes boolean age_restricted - WithdrawState carries age_commitment and its hash - withdraw_run derives new age commitment, if applicable - Added age parameter to testing (13 as example) Various Fixes and changes - Fixes of post handler for /management/extensions - Fixes for offline tool extensions signing - Slight refactoring of extensions - Age restriction extension simplified - config is now global to extension - added global TEH_age_restriction_enabled and TEH_age_mask in taler-exchange-httpd - helper functions and macros introduced
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/exchange_api_common.c34
-rw-r--r--src/lib/exchange_api_deposit.c24
-rw-r--r--src/lib/exchange_api_handle.c58
-rw-r--r--src/lib/exchange_api_link.c12
-rw-r--r--src/lib/exchange_api_management_get_keys.c2
-rw-r--r--src/lib/exchange_api_management_post_extensions.c4
-rw-r--r--src/lib/exchange_api_refresh_common.c1
-rw-r--r--src/lib/exchange_api_refresh_common.h13
-rw-r--r--src/lib/exchange_api_refreshes_reveal.c11
-rw-r--r--src/lib/exchange_api_refund.c5
-rw-r--r--src/lib/exchange_api_withdraw.c10
11 files changed, 134 insertions, 40 deletions
diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c
index 53a75a934..d03409244 100644
--- a/src/lib/exchange_api_common.c
+++ b/src/lib/exchange_api_common.c
@@ -477,6 +477,7 @@ TALER_EXCHANGE_verify_coin_history (
struct TALER_MerchantPublicKeyP merchant_pub;
struct GNUNET_TIME_Timestamp refund_deadline = {0};
struct TALER_CoinSpendSignatureP sig;
+ struct TALER_AgeCommitmentHash *hac = NULL;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("coin_sig",
&sig),
@@ -511,6 +512,7 @@ TALER_EXCHANGE_verify_coin_history (
&fee,
&h_wire,
&h_contract_terms,
+ hac,
NULL /* h_extensions! */,
h_denom_pub,
wallet_timestamp,
@@ -543,6 +545,7 @@ TALER_EXCHANGE_verify_coin_history (
{
struct TALER_CoinSpendSignatureP sig;
struct TALER_RefreshCommitmentP rc;
+ struct TALER_AgeCommitmentHash h_age_commitment = {0};
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("coin_sig",
&sig),
@@ -550,6 +553,9 @@ TALER_EXCHANGE_verify_coin_history (
&rc),
GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
h_denom_pub),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
+ &h_age_commitment)),
TALER_JSON_spec_amount_any ("melt_fee",
&fee),
GNUNET_JSON_spec_end ()
@@ -563,6 +569,7 @@ TALER_EXCHANGE_verify_coin_history (
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
+
if (NULL != dk)
{
/* check that melt fee matches our expectations from /keys! */
@@ -577,16 +584,25 @@ TALER_EXCHANGE_verify_coin_history (
return GNUNET_SYSERR;
}
}
- if (GNUNET_OK !=
- TALER_wallet_melt_verify (&amount,
- &fee,
- &rc,
- h_denom_pub,
- coin_pub,
- &sig))
+
{
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
+ const struct TALER_AgeCommitmentHash *ahc = &h_age_commitment;
+
+ if (TALER_AgeCommitmentHash_isNullOrZero (ahc))
+ ahc = NULL;
+
+ if (GNUNET_OK !=
+ TALER_wallet_melt_verify (&amount,
+ &fee,
+ &rc,
+ h_denom_pub,
+ ahc,
+ coin_pub,
+ &sig))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
}
add = GNUNET_YES;
}
diff --git a/src/lib/exchange_api_deposit.c b/src/lib/exchange_api_deposit.c
index 7ff596518..2bfaaf6ce 100644
--- a/src/lib/exchange_api_deposit.c
+++ b/src/lib/exchange_api_deposit.c
@@ -463,6 +463,7 @@ handle_deposit_finished (void *cls,
* @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the exchange)
* @param ech hash over contract extensions
* @param coin_pub coin’s public key
+ * @param h_age_commitment coin’s hash of age commitment, might be NULL
* @param denom_sig exchange’s unblinded signature of the coin
* @param denom_pub denomination key with which the coin is signed
* @param denom_pub_hash hash of @a denom_pub
@@ -479,6 +480,7 @@ verify_signatures (const struct TALER_EXCHANGE_DenomPublicKey *dki,
const struct TALER_PrivateContractHash *h_contract_terms,
const struct TALER_ExtensionContractHash *ech,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const struct TALER_AgeCommitmentHash *h_age_commitment,
const struct TALER_DenominationSignature *denom_sig,
const struct TALER_DenominationPublicKey *denom_pub,
const struct TALER_DenominationHash *denom_pub_hash,
@@ -492,6 +494,7 @@ verify_signatures (const struct TALER_EXCHANGE_DenomPublicKey *dki,
&dki->fee_deposit,
h_wire,
h_contract_terms,
+ h_age_commitment,
ech,
denom_pub_hash,
timestamp,
@@ -515,8 +518,12 @@ verify_signatures (const struct TALER_EXCHANGE_DenomPublicKey *dki,
.coin_pub = *coin_pub,
.denom_pub_hash = *denom_pub_hash,
.denom_sig = *denom_sig,
- .age_commitment_hash = {{{0}}} /* FIXME-Oec */
+ .age_commitment_hash = {{{0}}}
};
+ if (NULL != h_age_commitment)
+ {
+ coin_info.age_commitment_hash = *h_age_commitment;
+ }
if (GNUNET_YES !=
TALER_test_coin_valid (&coin_info,
@@ -548,6 +555,7 @@ TALER_EXCHANGE_deposit (
const char *merchant_payto_uri,
const struct TALER_WireSaltP *wire_salt,
const struct TALER_PrivateContractHash *h_contract_terms,
+ const struct TALER_AgeCommitmentHash *h_age_commitment,
const json_t *extension_details,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_DenominationSignature *denom_sig,
@@ -600,11 +608,14 @@ TALER_EXCHANGE_deposit (
}
GNUNET_assert (GNUNET_YES ==
TEAH_handle_is_ready (exchange));
+
/* initialize h_wire */
TALER_merchant_wire_signature_hash (merchant_payto_uri,
wire_salt,
&h_wire);
+
key_state = TALER_EXCHANGE_get_keys (exchange);
+
dki = TALER_EXCHANGE_get_denomination_key (key_state,
denom_pub);
if (NULL == dki)
@@ -613,6 +624,7 @@ TALER_EXCHANGE_deposit (
GNUNET_break_op (0);
return NULL;
}
+
if (0 >
TALER_amount_subtract (&amount_without_fee,
amount,
@@ -622,17 +634,18 @@ TALER_EXCHANGE_deposit (
GNUNET_break_op (0);
return NULL;
}
+
TALER_denom_pub_hash (denom_pub,
&denom_pub_hash);
+
if (GNUNET_OK !=
verify_signatures (dki,
amount,
&h_wire,
h_contract_terms,
- (NULL != extension_details)
- ? &ech
- : NULL,
+ (NULL != extension_details) ? &ech : NULL,
coin_pub,
+ h_age_commitment,
denom_sig,
denom_pub,
&denom_pub_hash,
@@ -655,6 +668,9 @@ TALER_EXCHANGE_deposit (
wire_salt),
GNUNET_JSON_pack_data_auto ("h_contract_terms",
h_contract_terms),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_data_auto ("h_age_commitment",
+ h_age_commitment)),
GNUNET_JSON_pack_data_auto ("denom_pub_hash",
&denom_pub_hash),
TALER_JSON_pack_denom_sig ("ub_sig",
diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c
index cf3d69d6a..3243f5e95 100644
--- a/src/lib/exchange_api_handle.c
+++ b/src/lib/exchange_api_handle.c
@@ -667,7 +667,9 @@ decode_keys_json (const json_t *resp_obj,
enum TALER_EXCHANGE_VersionCompatibility *vc)
{
struct TALER_ExchangeSignatureP sig;
- struct GNUNET_HashContext *hash_context;
+ struct GNUNET_HashContext *hash_context = NULL;
+ struct GNUNET_HashContext *hash_context_restricted = NULL;
+ bool have_age_restricted_denom = false;
struct TALER_ExchangePublicKeyP pub;
const char *currency;
struct GNUNET_JSON_Specification mspec[] = {
@@ -746,7 +748,6 @@ decode_keys_json (const json_t *resp_obj,
key_data->version = GNUNET_strdup (ver);
}
- hash_context = NULL;
EXITIF (GNUNET_OK !=
GNUNET_JSON_parse (resp_obj,
(check_sig) ? mspec : &mspec[2],
@@ -766,7 +767,10 @@ decode_keys_json (const json_t *resp_obj,
/* parse the master public key and issue date of the response */
if (check_sig)
+ {
hash_context = GNUNET_CRYPTO_hash_context_start ();
+ hash_context_restricted = GNUNET_CRYPTO_hash_context_start ();
+ }
/* parse the signing keys */
{
@@ -829,6 +833,9 @@ decode_keys_json (const json_t *resp_obj,
EXITIF (GNUNET_OK !=
TALER_extensions_load_json_config (extensions));
}
+
+ /* 4. assuming we might have now a new value for age_mask, set it in key_data */
+ key_data->age_mask = TALER_extensions_age_restriction_ageMask ();
}
/* parse the denomination keys, merging with the
@@ -839,9 +846,15 @@ decode_keys_json (const json_t *resp_obj,
*/
struct
{ char *name;
- bool is_optional_age_restriction;} hive[2] = {
- { "denoms", false },
- { "age_restricted_denoms", true },
+ struct GNUNET_HashContext *hc;
+ bool is_optional_age_restriction;}
+ hive[2] = {
+ { "denoms",
+ hash_context,
+ false },
+ { "age_restricted_denoms",
+ hash_context_restricted,
+ true }
};
for (size_t s = 0; s < sizeof(hive) / sizeof(hive[0]); s++)
@@ -853,25 +866,19 @@ decode_keys_json (const json_t *resp_obj,
denom_keys_array = json_object_get (resp_obj,
hive[s].name);
- EXITIF (NULL == denom_keys_array &&
- ! hive[s].is_optional_age_restriction);
-
- if (NULL == denom_keys_array &&
- hive[s].is_optional_age_restriction)
+ if (NULL == denom_keys_array)
continue;
- /* if "age_restricted_denoms" exists, age-restriction better be enabled
- * (that is: mask non-zero) */
- EXITIF (NULL != denom_keys_array &&
- hive[s].is_optional_age_restriction &&
- 0 == key_data->age_mask.mask);
-
EXITIF (JSON_ARRAY != json_typeof (denom_keys_array));
json_array_foreach (denom_keys_array, index, denom_key_obj) {
struct TALER_EXCHANGE_DenomPublicKey dk;
bool found = false;
+ /* mark that we have at least one age restricted denomination, needed
+ * for the hash calculation and signature verification below. */
+ have_age_restricted_denom |= hive[s].is_optional_age_restriction;
+
memset (&dk,
0,
sizeof (dk));
@@ -880,12 +887,7 @@ decode_keys_json (const json_t *resp_obj,
check_sig,
denom_key_obj,
&key_data->master_pub,
- hash_context));
-
- /* Mark age restriction according where we got this denomination from,
- * "denoms" or "age_restricted_denoms" */
- if (hive[s].is_optional_age_restriction)
- dk.age_restricted = true;
+ hive[s].hc));
for (unsigned int j = 0;
j<key_data->num_denom_keys;
@@ -1044,6 +1046,18 @@ decode_keys_json (const json_t *resp_obj,
.list_issue_date = GNUNET_TIME_timestamp_hton (key_data->list_issue_date)
};
+ /* If we had any age restricted denominations, add their hash to the end of
+ * the normal denominations. */
+ if (have_age_restricted_denom)
+ {
+ struct GNUNET_HashCode hcr;
+ GNUNET_CRYPTO_hash_context_finish (hash_context_restricted,
+ &hcr);
+ GNUNET_CRYPTO_hash_context_read (hash_context,
+ &hcr,
+ sizeof(struct GNUNET_HashCode));
+ }
+
GNUNET_CRYPTO_hash_context_finish (hash_context,
&ks.hc);
hash_context = NULL;
diff --git a/src/lib/exchange_api_link.c b/src/lib/exchange_api_link.c
index a44ccdcea..10ddd471d 100644
--- a/src/lib/exchange_api_link.c
+++ b/src/lib/exchange_api_link.c
@@ -113,6 +113,7 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
struct TALER_TransferSecretP secret;
struct TALER_PlanchetDetail pd;
struct TALER_CoinPubHash c_hash;
+ struct TALER_AgeCommitmentHash h_age_commitment = {0}; // TODO, see below.
/* parse reply */
memset (&nonce,
@@ -143,6 +144,7 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
&alg_values,
&bks,
&lci->coin_priv,
+ NULL, /* FIXME-oec. struct TALER_AgeCommitmentHash */
&c_hash,
&pd))
{
@@ -179,6 +181,15 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
GNUNET_CRYPTO_eddsa_key_get_public (&lh->coin_priv.eddsa_priv,
&old_coin_pub.eddsa_pub);
+ /*
+ * TODO-oec: Derive the age commitment vector and hash it into
+ * h_age_commitment.
+ * Questions:
+ * - Where do we get the information about the support for age
+ * restriction of the denomination?
+ * - Where do we get the information bout the previous coin's age groups?
+ */
+
TALER_coin_ev_hash (&pd.blinded_planchet,
&pd.denom_pub_hash,
&coin_envelope_hash);
@@ -187,6 +198,7 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
trans_pub,
&coin_envelope_hash,
&old_coin_pub,
+ &h_age_commitment,
&link_sig))
{
GNUNET_break_op (0);
diff --git a/src/lib/exchange_api_management_get_keys.c b/src/lib/exchange_api_management_get_keys.c
index 4d6866338..ac419388f 100644
--- a/src/lib/exchange_api_management_get_keys.c
+++ b/src/lib/exchange_api_management_get_keys.c
@@ -32,7 +32,7 @@
/**
* Set to 1 for extra debug logging.
*/
-#define DEBUG 0
+#define DEBUG 1 /* FIXME-oec */
/**
diff --git a/src/lib/exchange_api_management_post_extensions.c b/src/lib/exchange_api_management_post_extensions.c
index c0ab143f6..87b0e0be8 100644
--- a/src/lib/exchange_api_management_post_extensions.c
+++ b/src/lib/exchange_api_management_post_extensions.c
@@ -151,7 +151,7 @@ TALER_EXCHANGE_management_post_extensions (
body = GNUNET_JSON_PACK (
GNUNET_JSON_pack_object_steal ("extensions",
ped->extensions),
- GNUNET_JSON_pack_data_auto ("extensions_sigs",
+ GNUNET_JSON_pack_data_auto ("extensions_sig",
&ped->extensions_sig));
eh = curl_easy_init ();
@@ -168,7 +168,7 @@ TALER_EXCHANGE_management_post_extensions (
return NULL;
}
json_decref (body);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Requesting URL '%s'\n",
ph->url);
GNUNET_assert (CURLE_OK == curl_easy_setopt (eh,
diff --git a/src/lib/exchange_api_refresh_common.c b/src/lib/exchange_api_refresh_common.c
index e944b79a1..89ee1e178 100644
--- a/src/lib/exchange_api_refresh_common.c
+++ b/src/lib/exchange_api_refresh_common.c
@@ -175,6 +175,7 @@ TALER_EXCHANGE_get_melt_data_ (
&alg_values[j],
bks,
coin_priv,
+ NULL, /* FIXME-oec: This needs to be setup !*/
&c_hash,
&pd))
{
diff --git a/src/lib/exchange_api_refresh_common.h b/src/lib/exchange_api_refresh_common.h
index ab19ad7d1..b6926b51f 100644
--- a/src/lib/exchange_api_refresh_common.h
+++ b/src/lib/exchange_api_refresh_common.h
@@ -53,6 +53,12 @@ struct MeltedCoin
struct TALER_Amount original_value;
/**
+ * The original age commitment hash. MUST be all zeroes, if no age
+ * commitment was set.
+ */
+ struct TALER_AgeCommitmentHash h_age_commitment;
+
+ /**
* Timestamp indicating when coins of this denomination become invalid.
*/
struct GNUNET_TIME_Timestamp expire_deposit;
@@ -93,6 +99,13 @@ struct FreshCoinData
struct TALER_CoinSpendPrivateKeyP coin_priv;
/**
+ * Arrays age commitments to be created, one for each cut-and-choose
+ * dimension. The entries in each list might be NULL and indicate no age
+ * commitment/restriction on the particular coin.
+ */
+ struct TALER_AgeCommitment *age_commitment[TALER_CNC_KAPPA];
+
+ /**
* Blinding key secrets for the coins, depending on the
* cut-and-choose.
*/
diff --git a/src/lib/exchange_api_refreshes_reveal.c b/src/lib/exchange_api_refreshes_reveal.c
index 08357c14e..8d04c279a 100644
--- a/src/lib/exchange_api_refreshes_reveal.c
+++ b/src/lib/exchange_api_refreshes_reveal.c
@@ -142,6 +142,7 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
&rcis[i];
const struct FreshCoinData *fcd = &rrh->md.fcds[i];
const struct TALER_DenominationPublicKey *pk;
+ struct TALER_AgeCommitmentHash *ach = NULL;
json_t *jsonai;
struct TALER_BlindedDenominationSignature blind_sig;
struct TALER_CoinSpendPublicKeyP coin_pub;
@@ -160,6 +161,12 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
jsonai = json_array_get (jsona, i);
GNUNET_assert (NULL != jsonai);
+ if (! TALER_AgeCommitmentHash_isNullOrZero (
+ &rrh->md.melted_coin.h_age_commitment))
+ {
+ /* FIXME-oec: need to pull fresh_ach from somewhere */
+ }
+
if (GNUNET_OK !=
GNUNET_JSON_parse (jsonai,
spec,
@@ -180,15 +187,15 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
hence recomputing it here... */
GNUNET_CRYPTO_eddsa_key_get_public (&rci->coin_priv.eddsa_priv,
&coin_pub.eddsa_pub);
- /* FIXME-Oec: Age commitment hash. */
TALER_coin_pub_hash (&coin_pub,
- NULL, /* FIXME-Oec */
+ ach,
&coin_hash);
if (GNUNET_OK !=
TALER_planchet_to_coin (pk,
&blind_sig,
&bks,
&rci->coin_priv,
+ ach,
&coin_hash,
&rrh->alg_values[i],
&coin))
diff --git a/src/lib/exchange_api_refund.c b/src/lib/exchange_api_refund.c
index 94909470a..a9510715b 100644
--- a/src/lib/exchange_api_refund.c
+++ b/src/lib/exchange_api_refund.c
@@ -203,6 +203,7 @@ verify_conflict_history_ok (struct TALER_EXCHANGE_RefundHandle *rh,
struct TALER_Amount deposit_fee;
struct TALER_MerchantWireHash h_wire;
struct TALER_PrivateContractHash h_contract_terms;
+ struct TALER_AgeCommitmentHash h_age_commitment = {{{0}}};
// struct TALER_ExtensionContractHash h_extensions; // FIXME!
struct TALER_DenominationHash h_denom_pub;
struct GNUNET_TIME_Timestamp wallet_timestamp;
@@ -218,6 +219,9 @@ verify_conflict_history_ok (struct TALER_EXCHANGE_RefundHandle *rh,
&h_wire),
GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
&h_denom_pub),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
+ &h_age_commitment)),
GNUNET_JSON_spec_timestamp ("timestamp",
&wallet_timestamp),
GNUNET_JSON_spec_timestamp ("refund_deadline",
@@ -243,6 +247,7 @@ verify_conflict_history_ok (struct TALER_EXCHANGE_RefundHandle *rh,
&deposit_fee,
&h_wire,
&h_contract_terms,
+ &h_age_commitment,
NULL /* h_extensions! */,
&h_denom_pub,
wallet_timestamp,
diff --git a/src/lib/exchange_api_withdraw.c b/src/lib/exchange_api_withdraw.c
index c832699a2..efc8a99c2 100644
--- a/src/lib/exchange_api_withdraw.c
+++ b/src/lib/exchange_api_withdraw.c
@@ -89,6 +89,11 @@ struct TALER_EXCHANGE_WithdrawHandle
struct TALER_ExchangeWithdrawValues alg_values;
/**
+ * Hash of the age commitment for this coin, if applicable. Maybe NULL
+ */
+ const struct TALER_AgeCommitmentHash *ach;
+
+ /**
* Denomination key we are withdrawing.
*/
struct TALER_EXCHANGE_DenomPublicKey pk;
@@ -137,6 +142,7 @@ handle_reserve_withdraw_finished (
blind_sig,
&wh->bks,
&wh->priv,
+ wh->ach,
&wh->c_hash,
&wh->alg_values,
&fc))
@@ -222,6 +228,7 @@ withdraw_cs_stage_two_callback (void *cls,
&wh->alg_values,
&wh->bks,
&wh->priv,
+ wh->ach,
&wh->c_hash,
&wh->pd))
{
@@ -249,6 +256,7 @@ TALER_EXCHANGE_withdraw (
const struct TALER_EXCHANGE_DenomPublicKey *pk,
const struct TALER_ReservePrivateKeyP *reserve_priv,
const struct TALER_PlanchetMasterSecretP *ps,
+ const struct TALER_AgeCommitmentHash *ach,
TALER_EXCHANGE_WithdrawCallback res_cb,
void *res_cb_cls)
{
@@ -260,6 +268,7 @@ TALER_EXCHANGE_withdraw (
wh->cb_cls = res_cb_cls;
wh->reserve_priv = reserve_priv;
wh->ps = *ps;
+ wh->ach = ach;
wh->pk = *pk;
TALER_denom_pub_deep_copy (&wh->pk.key,
&pk->key);
@@ -280,6 +289,7 @@ TALER_EXCHANGE_withdraw (
&wh->alg_values,
&wh->bks,
&wh->priv,
+ wh->ach,
&wh->c_hash,
&wh->pd))
{