diff options
Diffstat (limited to 'src/exchange/taler-exchange-httpd_transfers_get.c')
-rw-r--r-- | src/exchange/taler-exchange-httpd_transfers_get.c | 222 |
1 files changed, 162 insertions, 60 deletions
diff --git a/src/exchange/taler-exchange-httpd_transfers_get.c b/src/exchange/taler-exchange-httpd_transfers_get.c index e63acdc2a..18d96f955 100644 --- a/src/exchange/taler-exchange-httpd_transfers_get.c +++ b/src/exchange/taler-exchange-httpd_transfers_get.c @@ -51,7 +51,7 @@ struct AggregatedDepositDetail /** * Hash of the contract terms. */ - struct TALER_PrivateContractHash h_contract_terms; + struct TALER_PrivateContractHashP h_contract_terms; /** * Coin's public key of the deposited coin. @@ -59,14 +59,20 @@ struct AggregatedDepositDetail struct TALER_CoinSpendPublicKeyP coin_pub; /** - * Total value of the coin in the deposit. + * Total value of the coin in the deposit (after + * refunds). */ struct TALER_Amount deposit_value; /** - * Fees charged by the exchange for the deposit of this coin. + * Fees charged by the exchange for the deposit of this coin (possibly after reduction due to refunds). */ struct TALER_Amount deposit_fee; + + /** + * Total amount refunded for this coin. + */ + struct TALER_Amount refund_total; }; @@ -89,17 +95,16 @@ reply_transfer_details (struct MHD_Connection *connection, const struct TALER_MerchantPublicKeyP *merchant_pub, const char *payto_uri, const struct TALER_Amount *wire_fee, - struct GNUNET_TIME_Absolute exec_time, + struct GNUNET_TIME_Timestamp exec_time, const struct AggregatedDepositDetail *wdd_head) { json_t *deposits; - struct TALER_WireDepositDetailP dd; struct GNUNET_HashContext *hash_context; - struct TALER_WireDepositDataPS wdp; + struct GNUNET_HashCode h_details; struct TALER_ExchangePublicKeyP pub; struct TALER_ExchangeSignatureP sig; + struct TALER_PaytoHashP h_payto; - GNUNET_TIME_round_abs (&exec_time); deposits = json_array (); GNUNET_assert (NULL != deposits); hash_context = GNUNET_CRYPTO_hash_context_start (); @@ -107,16 +112,12 @@ reply_transfer_details (struct MHD_Connection *connection, NULL != wdd_pos; wdd_pos = wdd_pos->next) { - dd.h_contract_terms = wdd_pos->h_contract_terms; - dd.execution_time = GNUNET_TIME_absolute_hton (exec_time); - dd.coin_pub = wdd_pos->coin_pub; - TALER_amount_hton (&dd.deposit_value, - &wdd_pos->deposit_value); - TALER_amount_hton (&dd.deposit_fee, - &wdd_pos->deposit_fee); - GNUNET_CRYPTO_hash_context_read (hash_context, - &dd, - sizeof (struct TALER_WireDepositDetailP)); + TALER_exchange_online_wire_deposit_append (hash_context, + &wdd_pos->h_contract_terms, + exec_time, + &wdd_pos->coin_pub, + &wdd_pos->deposit_value, + &wdd_pos->deposit_fee); if (0 != json_array_append_new ( deposits, @@ -125,6 +126,13 @@ reply_transfer_details (struct MHD_Connection *connection, &wdd_pos->h_contract_terms), GNUNET_JSON_pack_data_auto ("coin_pub", &wdd_pos->coin_pub), + + GNUNET_JSON_pack_allow_null ( + TALER_JSON_pack_amount ("refund_total", + TALER_amount_is_zero ( + &wdd_pos->refund_total) + ? NULL + : &wdd_pos->refund_total)), TALER_JSON_pack_amount ("deposit_value", &wdd_pos->deposit_value), TALER_JSON_pack_amount ("deposit_fee", @@ -138,24 +146,21 @@ reply_transfer_details (struct MHD_Connection *connection, "json_array_append_new() failed"); } } - wdp.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT); - wdp.purpose.size = htonl (sizeof (struct TALER_WireDepositDataPS)); - TALER_amount_hton (&wdp.total, - total); - TALER_amount_hton (&wdp.wire_fee, - wire_fee); - wdp.merchant_pub = *merchant_pub; - TALER_payto_hash (payto_uri, - &wdp.h_payto); GNUNET_CRYPTO_hash_context_finish (hash_context, - &wdp.h_details); + &h_details); { enum TALER_ErrorCode ec; if (TALER_EC_NONE != - (ec = TEH_keys_exchange_sign (&wdp, - &pub, - &sig))) + (ec = TALER_exchange_online_wire_deposit_sign ( + &TEH_keys_exchange_sign_, + total, + wire_fee, + merchant_pub, + payto_uri, + &h_details, + &pub, + &sig))) { json_decref (deposits); return TALER_MHD_reply_with_ec (connection, @@ -164,6 +169,8 @@ reply_transfer_details (struct MHD_Connection *connection, } } + TALER_payto_hash (payto_uri, + &h_payto); return TALER_MHD_REPLY_JSON_PACK ( connection, MHD_HTTP_OK, @@ -174,9 +181,9 @@ reply_transfer_details (struct MHD_Connection *connection, GNUNET_JSON_pack_data_auto ("merchant_pub", merchant_pub), GNUNET_JSON_pack_data_auto ("h_payto", - &wdp.h_payto), - GNUNET_JSON_pack_time_abs ("execution_time", - exec_time), + &h_payto), + GNUNET_JSON_pack_timestamp ("execution_time", + exec_time), GNUNET_JSON_pack_array_steal ("deposits", deposits), GNUNET_JSON_pack_data_auto ("exchange_sig", @@ -212,14 +219,14 @@ struct WtidTransactionContext struct TALER_MerchantPublicKeyP merchant_pub; /** - * Wire fee applicable at @e exec_time. + * Wire fees applicable at @e exec_time. */ - struct TALER_Amount wire_fee; + struct TALER_WireFeeSet fees; /** * Execution time of the wire transfer */ - struct GNUNET_TIME_Absolute exec_time; + struct GNUNET_TIME_Timestamp exec_time; /** * Head of DLL with deposit details for transfers GET response. @@ -254,6 +261,31 @@ struct WtidTransactionContext /** + * Callback that totals up the applicable refunds. + * + * @param cls a `struct TALER_Amount` where we keep the total + * @param amount_with_fee amount being refunded + */ +static enum GNUNET_GenericReturnValue +add_refunds (void *cls, + const struct TALER_Amount *amount_with_fee) + +{ + struct TALER_Amount *total = cls; + + if (0 > + TALER_amount_add (total, + total, + amount_with_fee)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** * Function called with the results of the lookup of the individual deposits * that were aggregated for the given wire transfer. * @@ -261,31 +293,101 @@ struct WtidTransactionContext * @param rowid which row in the DB is the information from (for diagnostics), ignored * @param merchant_pub public key of the merchant (should be same for all callbacks with the same @e cls) * @param account_payto_uri where the funds were sent + * @param h_payto hash over @a account_payto_uri as it is in the DB * @param exec_time execution time of the wire transfer (should be same for all callbacks with the same @e cls) * @param h_contract_terms which proposal was this payment about * @param denom_pub denomination public key of the @a coin_pub (ignored) * @param coin_pub which public key was this payment about - * @param deposit_value amount contributed by this coin in total + * @param deposit_value amount contributed by this coin in total (including fee) * @param deposit_fee deposit fee charged by exchange for this coin */ static void -handle_deposit_data (void *cls, - uint64_t rowid, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const char *account_payto_uri, - struct GNUNET_TIME_Absolute exec_time, - const struct TALER_PrivateContractHash *h_contract_terms, - const struct TALER_DenominationPublicKey *denom_pub, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_Amount *deposit_value, - const struct TALER_Amount *deposit_fee) +handle_deposit_data ( + void *cls, + uint64_t rowid, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const char *account_payto_uri, + const struct TALER_PaytoHashP *h_payto, + struct GNUNET_TIME_Timestamp exec_time, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_DenominationPublicKey *denom_pub, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_Amount *deposit_value, + const struct TALER_Amount *deposit_fee) { struct WtidTransactionContext *ctx = cls; + struct TALER_Amount total_refunds; + struct TALER_Amount dval; + struct TALER_Amount dfee; + enum GNUNET_DB_QueryStatus qs; (void) rowid; (void) denom_pub; + (void) h_payto; if (GNUNET_SYSERR == ctx->is_valid) return; + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (deposit_value->currency, + &total_refunds)); + qs = TEH_plugin->select_refunds_by_coin (TEH_plugin->cls, + coin_pub, + merchant_pub, + h_contract_terms, + &add_refunds, + &total_refunds); + if (qs < 0) + { + GNUNET_break (0); + ctx->is_valid = GNUNET_SYSERR; + return; + } + if (1 == + TALER_amount_cmp (&total_refunds, + deposit_value)) + { + /* Refunds exceeded total deposit? not OK! */ + GNUNET_break (0); + ctx->is_valid = GNUNET_SYSERR; + return; + } + if (0 == + TALER_amount_cmp (&total_refunds, + deposit_value)) + { + /* total_refunds == deposit_value; + in this case, the total contributed to the + wire transfer is zero (as are fees) */ + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (deposit_value->currency, + &dval)); + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (deposit_value->currency, + &dfee)); + + } + else + { + /* Compute deposit value by subtracting refunds */ + GNUNET_assert (0 < + TALER_amount_subtract (&dval, + deposit_value, + &total_refunds)); + if (-1 == + TALER_amount_cmp (&dval, + deposit_fee)) + { + /* dval < deposit_fee, so after refunds less than + the deposit fee remains; reduce deposit fee to + the remaining value of the coin */ + dfee = dval; + } + else + { + /* Partial refund, deposit fee remains */ + dfee = *deposit_fee; + } + } + if (GNUNET_NO == ctx->is_valid) { /* First one we encounter, setup general information in 'ctx' */ @@ -295,8 +397,8 @@ handle_deposit_data (void *cls, ctx->is_valid = GNUNET_YES; if (0 > TALER_amount_subtract (&ctx->total, - deposit_value, - deposit_fee)) + &dval, + &dfee)) { GNUNET_break (0); ctx->is_valid = GNUNET_SYSERR; @@ -320,8 +422,8 @@ handle_deposit_data (void *cls, } if (0 > TALER_amount_subtract (&delta, - deposit_value, - deposit_fee)) + &dval, + &dfee)) { GNUNET_break (0); ctx->is_valid = GNUNET_SYSERR; @@ -342,8 +444,9 @@ handle_deposit_data (void *cls, struct AggregatedDepositDetail *wdd; wdd = GNUNET_new (struct AggregatedDepositDetail); - wdd->deposit_value = *deposit_value; - wdd->deposit_fee = *deposit_fee; + wdd->deposit_value = dval; + wdd->deposit_fee = dfee; + wdd->refund_total = total_refunds; wdd->h_contract_terms = *h_contract_terms; wdd->coin_pub = *coin_pub; GNUNET_CONTAINER_DLL_insert (ctx->wdd_head, @@ -397,10 +500,9 @@ get_transfer_deposits (void *cls, { struct WtidTransactionContext *ctx = cls; enum GNUNET_DB_QueryStatus qs; - struct GNUNET_TIME_Absolute wire_fee_start_date; - struct GNUNET_TIME_Absolute wire_fee_end_date; + struct GNUNET_TIME_Timestamp wire_fee_start_date; + struct GNUNET_TIME_Timestamp wire_fee_end_date; struct TALER_MasterSignatureP wire_fee_master_sig; - struct TALER_Amount closing_fee; /* resetting to NULL/0 in case transaction was repeated after serialization failure */ @@ -456,8 +558,7 @@ get_transfer_deposits (void *cls, ctx->exec_time, &wire_fee_start_date, &wire_fee_end_date, - &ctx->wire_fee, - &closing_fee, + &ctx->fees, &wire_fee_master_sig); GNUNET_free (wire_method); } @@ -477,7 +578,7 @@ get_transfer_deposits (void *cls, if (0 > TALER_amount_subtract (&ctx->total, &ctx->total, - &ctx->wire_fee)) + &ctx->fees.wire)) { GNUNET_break (0); *mhd_ret = TALER_MHD_reply_with_error (connection, @@ -515,6 +616,7 @@ TEH_handler_transfers_get (struct TEH_RequestContext *rc, if (GNUNET_OK != TEH_DB_run_transaction (rc->connection, "run transfers GET", + TEH_MT_REQUEST_OTHER, &mhd_ret, &get_transfer_deposits, &ctx)) @@ -526,7 +628,7 @@ TEH_handler_transfers_get (struct TEH_RequestContext *rc, &ctx.total, &ctx.merchant_pub, ctx.payto_uri, - &ctx.wire_fee, + &ctx.fees.wire, ctx.exec_time, ctx.wdd_head); free_ctx (&ctx); |