commit ae162bb9512a246afd9b8dbf2ee4b07f88e91fda parent d54a086f05da629d91dc009e76f6cd84a8fac0d8 Author: Christian Grothoff <christian@grothoff.org> Date: Mon, 9 Mar 2026 17:13:48 +0100 need to return accumulated_total_without_fee in /batch-deposit Diffstat:
19 files changed, 242 insertions(+), 22 deletions(-)
diff --git a/bootstrap b/bootstrap @@ -30,6 +30,7 @@ existence() for n in 0001 0002 0003 0004 0005 0006 0007 0008 do chmod -w src/exchangedb/exchange-$n.sql* + chmod -w src/exchangedb/$n-*.sql &> /dev/null || true done for n in 0001 do @@ -38,6 +39,7 @@ done for n in 0001 0002 do chmod -w src/auditordb/auditor-$n.sql* + chmod -w src/auditordb/$n-*.sql &> /dev/null || true done if existence uncrustify; then diff --git a/src/benchmark/taler-aggregator-benchmark.c b/src/benchmark/taler-aggregator-benchmark.c @@ -318,19 +318,29 @@ add_deposit (const struct Merchant *m) <, bd.refund_deadline)); - make_amount (1, 0, &deposit.amount_with_fee); + make_amount (1, + 0, + &deposit.amount_with_fee); { struct GNUNET_TIME_Timestamp now; + struct TALER_Amount deposit_fee; + struct TALER_Amount total; bool balance_ok; uint32_t bad_idx; bool conflict; + GNUNET_assert (1 == bd.num_cdis); + make_amount (0, + 0, + &deposit_fee); now = random_time (); if (0 >= plugin->do_deposit (plugin->cls, &bd, + &deposit_fee, &now, + &total, &balance_ok, &bad_idx, &conflict)) diff --git a/src/exchange/taler-exchange-httpd_batch-deposit.c b/src/exchange/taler-exchange-httpd_batch-deposit.c @@ -269,6 +269,8 @@ bdc_phase_reply_success ( MHD_HTTP_OK, GNUNET_JSON_pack_timestamp ("exchange_timestamp", bdc->exchange_timestamp), + TALER_JSON_pack_amount ("accumulated_total_without_fee", + &bdc->accumulated_total_without_fee), GNUNET_JSON_pack_data_auto ("exchange_pub", &pub), GNUNET_JSON_pack_data_auto ("exchange_sig", @@ -336,11 +338,12 @@ batch_deposit_transaction (void *cls, if (qs < 0) return qs; } - qs = TEH_plugin->do_deposit ( TEH_plugin->cls, bd, + bdc->deposit_fees, &bdc->exchange_timestamp, + &bdc->accumulated_total_without_fee, &balance_ok, &bad_balance_coin_index, &in_conflict); diff --git a/src/exchange/taler-exchange-sanctionscheck.c b/src/exchange/taler-exchange-sanctionscheck.c @@ -179,7 +179,7 @@ sync_row (void) uint64_t r = GNUNET_htonll (min_row_id); ssize_t rval; - GNUNET_break (-1 != min_row_fd); + GNUNET_assert (-1 != min_row_fd); GNUNET_break (0 == lseek (min_row_fd, 0, SEEK_SET)); diff --git a/src/exchangedb/0002-batch_deposits.sql b/src/exchangedb/0002-batch_deposits.sql @@ -94,7 +94,7 @@ BEGIN ,partition_suffix ); PERFORM comment_partitioned_column( - 'total amount' + 'total amount deposited for this contract ever, including deposit fees' ,'total_amount' ,'batch_deposits' ,partition_suffix diff --git a/src/exchangedb/0009-batch_deposits.sql b/src/exchangedb/0009-batch_deposits.sql @@ -0,0 +1,46 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2026 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/> +-- + +CREATE FUNCTION alter_table_batch_deposits9() +RETURNS void +LANGUAGE plpgsql +AS $$ +BEGIN + -- This works because at the time of the migration + -- supported production systems did not NOT use any fees. + -- Otherwise, we'd have to iterate over the coins + -- deposited in this batch and subtract the deposit fees here. + ALTER TABLE batch_deposits + ADD COLUMN total_without_fee taler_amount; + UPDATE batch_deposits + SET total_without_fee=total_amount; + ALTER TABLE batch_deposits + ALTER COLUMN total_without_fee SET NOT NULL; +END +$$; + +INSERT INTO exchange_tables + (name + ,version + ,action + ,partitioned + ,by_range) + VALUES + ('batch_deposits9' + ,'exchange-0009' + ,'alter' + ,TRUE + ,FALSE); diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am @@ -25,13 +25,11 @@ sqlinputs = \ exchange_do_*.sql \ exchange_statistics_*.sql \ exchange_trigger_*.sql \ - procedures.sql.in \ + *.sql.in \ 0002-*.sql \ - exchange-0002.sql.in \ 0003-*.sql \ - exchange-0003.sql.in \ 0004-*.sql \ - exchange-0004.sql.in + 0009-*.sql sql_DATA = \ benchmark-0001.sql \ @@ -45,6 +43,7 @@ sql_DATA = \ exchange-0006.sql \ exchange-0007.sql \ exchange-0008.sql \ + exchange-0009.sql \ drop.sql \ procedures.sql \ tops-0001.sql @@ -59,6 +58,7 @@ CLEANFILES = \ exchange-0002.sql \ exchange-0003.sql \ exchange-0004.sql \ + exchange-0009.sql \ procedures.sql procedures.sql: procedures.sql.in exchange_do_*.sql exchange_statistics_*.sql exchange_trigger_*.sql @@ -81,6 +81,11 @@ exchange-0004.sql: exchange-0004.sql.in 0004-*.sql gcc -E -P -undef - < exchange-0004.sql.in 2>/dev/null | sed -e "s/--.*//" | awk 'NF' - >$@ chmod ugo-w $@ +exchange-0009.sql: exchange-0009.sql.in 0009-*.sql + chmod +w $@ 2> /dev/null || true + gcc -E -P -undef - < exchange-0009.sql.in 2>/dev/null | sed -e "s/--.*//" | awk 'NF' - >$@ + chmod ugo-w $@ + check_SCRIPTS = \ test_idempotency.sh diff --git a/src/exchangedb/exchange-0009.sql.in b/src/exchangedb/exchange-0009.sql.in @@ -0,0 +1,24 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2026 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/> +-- + +BEGIN; + +SELECT _v.register_patch('exchange-0009', NULL, NULL); +SET search_path TO exchange; + +#include "0009-batch_deposits.sql" + +COMMIT; diff --git a/src/exchangedb/exchange_do_deposit.sql b/src/exchangedb/exchange_do_deposit.sql @@ -37,10 +37,13 @@ CREATE FUNCTION exchange_do_deposit( IN ina_coin_pub BYTEA[], IN ina_coin_sig BYTEA[], IN ina_amount_with_fee taler_amount[], + IN ina_deposit_fee taler_amount[], IN in_total_amount taler_amount, + IN in_total_without_fee taler_amount, IN in_is_wallet BOOL, IN in_extra_wire_subject_metadata TEXT, OUT out_exchange_timestamp INT8, + OUT out_accumulated_total_without_fee taler_amount, OUT out_insufficient_balance_coin_index INT4, -- index of coin with bad balance, NULL if none OUT out_conflict BOOL ) @@ -52,10 +55,12 @@ DECLARE i INT4; my_record RECORD; ini_amount_with_fee taler_amount; + ini_deposit_fee taler_amount; ini_coin_pub BYTEA; ini_coin_sig BYTEA; my_update BOOL := FALSE; my_total taler_amount; + my_total_without_fee taler_amount; BEGIN -- Shards: -- INSERT wire_targets (by h_payto), ON CONFLICT DO NOTHING; @@ -113,6 +118,7 @@ INSERT INTO batch_deposits ,policy_details_serial_id ,policy_blocked ,total_amount + ,total_without_fee ,extra_wire_subject_metadata ) VALUES ( in_shard @@ -129,6 +135,7 @@ INSERT INTO batch_deposits ,in_policy_details_serial_id ,in_policy_blocked ,in_total_amount + ,in_total_without_fee ,in_extra_wire_subject_metadata) ON CONFLICT DO NOTHING -- for CONFLICT ON (merchant_pub, h_contract_terms) RETURNING @@ -136,8 +143,11 @@ INSERT INTO batch_deposits INTO bdsi; -IF NOT FOUND +IF FOUND THEN + -- First batch deposit, we can skip all the 'my_update' logic! + out_accumulated_total_without_fee = in_total_without_fee; +ELSE -- Idempotency check: see if an identical record exists. -- We do select over merchant_pub, h_contract_terms and wire_target_h_payto -- first to maximally increase the chance of using the existing index. @@ -145,6 +155,7 @@ THEN exchange_timestamp ,batch_deposit_serial_id ,total_amount + ,total_without_fee INTO my_record FROM batch_deposits @@ -170,6 +181,7 @@ THEN out_exchange_timestamp = my_record.exchange_timestamp; bdsi = my_record.batch_deposit_serial_id; my_total = my_record.total_amount; + my_total_without_fee = my_record.total_without_fee; my_update = TRUE; END IF; @@ -182,6 +194,7 @@ LOOP ini_coin_pub = ina_coin_pub[i]; ini_coin_sig = ina_coin_sig[i]; ini_amount_with_fee = ina_amount_with_fee[i]; + ini_deposit_fee = ina_deposit_fee[i]; INSERT INTO coin_deposits (batch_deposit_serial_id @@ -199,14 +212,6 @@ LOOP IF FOUND THEN -- Insert did happen, update balance in known_coins! - IF my_update - THEN - SELECT * - INTO my_total - FROM amount_add (my_total, - ini_amount_with_fee); - END IF; - UPDATE known_coins kc SET remaining.frac=(kc.remaining).frac-ini_amount_with_fee.frac @@ -233,6 +238,23 @@ LOOP out_insufficient_balance_coin_index=i-1; RETURN; END IF; + + IF my_update + THEN + -- Prepare to update totals in batch_deposits + SELECT * + INTO my_total + FROM amount_add (my_total, + ini_amount_with_fee); + SELECT * + INTO my_total_without_fee + FROM amount_add (my_total_without_fee, + ini_amount_with_fee); + SELECT diff + INTO my_total_without_fee + FROM amount_left_minus_right (my_total_without_fee, + ini_deposit_fee); + END IF; END IF; END LOOP; -- end FOR all coins @@ -240,9 +262,11 @@ IF my_update THEN UPDATE batch_deposits SET total_amount = my_total + ,total_without_fee = my_total_without_fee WHERE batch_deposit_serial_id = bdsi AND merchant_pub = in_merchant_pub AND h_contract_terms = in_h_contract_terms; + out_accumulated_total_without_fee = my_total_without_fee; END IF; END $$; diff --git a/src/exchangedb/perf_deposits_get_ready.c b/src/exchangedb/perf_deposits_get_ready.c @@ -427,15 +427,19 @@ run (void *cls) } { struct GNUNET_TIME_Timestamp now; + struct TALER_Amount total; bool balance_ok; uint32_t bad_idx; bool ctr_conflict; + GNUNET_assert (1 == bd.num_cdis); now = GNUNET_TIME_timestamp_get (); FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->do_deposit (plugin->cls, &bd, + &fees.deposit, &now, + &total, &balance_ok, &bad_idx, &ctr_conflict)); diff --git a/src/exchangedb/perf_select_refunds_by_coin.c b/src/exchangedb/perf_select_refunds_by_coin.c @@ -410,15 +410,19 @@ run (void *cls) } { struct GNUNET_TIME_Timestamp now; + struct TALER_Amount total; bool balance_ok; uint32_t bad_idx; bool in_conflict; now = GNUNET_TIME_timestamp_get (); + GNUNET_assert (1 == bd.num_cdis); FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->do_deposit (plugin->cls, &bd, + &fees.deposit, &now, + &total, &balance_ok, &bad_idx, &in_conflict)); diff --git a/src/exchangedb/pg_do_deposit.c b/src/exchangedb/pg_do_deposit.c @@ -31,7 +31,9 @@ enum GNUNET_DB_QueryStatus TEH_PG_do_deposit ( void *cls, const struct TALER_EXCHANGEDB_BatchDeposit *bd, + const struct TALER_Amount deposit_fees[], struct GNUNET_TIME_Timestamp *exchange_timestamp, + struct TALER_Amount *accumulated_total_without_fee, bool *balance_ok, uint32_t *bad_balance_index, bool *ctr_conflict) @@ -42,6 +44,7 @@ TEH_PG_do_deposit ( const struct TALER_CoinSpendSignatureP *coin_sigs[GNUNET_NZL (bd->num_cdis)]; struct TALER_Amount amounts_with_fee[GNUNET_NZL (bd->num_cdis)]; struct TALER_Amount total_amount; + struct TALER_Amount total_without_fee; struct TALER_NormalizedPaytoHashP h_normalized_payto; struct GNUNET_PQ_QueryParam params[] = { /* data for batch_deposits */ @@ -75,8 +78,13 @@ TEH_PG_do_deposit ( TALER_PQ_query_param_array_amount (bd->num_cdis, amounts_with_fee, pg->conn), + TALER_PQ_query_param_array_amount (bd->num_cdis, + deposit_fees, + pg->conn), TALER_PQ_query_param_amount (pg->conn, &total_amount), + TALER_PQ_query_param_amount (pg->conn, + &total_without_fee), GNUNET_PQ_query_param_bool (TALER_payto_is_wallet ( bd->receiver_wire_account.full_payto)), NULL == bd->extra_wire_subject_metadata @@ -85,12 +93,17 @@ TEH_PG_do_deposit ( GNUNET_PQ_query_param_end }; bool no_time; + bool no_amount; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_timestamp ("exchange_timestamp", exchange_timestamp), &no_time), GNUNET_PQ_result_spec_allow_null ( + TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total_without_fee", + accumulated_total_without_fee), + &no_amount), + GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_uint32 ("insufficient_balance_coin_index", bad_balance_index), balance_ok), @@ -111,6 +124,7 @@ TEH_PG_do_deposit ( if (0 == i) { total_amount = cdi->amount_with_fee; + total_without_fee = cdi->amount_with_fee; } else { @@ -118,7 +132,17 @@ TEH_PG_do_deposit ( TALER_amount_add (&total_amount, &total_amount, &cdi->amount_with_fee)); + GNUNET_assert (0 <= + TALER_amount_add (&total_without_fee, + &total_without_fee, + &cdi->amount_with_fee)); } + GNUNET_assert (0 <= + TALER_amount_subtract ( + &total_without_fee, + &total_without_fee, + &deposit_fees[i])); + amounts_with_fee[i] = cdi->amount_with_fee; coin_pubs[i] = &cdi->coin.coin_pub; coin_sigs[i] = &cdi->csig; @@ -131,16 +155,21 @@ TEH_PG_do_deposit ( "call_deposit", "SELECT " " out_exchange_timestamp AS exchange_timestamp" + ",out_accumulated_total_without_fee AS accumulated_total_without_fee" ",out_insufficient_balance_coin_index AS insufficient_balance_coin_index" ",out_conflict AS conflicted" " FROM exchange_do_deposit" " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10" ",$11,$12,$13,$14,$15,$16,$17,$18,$19,$20" - ",$21);"); + ",$21,$22,$23);"); qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "call_deposit", params, rs); GNUNET_PQ_cleanup_query_params_closures (params); + if (no_amount) + memset (accumulated_total_without_fee, + 0, + sizeof (struct TALER_Amount)); return qs; } diff --git a/src/exchangedb/pg_do_deposit.h b/src/exchangedb/pg_do_deposit.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2022 Taler Systems SA + Copyright (C) 2022, 2026 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 @@ -32,7 +32,11 @@ * * @param cls the `struct PostgresClosure` with the plugin-specific state * @param bd batch deposit operation details + * @param deposit_fees array of "bd->num_cids" deposit fees + * of the respective coins * @param[in,out] exchange_timestamp time to use for the deposit (possibly updated) + * @param[out] accumulated_total_without_fee set to the sum of all deposits + * made for this merchant and contract (minus deposit fees) * @param[out] balance_ok set to true if the balance was sufficient * @param[out] bad_balance_index set to the first index of a coin for which the balance was insufficient, * only used if @a balance_ok is set to false. @@ -43,7 +47,9 @@ enum GNUNET_DB_QueryStatus TEH_PG_do_deposit ( void *cls, const struct TALER_EXCHANGEDB_BatchDeposit *bd, + const struct TALER_Amount deposit_fees[], struct GNUNET_TIME_Timestamp *exchange_timestamp, + struct TALER_Amount *accumulated_total_without_fee, bool *balance_ok, uint32_t *bad_balance_index, bool *in_conflict); diff --git a/src/include/taler/taler-exchange/post-batch-deposit.h b/src/include/taler/taler-exchange/post-batch-deposit.h @@ -221,6 +221,12 @@ struct TALER_EXCHANGE_PostBatchDepositResponse */ const char *transaction_base_url; + /** + * Total amount deposited so far under this contract terms for + * this merchant. + */ + struct TALER_Amount accumulated_total_without_fee; + } ok; /** diff --git a/src/include/taler/taler_exchangedb_plugin.h b/src/include/taler/taler_exchangedb_plugin.h @@ -4448,7 +4448,11 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls the `struct PostgresClosure` with the plugin-specific state * @param bd batch deposit operation details + * @param deposit_fees array of "bd->num_cids" deposit fees + * of the respective coins * @param[in,out] exchange_timestamp time to use for the deposit (possibly updated) + * @param[out] accumulated_total_without_fee set to the sum of all deposits + * made for this merchant and contract (minus deposit fees) * @param[out] balance_ok set to true if the balance was sufficient * @param[out] bad_balance_index set to the first index of a coin for which the balance was insufficient, * only used if @a balance_ok is set to false. @@ -4459,7 +4463,9 @@ struct TALER_EXCHANGEDB_Plugin (*do_deposit)( void *cls, const struct TALER_EXCHANGEDB_BatchDeposit *bd, + const struct TALER_Amount deposit_fees[], struct GNUNET_TIME_Timestamp *exchange_timestamp, + struct TALER_Amount *accumulated_total_without_fee, bool *balance_ok, uint32_t *bad_balance_index, bool *ctr_conflict); diff --git a/src/lib/exchange_api_post-batch-deposit.c b/src/lib/exchange_api_post-batch-deposit.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2024 Taler Systems SA + Copyright (C) 2014-2026 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 @@ -323,6 +323,12 @@ auditor_cb (void *cls, &spk->master_sig, &acc_confirmation_cb, aie); + if (NULL == aie->dch) + { + GNUNET_break (0); + GNUNET_free (aie); + return; + } GNUNET_CONTAINER_DLL_insert (dh->ai_head, dh->ai_tail, aie); @@ -357,12 +363,19 @@ handle_deposit_finished (void *cls, break; case MHD_HTTP_OK: { + bool prev33; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_fixed_auto ("exchange_sig", &dh->exchange_sig), GNUNET_JSON_spec_fixed_auto ("exchange_pub", &dh->exchange_pub), GNUNET_JSON_spec_mark_optional ( + TALER_JSON_spec_amount ( + "accumulated_total_without_fee", + dh->total_without_fee.currency, + &dr->details.ok.accumulated_total_without_fee), + &prev33), + GNUNET_JSON_spec_mark_optional ( TALER_JSON_spec_web_url ("transaction_base_url", &dr->details.ok.transaction_base_url), NULL), @@ -390,6 +403,19 @@ handle_deposit_finished (void *cls, dr->hr.ec = TALER_EC_EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE; break; } + if (prev33) + dr->details.ok.accumulated_total_without_fee + = dh->total_without_fee; + if (1 == + TALER_amount_cmp (&dh->total_without_fee, + &dr->details.ok.accumulated_total_without_fee)) + { + /* Amount signed by exchange is SMALLER than what we deposited */ + GNUNET_break_op (0); + dr->hr.http_status = 0; + dr->hr.ec = TALER_EC_EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE; + break; + } { const struct TALER_CoinSpendSignatureP *csigs[ GNUNET_NZL (dh->num_cdds)]; @@ -404,7 +430,7 @@ handle_deposit_finished (void *cls, dh->exchange_timestamp, dh->dcd.wire_deadline, dh->dcd.refund_deadline, - &dh->total_without_fee, + &dr->details.ok.accumulated_total_without_fee, dh->num_cdds, csigs, &dh->dcd.merchant_pub, @@ -417,6 +443,7 @@ handle_deposit_finished (void *cls, break; } } + dh->total_without_fee = dr->details.ok.accumulated_total_without_fee; TALER_EXCHANGE_get_auditors_for_dc_ (dh->keys, &auditor_cb, dh); diff --git a/src/testing/testing_api_cmd_auditor_deposit_confirmation.c b/src/testing/testing_api_cmd_auditor_deposit_confirmation.c @@ -201,6 +201,7 @@ deposit_confirmation_run (void *cls, struct GNUNET_TIME_Timestamp refund_deadline = GNUNET_TIME_UNIT_ZERO_TS; struct TALER_Amount amount_without_fee; + const struct TALER_Amount *cumulative_total; struct TALER_CoinSpendPublicKeyP coin_pubs[dcs->num_coins]; const struct TALER_CoinSpendPublicKeyP *coin_pubps[dcs->num_coins]; const struct TALER_CoinSpendSignatureP *coin_sigps[dcs->num_coins]; @@ -257,6 +258,9 @@ deposit_confirmation_run (void *cls, 0, &exchange_sig)); GNUNET_assert (GNUNET_OK == + TALER_TESTING_get_trait_amount (deposit_cmd, + &cumulative_total)); + GNUNET_assert (GNUNET_OK == TALER_TESTING_get_trait_timestamp (deposit_cmd, 0, &exchange_timestamp)); @@ -333,6 +337,16 @@ deposit_confirmation_run (void *cls, if (GNUNET_TIME_absolute_is_zero (refund_deadline.abs_time)) refund_deadline = timestamp; } + if (-1 == + TALER_amount_cmp (cumulative_total, + &amount_without_fee)) + { + + /* Cumulative must not below the amount we deposited this time */ + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } dcs->dc = TALER_AUDITOR_deposit_confirmation ( TALER_TESTING_interpreter_get_context (is), auditor_url, @@ -342,7 +356,7 @@ deposit_confirmation_run (void *cls, *exchange_timestamp, *wire_deadline, refund_deadline, - &amount_without_fee, + cumulative_total, dcs->num_coins, coin_pubps, coin_sigps, diff --git a/src/testing/testing_api_cmd_deposit.c b/src/testing/testing_api_cmd_deposit.c @@ -176,6 +176,11 @@ struct DepositState struct TALER_ExchangeSignatureP exchange_sig; /** + * Cumulative total the @e exchange_sig signed over. + */ + struct TALER_Amount cumulative_total; + + /** * Reference to previous deposit operation. * Only present if we're supposed to replay the previous deposit. */ @@ -284,6 +289,7 @@ deposit_cb (void *cls, ds->exchange_timestamp = dr->details.ok.deposit_timestamp; ds->exchange_pub = *dr->details.ok.exchange_pub; ds->exchange_sig = *dr->details.ok.exchange_sig; + ds->cumulative_total = dr->details.ok.accumulated_total_without_fee; } TALER_TESTING_interpreter_next (ds->is); } @@ -689,6 +695,7 @@ deposit_traits (void *cls, &ds->exchange_pub), TALER_TESTING_make_trait_exchange_sig (0, &ds->exchange_sig), + TALER_TESTING_make_trait_amount (&ds->cumulative_total), /* These traits are always available */ TALER_TESTING_make_trait_coin_history (0, &ds->che), diff --git a/src/testing/testing_api_cmd_insert_deposit.c b/src/testing/testing_api_cmd_insert_deposit.c @@ -280,6 +280,7 @@ insert_deposit_run (void *cls, /* finally, actually perform the DB operation */ { uint64_t known_coin_id; + struct TALER_Amount total; struct TALER_DenominationHashP dph; struct TALER_AgeCommitmentHashP agh; bool balance_ok; @@ -298,7 +299,9 @@ insert_deposit_run (void *cls, (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != ids->plugin->do_deposit (ids->plugin->cls, &bd, + &issue.fees.deposit, &ids->exchange_timestamp, + &total, &balance_ok, &bad_index, &ctr_conflict)) ||