-deduplicate purse creation confirmation logic

This commit is contained in:
Christian Grothoff 2022-07-05 12:07:27 +02:00
parent 9e5dc2a542
commit 3ff92b9bbc
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
4 changed files with 144 additions and 176 deletions

View File

@ -39,26 +39,12 @@
*/ */
struct PurseCreateContext struct PurseCreateContext
{ {
/**
* Public key of the purse we are creating.
*/
const struct TALER_PurseContractPublicKeyP *purse_pub;
/**
* Total amount to be put into the purse.
*/
struct TALER_Amount amount;
/** /**
* Total actually deposited by all the coins. * Total actually deposited by all the coins.
*/ */
struct TALER_Amount deposit_total; struct TALER_Amount deposit_total;
/**
* When should the purse expire.
*/
struct GNUNET_TIME_Timestamp purse_expiration;
/** /**
* Our current time. * Our current time.
*/ */
@ -80,9 +66,9 @@ struct PurseCreateContext
struct TALER_PurseContractSignatureP purse_sig; struct TALER_PurseContractSignatureP purse_sig;
/** /**
* Hash of the contract terms of the purse. * Fundamental details about the purse.
*/ */
struct TALER_PrivateContractHashP h_contract_terms; struct TEH_PurseDetails pd;
/** /**
* Array of coins being deposited. * Array of coins being deposited.
@ -107,52 +93,6 @@ struct PurseCreateContext
}; };
/**
* Send confirmation of purse creation success to client.
*
* @param connection connection to the client
* @param pcc details about the request that succeeded
* @return MHD result code
*/
static MHD_RESULT
reply_create_success (struct MHD_Connection *connection,
const struct PurseCreateContext *pcc)
{
struct TALER_ExchangePublicKeyP pub;
struct TALER_ExchangeSignatureP sig;
enum TALER_ErrorCode ec;
if (TALER_EC_NONE !=
(ec = TALER_exchange_online_purse_created_sign (
&TEH_keys_exchange_sign_,
pcc->exchange_timestamp,
pcc->purse_expiration,
&pcc->amount,
&pcc->deposit_total,
pcc->purse_pub,
&pcc->h_contract_terms,
&pub,
&sig)))
{
GNUNET_break (0);
return TALER_MHD_reply_with_ec (connection,
ec,
NULL);
}
return TALER_MHD_REPLY_JSON_PACK (
connection,
MHD_HTTP_OK,
TALER_JSON_pack_amount ("total_deposited",
&pcc->deposit_total),
GNUNET_JSON_pack_timestamp ("exchange_timestamp",
pcc->exchange_timestamp),
GNUNET_JSON_pack_data_auto ("exchange_sig",
&sig),
GNUNET_JSON_pack_data_auto ("exchange_pub",
&pub));
}
/** /**
* Execute database transaction for /purses/$PID/create. Runs the transaction * Execute database transaction for /purses/$PID/create. Runs the transaction
* logic; IF it returns a non-error code, the transaction logic MUST NOT queue * logic; IF it returns a non-error code, the transaction logic MUST NOT queue
@ -177,19 +117,19 @@ create_transaction (void *cls,
bool in_conflict = true; bool in_conflict = true;
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (pcc->amount.currency, TALER_amount_set_zero (TEH_currency,
&purse_fee)); &purse_fee));
/* 1) create purse */ /* 1) create purse */
qs = TEH_plugin->insert_purse_request ( qs = TEH_plugin->insert_purse_request (
TEH_plugin->cls, TEH_plugin->cls,
pcc->purse_pub, &pcc->pd.purse_pub,
&pcc->merge_pub, &pcc->merge_pub,
pcc->purse_expiration, pcc->pd.purse_expiration,
&pcc->h_contract_terms, &pcc->pd.h_contract_terms,
pcc->min_age, pcc->min_age,
TALER_WAMF_MODE_MERGE_FULLY_PAID_PURSE, TALER_WAMF_MODE_MERGE_FULLY_PAID_PURSE,
&purse_fee, &purse_fee,
&pcc->amount, &pcc->pd.target_amount,
&pcc->purse_sig, &pcc->purse_sig,
&in_conflict); &in_conflict);
if (qs < 0) if (qs < 0)
@ -217,7 +157,7 @@ create_transaction (void *cls,
TEH_plugin->rollback (TEH_plugin->cls); TEH_plugin->rollback (TEH_plugin->cls);
qs = TEH_plugin->select_purse_request (TEH_plugin->cls, qs = TEH_plugin->select_purse_request (TEH_plugin->cls,
pcc->purse_pub, &pcc->pd.purse_pub,
&merge_pub, &merge_pub,
&purse_expiration, &purse_expiration,
&h_contract_terms, &h_contract_terms,
@ -269,7 +209,7 @@ create_transaction (void *cls,
if (qs < 0) if (qs < 0)
return qs; return qs;
qs = TEH_plugin->do_purse_deposit (TEH_plugin->cls, qs = TEH_plugin->do_purse_deposit (TEH_plugin->cls,
pcc->purse_pub, &pcc->pd.purse_pub,
&coin->cpi.coin_pub, &coin->cpi.coin_pub,
&coin->amount, &coin->amount,
&coin->coin_sig, &coin->coin_sig,
@ -310,7 +250,7 @@ create_transaction (void *cls,
TEH_plugin->rollback (TEH_plugin->cls); TEH_plugin->rollback (TEH_plugin->cls);
qs = TEH_plugin->get_purse_deposit (TEH_plugin->cls, qs = TEH_plugin->get_purse_deposit (TEH_plugin->cls,
pcc->purse_pub, &pcc->pd.purse_pub,
&coin->cpi.coin_pub, &coin->cpi.coin_pub,
&amount, &amount,
&h_denom_pub, &h_denom_pub,
@ -357,7 +297,7 @@ create_transaction (void *cls,
{ {
in_conflict = true; in_conflict = true;
qs = TEH_plugin->insert_contract (TEH_plugin->cls, qs = TEH_plugin->insert_contract (TEH_plugin->cls,
pcc->purse_pub, &pcc->pd.purse_pub,
&pcc->econtract, &pcc->econtract,
&in_conflict); &in_conflict);
if (qs < 0) if (qs < 0)
@ -378,7 +318,7 @@ create_transaction (void *cls,
qs = TEH_plugin->select_contract_by_purse ( qs = TEH_plugin->select_contract_by_purse (
TEH_plugin->cls, TEH_plugin->cls,
pcc->purse_pub, &pcc->pd.purse_pub,
&econtract); &econtract);
if (qs <= 0) if (qs <= 0)
{ {
@ -444,7 +384,7 @@ parse_coin (struct MHD_Connection *connection,
(iret = TEH_common_deposit_check_purse_deposit ( (iret = TEH_common_deposit_check_purse_deposit (
connection, connection,
coin, coin,
pcc->purse_pub, &pcc->pd.purse_pub,
pcc->min_age))) pcc->min_age)))
return iret; return iret;
if (0 > if (0 >
@ -472,7 +412,7 @@ TEH_handler_purses_create (
const json_t *root) const json_t *root)
{ {
struct PurseCreateContext pcc = { struct PurseCreateContext pcc = {
.purse_pub = purse_pub, .pd.purse_pub = *purse_pub,
.exchange_timestamp = GNUNET_TIME_timestamp_get () .exchange_timestamp = GNUNET_TIME_timestamp_get ()
}; };
json_t *deposits; json_t *deposits;
@ -481,7 +421,7 @@ TEH_handler_purses_create (
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_amount ("amount", TALER_JSON_spec_amount ("amount",
TEH_currency, TEH_currency,
&pcc.amount), &pcc.pd.target_amount),
GNUNET_JSON_spec_uint32 ("min_age", GNUNET_JSON_spec_uint32 ("min_age",
&pcc.min_age), &pcc.min_age),
GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_mark_optional (
@ -493,11 +433,11 @@ TEH_handler_purses_create (
GNUNET_JSON_spec_fixed_auto ("purse_sig", GNUNET_JSON_spec_fixed_auto ("purse_sig",
&pcc.purse_sig), &pcc.purse_sig),
GNUNET_JSON_spec_fixed_auto ("h_contract_terms", GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
&pcc.h_contract_terms), &pcc.pd.h_contract_terms),
GNUNET_JSON_spec_json ("deposits", GNUNET_JSON_spec_json ("deposits",
&deposits), &deposits),
GNUNET_JSON_spec_timestamp ("purse_expiration", GNUNET_JSON_spec_timestamp ("purse_expiration",
&pcc.purse_expiration), &pcc.pd.purse_expiration),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
const struct TEH_GlobalFee *gf; const struct TEH_GlobalFee *gf;
@ -522,7 +462,7 @@ TEH_handler_purses_create (
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TEH_currency, TALER_amount_set_zero (TEH_currency,
&pcc.deposit_total)); &pcc.deposit_total));
if (GNUNET_TIME_timestamp_cmp (pcc.purse_expiration, if (GNUNET_TIME_timestamp_cmp (pcc.pd.purse_expiration,
<, <,
pcc.exchange_timestamp)) pcc.exchange_timestamp))
{ {
@ -533,7 +473,7 @@ TEH_handler_purses_create (
TALER_EC_EXCHANGE_PURSE_CREATE_EXPIRATION_BEFORE_NOW, TALER_EC_EXCHANGE_PURSE_CREATE_EXPIRATION_BEFORE_NOW,
NULL); NULL);
} }
if (GNUNET_TIME_absolute_is_never (pcc.purse_expiration.abs_time)) if (GNUNET_TIME_absolute_is_never (pcc.pd.purse_expiration.abs_time))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
@ -615,12 +555,12 @@ TEH_handler_purses_create (
if (GNUNET_OK != if (GNUNET_OK !=
TALER_wallet_purse_create_verify ( TALER_wallet_purse_create_verify (
pcc.purse_expiration, pcc.pd.purse_expiration,
&pcc.h_contract_terms, &pcc.pd.h_contract_terms,
&pcc.merge_pub, &pcc.merge_pub,
pcc.min_age, pcc.min_age,
&pcc.amount, &pcc.pd.target_amount,
pcc.purse_pub, &pcc.pd.purse_pub,
&pcc.purse_sig)) &pcc.purse_sig))
{ {
TALER_LOG_WARNING ("Invalid signature on /purses/$PID/create request\n"); TALER_LOG_WARNING ("Invalid signature on /purses/$PID/create request\n");
@ -691,8 +631,10 @@ TEH_handler_purses_create (
{ {
MHD_RESULT res; MHD_RESULT res;
res = reply_create_success (connection, res = TEH_RESPONSE_reply_purse_created (connection,
&pcc); pcc.exchange_timestamp,
&pcc.deposit_total,
&pcc.pd);
for (unsigned int i = 0; i<pcc.num_coins; i++) for (unsigned int i = 0; i<pcc.num_coins; i++)
TEH_common_purse_deposit_free_coin (&pcc.coins[i]); TEH_common_purse_deposit_free_coin (&pcc.coins[i]);
GNUNET_free (pcc.coins); GNUNET_free (pcc.coins);

View File

@ -55,11 +55,6 @@ struct ReservePurseContext
*/ */
struct TALER_ReserveSignatureP reserve_sig; struct TALER_ReserveSignatureP reserve_sig;
/**
* Total amount to be put into the purse.
*/
struct TALER_Amount amount;
/** /**
* Purse fee the client is willing to pay. * Purse fee the client is willing to pay.
*/ */
@ -70,11 +65,6 @@ struct ReservePurseContext
*/ */
struct TALER_Amount deposit_total; struct TALER_Amount deposit_total;
/**
* When should the purse expire.
*/
struct GNUNET_TIME_Timestamp purse_expiration;
/** /**
* Merge time. * Merge time.
*/ */
@ -100,20 +90,15 @@ struct ReservePurseContext
*/ */
struct TALER_PurseMergeSignatureP merge_sig; struct TALER_PurseMergeSignatureP merge_sig;
/**
* Public key of the purse we are creating.
*/
struct TALER_PurseContractPublicKeyP purse_pub;
/** /**
* Signature of the client affiming this request. * Signature of the client affiming this request.
*/ */
struct TALER_PurseContractSignatureP purse_sig; struct TALER_PurseContractSignatureP purse_sig;
/** /**
* Hash of the contract terms of the purse. * Fundamental details about the purse.
*/ */
struct TALER_PrivateContractHashP h_contract_terms; struct TEH_PurseDetails pd;
/** /**
* Minimum age for deposits into this purse. * Minimum age for deposits into this purse.
@ -133,53 +118,6 @@ struct ReservePurseContext
}; };
/**
* Send confirmation of purse creation success to client.
*
* @param connection connection to the client
* @param rpc details about the request that succeeded
* @return MHD result code
*/
static MHD_RESULT
reply_purse_success (struct MHD_Connection *connection,
const struct ReservePurseContext *rpc)
{
struct TALER_ExchangePublicKeyP pub;
struct TALER_ExchangeSignatureP sig;
enum TALER_ErrorCode ec;
if (TALER_EC_NONE !=
(ec = TALER_exchange_online_purse_created_sign (
&TEH_keys_exchange_sign_,
rpc->exchange_timestamp,
rpc->purse_expiration,
&rpc->amount,
&rpc->deposit_total,
&rpc->purse_pub,
&rpc->h_contract_terms,
&pub,
&sig)))
{
GNUNET_break (0);
return TALER_MHD_reply_with_ec (connection,
ec,
NULL);
}
// FIXME: share logic with /purses/$PID/create API!
return TALER_MHD_REPLY_JSON_PACK (
connection,
MHD_HTTP_OK,
TALER_JSON_pack_amount ("total_deposited",
&rpc->deposit_total),
GNUNET_JSON_pack_timestamp ("exchange_timestamp",
rpc->exchange_timestamp),
GNUNET_JSON_pack_data_auto ("exchange_sig",
&sig),
GNUNET_JSON_pack_data_auto ("exchange_pub",
&pub));
}
/** /**
* Execute database transaction for /reserves/$PID/purse. Runs the transaction * Execute database transaction for /reserves/$PID/purse. Runs the transaction
* logic; IF it returns a non-error code, the transaction logic MUST NOT queue * logic; IF it returns a non-error code, the transaction logic MUST NOT queue
@ -207,14 +145,14 @@ purse_transaction (void *cls,
/* 1) store purse */ /* 1) store purse */
qs = TEH_plugin->insert_purse_request ( qs = TEH_plugin->insert_purse_request (
TEH_plugin->cls, TEH_plugin->cls,
&rpc->purse_pub, &rpc->pd.purse_pub,
&rpc->merge_pub, &rpc->merge_pub,
rpc->purse_expiration, rpc->pd.purse_expiration,
&rpc->h_contract_terms, &rpc->pd.h_contract_terms,
rpc->min_age, rpc->min_age,
rpc->flags, rpc->flags,
&rpc->purse_fee, &rpc->purse_fee,
&rpc->amount, &rpc->pd.target_amount,
&rpc->purse_sig, &rpc->purse_sig,
&in_conflict); &in_conflict);
if (qs < 0) if (qs < 0)
@ -245,7 +183,7 @@ purse_transaction (void *cls,
TEH_plugin->rollback (TEH_plugin->cls); TEH_plugin->rollback (TEH_plugin->cls);
qs = TEH_plugin->select_purse_request ( qs = TEH_plugin->select_purse_request (
TEH_plugin->cls, TEH_plugin->cls,
&rpc->purse_pub, &rpc->pd.purse_pub,
&merge_pub, &merge_pub,
&purse_expiration, &purse_expiration,
&h_contract_terms, &h_contract_terms,
@ -299,7 +237,7 @@ purse_transaction (void *cls,
rpc->flags); rpc->flags);
qs = TEH_plugin->do_reserve_purse ( qs = TEH_plugin->do_reserve_purse (
TEH_plugin->cls, TEH_plugin->cls,
&rpc->purse_pub, &rpc->pd.purse_pub,
&rpc->merge_sig, &rpc->merge_sig,
rpc->merge_timestamp, rpc->merge_timestamp,
&rpc->reserve_sig, &rpc->reserve_sig,
@ -412,7 +350,7 @@ purse_transaction (void *cls,
bool in_conflict = true; bool in_conflict = true;
qs = TEH_plugin->insert_contract (TEH_plugin->cls, qs = TEH_plugin->insert_contract (TEH_plugin->cls,
&rpc->purse_pub, &rpc->pd.purse_pub,
&rpc->econtract, &rpc->econtract,
&in_conflict); &in_conflict);
if (qs < 0) if (qs < 0)
@ -433,7 +371,7 @@ purse_transaction (void *cls,
qs = TEH_plugin->select_contract_by_purse ( qs = TEH_plugin->select_contract_by_purse (
TEH_plugin->cls, TEH_plugin->cls,
&rpc->purse_pub, &rpc->pd.purse_pub,
&econtract); &econtract);
if (qs <= 0) if (qs <= 0)
{ {
@ -486,7 +424,7 @@ TEH_handler_reserves_purse (
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_amount ("purse_value", TALER_JSON_spec_amount ("purse_value",
TEH_currency, TEH_currency,
&rpc.amount), &rpc.pd.target_amount),
GNUNET_JSON_spec_uint32 ("min_age", GNUNET_JSON_spec_uint32 ("min_age",
&rpc.min_age), &rpc.min_age),
GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_mark_optional (
@ -505,15 +443,15 @@ TEH_handler_reserves_purse (
GNUNET_JSON_spec_fixed_auto ("reserve_sig", GNUNET_JSON_spec_fixed_auto ("reserve_sig",
&rpc.reserve_sig), &rpc.reserve_sig),
GNUNET_JSON_spec_fixed_auto ("purse_pub", GNUNET_JSON_spec_fixed_auto ("purse_pub",
&rpc.purse_pub), &rpc.pd.purse_pub),
GNUNET_JSON_spec_fixed_auto ("purse_sig", GNUNET_JSON_spec_fixed_auto ("purse_sig",
&rpc.purse_sig), &rpc.purse_sig),
GNUNET_JSON_spec_fixed_auto ("h_contract_terms", GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
&rpc.h_contract_terms), &rpc.pd.h_contract_terms),
GNUNET_JSON_spec_timestamp ("merge_timestamp", GNUNET_JSON_spec_timestamp ("merge_timestamp",
&rpc.merge_timestamp), &rpc.merge_timestamp),
GNUNET_JSON_spec_timestamp ("purse_expiration", GNUNET_JSON_spec_timestamp ("purse_expiration",
&rpc.purse_expiration), &rpc.pd.purse_expiration),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
@ -537,7 +475,7 @@ TEH_handler_reserves_purse (
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TEH_currency, TALER_amount_set_zero (TEH_currency,
&rpc.deposit_total)); &rpc.deposit_total));
if (GNUNET_TIME_timestamp_cmp (rpc.purse_expiration, if (GNUNET_TIME_timestamp_cmp (rpc.pd.purse_expiration,
<, <,
rpc.exchange_timestamp)) rpc.exchange_timestamp))
{ {
@ -548,7 +486,7 @@ TEH_handler_reserves_purse (
TALER_EC_EXCHANGE_RESERVES_PURSE_EXPIRATION_BEFORE_NOW, TALER_EC_EXCHANGE_RESERVES_PURSE_EXPIRATION_BEFORE_NOW,
NULL); NULL);
} }
if (GNUNET_TIME_absolute_is_never (rpc.purse_expiration.abs_time)) if (GNUNET_TIME_absolute_is_never (rpc.pd.purse_expiration.abs_time))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
@ -607,12 +545,12 @@ TEH_handler_reserves_purse (
} }
TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++; TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
if (GNUNET_OK != if (GNUNET_OK !=
TALER_wallet_purse_create_verify (rpc.purse_expiration, TALER_wallet_purse_create_verify (rpc.pd.purse_expiration,
&rpc.h_contract_terms, &rpc.pd.h_contract_terms,
&rpc.merge_pub, &rpc.merge_pub,
rpc.min_age, rpc.min_age,
&rpc.amount, &rpc.pd.target_amount,
&rpc.purse_pub, &rpc.pd.purse_pub,
&rpc.purse_sig)) &rpc.purse_sig))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
@ -626,7 +564,7 @@ TEH_handler_reserves_purse (
if (GNUNET_OK != if (GNUNET_OK !=
TALER_wallet_purse_merge_verify (TEH_base_url, TALER_wallet_purse_merge_verify (TEH_base_url,
rpc.merge_timestamp, rpc.merge_timestamp,
&rpc.purse_pub, &rpc.pd.purse_pub,
&rpc.merge_pub, &rpc.merge_pub,
&rpc.merge_sig)) &rpc.merge_sig))
{ {
@ -640,10 +578,10 @@ TEH_handler_reserves_purse (
} }
if (GNUNET_OK != if (GNUNET_OK !=
TALER_wallet_account_merge_verify (rpc.merge_timestamp, TALER_wallet_account_merge_verify (rpc.merge_timestamp,
&rpc.purse_pub, &rpc.pd.purse_pub,
rpc.purse_expiration, rpc.pd.purse_expiration,
&rpc.h_contract_terms, &rpc.pd.h_contract_terms,
&rpc.amount, &rpc.pd.target_amount,
&rpc.purse_fee, &rpc.purse_fee,
rpc.min_age, rpc.min_age,
rpc.flags, rpc.flags,
@ -663,7 +601,7 @@ TEH_handler_reserves_purse (
TALER_wallet_econtract_upload_verify (rpc.econtract.econtract, TALER_wallet_econtract_upload_verify (rpc.econtract.econtract,
rpc.econtract.econtract_size, rpc.econtract.econtract_size,
&rpc.econtract.contract_pub, &rpc.econtract.contract_pub,
&rpc.purse_pub, &rpc.pd.purse_pub,
&rpc.econtract.econtract_sig)) ) &rpc.econtract.econtract_sig)) )
{ {
TALER_LOG_WARNING ("Invalid signature on /reserves/$PID/purse request\n"); TALER_LOG_WARNING ("Invalid signature on /reserves/$PID/purse request\n");
@ -707,8 +645,10 @@ TEH_handler_reserves_purse (
{ {
MHD_RESULT res; MHD_RESULT res;
res = reply_purse_success (connection, res = TEH_RESPONSE_reply_purse_created (connection,
&rpc); rpc.exchange_timestamp,
&rpc.deposit_total,
&rpc.pd);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
return res; return res;
} }

View File

@ -937,4 +937,46 @@ TEH_RESPONSE_reply_reserve_insufficient_balance (
} }
MHD_RESULT
TEH_RESPONSE_reply_purse_created (
struct MHD_Connection *connection,
struct GNUNET_TIME_Timestamp exchange_timestamp,
const struct TALER_Amount *purse_balance,
const struct TEH_PurseDetails *pd)
{
struct TALER_ExchangePublicKeyP pub;
struct TALER_ExchangeSignatureP sig;
enum TALER_ErrorCode ec;
if (TALER_EC_NONE !=
(ec = TALER_exchange_online_purse_created_sign (
&TEH_keys_exchange_sign_,
exchange_timestamp,
pd->purse_expiration,
&pd->target_amount,
purse_balance,
&pd->purse_pub,
&pd->h_contract_terms,
&pub,
&sig)))
{
GNUNET_break (0);
return TALER_MHD_reply_with_ec (connection,
ec,
NULL);
}
return TALER_MHD_REPLY_JSON_PACK (
connection,
MHD_HTTP_OK,
TALER_JSON_pack_amount ("total_deposited",
purse_balance),
GNUNET_JSON_pack_timestamp ("exchange_timestamp",
exchange_timestamp),
GNUNET_JSON_pack_data_auto ("exchange_sig",
&sig),
GNUNET_JSON_pack_data_auto ("exchange_pub",
&pub));
}
/* end of taler-exchange-httpd_responses.c */ /* end of taler-exchange-httpd_responses.c */

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014-2019 Taler Systems SA Copyright (C) 2014-2022 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software terms of the GNU Affero General Public License as published by the Free Software
@ -124,6 +124,50 @@ TEH_RESPONSE_reply_coin_insufficient_funds (
const struct TALER_DenominationHashP *h_denom_pub, const struct TALER_DenominationHashP *h_denom_pub,
const struct TALER_CoinSpendPublicKeyP *coin_pub); const struct TALER_CoinSpendPublicKeyP *coin_pub);
/**
* Fundamental details about a purse.
*/
struct TEH_PurseDetails
{
/**
* When should the purse expire.
*/
struct GNUNET_TIME_Timestamp purse_expiration;
/**
* Hash of the contract terms of the purse.
*/
struct TALER_PrivateContractHashP h_contract_terms;
/**
* Public key of the purse we are creating.
*/
struct TALER_PurseContractPublicKeyP purse_pub;
/**
* Total amount to be put into the purse.
*/
struct TALER_Amount target_amount;
};
/**
* Send confirmation that a purse was created with
* the current purse balance.
*
* @param connection connection to the client
* @param pd purse details
* @param exchange_timestamp our time for purse creation
* @param purse_balance current balance in the purse
* @return MHD result code
*/
MHD_RESULT
TEH_RESPONSE_reply_purse_created (
struct MHD_Connection *connection,
struct GNUNET_TIME_Timestamp exchange_timestamp,
const struct TALER_Amount *purse_balance,
const struct TEH_PurseDetails *pd);
/** /**
* Compile the transaction history of a coin into a JSON object. * Compile the transaction history of a coin into a JSON object.