LCOV - code coverage report
Current view: top level - exchangedb - get_pending_aggregation.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 11 11
Test Date: 2026-09-11 18:55:36 Functions: 100.0 % 1 1

            Line data    Source code
       1              : /*
       2              :    This file is part of TALER
       3              :    Copyright (C) 2026 Taler Systems SA
       4              : 
       5              :    TALER is free software; you can redistribute it and/or modify it under the
       6              :    terms of the GNU General Public License as published by the Free Software
       7              :    Foundation; either version 3, or (at your option) any later version.
       8              : 
       9              :    TALER is distributed in the hope that it will be useful, but WITHOUT ANY
      10              :    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
      11              :    A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
      12              : 
      13              :    You should have received a copy of the GNU General Public License along with
      14              :    TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
      15              :  */
      16              : /**
      17              :  * @file src/exchangedb/get_pending_aggregation.c
      18              :  * @brief Implementation of the get_pending_aggregation function for Postgres
      19              :  * @author Christian Grothoff
      20              :  */
      21              : #include "taler/taler_pq_lib.h"
      22              : #include "helper.h"
      23              : #include "exchange-database/get_pending_aggregation.h"
      24              : 
      25              : 
      26              : enum GNUNET_DB_QueryStatus
      27            3 : TALER_EXCHANGEDB_get_pending_aggregation (
      28              :   struct TALER_EXCHANGEDB_PostgresContext *pg,
      29              :   const struct TALER_WireTransferIdentifierRawP *wtid,
      30              :   struct TALER_FullPaytoHashP *wire_target_h_payto,
      31              :   struct TALER_FullPayto *payto_uri,
      32              :   struct TALER_Amount *total_deposited,
      33              :   struct TALER_Amount *total_refunded,
      34              :   struct TALER_Amount *total_deposit_fee)
      35              : {
      36            3 :   struct GNUNET_PQ_QueryParam params[] = {
      37            3 :     GNUNET_PQ_query_param_auto_from_type (wtid),
      38              :     GNUNET_PQ_query_param_end
      39              :   };
      40            3 :   struct GNUNET_PQ_ResultSpec rs[] = {
      41            3 :     GNUNET_PQ_result_spec_auto_from_type ("wire_target_h_payto",
      42              :                                           wire_target_h_payto),
      43            3 :     GNUNET_PQ_result_spec_string ("payto_uri",
      44              :                                   &payto_uri->full_payto),
      45            3 :     TALER_PQ_RESULT_SPEC_AMOUNT ("total_deposited",
      46              :                                  total_deposited),
      47            3 :     TALER_PQ_RESULT_SPEC_AMOUNT ("total_refunded",
      48              :                                  total_refunded),
      49            3 :     TALER_PQ_RESULT_SPEC_AMOUNT ("total_deposit_fee",
      50              :                                  total_deposit_fee),
      51              :     GNUNET_PQ_result_spec_end
      52              :   };
      53              : 
      54              :   /* This mirrors the arithmetic of `exchange_do_aggregate' (see
      55              :      do_aggregate.c) so that the result can be compared with what the exchange
      56              :      itself computed.  The one subtlety worth preserving is
      57              :      `fully_refunded_coins': the exchange does not keep the deposit fee of a
      58              :      coin whose deposit was refunded in full, so neither may we.
      59              : 
      60              :      The `NOT EXISTS' on wire_out is what makes this a *pending* aggregation;
      61              :      once the transfer is executed the query returns no rows and the caller
      62              :      drops the hold. */
      63            3 :   PREPARE (pg,
      64              :            "get_pending_aggregation",
      65              :            "WITH bd AS ("
      66              :            "  SELECT bdep.batch_deposit_serial_id"
      67              :            "        ,bdep.wire_target_h_payto"
      68              :            "    FROM aggregation_tracking atr"
      69              :            "    JOIN batch_deposits bdep"
      70              :            "      USING (batch_deposit_serial_id)"
      71              :            "   WHERE atr.wtid_raw=$1)"
      72              :            " ,cd AS ("
      73              :            "  SELECT cdep.coin_pub"
      74              :            "        ,cdep.batch_deposit_serial_id"
      75              :            "        ,cdep.amount_with_fee AS amount"
      76              :            "    FROM coin_deposits cdep"
      77              :            "   WHERE cdep.batch_deposit_serial_id IN"
      78              :            "         (SELECT batch_deposit_serial_id FROM bd))"
      79              :            " ,ref AS ("
      80              :            "  SELECT r.amount_with_fee AS refund"
      81              :            "        ,r.coin_pub"
      82              :            "        ,r.batch_deposit_serial_id"
      83              :            "    FROM refunds r"
      84              :            "   WHERE r.batch_deposit_serial_id IN"
      85              :            "         (SELECT batch_deposit_serial_id FROM bd))"
      86              :            " ,ref_by_coin AS ("
      87              :            "  SELECT SUM((ref.refund).val) AS sum_val"
      88              :            "        ,SUM((ref.refund).frac) AS sum_frac"
      89              :            "        ,coin_pub"
      90              :            "        ,batch_deposit_serial_id"
      91              :            "    FROM ref"
      92              :            "   GROUP BY coin_pub, batch_deposit_serial_id)"
      93              :            " ,fully_refunded_coins AS ("
      94              :            "  SELECT cd.coin_pub"
      95              :            "        ,cd.batch_deposit_serial_id"
      96              :            "    FROM ref_by_coin n"
      97              :            "    JOIN cd"
      98              :            "      ON (n.coin_pub = cd.coin_pub"
      99              :            "      AND n.batch_deposit_serial_id = cd.batch_deposit_serial_id"
     100              :            "      AND n.sum_val + n.sum_frac / 100000000 = (cd.amount).val"
     101              :            "      AND n.sum_frac % 100000000 = (cd.amount).frac))"
     102              :            " ,fees AS ("
     103              :            "  SELECT denom.fee_deposit AS fee"
     104              :            "    FROM cd"
     105              :            "    JOIN known_coins kc"
     106              :            "      USING (coin_pub)"
     107              :            "    JOIN denominations denom"
     108              :            "      USING (denominations_serial)"
     109              :            "   WHERE (cd.coin_pub, cd.batch_deposit_serial_id) NOT IN"
     110              :            "         (SELECT coin_pub, batch_deposit_serial_id"
     111              :            "            FROM fully_refunded_coins))"
     112              :            "SELECT"
     113              :            "  (SELECT wire_target_h_payto FROM bd LIMIT 1)"
     114              :            "    AS wire_target_h_payto"
     115              :            " ,(SELECT wt.payto_uri"
     116              :            "     FROM wire_targets wt"
     117              :            "    WHERE wt.wire_target_h_payto="
     118              :            "          (SELECT wire_target_h_payto FROM bd LIMIT 1))"
     119              :            "    AS payto_uri"
     120              :            " ,ROW(COALESCE(SUM((cd.amount).val),0)"
     121              :            "      + COALESCE(SUM((cd.amount).frac),0) / 100000000"
     122              :            "     ,COALESCE(SUM((cd.amount).frac),0) % 100000000)::taler_amount"
     123              :            "    AS total_deposited"
     124              :            " ,(SELECT ROW(COALESCE(SUM((ref.refund).val),0)"
     125              :            "              + COALESCE(SUM((ref.refund).frac),0) / 100000000"
     126              :            "             ,COALESCE(SUM((ref.refund).frac),0)"
     127              :            "              % 100000000)::taler_amount"
     128              :            "     FROM ref)"
     129              :            "    AS total_refunded"
     130              :            " ,(SELECT ROW(COALESCE(SUM((fees.fee).val),0)"
     131              :            "              + COALESCE(SUM((fees.fee).frac),0) / 100000000"
     132              :            "             ,COALESCE(SUM((fees.fee).frac),0)"
     133              :            "              % 100000000)::taler_amount"
     134              :            "     FROM fees)"
     135              :            "    AS total_deposit_fee"
     136              :            "  FROM cd"
     137              :            " WHERE NOT EXISTS ("
     138              :            "   SELECT 1 FROM wire_out wo WHERE wo.wtid_raw=$1)"
     139              :            " HAVING COUNT(*) > 0;");
     140            3 :   return GNUNET_PQ_eval_prepared_singleton_select (
     141              :     pg->conn,
     142              :     "get_pending_aggregation",
     143              :     params,
     144              :     rs);
     145              : }
        

Generated by: LCOV version 2.0-1